unix pipes in Alsa driver

Rob Crittenden <[email protected]>
Newsgroups gmane.comp.emulators.winex.devel
Message-ID <[email protected]>
Here is another one. I diffed this against the current CVS and it doesn't
have the previous patch included (so you can reject one or both of these
without impacting the other).

This one adds unix pipe support to the Alsa audio driver.

rob
pipe.diff (text/plain, 4 KB)
Index: audio.c
===================================================================
RCS file: /cvsroot/winex/wine/dlls/winmm/winealsa/audio.c,v
retrieving revision 1.2
diff -u -r1.2 audio.c
--- audio.c	15 Oct 2003 02:53:13 -0000	1.2
+++ audio.c	7 Nov 2003 16:13:15 -0000
@@ -7,6 +7,9 @@
  *              2002 Marco Pietrobono
  */
 
+/* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */
+#define USE_PIPE_SYNC
+
 #include "config.h"
 
 #include <stdlib.h>
@@ -78,6 +81,36 @@
     WINE_WM_UPDATE, WINE_WM_BREAKLOOP, WINE_WM_CLOSING
 };
 
+#ifdef USE_PIPE_SYNC
+#define SIGNAL_OMR(omr) do { int x = 0; write((omr)->msg_pipe[1], &x, sizeof(x)); } while (0)
+#define CLEAR_OMR(omr) do { int x = 0; read((omr)->msg_pipe[0], &x, sizeof(x)); } while (0)  
+#define RESET_OMR(omr) do { } while (0)
+#define WAIT_OMR(omr, sleep) \
+  do { \
+    struct pollfd pfd; \
+    int sleep_for = sleep; \
+\
+    pfd.fd = (omr)->msg_pipe[0]; \
+    pfd.events = POLLIN; \
+    if( poll(&pfd, 1, sleep_for) < 0 ) \
+    { \
+      if( errno == EINTR ) \
+      { \
+        /* interrupted, sleep again for 1/4 of the time to avoid infinite loop */ \
+        sleep_for >>= 2; \
+        continue; \
+      } \
+      else ERR( "poll returned %d:%s\n", errno, strerror(errno) ); \
+    } \
+  } while (0)
+#else
+#define SIGNAL_OMR(omr) do { SetEvent((omr)->msg_event); } while (0)
+#define CLEAR_OMR(omr) do { } while (0)
+#define RESET_OMR(omr) do { ResetEvent((omr)->msg_event); } while (0)
+#define WAIT_OMR(omr, sleep) \
+  do { WaitForSingleObject((omr)->msg_event, sleep); } while (0)
+#endif
+
 typedef struct {
     enum win_wm_message 	msg;	/* message identifier */
     DWORD	                param;  /* parameter for this message */
@@ -94,7 +127,11 @@
     ALSA_MSG			messages[ALSA_RING_BUFFER_SIZE];
     int				msg_tosave;
     int				msg_toget;
-    HANDLE			msg_event;
+#ifdef USE_PIPE_SYNC
+    int                         msg_pipe[2];
+#else
+    HANDLE                      msg_event;
+#endif
     CRITICAL_SECTION		msg_crst;
 } ALSA_MSG_RING;
 
@@ -503,7 +540,15 @@
 {
     omr->msg_toget = 0;
     omr->msg_tosave = 0;
+#ifdef USE_PIPE_SYNC
+    if (pipe(omr->msg_pipe) < 0) {
+        omr->msg_pipe[0] = -1;
+        omr->msg_pipe[1] = -1;
+        ERR("could not create pipe, error=%s\n", strerror(errno));
+    }
+#else
     omr->msg_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+#endif
     memset(omr->messages, 0, sizeof(ALSA_MSG) * ALSA_RING_BUFFER_SIZE);
     InitializeCriticalSection(&omr->msg_crst);
     return 0;
@@ -515,7 +560,12 @@
  */
 static int ALSA_DestroyRingMessage(ALSA_MSG_RING* omr)
 {
+#ifdef USE_PIPE_SYNC
+    close(omr->msg_pipe[0]);
+    close(omr->msg_pipe[1]);
+#else
     CloseHandle(omr->msg_event);
+#endif
     DeleteCriticalSection(&omr->msg_crst);
     return 0;
 }
@@ -564,7 +614,7 @@
     }
     LeaveCriticalSection(&omr->msg_crst);
     /* signal a new message */
-    SetEvent(omr->msg_event);
+    SIGNAL_OMR(omr);
     if (wait)
     {
         /* wait for playback/record thread to have processed the message */
@@ -595,6 +645,7 @@
     *param = omr->messages[omr->msg_toget].param;
     *hEvent = omr->messages[omr->msg_toget].hEvent;
     omr->msg_toget = (omr->msg_toget + 1) % ALSA_RING_BUFFER_SIZE;
+    CLEAR_OMR(omr);
     LeaveCriticalSection(&omr->msg_crst);
     return 1;
 }
@@ -854,7 +905,7 @@
 
         wodNotifyClient(wwo, WOM_DONE, param, 0);
     }
-    ResetEvent(wwo->msgRing.msg_event);
+    RESET_OMR(&wwo->msgRing);
     LeaveCriticalSection(&wwo->msgRing.msg_crst);
 }
 
@@ -977,7 +1028,7 @@
          */
         dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime);
         TRACE("waiting %lums (%lu,%lu)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime);
-        WaitForSingleObject(wwo->msgRing.msg_event, dwSleepTime);
+        WAIT_OMR(&wwo->msgRing, dwSleepTime);
 	wodPlayer_ProcessMessages(wwo);
 	if (wwo->state == WINE_WS_PLAYING) {
 	    dwNextFeedTime = wodPlayer_FeedDSP(wwo);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.