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);