Commit ffccadd3 authored by Alexandre Bique's avatar Alexandre Bique Committed by Alexandre Julliard

winealsa.drv: midiSeq must be protected by a critical section.

parent 40c8d6aa
...@@ -95,6 +95,14 @@ static int MODM_NumDevs = 0; ...@@ -95,6 +95,14 @@ static int MODM_NumDevs = 0;
/* this is the total number of MIDI out devices found */ /* this is the total number of MIDI out devices found */
static int MIDM_NumDevs = 0; static int MIDM_NumDevs = 0;
static CRITICAL_SECTION midiSeqLock;
static CRITICAL_SECTION_DEBUG midiSeqLockDebug =
{
0, 0, &midiSeqLock,
{ &midiSeqLockDebug.ProcessLocksList, &midiSeqLockDebug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": midiSeqLock") }
};
static CRITICAL_SECTION midiSeqLock = { &midiSeqLockDebug, -1, 0, 0, 0, 0 };
static snd_seq_t* midiSeq = NULL; static snd_seq_t* midiSeq = NULL;
static int numOpenMidiSeq = 0; static int numOpenMidiSeq = 0;
static int numStartedMidiIn = 0; static int numStartedMidiIn = 0;
...@@ -222,6 +230,7 @@ static BOOL midi_warn = TRUE; ...@@ -222,6 +230,7 @@ static BOOL midi_warn = TRUE;
*/ */
static int midiOpenSeq(BOOL create_client) static int midiOpenSeq(BOOL create_client)
{ {
EnterCriticalSection(&midiSeqLock);
if (numOpenMidiSeq == 0) { if (numOpenMidiSeq == 0) {
if (snd_seq_open(&midiSeq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) if (snd_seq_open(&midiSeq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0)
{ {
...@@ -230,6 +239,7 @@ static int midiOpenSeq(BOOL create_client) ...@@ -230,6 +239,7 @@ static int midiOpenSeq(BOOL create_client)
WARN("Error opening ALSA sequencer.\n"); WARN("Error opening ALSA sequencer.\n");
} }
midi_warn = FALSE; midi_warn = FALSE;
LeaveCriticalSection(&midiSeqLock);
return -1; return -1;
} }
...@@ -262,6 +272,7 @@ static int midiOpenSeq(BOOL create_client) ...@@ -262,6 +272,7 @@ static int midiOpenSeq(BOOL create_client)
} }
} }
numOpenMidiSeq++; numOpenMidiSeq++;
LeaveCriticalSection(&midiSeqLock);
return 0; return 0;
} }
...@@ -270,12 +281,14 @@ static int midiOpenSeq(BOOL create_client) ...@@ -270,12 +281,14 @@ static int midiOpenSeq(BOOL create_client)
*/ */
static int midiCloseSeq(void) static int midiCloseSeq(void)
{ {
EnterCriticalSection(&midiSeqLock);
if (--numOpenMidiSeq == 0) { if (--numOpenMidiSeq == 0) {
snd_seq_delete_simple_port(midiSeq, port_out); snd_seq_delete_simple_port(midiSeq, port_out);
snd_seq_delete_simple_port(midiSeq, port_in); snd_seq_delete_simple_port(midiSeq, port_in);
snd_seq_close(midiSeq); snd_seq_close(midiSeq);
midiSeq = NULL; midiSeq = NULL;
} }
LeaveCriticalSection(&midiSeqLock);
return 0; return 0;
} }
...@@ -283,14 +296,17 @@ static DWORD WINAPI midRecThread(LPVOID arg) ...@@ -283,14 +296,17 @@ static DWORD WINAPI midRecThread(LPVOID arg)
{ {
int npfd; int npfd;
struct pollfd *pfd; struct pollfd *pfd;
int ret;
TRACE("Thread startup\n"); TRACE("Thread startup\n");
while(!end_thread) { while(!end_thread) {
TRACE("Thread loop\n"); TRACE("Thread loop\n");
EnterCriticalSection(&midiSeqLock);
npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN); npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN);
pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd)); pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd));
snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN); snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN);
LeaveCriticalSection(&midiSeqLock);
/* Check if an event is present */ /* Check if an event is present */
if (poll(pfd, npfd, 250) <= 0) { if (poll(pfd, npfd, 250) <= 0) {
...@@ -309,7 +325,9 @@ static DWORD WINAPI midRecThread(LPVOID arg) ...@@ -309,7 +325,9 @@ static DWORD WINAPI midRecThread(LPVOID arg)
do { do {
WORD wDevID; WORD wDevID;
snd_seq_event_t* ev; snd_seq_event_t* ev;
EnterCriticalSection(&midiSeqLock);
snd_seq_event_input(midiSeq, &ev); snd_seq_event_input(midiSeq, &ev);
LeaveCriticalSection(&midiSeqLock);
/* Find the target device */ /* Find the target device */
for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++) for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++)
if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) ) if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) )
...@@ -415,7 +433,11 @@ static DWORD WINAPI midRecThread(LPVOID arg) ...@@ -415,7 +433,11 @@ static DWORD WINAPI midRecThread(LPVOID arg)
} }
} }
snd_seq_free_event(ev); snd_seq_free_event(ev);
} while(snd_seq_event_input_pending(midiSeq, 0) > 0);
EnterCriticalSection(&midiSeqLock);
ret = snd_seq_event_input_pending(midiSeq, 0);
LeaveCriticalSection(&midiSeqLock);
} while(ret > 0);
HeapFree(GetProcessHeap(), 0, pfd); HeapFree(GetProcessHeap(), 0, pfd);
} }
...@@ -443,6 +465,8 @@ static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPSW lpCaps, DWORD dwSize) ...@@ -443,6 +465,8 @@ static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPSW lpCaps, DWORD dwSize)
*/ */
static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
{ {
int ret = 0;
TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags); TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
if (lpDesc == NULL) { if (lpDesc == NULL) {
...@@ -489,7 +513,11 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) ...@@ -489,7 +513,11 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
MidiInDev[wDevID].startTime = 0; MidiInDev[wDevID].startTime = 0;
/* Connect our app port to the device port */ /* Connect our app port to the device port */
if (snd_seq_connect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port) < 0) EnterCriticalSection(&midiSeqLock);
ret = snd_seq_connect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client,
MidiInDev[wDevID].addr.port);
LeaveCriticalSection(&midiSeqLock);
if (ret < 0)
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
TRACE("Input port :%d connected %d:%d\n",port_in,MidiInDev[wDevID].addr.client,MidiInDev[wDevID].addr.port); TRACE("Input port :%d connected %d:%d\n",port_in,MidiInDev[wDevID].addr.client,MidiInDev[wDevID].addr.port);
...@@ -546,7 +574,9 @@ static DWORD midClose(WORD wDevID) ...@@ -546,7 +574,9 @@ static DWORD midClose(WORD wDevID)
TRACE("Stopped thread for midi-in\n"); TRACE("Stopped thread for midi-in\n");
} }
EnterCriticalSection(&midiSeqLock);
snd_seq_disconnect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port); snd_seq_disconnect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port);
LeaveCriticalSection(&midiSeqLock);
midiCloseSeq(); midiCloseSeq();
MidiInDev[wDevID].bufsize = 0; MidiInDev[wDevID].bufsize = 0;
...@@ -704,6 +734,8 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize) ...@@ -704,6 +734,8 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
*/ */
static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
{ {
int ret;
TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags); TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
if (lpDesc == NULL) { if (lpDesc == NULL) {
WARN("Invalid Parameter !\n"); WARN("Invalid Parameter !\n");
...@@ -750,7 +782,11 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) ...@@ -750,7 +782,11 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
MidiOutDev[wDevID].midiDesc = *lpDesc; MidiOutDev[wDevID].midiDesc = *lpDesc;
/* Connect our app port to the device port */ /* Connect our app port to the device port */
if (snd_seq_connect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port) < 0) EnterCriticalSection(&midiSeqLock);
ret = snd_seq_connect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client,
MidiOutDev[wDevID].addr.port);
LeaveCriticalSection(&midiSeqLock);
if (ret < 0)
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
TRACE("Output port :%d connected %d:%d\n",port_out,MidiOutDev[wDevID].addr.client,MidiOutDev[wDevID].addr.port); TRACE("Output port :%d connected %d:%d\n",port_out,MidiOutDev[wDevID].addr.client,MidiOutDev[wDevID].addr.port);
...@@ -785,7 +821,9 @@ static DWORD modClose(WORD wDevID) ...@@ -785,7 +821,9 @@ static DWORD modClose(WORD wDevID)
case MOD_FMSYNTH: case MOD_FMSYNTH:
case MOD_MIDIPORT: case MOD_MIDIPORT:
case MOD_SYNTH: case MOD_SYNTH:
EnterCriticalSection(&midiSeqLock);
snd_seq_disconnect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); snd_seq_disconnect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
LeaveCriticalSection(&midiSeqLock);
midiCloseSeq(); midiCloseSeq();
break; break;
default: default:
...@@ -904,8 +942,11 @@ static DWORD modData(WORD wDevID, DWORD dwParam) ...@@ -904,8 +942,11 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
} }
break; break;
} }
if (handled) if (handled) {
EnterCriticalSection(&midiSeqLock);
snd_seq_event_output_direct(midiSeq, &event); snd_seq_event_output_direct(midiSeq, &event);
LeaveCriticalSection(&midiSeqLock);
}
} }
break; break;
default: default:
...@@ -994,7 +1035,9 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize) ...@@ -994,7 +1035,9 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
snd_seq_ev_set_dest(&event, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); snd_seq_ev_set_dest(&event, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
TRACE("destination %d:%d\n", MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); TRACE("destination %d:%d\n", MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData); snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData);
EnterCriticalSection(&midiSeqLock);
snd_seq_event_output_direct(midiSeq, &event); snd_seq_event_output_direct(midiSeq, &event);
LeaveCriticalSection(&midiSeqLock);
HeapFree(GetProcessHeap(), 0, lpNewData); HeapFree(GetProcessHeap(), 0, lpNewData);
break; break;
default: default:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment