123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #include "FLVCOM.h"
- #include "AMFDispatch.h"
- FLVCOM flvCOM;
- extern bool mute;
- static HANDLE DuplicateCurrentThread()
- {
- HANDLE fakeHandle = GetCurrentThread();
- HANDLE copiedHandle = 0;
- HANDLE processHandle = GetCurrentProcess();
- DuplicateHandle(processHandle, fakeHandle, processHandle, &copiedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
- return copiedHandle;
- }
- enum
- {
- DISP_FLV_REGISTER_CALLBACK,
- DISP_FLV_UNREGISTER_CALLBACK,
- DISP_FLV_SETMUTE,
- };
- #define CHECK_ID(str, id) if (wcscmp(rgszNames[i], L##str) == 0) { rgdispid[i] = id; continue; }
- HRESULT FLVCOM::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
- {
- bool unknowns = false;
- for (unsigned int i = 0;i != cNames;i++)
- {
- CHECK_ID("RegisterCallback", DISP_FLV_REGISTER_CALLBACK)
- CHECK_ID("UnregisterCallback", DISP_FLV_UNREGISTER_CALLBACK)
- CHECK_ID("SetMute", DISP_FLV_SETMUTE)
- rgdispid[i] = DISPID_UNKNOWN;
- unknowns = true;
- }
- if (unknowns)
- return DISP_E_UNKNOWNNAME;
- else
- return S_OK;
- }
- HRESULT FLVCOM::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
- {
- return E_NOTIMPL;
- }
- HRESULT FLVCOM::GetTypeInfoCount(unsigned int FAR * pctinfo)
- {
- return E_NOTIMPL;
- }
- HRESULT FLVCOM::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
- {
- if (pvarResult)
- VariantInit(pvarResult);
- switch (dispid)
- {
- case DISP_FLV_SETMUTE:
- {
- if (pdispparams->rgvarg[0].boolVal)
- mute = true;
- else
- mute = false;
- }
- return S_OK;
- case DISP_FLV_REGISTER_CALLBACK:
- {
- IDispatch *callback = pdispparams->rgvarg[0].pdispVal;
- callbacks.push_back(DispatchCallbackInfo(callback, GetCurrentThreadId(), DuplicateCurrentThread()));
- return S_OK;
- }
- break;
- case DISP_FLV_UNREGISTER_CALLBACK:
- {
- IDispatch *callback = pdispparams->rgvarg[0].pdispVal;
- size_t numCallbacks = callbacks.size();
- while (numCallbacks--)
- {
- if (callbacks[numCallbacks].dispatch == callback)
- {
- CloseHandle(callbacks[numCallbacks].threadHandle);
- callbacks.erase(callbacks.begin() + numCallbacks);
- }
- }
- return S_OK;
- }
- break;
- }
- return DISP_E_MEMBERNOTFOUND;
- }
- STDMETHODIMP FLVCOM::QueryInterface(REFIID riid, PVOID *ppvObject)
- {
- if (!ppvObject)
- return E_POINTER;
- else if (IsEqualIID(riid, IID_IDispatch))
- *ppvObject = (IDispatch *)this;
- else if (IsEqualIID(riid, IID_IUnknown))
- *ppvObject = this;
- else
- {
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
- AddRef();
- return S_OK;
- }
- ULONG FLVCOM::AddRef(void)
- {
- return 0;
- }
- ULONG FLVCOM::Release(void)
- {
- return 0;
- }
- static void CallDispatchMethod(IDispatch *dispatch, DISPPARAMS ¶ms, OLECHAR *name)
- {
- try
- {
- unsigned int ret;
- DISPID dispid;
- if (SUCCEEDED(dispatch->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
- dispatch->Invoke(dispid, GUID_NULL, 0, DISPATCH_METHOD, ¶ms, 0, 0, &ret);
- }
- catch (...)
- {}
- }
- struct APCdata
- {
- IDispatch *disp;
- wchar_t *name;
- AMFDispatch *amf;
- };
- static VOID CALLBACK MetadataAPC(ULONG_PTR param)
- {
- APCdata *data = (APCdata *)param;
- DISPPARAMS params;
- VARIANT argument;
- params.cArgs = 1;
- params.cNamedArgs = 0;
- params.rgdispidNamedArgs = 0;
- params.rgvarg = &argument;
- VariantInit(&argument);
- V_VT(&argument) = VT_DISPATCH;
- V_DISPATCH(&argument) = data->amf;
- CallDispatchMethod(data->disp, params, data->name);
- data->disp->Release();
- data->amf->Release();
- free(data->name);
- delete data;
- }
- void FLVCOM::MetadataCallback(FLVMetadata::Tag *tag)
- {
- if (!callbacks.empty())
- {
- AMFDispatch *disp = new AMFDispatch(tag->parameters); // we're newing this we can refcount
- DWORD curThreadId = GetCurrentThreadId();
- for (size_t i = 0;i != callbacks.size();i++)
- {
- APCdata *data = new APCdata;
- data->disp = callbacks[i].dispatch;
- data->disp->AddRef();
- data->name = _wcsdup(tag->name.str);
- data->amf = disp;
- data->amf->AddRef();
- if (curThreadId == callbacks[i].threadId)
- MetadataAPC((ULONG_PTR)data);
- else
- {
- if (callbacks[i].threadHandle)
- QueueUserAPC(MetadataAPC, callbacks[i].threadHandle, (ULONG_PTR)data);
- }
- }
- disp->Release();
- }
- }
|