static void DX6_WaitAudio_EventWait(_THIS) { DWORD status; HRESULT result; /* Try to restore a lost sound buffer */ IDirectSoundBuffer_GetStatus(mixbuf, &status); if ( (status&DSBSTATUS_BUFFERLOST) ) { IDirectSoundBuffer_Restore(mixbuf); IDirectSoundBuffer_GetStatus(mixbuf, &status); if ( (status&DSBSTATUS_BUFFERLOST) ) { return; } } if ( ! (status&DSBSTATUS_PLAYING) ) { result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); if ( result != DS_OK ) { #ifdef DEBUG_SOUND SetDSerror("DirectSound Play", result); #endif return; } } WaitForSingleObject(audio_event, INFINITE); }
static void DSOUND_WaitDevice(_THIS) { DWORD status = 0; DWORD cursor = 0; DWORD junk = 0; HRESULT result = DS_OK; /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); if (result != DS_OK) { if (result == DSERR_BUFFERLOST) { IDirectSoundBuffer_Restore(this->hidden->mixbuf); } #ifdef DEBUG_SOUND SetDSerror("DirectSound GetCurrentPosition", result); #endif return; } while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) { /* FIXME: find out how much time is left and sleep that long */ SDL_Delay(1); /* Try to restore a lost sound buffer */ IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { IDirectSoundBuffer_Restore(this->hidden->mixbuf); IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { break; } } if (!(status & DSBSTATUS_PLAYING)) { result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0, DSBPLAY_LOOPING); if (result == DS_OK) { continue; } #ifdef DEBUG_SOUND SetDSerror("DirectSound Play", result); #endif return; } /* Find out where we are playing */ result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); if (result != DS_OK) { SetDSerror("DirectSound GetCurrentPosition", result); return; } } }
static void DX5_WaitAudio_BusyWait(_THIS) { DWORD status; DWORD cursor, junk; HRESULT result; /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); if ( result != DS_OK ) { if ( result == DSERR_BUFFERLOST ) { IDirectSoundBuffer_Restore(mixbuf); } #ifdef DEBUG_SOUND SetDSerror("DirectSound GetCurrentPosition", result); #endif return; } cursor /= mixlen; while ( cursor == playing ) { /* FIXME: find out how much time is left and sleep that long */ SDL_Delay(10); /* Try to restore a lost sound buffer */ IDirectSoundBuffer_GetStatus(mixbuf, &status); if ( (status&DSBSTATUS_BUFFERLOST) ) { IDirectSoundBuffer_Restore(mixbuf); IDirectSoundBuffer_GetStatus(mixbuf, &status); if ( (status&DSBSTATUS_BUFFERLOST) ) { break; } } if ( ! (status&DSBSTATUS_PLAYING) ) { result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); if ( result == DS_OK ) { continue; } #ifdef DEBUG_SOUND SetDSerror("DirectSound Play", result); #endif return; } /* Find out where we are playing */ result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &junk); if ( result != DS_OK ) { SetDSerror("DirectSound GetCurrentPosition", result); return; } cursor /= mixlen; } }
IDirectSoundBuffer *SndObjGetFreeBuffer(SNDOBJ *pSO) { IDirectSoundBuffer *pDSB; if (pSO == NULL) return NULL; if (pDSB = pSO->Buffers[pSO->iCurrent]) { HRESULT hres; DWORD dwStatus; hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus); if (FAILED(hres)) dwStatus = 0; if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING) { if (pSO->iAlloc > 1) { if (++pSO->iCurrent >= pSO->iAlloc) pSO->iCurrent = 0; pDSB = pSO->Buffers[pSO->iCurrent]; hres = IDirectSoundBuffer_GetStatus(pDSB, &dwStatus); if (SUCCEEDED(hres) && (dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING) { IDirectSoundBuffer_Stop(pDSB); IDirectSoundBuffer_SetCurrentPosition(pDSB, 0); } } else { pDSB = NULL; } } if (pDSB && (dwStatus & DSBSTATUS_BUFFERLOST)) { if (FAILED(IDirectSoundBuffer_Restore(pDSB)) || !DSFillSoundBuffer(pDSB, pSO->pbWaveData, pSO->cbWaveSize)) { pDSB = NULL; } } } return pDSB; }
static void DS_Exit(void) { DWORD statusInfo; if(updateBufferHandle) { /* Signal thread to exit and wait for the exit */ if (threadInUse) { threadInUse = 0; MUTEX_UNLOCK(vars); SetEvent (notifyUpdateHandle); WaitForSingleObject (updateBufferHandle, INFINITE); MUTEX_LOCK(vars); } CloseHandle(updateBufferHandle), updateBufferHandle = NULL; } if (notifyUpdateHandle) { CloseHandle(notifyUpdateHandle), notifyUpdateHandle = NULL; } if (pSoundBufferNotify) { IDirectSoundNotify_Release(pSoundBufferNotify); pSoundBufferNotify = NULL; } if(pSoundBuffer) { if(IDirectSoundBuffer_GetStatus(pSoundBuffer,&statusInfo)==DS_OK) if(statusInfo&DSBSTATUS_PLAYING) IDirectSoundBuffer_Stop(pSoundBuffer); IDirectSoundBuffer_Release(pSoundBuffer); pSoundBuffer = NULL; } if(pPrimarySoundBuffer) { if(IDirectSoundBuffer_GetStatus(pPrimarySoundBuffer,&statusInfo)==DS_OK) if(statusInfo&DSBSTATUS_PLAYING) IDirectSoundBuffer_Stop(pPrimarySoundBuffer); IDirectSoundBuffer_Release(pPrimarySoundBuffer); pPrimarySoundBuffer = NULL; } if (pSoundCard) { IDirectSound_Release(pSoundCard); pSoundCard = NULL; } VC_Exit(); }
void I_UpdateSoundParams(int channel, int vol, int sep, int pitch) { // proff 07/04/98: Added for CYGWIN32 compatibility #ifdef HAVE_LIBDSOUND int DSB_Status; if (noDSound == true) return; // proff 07/26/98: Added volume check if (vol==0) { IDirectSoundBuffer_Stop(lpSecondaryDSB[channel]); return; } IDirectSoundBuffer_SetVolume(lpSecondaryDSB[channel],VOL(vol)); IDirectSoundBuffer_SetPan(lpSecondaryDSB[channel],SEP(sep)); IDirectSoundBuffer_SetFrequency (lpSecondaryDSB[channel], ChannelInfo[channel].samplerate+PITCH(pitch)); if (ChannelInfo[channel].playing == true) { IDirectSoundBuffer_GetStatus(lpSecondaryDSB[channel], &DSB_Status); if ((DSB_Status & DSBSTATUS_PLAYING) == 0) IDirectSoundBuffer_Play(lpSecondaryDSB[channel], 0, 0, 0); } #endif // HAVE_LIBDSOUND }
static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface) { HRESULT hr = S_OK; DSoundRenderImpl *This = (DSoundRenderImpl *)iface; TRACE("(%p/%p)->()\n", This, iface); EnterCriticalSection(&This->filter.csFilter); { DWORD state = 0; if (This->dsbuffer) { hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); if (SUCCEEDED(hr)) { if (state & DSBSTATUS_PLAYING) hr = IDirectSoundBuffer_Stop(This->dsbuffer); } } if (SUCCEEDED(hr)) This->filter.state = State_Stopped; /* Complete our transition */ SetEvent(This->state_change); SetEvent(This->blocked); MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk); } LeaveCriticalSection(&This->filter.csFilter); return hr; }
static guint gst_directsound_sink_delay (GstAudioSink * asink) { GstDirectSoundSink *dsoundsink; HRESULT hRes; DWORD dwCurrentPlayCursor; DWORD dwBytesInQueue = 0; gint nNbSamplesInQueue = 0; DWORD dwStatus; dsoundsink = GST_DIRECTSOUND_SINK (asink); /* get current buffer status */ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); if (dwStatus & DSBSTATUS_PLAYING) { /*evaluate the number of samples in queue in the circular buffer */ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); if (hRes == S_OK) { if (dwCurrentPlayCursor < dsoundsink->current_circular_offset) dwBytesInQueue = dsoundsink->current_circular_offset - dwCurrentPlayCursor; else dwBytesInQueue = dsoundsink->current_circular_offset + (dsoundsink->buffer_size - dwCurrentPlayCursor); nNbSamplesInQueue = dwBytesInQueue / dsoundsink->bytes_per_sample; } } return nNbSamplesInQueue; }
static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) { HRESULT hr = S_OK; DSoundRenderImpl *This = (DSoundRenderImpl *)iface; TRACE("(%p/%p)->()\n", This, iface); EnterCriticalSection(&This->filter.csFilter); if (This->filter.state != State_Paused) { DWORD state = 0; if (This->filter.state == State_Stopped) { This->pInputPin->end_of_stream = 0; } if (This->dsbuffer) { hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); if (SUCCEEDED(hr)) { if (state & DSBSTATUS_PLAYING) hr = IDirectSoundBuffer_Stop(This->dsbuffer); } } if (SUCCEEDED(hr)) This->filter.state = State_Paused; ResetEvent(This->blocked); ResetEvent(This->state_change); } LeaveCriticalSection(&This->filter.csFilter); return hr; }
/* * バッファをリストアする */ static BOOL RestoreBuffers(int nBuffer) { DWORD dwStatus; HRESULT hRet; assert(pDSBuffer[nBuffer] != NULL); assert(nBuffer >= 0 && nBuffer < MIXER_STREAMS); hRet = IDirectSoundBuffer_GetStatus(pDSBuffer[nBuffer], &dwStatus); if(hRet != DS_OK) return FALSE; if(dwStatus & DSBSTATUS_BUFFERLOST) { /* * アプリケーションがアクティブになったばかりなので * DirectSoundのコントロールを取得できない可能性がある。 * よって、コントロールを取得できるまでスリープする。 */ while(1) { Sleep(10); hRet = IDirectSoundBuffer_Restore(pDSBuffer[nBuffer]); if(hRet != DSERR_BUFFERLOST) break; } } return TRUE; }
DWORD DSW_GetOutputStatus( DSoundWrapper *dsw ) { DWORD status; if (IDirectSoundBuffer_GetStatus( dsw->dsw_OutputBuffer, &status ) != DS_OK) return( DSERR_INVALIDPARAM ); else return( status ); }
int I2_IsSourcePlaying(sndsource_t *buf) { DWORD status; IDirectSoundBuffer_GetStatus(buf->source, &status); // Restore the buffer if it's lost, but that shouldn't really matter since // it'll be released when it stops playing. if(status & DSBSTATUS_BUFFERLOST) IDirectSoundBuffer_Restore(buf->source); return (status & DSBSTATUS_PLAYING) != 0; }
static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPos, REFERENCE_TIME *pRefTime) { HRESULT hr; EnterCriticalSection(&This->filter.csFilter); { DWORD state; DWORD write_pos; hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); if (SUCCEEDED(hr) && !(state & DSBSTATUS_PLAYING) && This->filter.state == State_Running) { TRACE("Not playing, kickstarting the engine\n"); hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING); if (FAILED(hr)) ERR("Can't play sound buffer (%x)\n", hr); } if (SUCCEEDED(hr)) hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, &write_pos); if (hr == S_OK) { DWORD play_pos = *pPlayPos; if (play_pos < This->last_play_pos) This->play_loops++; This->last_play_pos = play_pos; /* If we really fell behind, start at the next possible position * Also happens when just starting playback for the first time, * or when flushing */ if ((This->play_loops*This->buf_size)+play_pos >= (This->write_loops*This->buf_size)+This->write_pos) This->write_pos = write_pos; if (pRefTime) { REFERENCE_TIME play_time; play_time = ((REFERENCE_TIME)This->play_loops*10000000) + ((REFERENCE_TIME)play_pos*10000000/This->buf_size); /* Don't let time run backwards */ if(play_time-This->play_time > 0) This->play_time = play_time; else hr = S_FALSE; *pRefTime = This->play_time; } } } LeaveCriticalSection(&This->filter.csFilter); return hr; }
/** \brief fill sound buffer \param data pointer to the sound data to copy \param len length of the data to copy in bytes \return number of copyed bytes */ static int write_buffer(struct ao *ao, unsigned char *data, int len) { struct priv *p = ao->priv; HRESULT res; LPVOID lpvPtr1; DWORD dwBytes1; LPVOID lpvPtr2; DWORD dwBytes2; p->underrun_check = 0; // Lock the buffer res = IDirectSoundBuffer_Lock(p->hdsbuf, p->write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); // If the buffer was lost, restore and retry lock. if (DSERR_BUFFERLOST == res) { IDirectSoundBuffer_Restore(p->hdsbuf); res = IDirectSoundBuffer_Lock(p->hdsbuf, p->write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); } if (SUCCEEDED(res)) { if (!AF_FORMAT_IS_AC3(ao->format)) { memcpy(lpvPtr1, data, dwBytes1); if (lpvPtr2 != NULL) memcpy(lpvPtr2, (char *)data + dwBytes1, dwBytes2); p->write_offset += dwBytes1 + dwBytes2; if (p->write_offset >= p->buffer_size) p->write_offset = dwBytes2; } else { // Write to pointers without reordering. memcpy(lpvPtr1, data, dwBytes1); if (NULL != lpvPtr2) memcpy(lpvPtr2, data + dwBytes1, dwBytes2); p->write_offset += dwBytes1 + dwBytes2; if (p->write_offset >= p->buffer_size) p->write_offset = dwBytes2; } // Release the data back to DirectSound. res = IDirectSoundBuffer_Unlock(p->hdsbuf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); if (SUCCEEDED(res)) { // Success. DWORD status; IDirectSoundBuffer_GetStatus(p->hdsbuf, &status); if (!(status & DSBSTATUS_PLAYING)) res = IDirectSoundBuffer_Play(p->hdsbuf, 0, 0, DSBPLAY_LOOPING); return dwBytes1 + dwBytes2; } } // Lock, Unlock, or Restore failed. return 0; }
void DSSoundFeedVoiceData(unsigned char* pSound,long lBytes) { LPVOID lpvPtr1, lpvPtr2; unsigned long dwBytes1,dwBytes2; unsigned long *lpSS, *lpSD; unsigned long dw,cplay,cwrite; HRESULT hr; unsigned long status; IDirectSoundBuffer_GetStatus(lpDSBSECONDARY1,&status); if (status & DSBSTATUS_BUFFERLOST) { if (IDirectSoundBuffer_Restore(lpDSBSECONDARY1) != DS_OK) return; IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING); } IDirectSoundBuffer_GetCurrentPosition(lpDSBSECONDARY1,&cplay,&cwrite); if(LastWrite == 0xffffffff) LastWrite=cwrite; hr = IDirectSoundBuffer_Lock(lpDSBSECONDARY1,LastWrite,lBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); if (hr != DS_OK) { LastWrite=0xffffffff; return; } lpSS = (unsigned long *)pSound; lpSD = (unsigned long *)lpvPtr1; dw = dwBytes1 >> 2; while(dw) { *lpSD++=*lpSS++; dw--; } if (lpvPtr2) { lpSD = (unsigned long *)lpvPtr2; dw = dwBytes2 >> 2; while(dw) { *lpSD++ = *lpSS++; dw--; } } IDirectSoundBuffer_Unlock(lpDSBSECONDARY1,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2); LastWrite += lBytes; if(LastWrite >= SOUNDSIZE) LastWrite -= SOUNDSIZE; LastPlay = cplay; }
static int ChannelPlaying( Channel *channel ) { DWORD status, Error; if(!channel) return( 0 ); Error = IDirectSoundBuffer_GetStatus( channel->buffer, &status); if( Error != DS_OK) return 0; return( status & DSBSTATUS_PLAYING ); }
/* ==================== SndSys_LockRenderBuffer Get the exclusive lock on "snd_renderbuffer" ==================== */ qboolean SndSys_LockRenderBuffer (void) { #ifdef SUPPORTDIRECTX int reps; HRESULT hresult; DWORD dwStatus; if (pDSBuf) { // if the buffer was lost or stopped, restore it and/or restart it if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DS_OK) Con_Print("Couldn't get sound buffer status\n"); if (dwStatus & DSBSTATUS_BUFFERLOST) { Con_Print("DSound buffer is lost!!\n"); IDirectSoundBuffer_Restore (pDSBuf); } if (!(dwStatus & DSBSTATUS_PLAYING)) IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); reps = 0; while ((hresult = IDirectSoundBuffer_Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&dsound_pbuf, &dsound_dwSize, (LPVOID*)&dsound_pbuf2, &dsound_dwSize2, 0)) != DS_OK) { if (hresult != DSERR_BUFFERLOST) { Con_Print("S_LockBuffer: DS: Lock Sound Buffer Failed\n"); S_Shutdown (); S_Startup (); return false; } if (++reps > 10000) { Con_Print("S_LockBuffer: DS: couldn't restore buffer\n"); S_Shutdown (); S_Startup (); return false; } } if ((void*)dsound_pbuf != snd_renderbuffer->ring) Sys_Error("SndSys_LockRenderBuffer: the ring address has changed!!!\n"); return true; } #endif return wav_init; }
//added 2000/01/15 Matt Mueller -- remove some duplication (and fix a big memory leak, in the kill=0 one case) static int DS_release_slot(int slot,int kill){ if (SoundSlots[slot].lpsb) { DWORD s; IDirectSoundBuffer_GetStatus(SoundSlots[slot].lpsb, &s); if (s & DSBSTATUS_PLAYING){ if (kill) IDirectSoundBuffer_Stop(SoundSlots[slot].lpsb); else return 0; } IDirectSoundBuffer_Release(SoundSlots[slot].lpsb); SoundSlots[slot].lpsb = NULL; } SoundSlots[slot].playing = 0; return 1; }
void CheckDStatus(void) { DWORD status; status=0; IDirectSoundBuffer_GetStatus(ppbufw, &status); if(status&DSBSTATUS_BUFFERLOST) { IDirectSoundBuffer_Restore(ppbufw); } if(!(status&DSBSTATUS_PLAYING)) { ToWritePos=0; IDirectSoundBuffer_SetFormat(ppbufw,&wf); IDirectSoundBuffer_Play(ppbufw,0,0,DSBPLAY_LOOPING); } }
void DSOUND_Restore(void) { // if the buffer was lost or stopped, restore it and/or restart it DWORD dwStatus; if (!pDSBuf) return; if (IDirectSoundBuffer_GetStatus (pDSBuf, &dwStatus) != DD_OK) Con_Printf ("Couldn't get sound buffer status\n"); if (dwStatus & DSBSTATUS_BUFFERLOST) IDirectSoundBuffer_Restore (pDSBuf); if (!(dwStatus & DSBSTATUS_PLAYING)) IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING); return; }
static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp, dsound *s) { HRESULT hr; hr = IDirectSoundBuffer_GetStatus (dsb, statusp); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer status\n"); return -1; } if (*statusp & DSERR_BUFFERLOST) { dsound_restore_out(dsb, s); return -1; } return 0; }
/************************************************************************** * MCICDA_GetStatus [internal] */ static DWORD MCICDA_GetStatus(WINE_MCICDAUDIO* wmcda) { CDROM_SUB_Q_DATA_FORMAT fmt; SUB_Q_CHANNEL_DATA data; DWORD br; DWORD mode = MCI_MODE_NOT_READY; fmt.Format = IOCTL_CDROM_CURRENT_POSITION; if(wmcda->hThread != 0) { DWORD status; HRESULT hr; hr = IDirectSoundBuffer_GetStatus(wmcda->dsBuf, &status); if(SUCCEEDED(hr)) { if(!(status&DSBSTATUS_PLAYING)) { if(WaitForSingleObject(wmcda->stopEvent, 0) == WAIT_OBJECT_0) mode = MCI_MODE_STOP; else mode = MCI_MODE_PAUSE; } else mode = MCI_MODE_PLAY; } } else if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), &data, sizeof(data), &br, NULL)) { if (GetLastError() == ERROR_NOT_READY) mode = MCI_MODE_OPEN; } else { switch (data.CurrentPosition.Header.AudioStatus) { case AUDIO_STATUS_IN_PROGRESS: mode = MCI_MODE_PLAY; break; case AUDIO_STATUS_PAUSED: mode = MCI_MODE_PAUSE; break; case AUDIO_STATUS_NO_STATUS: case AUDIO_STATUS_PLAY_COMPLETE: mode = MCI_MODE_STOP; break; case AUDIO_STATUS_PLAY_ERROR: case AUDIO_STATUS_NOT_SUPPORTED: default: break; } } return mode; }
static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp) { HRESULT hr; int i; for (i = 0; i < conf.getstatus_retries; ++i) { hr = IDirectSoundBuffer_GetStatus (dsb, statusp); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer status\n"); return -1; } if (*statusp & DSERR_BUFFERLOST) { if (dsound_restore_out (dsb)) { return -1; } continue; } break; } return 0; }
static HRESULT TimeGet( aout_stream_sys_t *sys, vlc_tick_t *delay ) { DWORD read, status; HRESULT hr; ssize_t size; hr = IDirectSoundBuffer_GetStatus( sys->p_dsbuffer, &status ); if( hr != DS_OK ) return hr; if( !(status & DSBSTATUS_PLAYING) ) return DSERR_INVALIDCALL ; hr = IDirectSoundBuffer_GetCurrentPosition( sys->p_dsbuffer, &read, NULL ); if( hr != DS_OK ) return hr; size = (ssize_t)read - sys->i_last_read; /* GetCurrentPosition cannot be trusted if the return doesn't change * Just return an error */ if( size == 0 ) return DSERR_GENERIC ; else if( size < 0 ) size += DS_BUF_SIZE; sys->i_data -= size; sys->i_last_read = read; if( sys->i_data < 0 ) /* underrun */ Flush(sys); *delay = vlc_tick_from_samples( sys->i_data / sys->i_bytes_per_sample, sys->i_rate ); return DS_OK; }
static guint gst_directsound_sink_write (GstAudioSink * asink, gpointer data, guint length) { GstDirectSoundSink *dsoundsink; DWORD dwStatus; HRESULT hRes; LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL; DWORD dwSizeBuffer1, dwSizeBuffer2; DWORD dwCurrentPlayCursor; dsoundsink = GST_DIRECTSOUND_SINK (asink); /* Fix endianness */ if (dsoundsink->buffer_format == GST_IEC958) _swab (data, data, length); GST_DSOUND_LOCK (dsoundsink); /* get current buffer status */ hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); /* get current play cursor position */ hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) { DWORD dwFreeBufferSize; calculate_freesize: /* calculate the free size of the circular buffer */ if (dwCurrentPlayCursor < dsoundsink->current_circular_offset) dwFreeBufferSize = dsoundsink->buffer_size - (dsoundsink->current_circular_offset - dwCurrentPlayCursor); else dwFreeBufferSize = dwCurrentPlayCursor - dsoundsink->current_circular_offset; if (length >= dwFreeBufferSize) { Sleep (100); hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary, &dwCurrentPlayCursor, NULL); hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus); if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) goto calculate_freesize; else { dsoundsink->first_buffer_after_reset = FALSE; GST_DSOUND_UNLOCK (dsoundsink); return 0; } } } if (dwStatus & DSBSTATUS_BUFFERLOST) { hRes = IDirectSoundBuffer_Restore (dsoundsink->pDSBSecondary); /*need a loop waiting the buffer is restored?? */ dsoundsink->current_circular_offset = 0; } hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary, dsoundsink->current_circular_offset, length, &pLockedBuffer1, &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L); if (SUCCEEDED (hRes)) { // Write to pointers without reordering. memcpy (pLockedBuffer1, data, dwSizeBuffer1); if (pLockedBuffer2 != NULL) memcpy (pLockedBuffer2, (LPBYTE) data + dwSizeBuffer1, dwSizeBuffer2); // Update where the buffer will lock (for next time) dsoundsink->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2; dsoundsink->current_circular_offset %= dsoundsink->buffer_size; /* Circular buffer */ hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer1, dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2); } /* if the buffer was not in playing state yet, call play on the buffer except if this buffer is the fist after a reset (base class call reset and write a buffer when setting the sink to pause) */ if (!(dwStatus & DSBSTATUS_PLAYING) && dsoundsink->first_buffer_after_reset == FALSE) { hRes = IDirectSoundBuffer_Play (dsoundsink->pDSBSecondary, 0, 0, DSBPLAY_LOOPING); } dsoundsink->first_buffer_after_reset = FALSE; GST_DSOUND_UNLOCK (dsoundsink); return length; }