Commit faf1b08e authored by Raphael Junqueira's avatar Raphael Junqueira Committed by Alexandre Julliard

- PMsg processing thread (currently only Notifications handling)

- a chained list bug - thread-safe lists - real close on CloseDown
parent 311e0348
...@@ -154,29 +154,6 @@ typedef struct DMUSIC_PRIVATE_PCHANNEL_ { ...@@ -154,29 +154,6 @@ typedef struct DMUSIC_PRIVATE_PCHANNEL_ {
IDirectMusicPort *port; /* ... at this port */ IDirectMusicPort *port; /* ... at this port */
} DMUSIC_PRIVATE_PCHANNEL, *LPDMUSIC_PRIVATE_PCHANNEL; } DMUSIC_PRIVATE_PCHANNEL, *LPDMUSIC_PRIVATE_PCHANNEL;
typedef struct DMUS_PMSGItem DMUS_PMSGItem;
struct DMUS_PMSGItem {
DMUS_PMSGItem* next;
DMUS_PMSGItem* prev;
REFERENCE_TIME rtItemTime;
BOOL bInUse;
DWORD cb;
DMUS_PMSG pMsg;
};
#define DMUS_PMSGToItem(pMSG) ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) - offsetof(DMUS_PMSGItem, pMsg)))
#define DMUS_ItemToPMSG(pItem) (&(pItem->pMsg))
#define DMUS_ItemRemoveFromQueue(This,pItem) \
{\
if (pItem->prev) pItem->prev->next = pItem->next;\
if (pItem->next) pItem->next->prev = pItem->prev;\
if (This->head == pItem) This->head = pItem->next;\
if (This->imm_head == pItem) This->imm_head = pItem->next;\
pItem->bInUse = FALSE;\
}
/***************************************************************************** /*****************************************************************************
* IDirectMusicPerformance8Impl implementation structure * IDirectMusicPerformance8Impl implementation structure
*/ */
...@@ -205,12 +182,17 @@ struct IDirectMusicPerformance8Impl { ...@@ -205,12 +182,17 @@ struct IDirectMusicPerformance8Impl {
HANDLE hNotification; HANDLE hNotification;
REFERENCE_TIME rtMinimum; REFERENCE_TIME rtMinimum;
REFERENCE_TIME rtLatencyTime;
DWORD dwBumperLength;
DWORD dwPrepareTime;
/** Message Processing */ /** Message Processing */
HANDLE procThread; HANDLE procThread;
DWORD procThreadId;
REFERENCE_TIME procThreadStartTime; REFERENCE_TIME procThreadStartTime;
BOOL procThreadTicStarted; BOOL procThreadTicStarted;
DMUS_PMSGItem* head; CRITICAL_SECTION safe;
DMUS_PMSGItem* imm_head; struct DMUS_PMSGItem* head;
struct DMUS_PMSGItem* imm_head;
}; };
/* IUnknown: */ /* IUnknown: */
......
...@@ -21,6 +21,124 @@ ...@@ -21,6 +21,124 @@
WINE_DEFAULT_DEBUG_CHANNEL(dmime); WINE_DEFAULT_DEBUG_CHANNEL(dmime);
typedef struct DMUS_PMSGItem DMUS_PMSGItem;
struct DMUS_PMSGItem {
DMUS_PMSGItem* next;
DMUS_PMSGItem* prev;
REFERENCE_TIME rtItemTime;
BOOL bInUse;
DWORD cb;
DMUS_PMSG pMsg;
};
#define DMUS_PMSGToItem(pMSG) ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) - offsetof(DMUS_PMSGItem, pMsg)))
#define DMUS_ItemToPMSG(pItem) (&(pItem->pMsg))
#define DMUS_ItemRemoveFromQueue(This,pItem) \
{\
if (pItem->prev) pItem->prev->next = pItem->next;\
if (pItem->next) pItem->next->prev = pItem->prev;\
if (This->head == pItem) This->head = pItem->next;\
if (This->imm_head == pItem) This->imm_head = pItem->next;\
pItem->bInUse = FALSE;\
}
#define PROCESSMSG_START (WM_APP + 0)
#define PROCESSMSG_EXIT (WM_APP + 1)
#define PROCESSMSG_REMOVE (WM_APP + 2)
#define PROCESSMSG_ADD (WM_APP + 4)
static void ProceedMsg(IDirectMusicPerformance8Impl* This, DMUS_PMSGItem* cur) {
if (cur->pMsg.dwType == DMUS_PMSGT_NOTIFICATION) {
SetEvent(This->hNotification);
}
DMUS_ItemRemoveFromQueue(This, cur);
switch (cur->pMsg.dwType) {
case DMUS_PMSGT_STOP:
default:
FIXME("Unhandled PMsg Type: 0x%lx\n", cur->pMsg.dwType);
break;
}
HeapFree(GetProcessHeap(), 0, cur);
}
static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
IDirectMusicPerformance8Impl* This = (IDirectMusicPerformance8Impl*) lpParam;
/*DWORD timeOut = INFINITE;*/
MSG msg;
HRESULT hr;
REFERENCE_TIME rtCurTime;
DMUS_PMSGItem* it = NULL;
DMUS_PMSGItem* it_next = NULL;
while (TRUE) {
DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
/*if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);*/
EnterCriticalSection(&This->safe);
hr = IDirectMusicPerformance8Impl_GetTime((IDirectMusicPerformance8*) This, &rtCurTime, NULL);
if (FAILED(hr)) {
goto outrefresh;
}
for (it = This->imm_head; NULL != it; ) {
it_next = it->next;
ProceedMsg(This, it);
it = it_next;
}
for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
it_next = it->next;
ProceedMsg(This, it);
it = it_next;
}
outrefresh:
LeaveCriticalSection(&This->safe);
while (TRUE == PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
/** if hwnd we suppose that is a windows event ... */
if (NULL != msg.hwnd) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
} else {
switch (msg.message) {
case WM_QUIT:
case PROCESSMSG_EXIT:
goto outofthread;
break;
case PROCESSMSG_START:
break;
case PROCESSMSG_ADD:
break;
case PROCESSMSG_REMOVE:
break;
default:
ERR("Unhandled message %u. Critical Path\n", msg.message);
break;
}
}
}
}
outofthread:
TRACE("(%p): Exiting\n", This);
return 0;
}
static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
This->procThread = CreateThread(NULL, 0, ProcessMsgThread, This, 0, &This->procThreadId);
if (NULL == This->procThread) return FALSE;
SetThreadPriority(This->procThread, THREAD_PRIORITY_TIME_CRITICAL);
This->procThreadTicStarted = TRUE;
}
return PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
}
/* IDirectMusicPerformance8 IUnknown part: */ /* IDirectMusicPerformance8 IUnknown part: */
HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface (LPDIRECTMUSICPERFORMANCE8 iface, REFIID riid, LPVOID *ppobj) { HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface (LPDIRECTMUSICPERFORMANCE8 iface, REFIID riid, LPVOID *ppobj) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
...@@ -49,6 +167,7 @@ ULONG WINAPI IDirectMusicPerformance8Impl_Release (LPDIRECTMUSICPERFORMANCE8 ifa ...@@ -49,6 +167,7 @@ ULONG WINAPI IDirectMusicPerformance8Impl_Release (LPDIRECTMUSICPERFORMANCE8 ifa
ULONG ref = --This->ref; ULONG ref = --This->ref;
TRACE("(%p): ReleaseRef to %ld\n", This, This->ref); TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
if (ref == 0) { if (ref == 0) {
DeleteCriticalSection(&This->safe);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
return ref; return ref;
...@@ -122,25 +241,35 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState (LPDIRECTMUSICPERFOR ...@@ -122,25 +241,35 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState (LPDIRECTMUSICPERFOR
HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) { HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %ld): stub\n", This, dwMilliSeconds); TRACE("(%p, %ld)\n", This, dwMilliSeconds);
This->dwPrepareTime = dwMilliSeconds;
return S_OK; return S_OK;
} }
HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) { HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %p): stub\n", This, pdwMilliSeconds); TRACE("(%p, %p)\n", This, pdwMilliSeconds);
if (NULL == pdwMilliSeconds) {
return E_POINTER;
}
*pdwMilliSeconds = This->dwPrepareTime;
return S_OK; return S_OK;
} }
HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) { HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %ld): stub\n", This, dwMilliSeconds); TRACE("(%p, %ld)\n", This, dwMilliSeconds);
This->dwBumperLength = dwMilliSeconds;
return S_OK; return S_OK;
} }
HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) { HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %p): stub\n", This, pdwMilliSeconds); TRACE("(%p, %p)\n", This, pdwMilliSeconds);
if (NULL == pdwMilliSeconds) {
return E_POINTER;
}
*pdwMilliSeconds = This->dwBumperLength;
return S_OK; return S_OK;
} }
...@@ -174,12 +303,13 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8 ...@@ -174,12 +303,13 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8
queue = &This->head; queue = &This->head;
} }
EnterCriticalSection(&This->safe);
for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) { for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
prev_it = it; prev_it = it;
} }
if (NULL == prev_it) { if (NULL == prev_it) {
pItem->prev = NULL; pItem->prev = NULL;
pItem->next = (*queue)->next; if (NULL != *queue) pItem->next = (*queue)->next;
/*assert( NULL == pItem->next->prev );*/ /*assert( NULL == pItem->next->prev );*/
if (NULL != pItem->next) pItem->next->prev = pItem; if (NULL != pItem->next) pItem->next->prev = pItem;
*queue = pItem; *queue = pItem;
...@@ -189,6 +319,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8 ...@@ -189,6 +319,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8
prev_it->next = pItem; prev_it->next = pItem;
if (NULL != pItem->next) pItem->next->prev = pItem; if (NULL != pItem->next) pItem->next->prev = pItem;
} }
LeaveCriticalSection(&This->safe);
/** now in use, prevent from stupid Frees */ /** now in use, prevent from stupid Frees */
pItem->bInUse = TRUE; pItem->bInUse = TRUE;
return S_OK; return S_OK;
...@@ -214,8 +346,22 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying (LPDIRECTMUSICPERFORMANCE8 ...@@ -214,8 +346,22 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying (LPDIRECTMUSICPERFORMANCE8
HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtNow, MUSIC_TIME* pmtNow) { HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtNow, MUSIC_TIME* pmtNow) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %p, %p): stub\n", This, prtNow, pmtNow); HRESULT hr = S_OK;
return S_OK; REFERENCE_TIME rtCur = 0;
/*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
if (TRUE == This->procThreadTicStarted) {
rtCur = ((REFERENCE_TIME) GetTickCount() * 10000) - This->procThreadStartTime;
} else {
/*return DMUS_E_NO_MASTER_CLOCK;*/
}
if (NULL != prtNow) {
*prtNow = rtCur;
}
if (NULL != pmtNow) {
hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
}
return hr;
} }
HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg (LPDIRECTMUSICPERFORMANCE8 iface, ULONG cb, DMUS_PMSG** ppPMSG) { HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg (LPDIRECTMUSICPERFORMANCE8 iface, ULONG cb, DMUS_PMSG** ppPMSG) {
...@@ -257,7 +403,10 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg (LPDIRECTMUSICPERFORMANCE8 ...@@ -257,7 +403,10 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg (LPDIRECTMUSICPERFORMANCE8
return DMUS_E_CANNOT_FREE; return DMUS_E_CANNOT_FREE;
} }
/** now we can remove it safely */ /** now we can remove it safely */
EnterCriticalSection(&This->safe);
DMUS_ItemRemoveFromQueue( This, pItem ); DMUS_ItemRemoveFromQueue( This, pItem );
LeaveCriticalSection(&This->safe);
/** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */ /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
HeapFree(GetProcessHeap(), 0, pItem); HeapFree(GetProcessHeap(), 0, pItem);
return S_OK; return S_OK;
...@@ -442,7 +591,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam (LPDIRECTMUSICPERFORM ...@@ -442,7 +591,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam (LPDIRECTMUSICPERFORM
HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) { HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p, %p): stub\n", This, prtTime); TRACE("(%p, %p): stub\n", This, prtTime);
*prtTime = This->rtLatencyTime;
return S_OK; return S_OK;
} }
...@@ -461,6 +611,19 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime (LPDIRECTMUSICPERFORMANCE ...@@ -461,6 +611,19 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime (LPDIRECTMUSICPERFORMANCE
HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown (LPDIRECTMUSICPERFORMANCE8 iface) { HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown (LPDIRECTMUSICPERFORMANCE8 iface) {
ICOM_THIS(IDirectMusicPerformance8Impl,iface); ICOM_THIS(IDirectMusicPerformance8Impl,iface);
FIXME("(%p): stub\n", This); FIXME("(%p): stub\n", This);
if (PostMessageToProcessMsgThread(This, PROCESSMSG_EXIT)) {
WaitForSingleObject(This->procThread, INFINITE);
This->procThreadTicStarted = FALSE;
CloseHandle(This->procThread);
}
if (NULL != This->pDirectSound) {
IDirectSound_Release((LPDIRECTSOUND) This->pDirectSound);
This->pDirectSound = NULL;
}
if (NULL != This->pDirectMusic) {
IDirectMusic8_Release((LPDIRECTMUSIC8) This->pDirectMusic);
This->pDirectMusic = NULL;
}
return S_OK; return S_OK;
} }
...@@ -549,6 +712,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio (LPDIRECTMUSICPERFORMANCE8 ...@@ -549,6 +712,8 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio (LPDIRECTMUSICPERFORMANCE8
} }
hr = IDirectMusicPerformance8Impl_CreateStandardAudioPath(iface, dwDefaultPathType, dwPChannelCount, FALSE, (IDirectMusicAudioPath**) &This->pDefaultPath); hr = IDirectMusicPerformance8Impl_CreateStandardAudioPath(iface, dwDefaultPathType, dwPChannelCount, FALSE, (IDirectMusicAudioPath**) &This->pDefaultPath);
PostMessageToProcessMsgThread(This, PROCESSMSG_START);
return hr; return hr;
} }
...@@ -782,6 +947,13 @@ HRESULT WINAPI DMUSIC_CreateDirectMusicPerformanceImpl (LPCGUID lpcGUID, LPVOID ...@@ -782,6 +947,13 @@ HRESULT WINAPI DMUSIC_CreateDirectMusicPerformanceImpl (LPCGUID lpcGUID, LPVOID
obj->pDirectMusic = NULL; obj->pDirectMusic = NULL;
obj->pDirectSound = NULL; obj->pDirectSound = NULL;
obj->pDefaultPath = NULL; obj->pDefaultPath = NULL;
InitializeCriticalSection(&obj->safe);
/**
* @see http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/latencyandbumpertime.asp
*/
obj->rtLatencyTime = 1000; /* 1s TO FIX */
obj->dwBumperLength = 50; /* 50ms default */
obj->dwPrepareTime = 1000; /* 1000ms default */
return IDirectMusicPerformance8Impl_QueryInterface ((LPDIRECTMUSICPERFORMANCE8)obj, lpcGUID, ppobj); return IDirectMusicPerformance8Impl_QueryInterface ((LPDIRECTMUSICPERFORMANCE8)obj, lpcGUID, ppobj);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment