Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendsoundrender.c
Go to the documentation of this file.
00001 /* 00002 * Direct Sound Audio Renderer 00003 * 00004 * Copyright 2004 Christian Costa 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include "quartz_private.h" 00024 #include "control_private.h" 00025 #include "pin.h" 00026 00027 #include "uuids.h" 00028 #include "vfwmsgs.h" 00029 #include "windef.h" 00030 #include "winbase.h" 00031 #include "dshow.h" 00032 #include "evcode.h" 00033 #include "strmif.h" 00034 #include "dsound.h" 00035 #include "amaudio.h" 00036 00037 #include "wine/unicode.h" 00038 #include "wine/debug.h" 00039 00040 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00041 00042 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; 00043 00044 static const IBaseFilterVtbl DSoundRender_Vtbl; 00045 static const IPinVtbl DSoundRender_InputPin_Vtbl; 00046 static const IBasicAudioVtbl IBasicAudio_Vtbl; 00047 static const IReferenceClockVtbl IReferenceClock_Vtbl; 00048 static const IMediaSeekingVtbl IMediaSeeking_Vtbl; 00049 static const IAMDirectSoundVtbl IAMDirectSound_Vtbl; 00050 00051 typedef struct DSoundRenderImpl 00052 { 00053 const IBaseFilterVtbl * lpVtbl; 00054 const IBasicAudioVtbl *IBasicAudio_vtbl; 00055 const IReferenceClockVtbl *IReferenceClock_vtbl; 00056 const IAMDirectSoundVtbl *IAMDirectSound_vtbl; 00057 00058 LONG refCount; 00059 CRITICAL_SECTION csFilter; 00060 FILTER_STATE state; 00061 REFERENCE_TIME rtStreamStart, rtLastStop; 00062 IReferenceClock * pClock; 00063 FILTER_INFO filterInfo; 00064 00065 InputPin * pInputPin; 00066 00067 IDirectSound8 *dsound; 00068 LPDIRECTSOUNDBUFFER dsbuffer; 00069 DWORD buf_size; 00070 DWORD write_pos; 00071 DWORD write_loops; 00072 00073 DWORD last_play_pos; 00074 DWORD play_loops; 00075 00076 REFERENCE_TIME play_time; 00077 MediaSeekingImpl mediaSeeking; 00078 00079 HANDLE state_change, blocked; 00080 00081 LONG volume; 00082 LONG pan; 00083 } DSoundRenderImpl; 00084 00085 /* Seeking is not needed for a renderer, rely on newsegment for the appropriate changes */ 00086 static HRESULT sound_mod_stop(IBaseFilter *iface) 00087 { 00088 TRACE("(%p)\n", iface); 00089 return S_OK; 00090 } 00091 00092 static HRESULT sound_mod_start(IBaseFilter *iface) 00093 { 00094 TRACE("(%p)\n", iface); 00095 00096 return S_OK; 00097 } 00098 00099 static HRESULT sound_mod_rate(IBaseFilter *iface) 00100 { 00101 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00102 00103 WAVEFORMATEX *format = (WAVEFORMATEX*)This->pInputPin->pin.mtCurrent.pbFormat; 00104 DWORD freq = format->nSamplesPerSec; 00105 double rate = This->mediaSeeking.dRate; 00106 00107 freq = (DWORD)((double)freq * rate); 00108 00109 TRACE("(%p)\n", iface); 00110 00111 if (freq > DSBFREQUENCY_MAX) 00112 return VFW_E_UNSUPPORTED_AUDIO; 00113 00114 if (freq < DSBFREQUENCY_MIN) 00115 return VFW_E_UNSUPPORTED_AUDIO; 00116 00117 return S_OK; 00118 } 00119 00120 static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPos, REFERENCE_TIME *pRefTime) 00121 { 00122 HRESULT hr; 00123 00124 EnterCriticalSection(&This->csFilter); 00125 { 00126 DWORD state; 00127 DWORD write_pos; 00128 00129 hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); 00130 if (SUCCEEDED(hr) && !(state & DSBSTATUS_PLAYING) && This->state == State_Running) 00131 { 00132 TRACE("Not playing, kickstarting the engine\n"); 00133 00134 hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING); 00135 if (FAILED(hr)) 00136 ERR("Can't play sound buffer (%x)\n", hr); 00137 } 00138 00139 if (SUCCEEDED(hr)) 00140 hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, &write_pos); 00141 if (hr == S_OK) 00142 { 00143 DWORD play_pos = *pPlayPos; 00144 00145 if (play_pos < This->last_play_pos) 00146 This->play_loops++; 00147 This->last_play_pos = play_pos; 00148 00149 /* If we really fell behind, start at the next possible position 00150 * Also happens when just starting playback for the first time, 00151 * or when flushing 00152 */ 00153 if ((This->play_loops*This->buf_size)+play_pos >= 00154 (This->write_loops*This->buf_size)+This->write_pos) 00155 This->write_pos = write_pos; 00156 00157 if (pRefTime) 00158 { 00159 REFERENCE_TIME play_time; 00160 play_time = ((REFERENCE_TIME)This->play_loops*10000000) + 00161 ((REFERENCE_TIME)play_pos*10000000/This->buf_size); 00162 00163 /* Don't let time run backwards */ 00164 if(play_time-This->play_time > 0) 00165 This->play_time = play_time; 00166 else 00167 hr = S_FALSE; 00168 00169 *pRefTime = This->play_time; 00170 } 00171 } 00172 } 00173 LeaveCriticalSection(&This->csFilter); 00174 00175 return hr; 00176 } 00177 00178 static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *data, DWORD size) 00179 { 00180 HRESULT hr = S_OK; 00181 LPBYTE lpbuf1 = NULL; 00182 LPBYTE lpbuf2 = NULL; 00183 DWORD dwsize1 = 0; 00184 DWORD dwsize2 = 0; 00185 DWORD size2; 00186 DWORD play_pos,buf_free; 00187 00188 do { 00189 00190 hr = DSoundRender_GetPos(This, &play_pos, NULL); 00191 if (hr != DS_OK) 00192 { 00193 ERR("GetPos returned error: %x\n", hr); 00194 break; 00195 } 00196 if (This->write_pos <= play_pos) 00197 buf_free = play_pos-This->write_pos; 00198 else 00199 buf_free = This->buf_size - This->write_pos + play_pos; 00200 00201 /* Wait for enough of the buffer to empty before filling it */ 00202 if(buf_free < This->buf_size/4) 00203 { 00204 Sleep(50); 00205 continue; 00206 } 00207 00208 size2 = min(buf_free, size); 00209 hr = IDirectSoundBuffer_Lock(This->dsbuffer, This->write_pos, size2, (LPVOID *)&lpbuf1, &dwsize1, (LPVOID *)&lpbuf2, &dwsize2, 0); 00210 if (hr != DS_OK) { 00211 ERR("Unable to lock sound buffer! (%x)\n", hr); 00212 break; 00213 } 00214 /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */ 00215 00216 memcpy(lpbuf1, data, dwsize1); 00217 if (dwsize2) 00218 memcpy(lpbuf2, data + dwsize1, dwsize2); 00219 00220 hr = IDirectSoundBuffer_Unlock(This->dsbuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); 00221 if (hr != DS_OK) 00222 ERR("Unable to unlock sound buffer! (%x)\n", hr); 00223 00224 size -= dwsize1 + dwsize2; 00225 data += dwsize1 + dwsize2; 00226 This->write_pos += dwsize1 + dwsize2; 00227 if (This->write_pos >= This->buf_size) 00228 { 00229 This->write_pos -= This->buf_size; 00230 This->write_loops++; 00231 } 00232 } while (size && This->state == State_Running); 00233 00234 return hr; 00235 } 00236 00237 static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) 00238 { 00239 DSoundRenderImpl *This = iface; 00240 LPBYTE pbSrcStream = NULL; 00241 LONG cbSrcStream = 0; 00242 REFERENCE_TIME tStart, tStop; 00243 HRESULT hr; 00244 AM_MEDIA_TYPE *amt; 00245 00246 TRACE("%p %p\n", iface, pSample); 00247 00248 /* Slightly incorrect, Pause completes when a frame is received so we should signal 00249 * pause completion here, but for sound playing a single frame doesn't make sense 00250 */ 00251 00252 EnterCriticalSection(&This->csFilter); 00253 00254 if (This->pInputPin->end_of_stream || This->pInputPin->flushing) 00255 { 00256 LeaveCriticalSection(&This->csFilter); 00257 return S_FALSE; 00258 } 00259 00260 if (This->state == State_Stopped) 00261 { 00262 LeaveCriticalSection(&This->csFilter); 00263 return VFW_E_WRONG_STATE; 00264 } 00265 00266 if (IMediaSample_GetMediaType(pSample, &amt) == S_OK) 00267 { 00268 AM_MEDIA_TYPE *orig = &This->pInputPin->pin.mtCurrent; 00269 WAVEFORMATEX *origfmt = (WAVEFORMATEX *)orig->pbFormat; 00270 WAVEFORMATEX *newfmt = (WAVEFORMATEX *)amt->pbFormat; 00271 00272 if (origfmt->wFormatTag == newfmt->wFormatTag && 00273 origfmt->nChannels == newfmt->nChannels && 00274 origfmt->nBlockAlign == newfmt->nBlockAlign && 00275 origfmt->wBitsPerSample == newfmt->wBitsPerSample && 00276 origfmt->cbSize == newfmt->cbSize) 00277 { 00278 if (origfmt->nSamplesPerSec != newfmt->nSamplesPerSec) 00279 { 00280 hr = IDirectSoundBuffer_SetFrequency(This->dsbuffer, 00281 newfmt->nSamplesPerSec); 00282 if (FAILED(hr)) 00283 { 00284 LeaveCriticalSection(&This->csFilter); 00285 return VFW_E_TYPE_NOT_ACCEPTED; 00286 } 00287 FreeMediaType(orig); 00288 CopyMediaType(orig, amt); 00289 IMediaSample_SetMediaType(pSample, NULL); 00290 } 00291 } 00292 else 00293 { 00294 LeaveCriticalSection(&This->csFilter); 00295 return VFW_E_TYPE_NOT_ACCEPTED; 00296 } 00297 } 00298 00299 SetEvent(This->state_change); 00300 00301 hr = IMediaSample_GetPointer(pSample, &pbSrcStream); 00302 if (FAILED(hr)) 00303 { 00304 ERR("Cannot get pointer to sample data (%x)\n", hr); 00305 LeaveCriticalSection(&This->csFilter); 00306 return hr; 00307 } 00308 00309 hr = IMediaSample_GetTime(pSample, &tStart, &tStop); 00310 if (FAILED(hr)) 00311 ERR("Cannot get sample time (%x)\n", hr); 00312 00313 if (This->rtLastStop != tStart && (IMediaSample_IsDiscontinuity(pSample) == S_FALSE)) 00314 WARN("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n", 00315 (DWORD)(This->rtLastStop / 10000000), (DWORD)((This->rtLastStop / 10000)%1000), 00316 (DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000)); 00317 This->rtLastStop = tStop; 00318 00319 if (IMediaSample_IsPreroll(pSample) == S_OK) 00320 { 00321 TRACE("Preroll!\n"); 00322 LeaveCriticalSection(&This->csFilter); 00323 return S_OK; 00324 } 00325 00326 if (This->state == State_Paused) 00327 { 00328 LeaveCriticalSection(&This->csFilter); 00329 WaitForSingleObject(This->blocked, INFINITE); 00330 EnterCriticalSection(&This->csFilter); 00331 if (This->state == State_Stopped) 00332 { 00333 LeaveCriticalSection(&This->csFilter); 00334 return VFW_E_WRONG_STATE; 00335 } 00336 00337 if (This->state == State_Paused) 00338 { 00339 /* Assuming we return because of flushing */ 00340 TRACE("Flushing\n"); 00341 LeaveCriticalSection(&This->csFilter); 00342 return S_OK; 00343 } 00344 } 00345 00346 cbSrcStream = IMediaSample_GetActualDataLength(pSample); 00347 TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); 00348 00349 #if 0 /* For debugging purpose */ 00350 { 00351 int i; 00352 for(i = 0; i < cbSrcStream; i++) 00353 { 00354 if ((i!=0) && !(i%16)) 00355 TRACE("\n"); 00356 TRACE("%02x ", pbSrcStream[i]); 00357 } 00358 TRACE("\n"); 00359 } 00360 #endif 00361 00362 hr = DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream); 00363 LeaveCriticalSection(&This->csFilter); 00364 return hr; 00365 } 00366 00367 static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) 00368 { 00369 WAVEFORMATEX* format; 00370 00371 if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio)) 00372 return S_FALSE; 00373 00374 format = (WAVEFORMATEX*)pmt->pbFormat; 00375 TRACE("Format = %p\n", format); 00376 TRACE("wFormatTag = %x %x\n", format->wFormatTag, WAVE_FORMAT_PCM); 00377 TRACE("nChannels = %d\n", format->nChannels); 00378 TRACE("nSamplesPerSec = %d\n", format->nAvgBytesPerSec); 00379 TRACE("nAvgBytesPerSec = %d\n", format->nAvgBytesPerSec); 00380 TRACE("nBlockAlign = %d\n", format->nBlockAlign); 00381 TRACE("wBitsPerSample = %d\n", format->wBitsPerSample); 00382 00383 if (!IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_PCM)) 00384 return S_FALSE; 00385 00386 return S_OK; 00387 } 00388 00389 HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) 00390 { 00391 HRESULT hr; 00392 PIN_INFO piInput; 00393 DSoundRenderImpl * pDSoundRender; 00394 00395 TRACE("(%p, %p)\n", pUnkOuter, ppv); 00396 00397 *ppv = NULL; 00398 00399 if (pUnkOuter) 00400 return CLASS_E_NOAGGREGATION; 00401 00402 pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl)); 00403 if (!pDSoundRender) 00404 return E_OUTOFMEMORY; 00405 ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl)); 00406 00407 pDSoundRender->lpVtbl = &DSoundRender_Vtbl; 00408 pDSoundRender->IBasicAudio_vtbl = &IBasicAudio_Vtbl; 00409 pDSoundRender->IReferenceClock_vtbl = &IReferenceClock_Vtbl; 00410 pDSoundRender->IAMDirectSound_vtbl = &IAMDirectSound_Vtbl; 00411 pDSoundRender->refCount = 1; 00412 InitializeCriticalSection(&pDSoundRender->csFilter); 00413 pDSoundRender->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"); 00414 pDSoundRender->state = State_Stopped; 00415 00416 /* construct input pin */ 00417 piInput.dir = PINDIR_INPUT; 00418 piInput.pFilter = (IBaseFilter *)pDSoundRender; 00419 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); 00420 hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin); 00421 00422 if (SUCCEEDED(hr)) 00423 { 00424 hr = DirectSoundCreate8(NULL, &pDSoundRender->dsound, NULL); 00425 if (FAILED(hr)) 00426 ERR("Cannot create Direct Sound object (%x)\n", hr); 00427 else 00428 IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY); 00429 } 00430 00431 if (SUCCEEDED(hr)) 00432 { 00433 MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter); 00434 pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl; 00435 00436 pDSoundRender->state_change = CreateEventW(NULL, TRUE, TRUE, NULL); 00437 pDSoundRender->blocked = CreateEventW(NULL, FALSE, FALSE, NULL); 00438 00439 if (!pDSoundRender->state_change || !pDSoundRender->blocked) 00440 { 00441 IUnknown_Release((IUnknown *)pDSoundRender); 00442 return HRESULT_FROM_WIN32(GetLastError()); 00443 } 00444 00445 *ppv = pDSoundRender; 00446 } 00447 else 00448 { 00449 if (pDSoundRender->pInputPin) 00450 IPin_Release((IPin*)pDSoundRender->pInputPin); 00451 pDSoundRender->csFilter.DebugInfo->Spare[0] = 0; 00452 DeleteCriticalSection(&pDSoundRender->csFilter); 00453 CoTaskMemFree(pDSoundRender); 00454 } 00455 00456 return hr; 00457 } 00458 00459 static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) 00460 { 00461 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00462 TRACE("(%p, %p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); 00463 00464 *ppv = NULL; 00465 00466 if (IsEqualIID(riid, &IID_IUnknown)) 00467 *ppv = This; 00468 else if (IsEqualIID(riid, &IID_IPersist)) 00469 *ppv = This; 00470 else if (IsEqualIID(riid, &IID_IMediaFilter)) 00471 *ppv = This; 00472 else if (IsEqualIID(riid, &IID_IBaseFilter)) 00473 *ppv = This; 00474 else if (IsEqualIID(riid, &IID_IBasicAudio)) 00475 *ppv = &This->IBasicAudio_vtbl; 00476 else if (IsEqualIID(riid, &IID_IReferenceClock)) 00477 *ppv = &This->IReferenceClock_vtbl; 00478 else if (IsEqualIID(riid, &IID_IMediaSeeking)) 00479 *ppv = &This->mediaSeeking.lpVtbl; 00480 else if (IsEqualIID(riid, &IID_IAMDirectSound)) 00481 *ppv = &This->IAMDirectSound_vtbl; 00482 00483 if (*ppv) 00484 { 00485 IUnknown_AddRef((IUnknown *)(*ppv)); 00486 return S_OK; 00487 } 00488 00489 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow)) 00490 FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); 00491 00492 return E_NOINTERFACE; 00493 } 00494 00495 static ULONG WINAPI DSoundRender_AddRef(IBaseFilter * iface) 00496 { 00497 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00498 ULONG refCount = InterlockedIncrement(&This->refCount); 00499 00500 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); 00501 00502 return refCount; 00503 } 00504 00505 static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface) 00506 { 00507 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00508 ULONG refCount = InterlockedDecrement(&This->refCount); 00509 00510 TRACE("(%p)->() Release from %d\n", This, refCount + 1); 00511 00512 if (!refCount) 00513 { 00514 IPin *pConnectedTo; 00515 00516 if (This->pClock) 00517 IReferenceClock_Release(This->pClock); 00518 00519 if (This->dsbuffer) 00520 IDirectSoundBuffer_Release(This->dsbuffer); 00521 This->dsbuffer = NULL; 00522 if (This->dsound) 00523 IDirectSound_Release(This->dsound); 00524 This->dsound = NULL; 00525 00526 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) 00527 { 00528 IPin_Disconnect(pConnectedTo); 00529 IPin_Release(pConnectedTo); 00530 } 00531 IPin_Disconnect((IPin *)This->pInputPin); 00532 00533 IPin_Release((IPin *)This->pInputPin); 00534 00535 This->lpVtbl = NULL; 00536 This->IBasicAudio_vtbl = NULL; 00537 00538 This->csFilter.DebugInfo->Spare[0] = 0; 00539 DeleteCriticalSection(&This->csFilter); 00540 00541 CloseHandle(This->state_change); 00542 CloseHandle(This->blocked); 00543 00544 TRACE("Destroying Audio Renderer\n"); 00545 CoTaskMemFree(This); 00546 00547 return 0; 00548 } 00549 else 00550 return refCount; 00551 } 00552 00555 static HRESULT WINAPI DSoundRender_GetClassID(IBaseFilter * iface, CLSID * pClsid) 00556 { 00557 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00558 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); 00559 00560 *pClsid = CLSID_DSoundRender; 00561 00562 return S_OK; 00563 } 00564 00567 static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface) 00568 { 00569 HRESULT hr = S_OK; 00570 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00571 00572 TRACE("(%p/%p)->()\n", This, iface); 00573 00574 EnterCriticalSection(&This->csFilter); 00575 { 00576 DWORD state = 0; 00577 if (This->dsbuffer) 00578 { 00579 hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); 00580 if (SUCCEEDED(hr)) 00581 { 00582 if (state & DSBSTATUS_PLAYING) 00583 hr = IDirectSoundBuffer_Stop(This->dsbuffer); 00584 } 00585 } 00586 if (SUCCEEDED(hr)) 00587 This->state = State_Stopped; 00588 00589 /* Complete our transition */ 00590 SetEvent(This->state_change); 00591 SetEvent(This->blocked); 00592 } 00593 LeaveCriticalSection(&This->csFilter); 00594 00595 return hr; 00596 } 00597 00598 static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) 00599 { 00600 HRESULT hr = S_OK; 00601 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00602 00603 TRACE("(%p/%p)->()\n", This, iface); 00604 00605 EnterCriticalSection(&This->csFilter); 00606 if (This->state != State_Paused) 00607 { 00608 DWORD state = 0; 00609 if (This->state == State_Stopped) 00610 { 00611 This->pInputPin->end_of_stream = 0; 00612 } 00613 00614 if (This->dsbuffer) 00615 { 00616 hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); 00617 if (SUCCEEDED(hr)) 00618 { 00619 if (state & DSBSTATUS_PLAYING) 00620 hr = IDirectSoundBuffer_Stop(This->dsbuffer); 00621 } 00622 } 00623 if (SUCCEEDED(hr)) 00624 This->state = State_Paused; 00625 00626 ResetEvent(This->blocked); 00627 ResetEvent(This->state_change); 00628 } 00629 LeaveCriticalSection(&This->csFilter); 00630 00631 return hr; 00632 } 00633 00634 static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStart) 00635 { 00636 HRESULT hr = S_OK; 00637 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00638 00639 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); 00640 00641 EnterCriticalSection(&This->csFilter); 00642 { 00643 This->rtStreamStart = tStart; 00644 if (This->state == State_Paused) 00645 { 00646 /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */ 00647 SetEvent(This->blocked); 00648 } 00649 else if (This->state == State_Stopped) 00650 { 00651 ResetEvent(This->state_change); 00652 This->pInputPin->end_of_stream = 0; 00653 } 00654 00655 This->state = State_Running; 00656 } 00657 LeaveCriticalSection(&This->csFilter); 00658 00659 return hr; 00660 } 00661 00662 static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) 00663 { 00664 HRESULT hr; 00665 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00666 00667 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); 00668 00669 if (WaitForSingleObject(This->state_change, dwMilliSecsTimeout) == WAIT_TIMEOUT) 00670 hr = VFW_S_STATE_INTERMEDIATE; 00671 else 00672 hr = S_OK; 00673 00674 EnterCriticalSection(&This->csFilter); 00675 { 00676 *pState = This->state; 00677 } 00678 LeaveCriticalSection(&This->csFilter); 00679 00680 return hr; 00681 } 00682 00683 static HRESULT WINAPI DSoundRender_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) 00684 { 00685 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00686 00687 TRACE("(%p/%p)->(%p)\n", This, iface, pClock); 00688 00689 EnterCriticalSection(&This->csFilter); 00690 { 00691 if (This->pClock) 00692 IReferenceClock_Release(This->pClock); 00693 This->pClock = pClock; 00694 if (This->pClock) 00695 IReferenceClock_AddRef(This->pClock); 00696 } 00697 LeaveCriticalSection(&This->csFilter); 00698 00699 return S_OK; 00700 } 00701 00702 static HRESULT WINAPI DSoundRender_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) 00703 { 00704 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00705 00706 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); 00707 00708 EnterCriticalSection(&This->csFilter); 00709 { 00710 *ppClock = This->pClock; 00711 if (This->pClock) 00712 IReferenceClock_AddRef(This->pClock); 00713 } 00714 LeaveCriticalSection(&This->csFilter); 00715 00716 return S_OK; 00717 } 00718 00721 static HRESULT DSoundRender_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) 00722 { 00723 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00724 00725 /* Our pins are static, not changing so setting static tick count is ok */ 00726 *lastsynctick = 0; 00727 00728 if (pos >= 1) 00729 return S_FALSE; 00730 00731 *pin = (IPin *)This->pInputPin; 00732 IPin_AddRef(*pin); 00733 return S_OK; 00734 } 00735 00736 static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) 00737 { 00738 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00739 00740 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); 00741 00742 return IEnumPinsImpl_Construct(ppEnum, DSoundRender_GetPin, iface); 00743 } 00744 00745 static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) 00746 { 00747 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00748 00749 TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin); 00750 00751 FIXME("DSoundRender::FindPin(...)\n"); 00752 00753 /* FIXME: critical section */ 00754 00755 return E_NOTIMPL; 00756 } 00757 00758 static HRESULT WINAPI DSoundRender_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) 00759 { 00760 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00761 00762 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); 00763 00764 strcpyW(pInfo->achName, This->filterInfo.achName); 00765 pInfo->pGraph = This->filterInfo.pGraph; 00766 00767 if (pInfo->pGraph) 00768 IFilterGraph_AddRef(pInfo->pGraph); 00769 00770 return S_OK; 00771 } 00772 00773 static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) 00774 { 00775 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00776 00777 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); 00778 00779 EnterCriticalSection(&This->csFilter); 00780 { 00781 if (pName) 00782 strcpyW(This->filterInfo.achName, pName); 00783 else 00784 *This->filterInfo.achName = '\0'; 00785 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ 00786 } 00787 LeaveCriticalSection(&This->csFilter); 00788 00789 return S_OK; 00790 } 00791 00792 static HRESULT WINAPI DSoundRender_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) 00793 { 00794 DSoundRenderImpl *This = (DSoundRenderImpl *)iface; 00795 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); 00796 return E_NOTIMPL; 00797 } 00798 00799 static const IBaseFilterVtbl DSoundRender_Vtbl = 00800 { 00801 DSoundRender_QueryInterface, 00802 DSoundRender_AddRef, 00803 DSoundRender_Release, 00804 DSoundRender_GetClassID, 00805 DSoundRender_Stop, 00806 DSoundRender_Pause, 00807 DSoundRender_Run, 00808 DSoundRender_GetState, 00809 DSoundRender_SetSyncSource, 00810 DSoundRender_GetSyncSource, 00811 DSoundRender_EnumPins, 00812 DSoundRender_FindPin, 00813 DSoundRender_QueryFilterInfo, 00814 DSoundRender_JoinFilterGraph, 00815 DSoundRender_QueryVendorInfo 00816 }; 00817 00818 static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 00819 { 00820 InputPin *This = (InputPin *)iface; 00821 PIN_DIRECTION pindirReceive; 00822 DSoundRenderImpl *DSImpl; 00823 HRESULT hr = S_OK; 00824 00825 TRACE("(%p)->(%p, %p)\n", This, pReceivePin, pmt); 00826 dump_AM_MEDIA_TYPE(pmt); 00827 00828 EnterCriticalSection(This->pin.pCritSec); 00829 { 00830 DSImpl = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; 00831 DSImpl->rtLastStop = -1; 00832 00833 if (This->pin.pConnectedTo) 00834 hr = VFW_E_ALREADY_CONNECTED; 00835 00836 if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK) 00837 hr = VFW_E_TYPE_NOT_ACCEPTED; 00838 00839 if (SUCCEEDED(hr)) 00840 { 00841 IPin_QueryDirection(pReceivePin, &pindirReceive); 00842 00843 if (pindirReceive != PINDIR_OUTPUT) 00844 { 00845 ERR("Can't connect from non-output pin\n"); 00846 hr = VFW_E_INVALID_DIRECTION; 00847 } 00848 } 00849 00850 if (SUCCEEDED(hr)) 00851 { 00852 WAVEFORMATEX *format; 00853 DSBUFFERDESC buf_desc; 00854 00855 TRACE("MajorType %s\n", debugstr_guid(&pmt->majortype)); 00856 TRACE("SubType %s\n", debugstr_guid(&pmt->subtype)); 00857 TRACE("Format %s\n", debugstr_guid(&pmt->formattype)); 00858 TRACE("Size %d\n", pmt->cbFormat); 00859 00860 format = (WAVEFORMATEX*)pmt->pbFormat; 00861 00862 DSImpl->buf_size = format->nAvgBytesPerSec; 00863 00864 memset(&buf_desc,0,sizeof(DSBUFFERDESC)); 00865 buf_desc.dwSize = sizeof(DSBUFFERDESC); 00866 buf_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | 00867 DSBCAPS_CTRLFREQUENCY | 00868 DSBCAPS_GETCURRENTPOSITION2; 00869 buf_desc.dwBufferBytes = DSImpl->buf_size; 00870 buf_desc.lpwfxFormat = format; 00871 hr = IDirectSound_CreateSoundBuffer(DSImpl->dsound, &buf_desc, &DSImpl->dsbuffer, NULL); 00872 if (FAILED(hr)) 00873 ERR("Can't create sound buffer (%x)\n", hr); 00874 } 00875 00876 if (SUCCEEDED(hr)) 00877 { 00878 hr = IDirectSoundBuffer_SetVolume(DSImpl->dsbuffer, DSImpl->volume); 00879 if (FAILED(hr)) 00880 ERR("Can't set volume to %d (%x)\n", DSImpl->volume, hr); 00881 00882 hr = IDirectSoundBuffer_SetPan(DSImpl->dsbuffer, DSImpl->pan); 00883 if (FAILED(hr)) 00884 ERR("Can't set pan to %d (%x)\n", DSImpl->pan, hr); 00885 00886 DSImpl->write_pos = 0; 00887 hr = S_OK; 00888 } 00889 00890 if (SUCCEEDED(hr)) 00891 { 00892 CopyMediaType(&This->pin.mtCurrent, pmt); 00893 This->pin.pConnectedTo = pReceivePin; 00894 IPin_AddRef(pReceivePin); 00895 } 00896 else if (hr != VFW_E_ALREADY_CONNECTED) 00897 { 00898 if (DSImpl->dsbuffer) 00899 IDirectSoundBuffer_Release(DSImpl->dsbuffer); 00900 DSImpl->dsbuffer = NULL; 00901 } 00902 } 00903 LeaveCriticalSection(This->pin.pCritSec); 00904 00905 return hr; 00906 } 00907 00908 static HRESULT WINAPI DSoundRender_InputPin_Disconnect(IPin * iface) 00909 { 00910 IPinImpl *This = (IPinImpl*)iface; 00911 DSoundRenderImpl *DSImpl; 00912 00913 TRACE("(%p)->()\n", iface); 00914 00915 DSImpl = (DSoundRenderImpl*)This->pinInfo.pFilter; 00916 if (DSImpl->dsbuffer) 00917 IDirectSoundBuffer_Release(DSImpl->dsbuffer); 00918 DSImpl->dsbuffer = NULL; 00919 00920 return IPinImpl_Disconnect(iface); 00921 } 00922 00923 static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) 00924 { 00925 InputPin* This = (InputPin*)iface; 00926 DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; 00927 IMediaEventSink* pEventSink; 00928 HRESULT hr; 00929 00930 EnterCriticalSection(This->pin.pCritSec); 00931 00932 TRACE("(%p/%p)->()\n", This, iface); 00933 hr = InputPin_EndOfStream(iface); 00934 if (hr != S_OK) 00935 { 00936 ERR("%08x\n", hr); 00937 LeaveCriticalSection(This->pin.pCritSec); 00938 return hr; 00939 } 00940 00941 hr = IFilterGraph_QueryInterface(me->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); 00942 if (SUCCEEDED(hr)) 00943 { 00944 BYTE * silence; 00945 00946 silence = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, me->buf_size); 00947 if (silence) 00948 { 00949 memset(silence, 0, me->buf_size); 00950 DSoundRender_SendSampleData((DSoundRenderImpl*)This->pin.pinInfo.pFilter, silence, me->buf_size); 00951 HeapFree(GetProcessHeap(), 0, silence); 00952 } 00953 00954 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); 00955 IMediaEventSink_Release(pEventSink); 00956 } 00957 LeaveCriticalSection(This->pin.pCritSec); 00958 00959 return hr; 00960 } 00961 00962 static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) 00963 { 00964 InputPin *This = (InputPin *)iface; 00965 DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; 00966 HRESULT hr; 00967 LPBYTE buffer; 00968 DWORD size; 00969 00970 TRACE("\n"); 00971 00972 EnterCriticalSection(This->pin.pCritSec); 00973 hr = InputPin_BeginFlush(iface); 00974 00975 if (pFilter->dsbuffer) 00976 { 00977 IDirectSoundBuffer_Stop(pFilter->dsbuffer); 00978 00979 /* Force a reset */ 00980 IDirectSoundBuffer_SetCurrentPosition(pFilter->dsbuffer, 0); 00981 pFilter->write_pos = pFilter->last_play_pos = 0; 00982 ++pFilter->play_loops; 00983 pFilter->write_loops = pFilter->play_loops; 00984 00985 IDirectSoundBuffer_Lock(pFilter->dsbuffer, 0, 0, (LPVOID *)&buffer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER); 00986 memset(buffer, 0, size); 00987 IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0); 00988 } 00989 00990 if (pFilter->state == State_Paused) 00991 SetEvent(pFilter->blocked); 00992 LeaveCriticalSection(This->pin.pCritSec); 00993 00994 return hr; 00995 } 00996 00997 static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) 00998 { 00999 InputPin *This = (InputPin *)iface; 01000 DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; 01001 HRESULT hr; 01002 01003 TRACE("\n"); 01004 01005 EnterCriticalSection(This->pin.pCritSec); 01006 hr = InputPin_EndFlush(iface); 01007 01008 if (pFilter->state == State_Paused) 01009 SetEvent(pFilter->blocked); 01010 LeaveCriticalSection(This->pin.pCritSec); 01011 01012 return hr; 01013 } 01014 01015 static const IPinVtbl DSoundRender_InputPin_Vtbl = 01016 { 01017 InputPin_QueryInterface, 01018 IPinImpl_AddRef, 01019 InputPin_Release, 01020 InputPin_Connect, 01021 DSoundRender_InputPin_ReceiveConnection, 01022 DSoundRender_InputPin_Disconnect, 01023 IPinImpl_ConnectedTo, 01024 IPinImpl_ConnectionMediaType, 01025 IPinImpl_QueryPinInfo, 01026 IPinImpl_QueryDirection, 01027 IPinImpl_QueryId, 01028 IPinImpl_QueryAccept, 01029 IPinImpl_EnumMediaTypes, 01030 IPinImpl_QueryInternalConnections, 01031 DSoundRender_InputPin_EndOfStream, 01032 DSoundRender_InputPin_BeginFlush, 01033 DSoundRender_InputPin_EndFlush, 01034 InputPin_NewSegment 01035 }; 01036 01037 /*** IUnknown methods ***/ 01038 static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface, 01039 REFIID riid, 01040 LPVOID*ppvObj) { 01041 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01042 01043 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 01044 01045 return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); 01046 } 01047 01048 static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) { 01049 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01050 01051 TRACE("(%p/%p)->()\n", This, iface); 01052 01053 return DSoundRender_AddRef((IBaseFilter*)This); 01054 } 01055 01056 static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) { 01057 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01058 01059 TRACE("(%p/%p)->()\n", This, iface); 01060 01061 return DSoundRender_Release((IBaseFilter*)This); 01062 } 01063 01064 /*** IDispatch methods ***/ 01065 static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface, 01066 UINT*pctinfo) { 01067 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01068 01069 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); 01070 01071 return S_OK; 01072 } 01073 01074 static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface, 01075 UINT iTInfo, 01076 LCID lcid, 01077 ITypeInfo**ppTInfo) { 01078 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01079 01080 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); 01081 01082 return S_OK; 01083 } 01084 01085 static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface, 01086 REFIID riid, 01087 LPOLESTR*rgszNames, 01088 UINT cNames, 01089 LCID lcid, 01090 DISPID*rgDispId) { 01091 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01092 01093 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 01094 01095 return S_OK; 01096 } 01097 01098 static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface, 01099 DISPID dispIdMember, 01100 REFIID riid, 01101 LCID lcid, 01102 WORD wFlags, 01103 DISPPARAMS*pDispParams, 01104 VARIANT*pVarResult, 01105 EXCEPINFO*pExepInfo, 01106 UINT*puArgErr) { 01107 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01108 01109 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 01110 01111 return S_OK; 01112 } 01113 01114 /*** IBasicAudio methods ***/ 01115 static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface, 01116 LONG lVolume) { 01117 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01118 01119 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume); 01120 01121 if (lVolume > DSBVOLUME_MAX || lVolume < DSBVOLUME_MIN) 01122 return E_INVALIDARG; 01123 01124 if (This->dsbuffer) { 01125 if (FAILED(IDirectSoundBuffer_SetVolume(This->dsbuffer, lVolume))) 01126 return E_FAIL; 01127 } 01128 01129 This->volume = lVolume; 01130 return S_OK; 01131 } 01132 01133 static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface, 01134 LONG *plVolume) { 01135 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01136 01137 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume); 01138 01139 if (!plVolume) 01140 return E_POINTER; 01141 01142 *plVolume = This->volume; 01143 return S_OK; 01144 } 01145 01146 static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface, 01147 LONG lBalance) { 01148 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01149 01150 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance); 01151 01152 if (lBalance < DSBPAN_LEFT || lBalance > DSBPAN_RIGHT) 01153 return E_INVALIDARG; 01154 01155 if (This->dsbuffer) { 01156 if (FAILED(IDirectSoundBuffer_SetPan(This->dsbuffer, lBalance))) 01157 return E_FAIL; 01158 } 01159 01160 This->pan = lBalance; 01161 return S_OK; 01162 } 01163 01164 static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface, 01165 LONG *plBalance) { 01166 ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); 01167 01168 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance); 01169 01170 if (!plBalance) 01171 return E_POINTER; 01172 01173 *plBalance = This->pan; 01174 return S_OK; 01175 } 01176 01177 static const IBasicAudioVtbl IBasicAudio_Vtbl = 01178 { 01179 Basicaudio_QueryInterface, 01180 Basicaudio_AddRef, 01181 Basicaudio_Release, 01182 Basicaudio_GetTypeInfoCount, 01183 Basicaudio_GetTypeInfo, 01184 Basicaudio_GetIDsOfNames, 01185 Basicaudio_Invoke, 01186 Basicaudio_put_Volume, 01187 Basicaudio_get_Volume, 01188 Basicaudio_put_Balance, 01189 Basicaudio_get_Balance 01190 }; 01191 01192 01193 /*** IUnknown methods ***/ 01194 static HRESULT WINAPI ReferenceClock_QueryInterface(IReferenceClock *iface, 01195 REFIID riid, 01196 LPVOID*ppvObj) 01197 { 01198 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01199 01200 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 01201 01202 return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); 01203 } 01204 01205 static ULONG WINAPI ReferenceClock_AddRef(IReferenceClock *iface) 01206 { 01207 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01208 01209 TRACE("(%p/%p)->()\n", This, iface); 01210 01211 return DSoundRender_AddRef((IBaseFilter*)This); 01212 } 01213 01214 static ULONG WINAPI ReferenceClock_Release(IReferenceClock *iface) 01215 { 01216 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01217 01218 TRACE("(%p/%p)->()\n", This, iface); 01219 01220 return DSoundRender_Release((IBaseFilter*)This); 01221 } 01222 01223 /*** IReferenceClock methods ***/ 01224 static HRESULT WINAPI ReferenceClock_GetTime(IReferenceClock *iface, 01225 REFERENCE_TIME *pTime) 01226 { 01227 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01228 HRESULT hr = E_FAIL; 01229 DWORD play_pos; 01230 01231 TRACE("(%p/%p)->(%p)\n", This, iface, pTime); 01232 01233 if (This->dsbuffer) 01234 hr = DSoundRender_GetPos(This, &play_pos, pTime); 01235 if (FAILED(hr)) 01236 ERR("Could not get reference time (%x)!\n", hr); 01237 01238 return hr; 01239 } 01240 01241 static HRESULT WINAPI ReferenceClock_AdviseTime(IReferenceClock *iface, 01242 REFERENCE_TIME rtBaseTime, 01243 REFERENCE_TIME rtStreamTime, 01244 HEVENT hEvent, 01245 DWORD_PTR *pdwAdviseCookie) 01246 { 01247 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01248 01249 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hEvent, pdwAdviseCookie); 01250 01251 return E_NOTIMPL; 01252 } 01253 01254 static HRESULT WINAPI ReferenceClock_AdvisePeriodic(IReferenceClock *iface, 01255 REFERENCE_TIME rtBaseTime, 01256 REFERENCE_TIME rtStreamTime, 01257 HSEMAPHORE hSemaphore, 01258 DWORD_PTR *pdwAdviseCookie) 01259 { 01260 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01261 01262 FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hSemaphore, pdwAdviseCookie); 01263 01264 return E_NOTIMPL; 01265 } 01266 01267 static HRESULT WINAPI ReferenceClock_Unadvise(IReferenceClock *iface, 01268 DWORD_PTR dwAdviseCookie) 01269 { 01270 ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); 01271 01272 FIXME("(%p/%p)->(%p): stub!\n", This, iface, (void*)dwAdviseCookie); 01273 01274 return S_FALSE; 01275 } 01276 01277 static const IReferenceClockVtbl IReferenceClock_Vtbl = 01278 { 01279 ReferenceClock_QueryInterface, 01280 ReferenceClock_AddRef, 01281 ReferenceClock_Release, 01282 ReferenceClock_GetTime, 01283 ReferenceClock_AdviseTime, 01284 ReferenceClock_AdvisePeriodic, 01285 ReferenceClock_Unadvise 01286 }; 01287 01288 static inline DSoundRenderImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) 01289 { 01290 return (DSoundRenderImpl *)((char*)iface - FIELD_OFFSET(DSoundRenderImpl, mediaSeeking.lpVtbl)); 01291 } 01292 01293 static HRESULT WINAPI sound_seek_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) 01294 { 01295 DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); 01296 01297 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); 01298 } 01299 01300 static ULONG WINAPI sound_seek_AddRef(IMediaSeeking * iface) 01301 { 01302 DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); 01303 01304 return IUnknown_AddRef((IUnknown *)This); 01305 } 01306 01307 static ULONG WINAPI sound_seek_Release(IMediaSeeking * iface) 01308 { 01309 DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); 01310 01311 return IUnknown_Release((IUnknown *)This); 01312 } 01313 01314 static const IMediaSeekingVtbl IMediaSeeking_Vtbl = 01315 { 01316 sound_seek_QueryInterface, 01317 sound_seek_AddRef, 01318 sound_seek_Release, 01319 MediaSeekingImpl_GetCapabilities, 01320 MediaSeekingImpl_CheckCapabilities, 01321 MediaSeekingImpl_IsFormatSupported, 01322 MediaSeekingImpl_QueryPreferredFormat, 01323 MediaSeekingImpl_GetTimeFormat, 01324 MediaSeekingImpl_IsUsingTimeFormat, 01325 MediaSeekingImpl_SetTimeFormat, 01326 MediaSeekingImpl_GetDuration, 01327 MediaSeekingImpl_GetStopPosition, 01328 MediaSeekingImpl_GetCurrentPosition, 01329 MediaSeekingImpl_ConvertTimeFormat, 01330 MediaSeekingImpl_SetPositions, 01331 MediaSeekingImpl_GetPositions, 01332 MediaSeekingImpl_GetAvailable, 01333 MediaSeekingImpl_SetRate, 01334 MediaSeekingImpl_GetRate, 01335 MediaSeekingImpl_GetPreroll 01336 }; 01337 01338 /*** IUnknown methods ***/ 01339 static HRESULT WINAPI AMDirectSound_QueryInterface(IAMDirectSound *iface, 01340 REFIID riid, 01341 LPVOID*ppvObj) 01342 { 01343 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01344 01345 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 01346 01347 return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); 01348 } 01349 01350 static ULONG WINAPI AMDirectSound_AddRef(IAMDirectSound *iface) 01351 { 01352 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01353 01354 TRACE("(%p/%p)->()\n", This, iface); 01355 01356 return DSoundRender_AddRef((IBaseFilter*)This); 01357 } 01358 01359 static ULONG WINAPI AMDirectSound_Release(IAMDirectSound *iface) 01360 { 01361 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01362 01363 TRACE("(%p/%p)->()\n", This, iface); 01364 01365 return DSoundRender_Release((IBaseFilter*)This); 01366 } 01367 01368 /*** IAMDirectSound methods ***/ 01369 static HRESULT WINAPI AMDirectSound_GetDirectSoundInterface(IAMDirectSound *iface, IDirectSound **ds) 01370 { 01371 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01372 01373 FIXME("(%p/%p)->(%p): stub\n", This, iface, ds); 01374 01375 return E_NOTIMPL; 01376 } 01377 01378 static HRESULT WINAPI AMDirectSound_GetPrimaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer **buf) 01379 { 01380 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01381 01382 FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); 01383 01384 return E_NOTIMPL; 01385 } 01386 01387 static HRESULT WINAPI AMDirectSound_GetSecondaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer **buf) 01388 { 01389 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01390 01391 FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); 01392 01393 return E_NOTIMPL; 01394 } 01395 01396 static HRESULT WINAPI AMDirectSound_ReleaseDirectSoundInterface(IAMDirectSound *iface, IDirectSound *ds) 01397 { 01398 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01399 01400 FIXME("(%p/%p)->(%p): stub\n", This, iface, ds); 01401 01402 return E_NOTIMPL; 01403 } 01404 01405 static HRESULT WINAPI AMDirectSound_ReleasePrimaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer *buf) 01406 { 01407 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01408 01409 FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); 01410 01411 return E_NOTIMPL; 01412 } 01413 01414 static HRESULT WINAPI AMDirectSound_ReleaseSecondaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer *buf) 01415 { 01416 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01417 01418 FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); 01419 01420 return E_NOTIMPL; 01421 } 01422 01423 static HRESULT WINAPI AMDirectSound_SetFocusWindow(IAMDirectSound *iface, HWND hwnd, BOOL bgsilent) 01424 { 01425 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01426 01427 FIXME("(%p/%p)->(%p,%d): stub\n", This, iface, hwnd, bgsilent); 01428 01429 return E_NOTIMPL; 01430 } 01431 01432 static HRESULT WINAPI AMDirectSound_GetFocusWindow(IAMDirectSound *iface, HWND hwnd) 01433 { 01434 ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); 01435 01436 FIXME("(%p/%p)->(%p): stub\n", This, iface, hwnd); 01437 01438 return E_NOTIMPL; 01439 } 01440 01441 static const IAMDirectSoundVtbl IAMDirectSound_Vtbl = 01442 { 01443 AMDirectSound_QueryInterface, 01444 AMDirectSound_AddRef, 01445 AMDirectSound_Release, 01446 AMDirectSound_GetDirectSoundInterface, 01447 AMDirectSound_GetPrimaryBufferInterface, 01448 AMDirectSound_GetSecondaryBufferInterface, 01449 AMDirectSound_ReleaseDirectSoundInterface, 01450 AMDirectSound_ReleasePrimaryBufferInterface, 01451 AMDirectSound_ReleaseSecondaryBufferInterface, 01452 AMDirectSound_SetFocusWindow, 01453 AMDirectSound_GetFocusWindow 01454 }; Generated on Sun May 27 2012 04:21:55 for ReactOS by
1.7.6.1
|