From be9c3cabb4dae662656797337942179f7a952581 Mon Sep 17 00:00:00 2001 From: paulc Date: Sat, 9 Jul 2005 18:27:49 +0000 Subject: [PATCH] Fixed DirectSound and OpenH323 modules for Windows. git-svn-id: http://yate.null.ro/svn/yate/trunk@440 acf43c95-373e-0410-b603-e72c3f656dc1 --- engine/Message.cpp | 10 +-- engine/String.cpp | 6 +- engine/Thread.cpp | 4 +- modules/dsoundchan.cpp | 183 +++++++++++++++++++++++++++-------------- modules/h323chan.cpp | 8 +- windows/.cvsignore | 1 + 6 files changed, 137 insertions(+), 75 deletions(-) diff --git a/engine/Message.cpp b/engine/Message.cpp index 27067455..63295c3f 100644 --- a/engine/Message.cpp +++ b/engine/Message.cpp @@ -226,7 +226,7 @@ MessageDispatcher::~MessageDispatcher() bool MessageDispatcher::install(MessageHandler* handler) { - DDebug(DebugAll,"MessageDispatcher::install(%p)",handler); + XDebug(DebugAll,"MessageDispatcher::install(%p)",handler); if (!handler) return false; Lock lock(m_mutex); @@ -242,11 +242,11 @@ bool MessageDispatcher::install(MessageHandler* handler) } m_changes++; if (l) { - DDebug(DebugAll,"Inserting handler [%p] on place #%d",handler,pos); + XDebug(DebugAll,"Inserting handler [%p] on place #%d",handler,pos); l->insert(handler); } else { - DDebug(DebugAll,"Appending handler [%p] on place #%d",handler,pos); + XDebug(DebugAll,"Appending handler [%p] on place #%d",handler,pos); m_handlers.append(handler); } handler->m_dispatcher = this; @@ -257,7 +257,7 @@ bool MessageDispatcher::install(MessageHandler* handler) bool MessageDispatcher::uninstall(MessageHandler* handler) { - DDebug(DebugAll,"MessageDispatcher::uninstall(%p)",handler); + XDebug(DebugAll,"MessageDispatcher::uninstall(%p)",handler); Lock lock(m_mutex); handler = static_cast(m_handlers.remove(handler,false)); if (handler) { @@ -269,7 +269,7 @@ bool MessageDispatcher::uninstall(MessageHandler* handler) bool MessageDispatcher::dispatch(Message& msg) { -#ifdef DEBUG +#ifdef XDEBUG Debugger debug("MessageDispatcher::dispatch","(%p) (\"%s\")",&msg,msg.c_str()); #endif #ifndef NDEBUG diff --git a/engine/String.cpp b/engine/String.cpp index 7008d16f..8bd71e80 100644 --- a/engine/String.cpp +++ b/engine/String.cpp @@ -858,7 +858,7 @@ Regexp::~Regexp() bool Regexp::matches(const char* value, StringMatchPrivate* matches) { - DDebug(DebugInfo,"Regexp::matches(\"%s\",%p)",value,matches); + XDebug(DebugInfo,"Regexp::matches(\"%s\",%p)",value,matches); if (!value) value = ""; if (!compile()) @@ -881,7 +881,7 @@ void Regexp::changed() bool Regexp::compile() { - DDebug(DebugInfo,"Regexp::compile()"); + XDebug(DebugInfo,"Regexp::compile()"); if (c_str() && !m_regexp) { regex_t *data = (regex_t *) ::malloc(sizeof(regex_t)); if (!data) { @@ -901,7 +901,7 @@ bool Regexp::compile() void Regexp::cleanup() { - DDebug(DebugInfo,"Regexp::cleanup()"); + XDebug(DebugInfo,"Regexp::cleanup()"); if (m_regexp) { regex_t *data = (regex_t *)m_regexp; m_regexp = 0; diff --git a/engine/Thread.cpp b/engine/Thread.cpp index fe623153..404c5785 100644 --- a/engine/Thread.cpp +++ b/engine/Thread.cpp @@ -497,7 +497,9 @@ void Thread::cancel(bool hard) void Thread::yield(bool exitCheck) { #ifdef _WINDOWS - ::Sleep(0); + // zero sleep is bad if we have high priority threads, they + // won't relinquish the timeslice for lower priority ones + ::Sleep(1); #else ::usleep(0); #endif diff --git a/modules/dsoundchan.cpp b/modules/dsoundchan.cpp index a6662c9b..5b2b5f96 100644 --- a/modules/dsoundchan.cpp +++ b/modules/dsoundchan.cpp @@ -39,10 +39,14 @@ using namespace TelEngine; +// we should use the primary sound buffer else we will lose sound while we have no input focus +#define USE_PRIMARY_BUFFER + // 20ms chunk, 100ms buffer #define CHUNK_SIZE 320 -#define MAX_SIZE (5*CHUNK_SIZE) +#define MIN_SIZE (3*CHUNK_SIZE) #define BUF_SIZE (4*CHUNK_SIZE) +#define MAX_SIZE (5*CHUNK_SIZE) class DSoundSource : public DataSource { @@ -86,6 +90,8 @@ private: LPGUID m_device; LPDIRECTSOUND m_ds; LPDIRECTSOUNDBUFFER m_dsb; + DWORD m_buffSize; + DWORD m_writePos; DataBlock m_buf; }; @@ -109,6 +115,8 @@ private: LPGUID m_device; LPDIRECTSOUNDCAPTURE m_ds; LPDIRECTSOUNDCAPTUREBUFFER m_dsb; + DWORD m_buffSize; + DWORD m_readPos; }; class DSoundChan : public Channel @@ -135,9 +143,6 @@ public: ~SoundDriver(); virtual void initialize(); virtual bool msgExecute(Message& msg, String& dest); -protected: - void statusModule(String& str); - void statusParams(String& str); private: AttachHandler* m_handler; }; @@ -146,7 +151,8 @@ INIT_PLUGIN(SoundDriver); DSoundPlay::DSoundPlay(DSoundConsumer* owner, LPGUID device) : Thread("DirectSound Play",High), - m_owner(owner), m_device(device), m_ds(0), m_dsb(0) + m_owner(owner), m_device(device), m_ds(0), m_dsb(0), + m_buffSize(0), m_writePos(0) { } @@ -175,19 +181,14 @@ bool DSoundPlay::init() HWND wnd = GetForegroundWindow(); if (!wnd) wnd = GetDesktopWindow(); +#ifdef USE_PRIMARY_BUFFER if (FAILED(hr = m_ds->SetCooperativeLevel(wnd,DSSCL_WRITEPRIMARY))) { +#else + if (FAILED(hr = m_ds->SetCooperativeLevel(wnd,DSSCL_EXCLUSIVE))) { +#endif Debug(DebugGoOn,"Could not set the DirectSound cooperative level, code 0x%X",hr); return false; } - DSBUFFERDESC bdesc; - ZeroMemory(&bdesc, sizeof(bdesc)); - bdesc.dwSize = sizeof(bdesc); - bdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_STICKYFOCUS; - // | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME - if (FAILED(hr = m_ds->CreateSoundBuffer(&bdesc, &m_dsb, NULL)) || !m_dsb) { - Debug(DebugGoOn,"Could not create the DirectSound buffer, code 0x%X",hr); - return false; - } WAVEFORMATEX fmt; fmt.wFormatTag = WAVE_FORMAT_PCM; fmt.nChannels = 1; @@ -196,10 +197,26 @@ bool DSoundPlay::init() fmt.nBlockAlign = 2; fmt.wBitsPerSample = 16; fmt.cbSize = 0; + DSBUFFERDESC bdesc; + ZeroMemory(&bdesc, sizeof(bdesc)); + bdesc.dwSize = sizeof(bdesc); +#ifdef USE_PRIMARY_BUFFER + bdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_STICKYFOCUS; +#else + bdesc.dwFlags = DSBCAPS_LOCSOFTWARE ; + bdesc.dwBufferBytes = BUF_SIZE; + bdesc.lpwfxFormat = &fmt; +#endif + if (FAILED(hr = m_ds->CreateSoundBuffer(&bdesc, &m_dsb, NULL)) || !m_dsb) { + Debug(DebugGoOn,"Could not create the DirectSound buffer, code 0x%X",hr); + return false; + } +#ifdef USE_PRIMARY_BUFFER if (FAILED(hr = m_dsb->SetFormat(&fmt))) { Debug(DebugGoOn,"Could not set the DirectSound buffer format, code 0x%X",hr); return false; } +#endif if (FAILED(hr = m_dsb->GetFormat(&fmt,sizeof(fmt),0))) { Debug(DebugGoOn,"Could not get the DirectSound buffer format, code 0x%X",hr); return false; @@ -213,16 +230,21 @@ bool DSoundPlay::init() fmt.wFormatTag,fmt.nChannels,fmt.nSamplesPerSec,fmt.wBitsPerSample); return false; } -#ifdef DEBUG DSBCAPS caps; caps.dwSize = sizeof(caps); - if (SUCCEEDED(m_dsb->GetCaps(&caps))) - Debug(DebugInfo,"DirectSound buffer size %u",caps.dwBufferBytes); -#endif - if (FAILED(hr = m_dsb->Play(0,0,DSBPLAY_LOOPING))) { - Debug(DebugGoOn,"Could not play the DirectSound buffer, code 0x%X",hr); + if (FAILED(hr = m_dsb->GetCaps(&caps))) { + Debug(DebugGoOn,"Could not get the DirectSound buffer capabilities, code 0x%X",hr); return false; } + m_buffSize = caps.dwBufferBytes; + Debug(&__plugin,DebugInfo,"DirectSound buffer size %u",m_buffSize); + if (FAILED(hr = m_dsb->Play(0,0,DSBPLAY_LOOPING))) { + if ((hr != DSERR_BUFFERLOST) || FAILED(hr = m_dsb->Restore())) { + Debug(DebugGoOn,"Could not play the DirectSound buffer, code 0x%X",hr); + return false; + } + m_dsb->Play(0,0,DSBPLAY_LOOPING); + } return true; } @@ -232,32 +254,50 @@ void DSoundPlay::run() return; if (m_owner) m_owner->m_dsound = this; - Debug(DebugInfo,"DSoundPlay is initialized and running"); + bool first = true; + Debug(&__plugin,DebugInfo,"DSoundPlay is initialized and running"); while (m_owner) { msleep(1,true); - if (m_dsb && (m_buf.length() >= CHUNK_SIZE)) { + if (first) { + if (m_buf.length() < MIN_SIZE) + continue; + first = false; + m_dsb->GetCurrentPosition(NULL,&m_writePos); + Debug(&__plugin,DebugAll,"DSoundPlay has %u in buffer and starts playing at %u", + m_buf.length(),m_writePos); + } + while (m_dsb && (m_buf.length() >= CHUNK_SIZE)) { void* buf = 0; void* buf2 = 0; DWORD len = 0; DWORD len2 = 0; - HRESULT hr = m_dsb->Lock(0,CHUNK_SIZE,&buf,&len,&buf2,&len2,DSBLOCK_FROMWRITECURSOR); + HRESULT hr = m_dsb->Lock(m_writePos,CHUNK_SIZE,&buf,&len,&buf2,&len2,0); if (FAILED(hr)) { + m_writePos = 0; if ((hr == DSERR_BUFFERLOST) && SUCCEEDED(m_dsb->Restore())) { - Debug(DebugAll,"DirectSound buffer lost and restored"); m_dsb->Play(0,0,DSBPLAY_LOOPING); + m_dsb->GetCurrentPosition(NULL,&m_writePos); + Debug(&__plugin,DebugAll,"DirectSound buffer lost and restored, playing at %u", + m_writePos); + } + else { + lock(); + m_buf.clear(); + unlock(); } - lock(); - m_buf.clear(); - unlock(); continue; } lock(); ::memcpy(buf,m_buf.data(),len); if (buf2) ::memcpy(buf2,((const char*)m_buf.data())+len,len2); - m_dsb->Unlock(buf,len,0,0); + m_dsb->Unlock(buf,len,buf2,len2); + m_writePos += CHUNK_SIZE; + if (m_writePos >= m_buffSize) + m_writePos -= m_buffSize; m_buf.cut(-CHUNK_SIZE); unlock(); + XDebug(&__plugin,DebugAll,"Locked %p,%d %p,%d",buf,len,buf2,len2); } } } @@ -284,16 +324,17 @@ void DSoundPlay::put(const DataBlock& data) lock(); if (m_buf.length() + data.length() <= MAX_SIZE) m_buf += data; -#ifdef XDEBUG +#ifdef DDEBUG else - Debug(DebugAll,"DSoundPlay skipped %u bytes, buffer is full",data.length()); + Debug(&__plugin,DebugMild,"DSoundPlay skipped %u bytes, buffer is full",data.length()); #endif unlock(); } DSoundRec::DSoundRec(DSoundSource* owner, LPGUID device) : Thread("DirectSound Rec"), - m_owner(owner), m_device(device), m_ds(0), m_dsb(0) + m_owner(owner), m_device(device), m_ds(0), m_dsb(0), + m_buffSize(0), m_readPos(0) { } @@ -350,6 +391,14 @@ bool DSoundRec::init() fmt.wFormatTag,fmt.nChannels,fmt.nSamplesPerSec,fmt.wBitsPerSample); return false; } + DSCBCAPS caps; + caps.dwSize = sizeof(caps); + if (FAILED(hr = m_dsb->GetCaps(&caps))) { + Debug(DebugGoOn,"Could not get the DirectSoundCapture buffer capabilities, code 0x%X",hr); + return false; + } + m_buffSize = caps.dwBufferBytes; + Debug(&__plugin,DebugInfo,"DirectSoundCapture buffer size %u",m_buffSize); if (FAILED(hr = m_dsb->Start(DSCBSTART_LOOPING))) { Debug(DebugGoOn,"Could not record to the DirectSoundCapture buffer, code 0x%X",hr); return false; @@ -363,16 +412,32 @@ void DSoundRec::run() return; if (m_owner) m_owner->m_dsound = this; - Debug(DebugInfo,"DSoundRec is initialized and running"); + Debug(&__plugin,DebugInfo,"DSoundRec is initialized and running"); while (m_owner) { msleep(1,true); if (m_dsb) { - void* buf = 0; - DWORD len = 0; - if (FAILED(m_dsb->Lock(0,CHUNK_SIZE,&buf,&len,0,0,0))) + DWORD pos = 0; + if (FAILED(m_dsb->GetCurrentPosition(0,&pos))) continue; - DataBlock data(buf,len); - m_dsb->Unlock(buf,len,0,0); + if (pos < m_readPos) + pos += m_buffSize; + pos -= m_readPos; + if (pos < CHUNK_SIZE) + continue; + void* buf = 0; + void* buf2 = 0; + DWORD len = 0; + DWORD len2 = 0; + if (FAILED(m_dsb->Lock(m_readPos,CHUNK_SIZE,&buf,&len,&buf2,&len2,0))) + continue; + DataBlock data(0,len+len2); + ::memcpy(data.data(),buf,len); + if (buf2) + ::memcpy(((char*)data.data())+len,buf2,len2); + m_dsb->Unlock(buf,len,buf2,len2); + m_readPos += (len+len2); + if (m_readPos >= m_buffSize) + m_readPos -= m_buffSize; if (m_owner) m_owner->Forward(data); } @@ -381,7 +446,7 @@ void DSoundRec::run() void DSoundRec::cleanup() { - Debug(DebugInfo,"DSoundRec cleaning up"); + Debug(&__plugin,DebugInfo,"DSoundRec cleaning up"); if (m_dsb) { m_dsb->Stop(); m_dsb->Release(); @@ -429,18 +494,19 @@ void DSoundConsumer::Consume(const DataBlock &data, unsigned long timeDelta) DSoundChan::DSoundChan() : Channel(__plugin) { - Debug(DebugAll,"DSoundChan::DSoundChan() [%p]",this); + Debug(this,DebugAll,"DSoundChan::DSoundChan() [%p]",this); - setSource(new DSoundSource); - getSource()->deref(); setConsumer(new DSoundConsumer); getConsumer()->deref(); Thread::msleep(50); + setSource(new DSoundSource); + getSource()->deref(); + Thread::msleep(50); } DSoundChan::~DSoundChan() { - Debug(DebugAll,"DSoundChan::~DSoundChan() [%p]",this); + Debug(this,DebugAll,"DSoundChan::~DSoundChan() [%p]",this); } bool AttachHandler::received(Message &msg) @@ -469,23 +535,24 @@ bool AttachHandler::received(Message &msg) dd = ch->setEndpoint(); } if (!dd) { - Debug(DebugWarn,"DSound attach request with no control or data channel!"); + Debug(&__plugin,DebugWarn,"DSound attach request with no control or data channel!"); return false; } - if (src) { - DSoundSource* s = new DSoundSource; - dd->setSource(s); - s->deref(); - } - if (cons) { DSoundConsumer* c = new DSoundConsumer; dd->setConsumer(c); c->deref(); + Thread::msleep(50); + } + + if (src) { + DSoundSource* s = new DSoundSource; + dd->setSource(s); + s->deref(); + Thread::msleep(50); } - Thread::msleep(50); // Stop dispatching if we handled all requested return !more; @@ -512,7 +579,7 @@ bool SoundDriver::msgExecute(Message& msg, String& dest) if (callto.null()) { const char *targ = msg.getValue("target"); if (!targ) { - Debug(DebugWarn,"DSound outgoing call with no target!"); + Debug(&__plugin,DebugWarn,"DSound outgoing call with no target!"); return false; } callto = msg.getValue("caller"); @@ -521,7 +588,7 @@ bool SoundDriver::msgExecute(Message& msg, String& dest) m.addParam("called",targ); m.addParam("caller",callto); if (!Engine::dispatch(m)) { - Debug(DebugWarn,"DSound outgoing call but no route!"); + Debug(&__plugin,DebugWarn,"DSound outgoing call but no route!"); return false; } callto = m.retValue(); @@ -536,23 +603,13 @@ bool SoundDriver::msgExecute(Message& msg, String& dest) ds->deref(); return true; } - Debug(DebugWarn,"DSound outgoing call not accepted!"); + Debug(&__plugin,DebugWarn,"DSound outgoing call not accepted!"); ds->destruct(); return false; } return true; } -void SoundDriver::statusModule(String& str) -{ - Module::statusModule(str); -} - -void SoundDriver::statusParams(String& str) -{ - //str << "sound=" << tones.count() << ",chans=" << channels().count(); -} - SoundDriver::SoundDriver() : Driver("dsound","misc"), m_handler(0) diff --git a/modules/h323chan.cpp b/modules/h323chan.cpp index bb1eb011..c33218e6 100644 --- a/modules/h323chan.cpp +++ b/modules/h323chan.cpp @@ -1425,11 +1425,11 @@ void YateH323AudioConsumer::Consume(const DataBlock &data, unsigned long timeDel BOOL YateH323AudioConsumer::Read(void *buf, PINDEX len) { + readDelay.Delay(len/16); while (!m_exit) { Lock lock(m_mutex); if (!getConnSource()) { ::memset(buf,0,len); - readDelay.Delay(len/16); break; } if (len >= (int)m_buffer.length()) { @@ -1441,12 +1441,14 @@ BOOL YateH323AudioConsumer::Read(void *buf, PINDEX len) } if (len > 0) { ::memcpy(buf,m_buffer.data(),len); - m_buffer.assign(len+(char *)m_buffer.data(),m_buffer.length()-len); + m_buffer.cut(-len); XDebug(&hplugin,DebugAll,"Consumer pulled %d bytes from buffer [%p]",len,this); break; } - else + else { len = 0; + Thread::yield(); + } } lastReadCount = len; return (len != 0); diff --git a/windows/.cvsignore b/windows/.cvsignore index 59293ef2..aa6de15f 100644 --- a/windows/.cvsignore +++ b/windows/.cvsignore @@ -1,6 +1,7 @@ Debug Release Output +Runtimes *.plg *.aps *.opt