+// Condition variable emulation
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void ConditionInit(HANDLE *handle)
+{
+ *handle = CreateEvent(NULL, TRUE, FALSE, NULL);
+ assert(*handle != NULL);
+}
+
+static void ConditionDestroy(HANDLE *handle)
+{
+ CloseHandle(*handle);
+}
+
+static void ConditionWait(HANDLE *handle, CRITICAL_SECTION *lock)
+{
+ DWORD dwWaitResult;
+
+ do {
+ LeaveCriticalSection(lock);
+ dwWaitResult = WaitForSingleObjectEx(*handle, INFINITE, TRUE);
+ EnterCriticalSection(lock);
+ } while(dwWaitResult == WAIT_IO_COMPLETION);
+
+ assert(dwWaitResult != WAIT_ABANDONED); /* another thread failed to cleanup! */
+ assert(dwWaitResult != WAIT_FAILED);
+ ResetEvent(*handle);
+}
+
+static void ConditionSignal(HANDLE *handle)
+{
+ SetEvent(*handle);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+// Event handling thread
+//
+// It bridges the gap between libvlc thread context and ActiveX/COM thread context.
+////////////////////////////////////////////////////////////////////////////////////////////////
+DWORD WINAPI ThreadProcEventHandler(LPVOID lpParam)
+{
+ CoInitialize(NULL);
+ VLCConnectionPointContainer *pCPC = (VLCConnectionPointContainer *)lpParam;
+
+ while(pCPC->isRunning)
+ {
+ EnterCriticalSection(&(pCPC->csEvents));
+ ConditionWait(&(pCPC->sEvents), &(pCPC->csEvents));
+
+ if (!pCPC->isRunning)
+ {
+ LeaveCriticalSection(&(pCPC->csEvents));
+ break;
+ }
+
+ while(!pCPC->_q_events.empty())
+ {
+ VLCDispatchEvent *ev = pCPC->_q_events.front();
+ pCPC->_q_events.pop();
+ pCPC->_p_events->fireEvent(ev->_dispId, &ev->_dispParams);
+ delete ev;
+
+
+ if (!pCPC->isRunning)
+ {
+ LeaveCriticalSection(&(pCPC->csEvents));
+ goto out;
+ }
+ }
+ LeaveCriticalSection(&(pCPC->csEvents));
+ }
+out:
+ CoUninitialize();
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+// VLCConnectionPoint
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+VLCConnectionPoint::VLCConnectionPoint(IConnectionPointContainer *p_cpc, REFIID iid) :
+ _iid(iid), _p_cpc(p_cpc)
+{
+ // Get the Global Interface Table per-process singleton:
+ CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0,
+ CLSCTX_INPROC_SERVER,
+ IID_IGlobalInterfaceTable,
+ reinterpret_cast<void**>(&m_pGIT));
+};
+
+VLCConnectionPoint::~VLCConnectionPoint()
+{
+ // Revoke interfaces from the GIT:
+ map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
+ map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
+
+ while( iter != end )
+ {
+ m_pGIT->RevokeInterfaceFromGlobal((DWORD)iter->second);
+ ++iter;
+ }
+ m_pGIT->Release();
+};