[WINEOSS] MidiIn: Timer -> Thread
Christian Costa
titan.costa at wanadoo.fr
Mon Feb 23 16:16:57 CST 2004
Hi,
This patch is the same as for alsa.
Bye.
Changelog :
Replaced the timer and its callback by a thread for receiving midi in
events.
Handled DRVM_EXIT in OSS_midMessage.
Christian Costa titan.costa at wanadoo.fr
-------------- next part --------------
Index: midi.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/wineoss/midi.c,v
retrieving revision 1.37
diff -u -r1.37 midi.c
--- midi.c 5 Feb 2004 01:24:28 -0000 1.37
+++ midi.c 23 Feb 2004 21:10:39 -0000
@@ -39,6 +39,9 @@
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
#include "windef.h"
#include "winbase.h"
@@ -93,9 +96,20 @@
static int midiSeqFD = -1;
static int numOpenMidiSeq = 0;
-static UINT midiInTimerID = 0;
static int numStartedMidiIn = 0;
+static CRITICAL_SECTION crit_sect; /* protects all MidiIn buffers queues */
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+ 0, 0, &crit_sect,
+ { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+ 0, 0, { 0, (DWORD)(__FILE__ ": crit_sect") }
+};
+static CRITICAL_SECTION crit_sect = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static int end_thread;
+static HANDLE hThread;
+
/*======================================================================*
* Low level MIDI implementation *
*======================================================================*/
@@ -407,12 +421,14 @@
midi_warn = 0;
return -1;
}
+#if 0
if (fcntl(midiSeqFD, F_SETFL, O_NONBLOCK) < 0) {
WARN("can't set sequencer fd to non-blocking, errno %d (%s)\n", errno, strerror(errno));
close(midiSeqFD);
midiSeqFD = -1;
return -1;
}
+#endif
fcntl(midiSeqFD, F_SETFD, 1); /* set close on exec flag */
ioctl(midiSeqFD, SNDCTL_SEQ_RESET);
}
@@ -478,10 +494,11 @@
}
if (MidiInDev[wDevID].state & 2) { /* system exclusive */
- LPMIDIHDR lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;
+ LPMIDIHDR lpMidiHdr;
WORD sbfb = FALSE;
- if (lpMidiHdr) {
+ EnterCriticalSection(&crit_sect);
+ if ((lpMidiHdr = MidiInDev[wDevID].lpQueueHdr) != NULL) {
LPBYTE lpData = lpMidiHdr->lpData;
lpData[lpMidiHdr->dwBytesRecorded++] = value;
@@ -502,6 +519,7 @@
WARN("Couldn't notify client\n");
}
}
+ LeaveCriticalSection(&crit_sect);
return;
}
@@ -571,45 +589,62 @@
}
}
-static VOID WINAPI midTimeCallback(HWND hwnd, UINT msg, UINT id, DWORD dwTime)
+static DWORD WINAPI midRecThread(LPVOID arg)
{
unsigned char buffer[256];
int len, idx;
-
- TRACE("(%p, %d, %d, %lu)\n", hwnd, msg, id, dwTime);
+ DWORD dwTime;
+ struct pollfd pfd;
- len = read(midiSeqFD, buffer, sizeof(buffer));
+ TRACE("Thread startup\n");
- if (len < 0) return;
- if ((len % 4) != 0) {
- WARN("Bad length %d, errno %d (%s)\n", len, errno, strerror(errno));
- return;
- }
+ pfd.fd = midiSeqFD;
+ pfd.fd = POLLIN;
+
+ while(!end_thread) {
+ TRACE("Thread loop\n");
- for (idx = 0; idx < len; ) {
- if (buffer[idx] & 0x80) {
- TRACE(
- "Reading<8> %02x %02x %02x %02x %02x %02x %02x %02x\n",
- buffer[idx + 0], buffer[idx + 1],
- buffer[idx + 2], buffer[idx + 3],
- buffer[idx + 4], buffer[idx + 5],
- buffer[idx + 6], buffer[idx + 7]);
- idx += 8;
- } else {
- switch (buffer[idx + 0]) {
- case SEQ_WAIT:
- case SEQ_ECHO:
- break;
- case SEQ_MIDIPUTC:
- midReceiveChar(buffer[idx + 2], buffer[idx + 1], dwTime);
- break;
- default:
- TRACE("Unsupported event %d\n", buffer[idx + 0]);
- break;
+ /* Check if a event is present */
+ if (poll(&pfd, 1, 250) <= 0)
+ continue;
+
+ len = read(midiSeqFD, buffer, sizeof(buffer));
+ TRACE("Reveived %d bytes\n", len);
+
+ if (len < 0) continue;
+ if ((len % 4) != 0) {
+ WARN("Bad length %d, errno %d (%s)\n", len, errno, strerror(errno));
+ continue;
+ }
+
+ dwTime = GetTickCount();
+
+ for (idx = 0; idx < len; ) {
+ if (buffer[idx] & 0x80) {
+ TRACE(
+ "Reading<8> %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buffer[idx + 0], buffer[idx + 1],
+ buffer[idx + 2], buffer[idx + 3],
+ buffer[idx + 4], buffer[idx + 5],
+ buffer[idx + 6], buffer[idx + 7]);
+ idx += 8;
+ } else {
+ switch (buffer[idx + 0]) {
+ case SEQ_WAIT:
+ case SEQ_ECHO:
+ break;
+ case SEQ_MIDIPUTC:
+ midReceiveChar(buffer[idx + 2], buffer[idx + 1], dwTime);
+ break;
+ default:
+ TRACE("Unsupported event %d\n", buffer[idx + 0]);
+ break;
+ }
+ idx += 4;
}
- idx += 4;
}
}
+ return 0;
}
/**************************************************************************
@@ -668,14 +703,15 @@
}
if (numStartedMidiIn++ == 0) {
- midiInTimerID = SetTimer(0, 0, 250, midTimeCallback);
- if (!midiInTimerID) {
+ end_thread = 0;
+ hThread = CreateThread(NULL, 0, midRecThread, NULL, 0, NULL);
+ if (!hThread) {
numStartedMidiIn = 0;
- WARN("Couldn't start timer for midi-in\n");
+ WARN("Couldn't create thread for midi-in\n");
midiCloseSeq();
return MMSYSERR_ERROR;
}
- TRACE("Starting timer (%u) for midi-in\n", midiInTimerID);
+ TRACE("Created thread for midi-in\n");
}
MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
@@ -721,11 +757,13 @@
return MMSYSERR_ERROR;
}
if (--numStartedMidiIn == 0) {
- TRACE("Stopping timer for midi-in\n");
- if (!KillTimer(0, midiInTimerID)) {
- WARN("Couldn't stop timer for midi-in\n");
+ TRACE("Stopping thread for midi-in\n");
+ end_thread = 1;
+ if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) {
+ WARN("Thread end not signaled, force termination\n");
+ TerminateThread(hThread, 0);
}
- midiInTimerID = 0;
+ TRACE("Stopped thread for midi-in\n");
}
midiCloseSeq();
@@ -754,6 +792,7 @@
if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;
+ EnterCriticalSection(&crit_sect);
if (MidiInDev[wDevID].lpQueueHdr == 0) {
MidiInDev[wDevID].lpQueueHdr = lpMidiHdr;
} else {
@@ -764,6 +803,8 @@
ptr = (LPMIDIHDR)ptr->lpNext);
ptr->lpNext = (struct midihdr_tag*)lpMidiHdr;
}
+ LeaveCriticalSection(&crit_sect);
+
return MMSYSERR_NOERROR;
}
@@ -820,6 +861,7 @@
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
+ EnterCriticalSection(&crit_sect);
while (MidiInDev[wDevID].lpQueueHdr) {
MidiInDev[wDevID].lpQueueHdr->dwFlags &= ~MHDR_INQUEUE;
MidiInDev[wDevID].lpQueueHdr->dwFlags |= MHDR_DONE;
@@ -830,6 +872,7 @@
}
MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)MidiInDev[wDevID].lpQueueHdr->lpNext;
}
+ LeaveCriticalSection(&crit_sect);
return MMSYSERR_NOERROR;
}
@@ -1597,6 +1640,7 @@
switch (wMsg) {
#ifdef HAVE_OSS_MIDI
case DRVM_INIT:
+ case DRVM_EXIT:
case DRVM_ENABLE:
case DRVM_DISABLE:
/* FIXME: Pretend this is supported */
More information about the wine-patches
mailing list