Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#include "FlashWidget.h"
#include "DDImage.h"
#include "SexyAppBase.h"
#include "WidgetManager.h"
#include "Debug.h"

using namespace Sexy;

#pragma comment(lib, "comsuppw.lib")

//////////////////////////////////////////////////////////////////////////
// Interfaces imported from flash.ocx

#include <comdef.h>

#pragma pack(push, 8)

namespace ShockwaveFlashObjects
{

//
// Forward references and typedefs
//

struct __declspec(uuid("d27cdb6b-ae6d-11cf-96b8-444553540000"))
/* LIBID */ __ShockwaveFlashObjects;
struct __declspec(uuid("d27cdb6c-ae6d-11cf-96b8-444553540000"))
/* dual interface */ IShockwaveFlash;
struct __declspec(uuid("d27cdb6d-ae6d-11cf-96b8-444553540000"))
/* dispinterface */ _IShockwaveFlashEvents;
struct /* coclass */ ShockwaveFlash;
struct /* coclass */ FlashProp;
struct __declspec(uuid("d27cdb70-ae6d-11cf-96b8-444553540000"))
/* interface */ IFlashFactory;
struct __declspec(uuid("d27cdb72-ae6d-11cf-96b8-444553540000"))
/* interface */ IFlashObjectInterface;
struct __declspec(uuid("a6ef9860-c720-11d0-9337-00a0c90dcaa9"))
/* interface */ IDispatchEx;
struct /* coclass */ FlashObjectInterface;

//
// Smart pointer typedef declarations
//

_COM_SMARTPTR_TYPEDEF(IShockwaveFlash, __uuidof(IShockwaveFlash));
_COM_SMARTPTR_TYPEDEF(_IShockwaveFlashEvents, __uuidof(_IShockwaveFlashEvents));
_COM_SMARTPTR_TYPEDEF(IFlashFactory, __uuidof(IFlashFactory));
_COM_SMARTPTR_TYPEDEF(IDispatchEx, __uuidof(IDispatchEx));
_COM_SMARTPTR_TYPEDEF(IFlashObjectInterface, __uuidof(IFlashObjectInterface));

//
// Type library items
//

struct __declspec(uuid("d27cdb6c-ae6d-11cf-96b8-444553540000"))
IShockwaveFlash : IDispatch
{
    //
    // Property data
    //

    __declspec(property(get=GetStacking,put=PutStacking))
    _bstr_t Stacking;
    __declspec(property(get=GetWMode,put=PutWMode))
    _bstr_t WMode;
    __declspec(property(get=GetMovie,put=PutMovie))
    _bstr_t Movie;
    __declspec(property(get=GetSAlign,put=PutSAlign))
    _bstr_t SAlign;
    __declspec(property(get=GetMenu,put=PutMenu))
    VARIANT_BOOL Menu;
    __declspec(property(get=GetQuality,put=PutQuality))
    int Quality;
    __declspec(property(get=GetLoop,put=PutLoop))
    VARIANT_BOOL Loop;
    __declspec(property(get=GetFrameNum,put=PutFrameNum))
    long FrameNum;
    __declspec(property(get=GetBase,put=PutBase))
    _bstr_t Base;
    __declspec(property(get=Getscale,put=Putscale))
    _bstr_t scale;
    __declspec(property(get=GetDeviceFont,put=PutDeviceFont))
    VARIANT_BOOL DeviceFont;
    __declspec(property(get=GetEmbedMovie,put=PutEmbedMovie))
    VARIANT_BOOL EmbedMovie;
    __declspec(property(get=GetBGColor,put=PutBGColor))
    _bstr_t BGColor;
    __declspec(property(get=GetQuality2,put=PutQuality2))
    _bstr_t Quality2;
    __declspec(property(get=GetReadyState))
    long ReadyState;
    __declspec(property(get=GetScaleMode,put=PutScaleMode))
    int ScaleMode;
    __declspec(property(get=GetAlignMode,put=PutAlignMode))
    int AlignMode;
    __declspec(property(get=GetBackgroundColor,put=PutBackgroundColor))
    long BackgroundColor;
    __declspec(property(get=GetTotalFrames))
    long TotalFrames;
    __declspec(property(get=GetPlaying,put=PutPlaying))
    VARIANT_BOOL Playing;
    __declspec(property(get=GetSWRemote,put=PutSWRemote))
    _bstr_t SWRemote;

    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall get_ReadyState (
        /*[out,retval]*/ long * thestate ) = 0;
      virtual HRESULT __stdcall get_TotalFrames (
        /*[out,retval]*/ long * numframes ) = 0;
      virtual HRESULT __stdcall get_Playing (
        /*[out,retval]*/ VARIANT_BOOL * Playing ) = 0;
      virtual HRESULT __stdcall put_Playing (
        /*[in]*/ VARIANT_BOOL Playing ) = 0;
      virtual HRESULT __stdcall get_Quality (
        /*[out,retval]*/ int * Quality ) = 0;
      virtual HRESULT __stdcall put_Quality (
        /*[in]*/ int Quality ) = 0;
      virtual HRESULT __stdcall get_ScaleMode (
        /*[out,retval]*/ int * scale ) = 0;
      virtual HRESULT __stdcall put_ScaleMode (
        /*[in]*/ int scale ) = 0;
      virtual HRESULT __stdcall get_AlignMode (
        /*[out,retval]*/ int * align ) = 0;
      virtual HRESULT __stdcall put_AlignMode (
        /*[in]*/ int align ) = 0;
      virtual HRESULT __stdcall get_BackgroundColor (
        /*[out,retval]*/ long * color ) = 0;
      virtual HRESULT __stdcall put_BackgroundColor (
        /*[in]*/ long color ) = 0;
      virtual HRESULT __stdcall get_Loop (
        /*[out,retval]*/ VARIANT_BOOL * Loop ) = 0;
      virtual HRESULT __stdcall put_Loop (
        /*[in]*/ VARIANT_BOOL Loop ) = 0;
      virtual HRESULT __stdcall get_Movie (
        /*[out,retval]*/ BSTR * path ) = 0;
      virtual HRESULT __stdcall put_Movie (
        /*[in]*/ BSTR path ) = 0;
      virtual HRESULT __stdcall get_FrameNum (
        /*[out,retval]*/ long * FrameNum ) = 0;
      virtual HRESULT __stdcall put_FrameNum (
        /*[in]*/ long FrameNum ) = 0;
      virtual HRESULT __stdcall SetZoomRect (
        /*[in]*/ long left,
        /*[in]*/ long top,
        /*[in]*/ long right,
        /*[in]*/ long bottom ) = 0;
      virtual HRESULT __stdcall Zoom (
        /*[in]*/ int factor ) = 0;
      virtual HRESULT __stdcall Pan (
        /*[in]*/ long x,
        /*[in]*/ long y,
        /*[in]*/ int mode ) = 0;
      virtual HRESULT __stdcall Play ( ) = 0;
      virtual HRESULT __stdcall Stop ( ) = 0;
      virtual HRESULT __stdcall Back ( ) = 0;
      virtual HRESULT __stdcall Forward ( ) = 0;
      virtual HRESULT __stdcall Rewind ( ) = 0;
      virtual HRESULT __stdcall StopPlay ( ) = 0;
      virtual HRESULT __stdcall GotoFrame (
        /*[in]*/ long FrameNum ) = 0;
      virtual HRESULT __stdcall CurrentFrame (
        /*[out,retval]*/ long * FrameNum ) = 0;
      virtual HRESULT __stdcall IsPlaying (
        /*[out,retval]*/ VARIANT_BOOL * Playing ) = 0;
      virtual HRESULT __stdcall PercentLoaded (
        /*[out,retval]*/ long * __MIDL_0011 ) = 0;
      virtual HRESULT __stdcall FrameLoaded (
        /*[in]*/ long FrameNum,
        /*[out,retval]*/ VARIANT_BOOL * loaded ) = 0;
      virtual HRESULT __stdcall FlashVersion (
        /*[out,retval]*/ long * version ) = 0;
      virtual HRESULT __stdcall get_WMode (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_WMode (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_SAlign (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_SAlign (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_Menu (
        /*[out,retval]*/ VARIANT_BOOL * pVal ) = 0;
      virtual HRESULT __stdcall put_Menu (
        /*[in]*/ VARIANT_BOOL pVal ) = 0;
      virtual HRESULT __stdcall get_Base (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_Base (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_scale (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_scale (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_DeviceFont (
        /*[out,retval]*/ VARIANT_BOOL * pVal ) = 0;
      virtual HRESULT __stdcall put_DeviceFont (
        /*[in]*/ VARIANT_BOOL pVal ) = 0;
      virtual HRESULT __stdcall get_EmbedMovie (
        /*[out,retval]*/ VARIANT_BOOL * pVal ) = 0;
      virtual HRESULT __stdcall put_EmbedMovie (
        /*[in]*/ VARIANT_BOOL pVal ) = 0;
      virtual HRESULT __stdcall get_BGColor (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_BGColor (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_Quality2 (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_Quality2 (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall LoadMovie (
        /*[in]*/ int layer,
        /*[in]*/ BSTR url ) = 0;
      virtual HRESULT __stdcall TGotoFrame (
        /*[in]*/ BSTR target,
        /*[in]*/ long FrameNum ) = 0;
      virtual HRESULT __stdcall TGotoLabel (
        /*[in]*/ BSTR target,
        /*[in]*/ BSTR label ) = 0;
      virtual HRESULT __stdcall TCurrentFrame (
        /*[in]*/ BSTR target,
        /*[out,retval]*/ long * FrameNum ) = 0;
      virtual HRESULT __stdcall TCurrentLabel (
        /*[in]*/ BSTR target,
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall TPlay (
        /*[in]*/ BSTR target ) = 0;
      virtual HRESULT __stdcall TStopPlay (
        /*[in]*/ BSTR target ) = 0;
      virtual HRESULT __stdcall SetVariable (
        /*[in]*/ BSTR name,
        /*[in]*/ BSTR value ) = 0;
      virtual HRESULT __stdcall GetVariable (
        /*[in]*/ BSTR name,
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall TSetProperty (
        /*[in]*/ BSTR target,
        /*[in]*/ int property,
        /*[in]*/ BSTR value ) = 0;
      virtual HRESULT __stdcall TGetProperty (
        /*[in]*/ BSTR target,
        /*[in]*/ int property,
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall TCallFrame (
        /*[in]*/ BSTR target,
        /*[in]*/ int FrameNum ) = 0;
      virtual HRESULT __stdcall TCallLabel (
        /*[in]*/ BSTR target,
        /*[in]*/ BSTR label ) = 0;
      virtual HRESULT __stdcall TSetPropertyNum (
        /*[in]*/ BSTR target,
        /*[in]*/ int property,
        /*[in]*/ double value ) = 0;
      virtual HRESULT __stdcall TGetPropertyNum (
        /*[in]*/ BSTR target,
        /*[in]*/ int property,
        /*[out,retval]*/ double * pVal ) = 0;
      virtual HRESULT __stdcall get_SWRemote (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_SWRemote (
        /*[in]*/ BSTR pVal ) = 0;
      virtual HRESULT __stdcall get_Stacking (
        /*[out,retval]*/ BSTR * pVal ) = 0;
      virtual HRESULT __stdcall put_Stacking (
        /*[in]*/ BSTR pVal ) = 0;
};

struct __declspec(uuid("d27cdb6d-ae6d-11cf-96b8-444553540000"))
_IShockwaveFlashEvents : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    // Methods:
    HRESULT OnReadyStateChange (
        long newState );
    HRESULT OnProgress (
        long percentDone );
    HRESULT FSCommand (
        _bstr_t command,
        _bstr_t args );
};

struct __declspec(uuid("d27cdb6e-ae6d-11cf-96b8-444553540000"))
ShockwaveFlash;
    // [ default ] interface IShockwaveFlash
    // [ default, source ] dispinterface _IShockwaveFlashEvents

struct __declspec(uuid("1171a62f-05d2-11d1-83fc-00a0c9089c5a"))
FlashProp;
    // [ default ] interface IUnknown

struct __declspec(uuid("d27cdb70-ae6d-11cf-96b8-444553540000"))
IFlashFactory : IUnknown
{};

struct __declspec(uuid("a6ef9860-c720-11d0-9337-00a0c90dcaa9"))
IDispatchEx : IDispatch
{
    //
    // Wrapper methods for error-handling
    //

    HRESULT GetDispID (
        _bstr_t bstrName,
        unsigned long grfdex,
        long * pid );
    HRESULT RemoteInvokeEx (
        long id,
        unsigned long lcid,
        unsigned long dwFlags,
        struct DISPPARAMS * pdp,
        VARIANT * pvarRes,
        struct EXCEPINFO * pei,
        struct IServiceProvider * pspCaller,
        unsigned int cvarRefArg,
        unsigned int * rgiRefArg,
        VARIANT * rgvarRefArg );
    HRESULT DeleteMemberByName (
        _bstr_t bstrName,
        unsigned long grfdex );
    HRESULT DeleteMemberByDispID (
        long id );
    HRESULT GetMemberProperties (
        long id,
        unsigned long grfdexFetch,
        unsigned long * pgrfdex );
    HRESULT GetMemberName (
        long id,
        BSTR * pbstrName );
    HRESULT GetNextDispID (
        unsigned long grfdex,
        long id,
        long * pid );
    HRESULT GetNameSpaceParent (
        IUnknown * * ppunk );

    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall raw_GetDispID (
        /*[in]*/ BSTR bstrName,
        /*[in]*/ unsigned long grfdex,
        /*[out]*/ long * pid ) = 0;
      virtual HRESULT __stdcall raw_RemoteInvokeEx (
        /*[in]*/ long id,
        /*[in]*/ unsigned long lcid,
        /*[in]*/ unsigned long dwFlags,
        /*[in]*/ struct DISPPARAMS * pdp,
        /*[out]*/ VARIANT * pvarRes,
        /*[out]*/ struct EXCEPINFO * pei,
        /*[in]*/ struct IServiceProvider * pspCaller,
        /*[in]*/ unsigned int cvarRefArg,
        /*[in]*/ unsigned int * rgiRefArg,
        /*[in,out]*/ VARIANT * rgvarRefArg ) = 0;
      virtual HRESULT __stdcall raw_DeleteMemberByName (
        /*[in]*/ BSTR bstrName,
        /*[in]*/ unsigned long grfdex ) = 0;
      virtual HRESULT __stdcall raw_DeleteMemberByDispID (
        /*[in]*/ long id ) = 0;
      virtual HRESULT __stdcall raw_GetMemberProperties (
        /*[in]*/ long id,
        /*[in]*/ unsigned long grfdexFetch,
        /*[out]*/ unsigned long * pgrfdex ) = 0;
      virtual HRESULT __stdcall raw_GetMemberName (
        /*[in]*/ long id,
        /*[out]*/ BSTR * pbstrName ) = 0;
      virtual HRESULT __stdcall raw_GetNextDispID (
        /*[in]*/ unsigned long grfdex,
        /*[in]*/ long id,
        /*[out]*/ long * pid ) = 0;
      virtual HRESULT __stdcall raw_GetNameSpaceParent (
        /*[out]*/ IUnknown * * ppunk ) = 0;
};

struct __declspec(uuid("d27cdb72-ae6d-11cf-96b8-444553540000"))
IFlashObjectInterface : IDispatchEx
{};

struct __declspec(uuid("d27cdb71-ae6d-11cf-96b8-444553540000"))
FlashObjectInterface;
    // [ default ] interface IFlashObjectInterface

} // namespace ShockwaveFlashObjects

#pragma pack(pop)

//////////////////////////////////////////////////////////////////////////
// FlashSink - Receives flash events  

namespace Sexy
{

class FlashSink : public ShockwaveFlashObjects::_IShockwaveFlashEvents
{
public:
        LPCONNECTIONPOINT               mConnectionPoint;      
        DWORD                                   mCookie;
        int                                             mRefCount;
        FlashWidget*                    mFlashWidget;

public:
        FlashSink()
        {              
                mCookie = 0;
                mConnectionPoint = NULL;
                mRefCount = 0;
                mFlashWidget = NULL;           
        }

        virtual ~FlashSink()
        {
                mFlashWidget->mCOMCount--;
        }

        HRESULT Init(FlashWidget* theFlashWidget)
        {
                mFlashWidget = theFlashWidget;
                mFlashWidget->mCOMCount++;

                HRESULT aResult = NOERROR;
                LPCONNECTIONPOINTCONTAINER aConnectionPoint = NULL;
                                               
                if ((mFlashWidget->mFlashInterface->QueryInterface(IID_IConnectionPointContainer, (void**) &aConnectionPoint) == S_OK) &&
                        (aConnectionPoint->FindConnectionPoint(__uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents), &mConnectionPoint) == S_OK))                   
                {
                        IDispatch* aDispatch = NULL;
                        QueryInterface(__uuidof(IDispatch), (void**) &aDispatch);
                        if (aDispatch != NULL)
                        {
                                aResult = mConnectionPoint->Advise((LPUNKNOWN)aDispatch, &mCookie);
                                aDispatch->Release();
                        }
                }
                               
                if (aConnectionPoint != NULL)
                        aConnectionPoint->Release();

                return aResult;
        }

        HRESULT Shutdown()
        {
                HRESULT aResult = S_OK;

                if (mConnectionPoint)
                {
                        if (mCookie)
                        {
                                aResult = mConnectionPoint->Unadvise(mCookie);
                                mCookie = 0;
                        }

                        mConnectionPoint->Release();
                        mConnectionPoint = NULL;
                }

                return aResult;
        }
 
        HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)
        {
                *ppv = NULL;

                if (riid == IID_IUnknown)
                {
                        *ppv = (LPUNKNOWN)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IDispatch)
                {
                        *ppv = (IDispatch*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == __uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents))
                {
                        *ppv = (ShockwaveFlashObjects::_IShockwaveFlashEvents*) this;
                        AddRef();
                        return S_OK;
                }
                else
                {  
                        return E_NOTIMPL;
                }
        }

        ULONG STDMETHODCALLTYPE AddRef()
        {  
                return ++mRefCount;
        }

        ULONG STDMETHODCALLTYPE Release()
        {  
                int aRefCount = --mRefCount;
                if (aRefCount == 0)            
                        delete this;           

                return aRefCount;
        }

 // IDispatch method
  virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo)
   { return E_NOTIMPL; }

        virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
        {
                return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
                UINT cNames, LCID lcid,DISPID* rgDispId)
        {
                return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
                WORD wFlags, ::DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult,
                ::EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr)
        {
                switch(dispIdMember)
                {
                case 0x7a6:                    
                        break;
                case 0x96:                     
                        if ((pDispParams->cArgs == 2) &&
                                (pDispParams->rgvarg[0].vt == VT_BSTR) &&
                                (pDispParams->rgvarg[1].vt == VT_BSTR))
                        {
                                FSCommand(pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].bstrVal);
                        }
                        break;
                case DISPID_READYSTATECHANGE:                                  
                        break;
                default:                       
                        return DISP_E_MEMBERNOTFOUND;
                }
               
                return NOERROR;
        }

        HRESULT OnReadyStateChange (long newState)
        {      
                return S_OK;
        }
   
        HRESULT OnProgress(long percentDone )
        {              
                return S_OK;
        }

        HRESULT FSCommand (_bstr_t command, _bstr_t args)
        {
                if (mFlashWidget->mFlashListener != NULL)
                        mFlashWidget->mFlashListener->FlashCommand(mFlashWidget->mId, (char*) command, (char*) args);
                return S_OK;
        }      
};

}

using namespace ShockwaveFlashObjects;

//////////////////////////////////////////////////////////////////////////
// ControlSite - container that holds the flash control

namespace Sexy
{

class ControlSite :    
        public IOleInPlaceSiteWindowless,
        public IOleClientSite  
{
public:
        int                                             mRefCount;
        FlashWidget*                    mFlashWidget;

public:
        ControlSite()
        {              
                mRefCount = 0;         
                mFlashWidget = NULL;
        }      

        virtual ~ControlSite()
        {
                if (mFlashWidget != NULL)
                        mFlashWidget->mCOMCount--;
        }

        void Init(FlashWidget* theFlashWidget)
        {
                mFlashWidget = theFlashWidget;
                mFlashWidget->mCOMCount++;
        }

        HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv)
        {
                *ppv = NULL;

                if (riid == IID_IUnknown)
                {
                        *ppv = (IUnknown*) (IOleWindow*) this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IOleWindow)
                {
                        *ppv = (IOleWindow*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IOleInPlaceSite)
                {
                        *ppv = (IOleInPlaceSite*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IOleInPlaceSiteEx)
                {
                        *ppv = (IOleInPlaceSiteEx*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IOleInPlaceSiteWindowless)
                {
                        *ppv = (IOleInPlaceSiteWindowless*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == IID_IOleClientSite)
                {
                        *ppv = (IOleClientSite*)this;
                        AddRef();
                        return S_OK;
                }
                else if (riid == __uuidof(ShockwaveFlashObjects::_IShockwaveFlashEvents))
                {
                        *ppv = (ShockwaveFlashObjects::_IShockwaveFlashEvents*) this;
                        AddRef();
                        return S_OK;
                }
                else
                {  
                        return E_NOTIMPL;
                }
        }

        ULONG STDMETHODCALLTYPE AddRef()
        {  
                return ++mRefCount;
        }

        ULONG STDMETHODCALLTYPE Release()
        {
                int aRefCount = --mRefCount;
                if (aRefCount == 0)            
                        delete this;           

                return aRefCount;
        }

        //////////////////////////////////////////////////////////////////////////     

        virtual HRESULT  STDMETHODCALLTYPE SaveObject(void)
        {
                return S_OK;
        }

        virtual HRESULT  STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker,IMoniker** ppmk )
        {
                *ppmk = NULL;
                return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer ** theContainerP)
        {
                //return QueryInterface(__uuidof(IOleContainer), (void**) theContainerP);                              
                return E_NOINTERFACE;
        }


        virtual HRESULT  STDMETHODCALLTYPE ShowObject(void)
        {
                return E_NOTIMPL;
        }

        virtual HRESULT  STDMETHODCALLTYPE OnShowWindow(BOOL)
        {
                return E_NOTIMPL;
        }

        virtual HRESULT  STDMETHODCALLTYPE RequestNewObjectLayout(void)
        {
                return E_NOTIMPL;
        }
                //             
       

        HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(/* [in] */ BOOL fEnterMode)
        {
            return S_OK;
        }

        HRESULT STDMETHODCALLTYPE GetWindow(/* [out] */ HWND __RPC_FAR* theWnndow)
        {
                return E_FAIL;

            //*theWnndow = NULL;
                //*theWnndow = gSexyAppBase->mHWnd;
                //return S_OK;
        }

        HRESULT STDMETHODCALLTYPE CanInPlaceActivate(void)
        {
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnInPlaceActivate(void)
        {              
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnUIActivate(void)
        {              
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE GetWindowContext(/* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame, /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc, /* [out] */ LPRECT lprcPosRect, /* [out] */ LPRECT lprcClipRect, /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
        {
                RECT aRect = mFlashWidget->GetRect().ToRECT();

                *lprcPosRect = aRect;
                *lprcClipRect = aRect;
               
                *ppFrame = NULL;
                QueryInterface(__uuidof(IOleInPlaceFrame), (void**) ppFrame);          
                *ppDoc = NULL;

                lpFrameInfo->fMDIApp = FALSE;
                lpFrameInfo->hwndFrame = NULL;
                lpFrameInfo->haccel = NULL;
                lpFrameInfo->cAccelEntries = 0;
               
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE Scroll(/* [in] */ SIZE scrollExtant)
        {
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnUIDeactivate(/* [in] */ BOOL fUndoable)
        {              
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(void)
        {      
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE DiscardUndoState(void)
        {
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE DeactivateAndUndo(void)
        {
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnPosRectChange(/* [in] */ LPCRECT lprcPosRect)
        {
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(/* [out] */ BOOL __RPC_FAR *pfNoRedraw, /* [in] */ DWORD dwFlags)
        {              
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(/* [in] */ BOOL fNoRedraw)
        {              
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE RequestUIActivate(void)
        {
                return S_FALSE;
        }


        HRESULT STDMETHODCALLTYPE CanWindowlessActivate(void)
        {
                // Allow windowless activation?
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE GetCapture(void)
        {
                // TODO capture the mouse for the object
                return S_FALSE;
        }


        HRESULT STDMETHODCALLTYPE SetCapture(/* [in] */ BOOL fCapture)
        {
                // TODO capture the mouse for the object
                return S_FALSE;
        }


        HRESULT STDMETHODCALLTYPE GetFocus(void)
        {
                return S_OK;
        }


        HRESULT STDMETHODCALLTYPE SetFocus(/* [in] */ BOOL fFocus)
        {
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE GetDC(/* [in] */ LPCRECT pRect, /* [in] */ DWORD grfFlags, /* [out] */ HDC __RPC_FAR *phDC)
        {              
                return E_INVALIDARG;           
        }


        HRESULT STDMETHODCALLTYPE ReleaseDC(/* [in] */ HDC hDC)
        {
                return E_INVALIDARG;
        }


        HRESULT STDMETHODCALLTYPE InvalidateRect(/* [in] */ LPCRECT pRect, /* [in] */ BOOL fErase)
        {      
                if (pRect == NULL)
                {
                        mFlashWidget->mDirtyRect = mFlashWidget->GetRect();
                        mFlashWidget->mFlashDirty = true;
                }
                else if (!mFlashWidget->mFlashDirty)
                {
                        mFlashWidget->mDirtyRect = Rect(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
                        mFlashWidget->mFlashDirty = true;
                }
                else
                {                      
                        mFlashWidget->mDirtyRect = mFlashWidget->mDirtyRect.Union(Rect(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top));
                }              
               
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE InvalidateRgn(/* [in] */ HRGN hRGN, /* [in] */ BOOL fErase)
        {      
                mFlashWidget->mDirtyRect = mFlashWidget->GetRect();
                mFlashWidget->mFlashDirty = true;
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE ScrollRect(/* [in] */ INT dx, /* [in] */ INT dy, /* [in] */ LPCRECT pRectScroll, /* [in] */ LPCRECT pRectClip)
        {
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE AdjustRect(/* [out][in] */ LPRECT prc)
        {
                if (prc == NULL)
                {
                        return E_INVALIDARG;
                }
               
                return S_OK;
        }

        HRESULT STDMETHODCALLTYPE OnDefWindowMessage(/* [in] */ UINT msg, /* [in] */ WPARAM wParam, /* [in] */ LPARAM lParam, /* [out] */ LRESULT __RPC_FAR *plResult)
        {
                return S_FALSE;
        }
};

}

//////////////////////////////////////////////////////////////////////////

const CLSID CLSID_ShockwaveFlash =
  { 0xD27CDB6E, 0xAE6D, 0x11cf, {0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };

typedef HRESULT (__stdcall *DllGetClassObjectFunc)(REFCLSID rclsid, REFIID riid, LPVOID * ppv);

FlashWidget::FlashWidget(int theId, FlashListener* theFlashListener)
{
        HRESULT aResult;

        mState = STATE_IDLE;

        mCurCursor = CURSOR_POINTER;
        mCurOverrideCursor = NULL;

        mCOMCount = 0;
        mPauseCount = 0;
        mAutoPause = true;
        mHasLostFocus = !gSexyAppBase->mHasFocus;
        mFlashDirty = true;    

        mBkgColor.mAlpha = 0;
        mId = theId;
        mFlashListener = theFlashListener;     

        mFlashSink = NULL;
       
        mImage = NULL; 
        mFlashInterface = NULL;
        mOleObject = NULL;
        mWindowlessObject = NULL;

        mBkgImage = NULL;
        mFlashLibHandle = NULL;

        CoInitialize(NULL);

        mControlSite = new ControlSite();
        mControlSite->AddRef();
        mControlSite->Init(this);
               
        mFlashLibHandle = LoadLibraryA("flash.ocx");
        if (mFlashLibHandle != NULL)
        {
                IClassFactory* aClassFactory = NULL;
                DllGetClassObjectFunc aDllGetClassObjectFunc = (DllGetClassObjectFunc) GetProcAddress(mFlashLibHandle, "DllGetClassObject");
                aResult = aDllGetClassObjectFunc(CLSID_ShockwaveFlash, IID_IClassFactory, (void**)&aClassFactory);
                aClassFactory->CreateInstance(NULL, IID_IOleObject, (void**)&mOleObject);
                aClassFactory->Release();      
        }
        else
        {
                CoCreateInstance(CLSID_ShockwaveFlash, NULL,
                        CLSCTX_INPROC_SERVER,
                        IID_IOleObject,
                        (void**)&mOleObject);
        }

        IOleClientSite* aClientSite = NULL;
        mControlSite->QueryInterface(__uuidof(IOleClientSite), (void**) &aClientSite);
        mOleObject->SetClientSite(aClientSite);

        mOleObject->QueryInterface(__uuidof(IShockwaveFlash), (LPVOID*) &mFlashInterface);
        _bstr_t aTrans = "Transparent";
        mFlashInterface->put_WMode(aTrans);

        aResult = mOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, aClientSite, 0, NULL, NULL);
        aClientSite->Release();
               
        mOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (LPVOID*) &mWindowlessObject);
                       
        mFlashSink = new FlashSink();
        mFlashSink->AddRef();  
        mFlashSink->Init(this);
}

FlashWidget::~FlashWidget()
{
        CleanupImages();
               
        if (mWindowlessObject != NULL)
                mWindowlessObject->Release();
        if (mFlashInterface != NULL)
                mFlashInterface->Release();    

        if (mFlashSink != NULL)
        {
                mFlashSink->Shutdown();
                mFlashSink->Release();
        }

        mOleObject->Close(OLECLOSE_NOSAVE);
               
        if (mOleObject != NULL)
                mOleObject->Release(); 

        if (mControlSite != NULL)
                mControlSite->Release();

        // Make sure all our COM objects were actually destroyed
        DBG_ASSERTE(mCOMCount == 0);

        if (mFlashLibHandle != NULL)
                FreeLibrary(mFlashLibHandle);  
}

double FlashWidget::GetFlashVersion()
{
        CoInitialize(NULL);

        IOleObject* anOleObject = NULL;
        if (FAILED(CoCreateInstance(CLSID_ShockwaveFlash, NULL,
                CLSCTX_INPROC_SERVER,
                IID_IOleObject,
                (void**) &anOleObject)))
                return 0.0;    

        IShockwaveFlash* aFlashInterface = NULL;
        if (FAILED(anOleObject->QueryInterface(__uuidof(IShockwaveFlash), (LPVOID*) &aFlashInterface)))
                return 0.0;
       
        long aVersion = 0;
        aFlashInterface->FlashVersion(&aVersion);

        aFlashInterface->Release();
        anOleObject->Release();

        return aVersion / 65536.0;
}

void FlashWidget::CleanupImages()
{
        if (mImage != NULL)
        {
                delete mImage;
                mImage = NULL;
        }
}

void FlashWidget::RebuildImages()
{
        CleanupImages();

        mImage = new DDImage(gSexyAppBase->mDDInterface);
        mImage->Create(mWidth, mHeight);
        mImage->SetImageMode(false, false);    
}

void FlashWidget::CheckCursor()
{
        HCURSOR aCursor = GetCursor();
        if (aCursor == ::LoadCursor(NULL, IDC_ARROW))
        {
                mCurCursor = CURSOR_POINTER;
                gSexyAppBase->mOverrideCursor = NULL;
                gSexyAppBase->SetCursor(mCurCursor);
        }
        else if (aCursor != NULL)
        {
                gSexyAppBase->mOverrideCursor = aCursor;
                mCurCursor = CURSOR_HAND;
                gSexyAppBase->SetCursor(mCurCursor);
        }
}

void FlashWidget::DrawFlashBackground(Graphics* g)
{
        if (mBkgColor.mAlpha != 0)
        {
                g->SetColor(mBkgColor);
                g->FillRect(0, 0, mWidth, mHeight);
        }

        if (mBkgImage != NULL)
        {
                if ((mBkgImageSrcRect.mWidth != 0) && (mBkgImageSrcRect.mHeight != 0))
                        g->DrawImage(mBkgImage, 0, 0, mBkgImageSrcRect);
                else
                        g->DrawImage(mBkgImage, 0, 0);
        }
}

bool FlashWidget::StartAnimation(const std::string& theFileName)
{
        std::string aFullPath = GetFullPath(theFileName);
       
        _bstr_t bstr((char*) aFullPath.c_str());               
        mFlashInterface->put_Movie(bstr); // you have to change the path here  
        if ((mPauseCount == 0) && (mFlashInterface->Play() != S_OK))
                return false;  

        if ((mWidgetManager != NULL) && (mIsOver))
                MouseMove(mWidgetManager->mLastMouseX - mX, mWidgetManager->mLastMouseY - mY);

        mState = STATE_PLAYING;
        return true;
}

void FlashWidget::SetQuality(int theQuality)
{
        static char* aQualityNames[3] = {"Low", "Medium", "High"};
       
        _bstr_t aNewStr = aQualityNames[theQuality];
        mFlashInterface->put_Quality2(aNewStr);
}

void FlashWidget::Pause()
{
        mPauseCount++;

        if (mState != STATE_STOPPED)
                mState = STATE_IDLE;

        if ((mPauseCount == 1) && (mFlashInterface != NULL) && (mState != STATE_STOPPED))
                mFlashInterface->StopPlay();
}

void FlashWidget::Unpause()
{
        mPauseCount--;
        if ((mPauseCount == 0) && (mFlashInterface != NULL) && (mState != STATE_STOPPED))
        {
                mState = STATE_PLAYING;
                mFlashInterface->Play();
        }
}

void FlashWidget::Rewind()
{
        if (mFlashInterface != NULL)
        {
                mFlashInterface->Rewind();
                mFlashInterface->Play();
        }
}

void FlashWidget::GotoFrame(int theFrameNum)
{
        if (mFlashInterface != NULL)
        {
                mFlashInterface->GotoFrame(theFrameNum);
                mFlashInterface->Play();
        }
}

void FlashWidget::Back()
{
        if (mFlashInterface != NULL)
        {
                mFlashInterface->Back();
                mFlashInterface->Play();
        }
}

void FlashWidget::Forward()
{
        if (mFlashInterface != NULL)
        {
                mFlashInterface->Forward();
                mFlashInterface->Play();
        }
}

bool FlashWidget::IsPlaying()
{
        VARIANT_BOOL aBool = 0;
        if (mFlashInterface != NULL)
                mFlashInterface->IsPlaying(&aBool);
        return aBool != 0;
}

int FlashWidget::GetCurrentFrame()
{      
        long aCurrentFrame = -1;
        if (mFlashInterface != NULL)
                mFlashInterface->CurrentFrame(&aCurrentFrame);
        return aCurrentFrame;
}

std::string FlashWidget::GetCurrentLabel(const std::string& theTimeline)
{
        BSTR aBStr = L"";
        if (mFlashInterface != NULL)
                mFlashInterface->TCurrentLabel(_bstr_t(theTimeline.c_str()), &aBStr);
        return (const char*) _bstr_t(aBStr);
}

void FlashWidget::CallFrame(const std::string& theTimeline, int theFrameNum)
{
        if (mFlashInterface != NULL)
                mFlashInterface->TCallFrame(_bstr_t(theTimeline.c_str()), theFrameNum);
}

void FlashWidget::CallLabel(const std::string& theTimeline, const std::string& theLabel)
{
        if (mFlashInterface != NULL)
                mFlashInterface->TCallLabel(_bstr_t(theTimeline.c_str()), _bstr_t(theLabel.c_str()));
}

std::string FlashWidget::GetVariable(const std::string& theName)
{
        BSTR aBStr = L"";
        if (mFlashInterface != NULL)
                mFlashInterface->GetVariable(_bstr_t(theName.c_str()), &aBStr);
        return (const char*) _bstr_t(aBStr);
}

void FlashWidget::SetVariable(const std::string& theName, const std::string& theValue)
{
        if (mFlashInterface != NULL)
                mFlashInterface->SetVariable(_bstr_t(theName.c_str()), _bstr_t(theValue.c_str()));
}

void FlashWidget::Update()
{
        if (mAutoPause)
        {
                if (!gSexyAppBase->mHasFocus)
                {
                        if (!mHasLostFocus)
                        {
                                if (mAutoPause)
                                        Pause();
                                mHasLostFocus = true;
                        }

                        return;
                }
                else
                {
                        if (mHasLostFocus)
                        {
                                if (mAutoPause)
                                        Unpause();
                                mHasLostFocus = false;
                        }
                }
        }

        if (mState == STATE_PLAYING)
        {
                VARIANT_BOOL isPlaying = 0;
                mFlashInterface->IsPlaying(&isPlaying);
                if (!isPlaying)
                {
                        mState = STATE_STOPPED;
                        if ((mFlashListener != NULL) && (mPauseCount == 0))
                                mFlashListener->FlashAnimEnded(mId);
                }
        }

        if (mFlashDirty)
                MarkDirty();
}

void FlashWidget::Resize(int theX, int theY, int theWidth, int theHeight)
{
        Widget::Resize(theX, theY, theWidth, theHeight);

        mDirtyRect = Rect(theX, theY, theWidth, theHeight);    

        RebuildImages();

        IOleInPlaceObject* anInPlaceObject = NULL;     
        mOleObject->QueryInterface(__uuidof(IOleInPlaceObject), (LPVOID*) &anInPlaceObject);                   

        if (anInPlaceObject != NULL)
        {
                RECT aRect = GetRect().ToRECT();
                anInPlaceObject->SetObjectRects(&aRect, &aRect);
                anInPlaceObject->Release();
        }
}

void FlashWidget::Draw(Graphics* g)
{      
        if (mFlashDirty)
        {
                Graphics anImageG(mImage);     
                DrawFlashBackground(&anImageG);

                LPDIRECTDRAWSURFACE aSurface = mImage->GetSurface();
                if (aSurface == NULL)
                        return;

                HDC aDC = NULL;
                if (aSurface->GetDC(&aDC) != S_OK)
                        return;

                IViewObject* aViewObject = NULL;
                mFlashInterface->QueryInterface(IID_IViewObject, (LPVOID*) &aViewObject);
                if (aViewObject != NULL)
                {
                        RECTL aRect = {0, 0, mWidth, mHeight};

                        Point anAbsPos = GetAbsPos();

                        HRGN aRgn = CreateRectRgn(mDirtyRect.mX - anAbsPos.mX, mDirtyRect.mY - anAbsPos.mY,
                                mDirtyRect.mX + mDirtyRect.mWidth - anAbsPos.mX,
                                mDirtyRect.mY + mDirtyRect.mHeight - anAbsPos.mY);
                        SelectClipRgn(aDC, aRgn);
                        DeleteObject(aRgn);

                        aViewObject->Draw(DVASPECT_CONTENT, 1,
                                NULL, NULL, NULL, aDC, &aRect, NULL, NULL,
                                0);

                        aViewObject->Release();
                }

                aSurface->ReleaseDC(aDC);

                mFlashDirty = false;
        }
       
        g->DrawImage(mImage, 0, 0);
}

void FlashWidget::MouseMove(int x, int y)
{      
        Widget::MouseMove(x, y);

        LRESULT aResult;
        Point anAbsPos = GetAbsPos();
        mWindowlessObject->OnWindowMessage(WM_MOUSEMOVE, 0, MAKELPARAM(x + anAbsPos.mX, y + anAbsPos.mY), &aResult);

        if (mIsOver)
                CheckCursor();
}

void FlashWidget::MouseDown(int x, int y, int theBtnNum, int theClickCount)
{
        if (theBtnNum == 0)
        {
                LRESULT aResult;
                Point anAbsPos = GetAbsPos();
                mWindowlessObject->OnWindowMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x + anAbsPos.mX, y + anAbsPos.mY), &aResult);
                CheckCursor();
        }
}

void FlashWidget::MouseUp(int x, int y, int theBtnNum, int theClickCount)
{
        if (theBtnNum == 0)
        {
                LRESULT aResult;
                Point anAbsPos = GetAbsPos();
                mWindowlessObject->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(x + anAbsPos.mX, y + anAbsPos.mY), &aResult);
                CheckCursor();
        }
}

void FlashWidget::MouseDrag(int x, int y)
{
        if (mWidgetManager->IsLeftButtonDown())
        {
                LRESULT aResult;
                Point anAbsPos = GetAbsPos();
                mWindowlessObject->OnWindowMessage(WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(x + anAbsPos.mX, y + anAbsPos.mY), &aResult);
                CheckCursor();
        }
}

void FlashWidget::MouseLeave()
{
        Widget::MouseLeave();

        // To prevent Flash control from setting our cursor if it thinks
        // our mouse is still over something
        MouseMove(-1, -1);

        gSexyAppBase->mOverrideCursor = NULL;
        gSexyAppBase->SetCursor(CURSOR_POINTER);       
}

void FlashWidget::SysColorChanged()
{
        mFlashDirty = true;
        mDirtyRect = GetRect();

        MarkDirty();
}