ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dsoundrender.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.