On Thu, 2008-04-17 at 17:03 -0400, Eric Hyche wrote:
> Rusty,
> 
> Here are my comments. Greg may want to comment further.
> 
> @@ -142,6 +141,7 @@
>       CreateInstanceCCF(CLSID_IHXMutex, (void**)&m_mtxWriteListPlayStateLock, 
> m_pContext);
>       CreateInstanceCCF(CLSID_IHXMutex, (void**)&m_mtxDeviceStateLock, 
> m_pContext);
>       CreateInstanceCCF(CLSID_IHXThread, (void**)&m_audioThread, m_pContext);
> +     HXEvent::MakeEvent(m_pAvailableDataEvent, "Available Audio Data", 
> FALSE);
> 
> You should create an IHXEvent just like the above
> code creates IHXThread or IHXMutex:
> 
> +     CreateInstanceCCF(CLSID_IHXEvent, (void**) &m_pAvailableDataEvent, 
> m_pContext);
> 
> and of course, m_pAvailableDataEvent should be an IHXEvent rather
> than an HXEvent:
> 
> +    IHXEvent*   m_pAvailableDataEvent;
> 
> and you should release it rather than delete it:
> 
> +    HX_RELEASE( m_pAvailableDataEvent );
> 

Ok, I started using IHXEvent, and since I wanted a infinite wait I am
calling:

m_pAvailableDataEvent->Wait(ALLFS);

... which I am just guessing (from looking at other code) is cool, but
ALLFS isn't translating to anything sensible in my brain, so let me know
if that is not something I behavior I can count on.

> 
> What would happen if the audio device was full and we
> still had data to write? It seems like we would just
> spin in a tight loop until the audio device had space
> for us to write. Not really a failure case, but
> seems like we should wait in that case as well.
> 
> Eric
> 

On an ALSA system _WriteBytes will eventually come down to an
snd_pcm_writei(), and since we are setting the audio device to blocking
in _OpenAudio(), then snd_pcm_writei() will block until the device is
able to consume all the bits.  

http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gf13067c0ebde29118ca05af76e5b17a9

Can I count on other UNIX systems having a blocking write behavior?  I
don't know.  I think esd (esound) blocks on write, but I'm having a hard
time finding any API documentation to verify that.

hmm... looks like Solaris is opening the device node using O_NONBLOCK.

Ok, here is a version of the patch that will do a microsleep if there is
data to write, but only if HELIX_FEATURE_ALSA is defined.

The block of code in question now looks more like...

if(bReadyToExit == FALSE && 
   (that->m_pWriteList->GetCount() == 0 || 
    that->m_wState == RA_AOS_OPEN_PAUSED))
{
     that->m_pAvailableDataEvent->Wait(ALLFS);
}
else
{
#if !defined(HELIX_FEATURE_ALSA)
    microsleep(that->m_ulSleepTime/4);
#endif
}



Index: platform/unix/audUnix.cpp
===================================================================
RCS file: /cvsroot/audio/device/platform/unix/audUnix.cpp,v
retrieving revision 1.12
diff -u -r1.12 audUnix.cpp
--- platform/unix/audUnix.cpp	6 Jul 2007 20:21:16 -0000	1.12
+++ platform/unix/audUnix.cpp	17 Apr 2008 23:25:14 -0000
@@ -73,7 +73,8 @@
 #include "hxprefs.h"
 #endif 
 
-
+#include "hxtlogutil.h"
+#include "ihxtlogsystem.h"
 
 //-1 is usually considered to be no file descriptor.
 const int CAudioOutUNIX::NO_FILE_DESCRIPTOR = -1;
@@ -102,6 +103,7 @@
     m_audioThread(NULL),
     m_bUserWantsThreads(TRUE),
     m_ulSleepTime(0),
+    m_pAvailableDataEvent(NULL),
 #endif
     m_pRollbackBuffer(NULL)
 {
@@ -114,7 +116,6 @@
     //Allco our write buffer list. Want to throw from here? You will, like
     //it or not.
     m_pWriteList = new CHXSimpleList();
-    
 }
 
 void CAudioOutUNIX::_initAfterContext()
@@ -142,6 +143,7 @@
 	CreateInstanceCCF(CLSID_IHXMutex, (void**)&m_mtxWriteListPlayStateLock, m_pContext);
 	CreateInstanceCCF(CLSID_IHXMutex, (void**)&m_mtxDeviceStateLock, m_pContext);
 	CreateInstanceCCF(CLSID_IHXThread, (void**)&m_audioThread, m_pContext);
+	CreateInstanceCCF(CLSID_IHXEvent, (void**)&m_pAvailableDataEvent, m_pContext);
     }
 #endif    
 
@@ -194,6 +196,7 @@
         HX_RELEASE( m_mtxWriteListPlayStateLock );
         HX_RELEASE( m_mtxDeviceStateLock );
         HX_RELEASE( m_audioThread );
+        HX_RELEASE( m_pAvailableDataEvent );
     }
 #endif    
 
@@ -201,6 +204,14 @@
 
 UINT16 CAudioOutUNIX::_Imp_GetVolume()
 {
+#if defined(_THREADED_AUDIO) && defined(_UNIX_THREADS_SUPPORTED)
+                //We want to sleep as a function of device buffer size.
+                //If we have a small m_ulDeviceBufferSize we can only 
+                //afford to sleep just a little while.
+                HX_ASSERT( m_ulDeviceBufferSize != 0 );
+                m_ulSleepTime = (((float)m_ulDeviceBufferSize/(float)m_uSampFrameSize)/
+                                 (float)m_unSampleRate) * 1000 / (float)m_unNumChannels;
+#endif
     if (!m_bMixerPresent)
         _OpenMixer();
 
@@ -271,14 +282,6 @@
             }
             else
             {
-#if defined(_THREADED_AUDIO) && defined(_UNIX_THREADS_SUPPORTED)
-                //We want to sleep as a function of device buffer size.
-                //If we have a small m_ulDeviceBufferSize we can only 
-                //afford to sleep just a little while.
-                HX_ASSERT( m_ulDeviceBufferSize != 0 );
-                m_ulSleepTime = (((float)m_ulDeviceBufferSize/(float)m_uSampFrameSize)/
-                                 (float)m_unSampleRate) * 1000 / (float)m_unNumChannels;
-#endif
                 if (!m_bMixerPresent)
                     _OpenMixer();   
 
@@ -353,6 +356,8 @@
     //Wait for it to do so and clean up.
     if( m_bUserWantsThreads )
     {
+        HXLOGL4 (HXLOG_ADEV, "CAudioUnixOUT::_Imp_Close signaling event..."); 
+        m_pAvailableDataEvent->SignalEvent();
         m_audioThread->Exit(0);
     }
     
@@ -778,8 +783,18 @@
         that->m_mtxDeviceStateLock->Unlock();
         that->m_mtxWriteListPlayStateLock->Unlock();
 
-        //OK, sleep the amount of time it takes to play 1/4 of the device's buffer.
-        microsleep(that->m_ulSleepTime/4); 
+        if(bReadyToExit == FALSE && (that->m_pWriteList->GetCount() == 0 || that->m_wState == RA_AOS_OPEN_PAUSED))
+	{
+	    HXLOGL4 (HXLOG_ADEV, "CAudioUnixOUT::AudioThread() waiting for audio data..."); 
+	    that->m_pAvailableDataEvent->Wait(ALLFS);
+	} 
+        else
+	{
+#if !defined(HELIX_FEATURE_ALSA)
+	    // OK, sleep the amount of time it takes to play 1/4 of the device's buffer.
+	    microsleep(that->m_ulSleepTime/4); 
+#endif
+	}
     }
 
     //Signal the parent thread that we are done.
@@ -833,6 +848,7 @@
     }
 
     UNLOCK(m_mtxWriteListPlayStateLock);
+    HXLOGL4 (HXLOG_ADEV, "CAudioUnixOUT::_PushBits() writing %i bits", (int)ulBufLen);
     _WriteBytes(pData, ulBufLen, lCount);
     LOCK(m_mtxWriteListPlayStateLock);
 
@@ -995,6 +1011,8 @@
     //grab the data and write it to the device.
     if( m_bUserWantsThreads )
     {
+        HXLOGL4 (HXLOG_ADEV, "CAudioUnixOUT::_Imp_Write signaling event..."); 
+        m_pAvailableDataEvent->SignalEvent();
         return RA_AOE_NOERR;
     }
 #endif    
Index: pub/platform/unix/audUnix.h
===================================================================
RCS file: /cvsroot/audio/device/pub/platform/unix/audUnix.h,v
retrieving revision 1.8
diff -u -r1.8 audUnix.h
--- pub/platform/unix/audUnix.h	6 Jul 2007 20:21:19 -0000	1.8
+++ pub/platform/unix/audUnix.h	17 Apr 2008 23:25:14 -0000
@@ -289,6 +289,7 @@
     IHXThread*	m_audioThread;
     HXBOOL      m_bUserWantsThreads;
     ULONG32	m_ulSleepTime;
+    IHXEvent*	m_pAvailableDataEvent;
 #endif    
     
   private:
_______________________________________________
Audio-dev mailing list
[email protected]
http://lists.helixcommunity.org/mailman/listinfo/audio-dev

Reply via email to