Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/winealsa.drv/Makefile.in | 2 +- dlls/winealsa.drv/alsa.c | 4 - dlls/winealsa.drv/alsamidi.c | 231 ++++++++++++++++++++++++--- dlls/winealsa.drv/midi.c | 287 ---------------------------------- dlls/winealsa.drv/unixlib.h | 33 ---- 5 files changed, 206 insertions(+), 351 deletions(-)
diff --git a/dlls/winealsa.drv/Makefile.in b/dlls/winealsa.drv/Makefile.in index 41be57d8b83..2113594fbe3 100644 --- a/dlls/winealsa.drv/Makefile.in +++ b/dlls/winealsa.drv/Makefile.in @@ -3,7 +3,7 @@ MODULE = winealsa.drv UNIXLIB = winealsa.so IMPORTS = uuid ole32 advapi32 DELAYIMPORTS = winmm -EXTRALIBS = $(ALSA_LIBS) +EXTRALIBS = $(ALSA_LIBS) $(PTHREAD_LIBS)
EXTRADLLFLAGS = -mcygwin
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index b18588ab1c0..e068f6608f3 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -2449,8 +2449,4 @@ unixlib_entry_t __wine_unix_call_funcs[] = midi_out_message, midi_in_message, midi_notify_wait, - - midi_seq_lock, /* temporary */ - midi_seq_open, - midi_handle_event, }; diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c index 1633268b533..8ec646281d2 100644 --- a/dlls/winealsa.drv/alsamidi.c +++ b/dlls/winealsa.drv/alsamidi.c @@ -60,6 +60,19 @@ struct midi_dest int port_out; };
+struct midi_src +{ + int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */ + MIDIOPENDESC midiDesc; + WORD wFlags; + MIDIHDR *lpQueueHdr; + UINT startTime; + MIDIINCAPSW caps; + snd_seq_t *seq; + snd_seq_addr_t addr; + int port_in; +}; + static pthread_mutex_t seq_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t in_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -70,6 +83,10 @@ static snd_seq_t *midi_seq; static unsigned int seq_refs; static int port_in = -1;
+static unsigned int num_midi_in_started; +static int rec_cancel_pipe[2]; +static pthread_t rec_thread_id; + static pthread_mutex_t notify_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t notify_cond = PTHREAD_COND_INITIALIZER; static BOOL notify_quit; @@ -87,14 +104,6 @@ static void seq_unlock(void) pthread_mutex_unlock(&seq_mutex); }
-NTSTATUS midi_seq_lock(void *args) -{ - if (args) seq_lock(); - else seq_unlock(); - - return STATUS_SUCCESS; -} - static void in_buffer_lock(void) { pthread_mutex_lock(&in_buffer_mutex); @@ -233,18 +242,6 @@ static void seq_close(void) seq_unlock(); }
-NTSTATUS midi_seq_open(void *args) -{ - struct midi_seq_open_params *params = args; - - if (!params->close) - params->seq = seq_open(params->port_in); - else - seq_close(); - - return STATUS_SUCCESS; -} - static int alsa_to_win_device_type(unsigned int type) { /* MOD_MIDIPORT output port @@ -458,8 +455,6 @@ NTSTATUS midi_init(void *args) free( pinfo );
*params->err = NOERROR; - params->num_srcs = num_srcs; - params->srcs = srcs;
TRACE("End\n");
@@ -1033,9 +1028,8 @@ static void handle_regular_event(struct midi_src *src, snd_seq_event_t *ev) } }
-NTSTATUS midi_handle_event(void *args) +static void midi_handle_event(snd_seq_event_t *ev) { - snd_seq_event_t *ev = args; struct midi_src *src;
/* Find the target device */ @@ -1043,14 +1037,193 @@ NTSTATUS midi_handle_event(void *args) if ((ev->source.client == src->addr.client) && (ev->source.port == src->addr.port)) break; if ((src == srcs + num_srcs) || (src->state != 1)) - return STATUS_SUCCESS; + return;
if (ev->type == SND_SEQ_EVENT_SYSEX) handle_sysex_event(src, ev->data.ext.ptr, ev->data.ext.len); else handle_regular_event(src, ev); +}
- return STATUS_SUCCESS; +static void *rec_thread_proc(void *arg) +{ + snd_seq_t *midi_seq = (snd_seq_t *)arg; + int num_fds; + struct pollfd *pollfd; + int ret; + + /* Add on one for the read end of the cancel pipe */ + num_fds = snd_seq_poll_descriptors_count(midi_seq, POLLIN) + 1; + pollfd = malloc(num_fds * sizeof(struct pollfd)); + + while(1) + { + pollfd[0].fd = rec_cancel_pipe[0]; + pollfd[0].events = POLLIN; + + seq_lock(); + snd_seq_poll_descriptors(midi_seq, pollfd + 1, num_fds - 1, POLLIN); + seq_unlock(); + + /* Check if an event is present */ + if (poll(pollfd, num_fds, -1) <= 0) + continue; + + if (pollfd[0].revents & POLLIN) /* cancelled */ + break; + + do + { + snd_seq_event_t *ev; + + seq_lock(); + snd_seq_event_input(midi_seq, &ev); + seq_unlock(); + + if (ev) + { + midi_handle_event(ev); + snd_seq_free_event(ev); + } + + seq_lock(); + ret = snd_seq_event_input_pending(midi_seq, 0); + seq_unlock(); + } while(ret > 0); + } + + free(pollfd); + return 0; +} + +static UINT midi_in_open(WORD dev_id, MIDIOPENDESC *desc, UINT flags, struct notify_context *notify) +{ + struct midi_src *src; + int ret = 0, port_in; + snd_seq_t *midi_seq; + + TRACE("(%04X, %p, %08X);\n", dev_id, desc, flags); + + if (!desc) + { + WARN("Invalid Parameter !\n"); + return MMSYSERR_INVALPARAM; + } + + /* FIXME: check that contents of desc are correct */ + + if (dev_id >= num_srcs) + { + WARN("dev_id too large (%u) !\n", dev_id); + return MMSYSERR_BADDEVICEID; + } + src = srcs + dev_id; + + if (src->state == -1) + { + WARN("device disabled\n"); + return MIDIERR_NODEVICE; + } + if (src->midiDesc.hMidi) + { + WARN("device already open !\n"); + return MMSYSERR_ALLOCATED; + } + if (flags & MIDI_IO_STATUS) + { + WARN("No support for MIDI_IO_STATUS in flags yet, ignoring it\n"); + flags &= ~MIDI_IO_STATUS; + } + if (flags & ~CALLBACK_TYPEMASK) + { + FIXME("Bad flags %08X\n", flags); + return MMSYSERR_INVALFLAG; + } + + if (!(midi_seq = seq_open(&port_in))) + return MMSYSERR_ERROR; + + src->wFlags = HIWORD(flags & CALLBACK_TYPEMASK); + + src->lpQueueHdr = NULL; + src->midiDesc = *desc; + src->state = 0; + src->startTime = 0; + src->seq = midi_seq; + src->port_in = port_in; + + /* Connect our app port to the device port */ + seq_lock(); + ret = snd_seq_connect_from(midi_seq, port_in, src->addr.client, src->addr.port); + seq_unlock(); + if (ret < 0) + return MMSYSERR_NOTENABLED; + + TRACE("Input port :%d connected %d:%d\n", port_in, src->addr.client, src->addr.port); + + if (num_midi_in_started++ == 0) + { + pipe(rec_cancel_pipe); + if (pthread_create(&rec_thread_id, NULL, rec_thread_proc, midi_seq)) + { + close(rec_cancel_pipe[0]); + close(rec_cancel_pipe[1]); + num_midi_in_started = 0; + WARN("Couldn't create thread for midi-in\n"); + seq_close(); + return MMSYSERR_ERROR; + } + } + + set_in_notify(notify, src, dev_id, MIM_OPEN, 0, 0); + return MMSYSERR_NOERROR; +} + +static UINT midi_in_close(WORD dev_id, struct notify_context *notify) +{ + struct midi_src *src; + + TRACE("(%04X);\n", dev_id); + + if (dev_id >= num_srcs) + { + WARN("dev_id too big (%u) !\n", dev_id); + return MMSYSERR_BADDEVICEID; + } + src = srcs + dev_id; + if (!src->midiDesc.hMidi) + { + WARN("device not opened !\n"); + return MMSYSERR_ERROR; + } + if (src->lpQueueHdr) + return MIDIERR_STILLPLAYING; + + if (src->seq == NULL) + { + WARN("ooops !\n"); + return MMSYSERR_ERROR; + } + if (--num_midi_in_started == 0) + { + TRACE("Stopping thread for midi-in\n"); + write(rec_cancel_pipe[1], "x", 1); + pthread_join(rec_thread_id, NULL); + close(rec_cancel_pipe[0]); + close(rec_cancel_pipe[1]); + TRACE("Stopped thread for midi-in\n"); + } + + seq_lock(); + snd_seq_disconnect_from(src->seq, src->port_in, src->addr.client, src->addr.port); + seq_unlock(); + seq_close(); + + set_in_notify(notify, src, dev_id, MIM_CLOSE, 0, 0); + src->midiDesc.hMidi = 0; + src->seq = NULL; + + return MMSYSERR_NOERROR; }
static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size) @@ -1257,6 +1430,12 @@ NTSTATUS midi_in_message(void *args) /* FIXME: Pretend this is supported */ *params->err = MMSYSERR_NOERROR; break; + case MIDM_OPEN: + *params->err = midi_in_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify); + break; + case MIDM_CLOSE: + *params->err = midi_in_close(params->dev_id, params->notify); + break; case MIDM_ADDBUFFER: *params->err = midi_in_add_buffer(params->dev_id, (MIDIHDR *)params->param_1, params->param_2); break; diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c index 327d4b7b200..b768517e655 100644 --- a/dlls/winealsa.drv/midi.c +++ b/dlls/winealsa.drv/midi.c @@ -47,26 +47,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(midi);
-static WINE_MIDIIN *MidiInDev; - -/* this is the total number of MIDI out devices found */ -static int MIDM_NumDevs = 0; - -static int numStartedMidiIn = 0; - -static int rec_cancel_pipe[2]; -static HANDLE hThread; - -static void seq_lock(void) -{ - ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)1); -} - -static void seq_unlock(void) -{ - ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)0); -} - static void notify_client(struct notify_context *notify) { TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n", notify->dev_id, notify->msg, notify->param_1, notify->param_2); @@ -75,264 +55,6 @@ static void notify_client(struct notify_context *notify) notify->instance, notify->param_1, notify->param_2); }
-/*======================================================================* - * Low level MIDI implementation * - *======================================================================*/ - -#if 0 /* Debug Purpose */ -static void error_handler(const char* file, int line, const char* function, int err, const char* fmt, ...) -{ - va_list arg; - if (err == ENOENT) - return; - va_start(arg, fmt); - fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); - vfprintf(stderr, fmt, arg); - if (err) - fprintf(stderr, ": %s", snd_strerror(err)); - putc('\n', stderr); - va_end(arg); -} -#endif - -/************************************************************************** - * MIDI_NotifyClient [internal] - */ -static void MIDI_NotifyClient(UINT wDevID, WORD wMsg, - DWORD_PTR dwParam1, DWORD_PTR dwParam2) -{ - DWORD_PTR dwCallBack; - UINT uFlags; - HANDLE hDev; - DWORD_PTR dwInstance; - - TRACE("wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n", - wDevID, wMsg, dwParam1, dwParam2); - - switch (wMsg) { - case MIM_OPEN: - case MIM_CLOSE: - if (wDevID > MIDM_NumDevs) return; - - dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback; - uFlags = MidiInDev[wDevID].wFlags; - hDev = MidiInDev[wDevID].midiDesc.hMidi; - dwInstance = MidiInDev[wDevID].midiDesc.dwInstance; - break; - default: - ERR("Unsupported MSW-MIDI message %u\n", wMsg); - return; - } - - DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2); -} - -/************************************************************************** - * midiOpenSeq [internal] - */ -static snd_seq_t *midiOpenSeq(int *port_in_ret) -{ - struct midi_seq_open_params params; - - params.port_in = port_in_ret; - params.close = 0; - ALSA_CALL(midi_seq_open, ¶ms); - - return params.seq; -} - -/************************************************************************** - * midiCloseSeq [internal] - */ -static int midiCloseSeq(void) -{ - struct midi_seq_open_params params; - - params.port_in = NULL; - params.close = 1; - ALSA_CALL(midi_seq_open, ¶ms); - - return 0; -} - -static DWORD WINAPI midRecThread(void *arg) -{ - snd_seq_t *midi_seq = arg; - int num_fds; - struct pollfd *pollfd; - int ret; - - /* Add on one for the read end of the cancel pipe */ - num_fds = snd_seq_poll_descriptors_count(midi_seq, POLLIN) + 1; - pollfd = malloc(num_fds * sizeof(struct pollfd)); - - while(1) { - pollfd[0].fd = rec_cancel_pipe[0]; - pollfd[0].events = POLLIN; - - seq_lock(); - snd_seq_poll_descriptors(midi_seq, pollfd + 1, num_fds - 1, POLLIN); - seq_unlock(); - - /* Check if an event is present */ - if (poll(pollfd, num_fds, -1) <= 0) - continue; - - if (pollfd[0].revents & POLLIN) /* cancelled */ - break; - - do { - snd_seq_event_t *ev; - - seq_lock(); - snd_seq_event_input(midi_seq, &ev); - seq_unlock(); - - if (ev) { - ALSA_CALL(midi_handle_event, ev); - snd_seq_free_event(ev); - } - - seq_lock(); - ret = snd_seq_event_input_pending(midi_seq, 0); - seq_unlock(); - } while(ret > 0); - } - - free(pollfd); - return 0; -} - -/************************************************************************** - * midOpen [internal] - */ -static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) -{ - int ret = 0, port_in; - snd_seq_t *midi_seq; - - TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags); - - if (lpDesc == NULL) { - WARN("Invalid Parameter !\n"); - return MMSYSERR_INVALPARAM; - } - - /* FIXME : - * how to check that content of lpDesc is correct ? - */ - if (wDevID >= MIDM_NumDevs) { - WARN("wDevID too large (%u) !\n", wDevID); - return MMSYSERR_BADDEVICEID; - } - if (MidiInDev[wDevID].state == -1) { - WARN("device disabled\n"); - return MIDIERR_NODEVICE; - } - if (MidiInDev[wDevID].midiDesc.hMidi != 0) { - WARN("device already open !\n"); - return MMSYSERR_ALLOCATED; - } - if ((dwFlags & MIDI_IO_STATUS) != 0) { - WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n"); - dwFlags &= ~MIDI_IO_STATUS; - } - if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) { - FIXME("Bad dwFlags\n"); - return MMSYSERR_INVALFLAG; - } - - if (!(midi_seq = midiOpenSeq(&port_in))) { - return MMSYSERR_ERROR; - } - - MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); - - MidiInDev[wDevID].lpQueueHdr = NULL; - MidiInDev[wDevID].midiDesc = *lpDesc; - MidiInDev[wDevID].state = 0; - MidiInDev[wDevID].startTime = 0; - MidiInDev[wDevID].seq = midi_seq; - MidiInDev[wDevID].port_in = port_in; - - /* Connect our app port to the device port */ - seq_lock(); - ret = snd_seq_connect_from(midi_seq, port_in, MidiInDev[wDevID].addr.client, - MidiInDev[wDevID].addr.port); - seq_unlock(); - if (ret < 0) - return MMSYSERR_NOTENABLED; - - TRACE("Input port :%d connected %d:%d\n",port_in,MidiInDev[wDevID].addr.client,MidiInDev[wDevID].addr.port); - - if (numStartedMidiIn++ == 0) { - pipe(rec_cancel_pipe); - hThread = CreateThread(NULL, 0, midRecThread, midi_seq, 0, NULL); - if (!hThread) { - close(rec_cancel_pipe[0]); - close(rec_cancel_pipe[1]); - numStartedMidiIn = 0; - WARN("Couldn't create thread for midi-in\n"); - midiCloseSeq(); - return MMSYSERR_ERROR; - } - SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); - TRACE("Created thread for midi-in\n"); - } - - MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L); - return MMSYSERR_NOERROR; -} - -/************************************************************************** - * midClose [internal] - */ -static DWORD midClose(WORD wDevID) -{ - int ret = MMSYSERR_NOERROR; - - TRACE("(%04X);\n", wDevID); - - if (wDevID >= MIDM_NumDevs) { - WARN("wDevID too big (%u) !\n", wDevID); - return MMSYSERR_BADDEVICEID; - } - if (MidiInDev[wDevID].midiDesc.hMidi == 0) { - WARN("device not opened !\n"); - return MMSYSERR_ERROR; - } - if (MidiInDev[wDevID].lpQueueHdr != 0) { - return MIDIERR_STILLPLAYING; - } - - if (MidiInDev[wDevID].seq == NULL) { - WARN("ooops !\n"); - return MMSYSERR_ERROR; - } - if (--numStartedMidiIn == 0) { - TRACE("Stopping thread for midi-in\n"); - write(rec_cancel_pipe[1], "x", 1); - if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) { - WARN("Thread end not signaled, force termination\n"); - TerminateThread(hThread, 0); - } - close(rec_cancel_pipe[0]); - close(rec_cancel_pipe[1]); - TRACE("Stopped thread for midi-in\n"); - } - - seq_lock(); - snd_seq_disconnect_from(MidiInDev[wDevID].seq, MidiInDev[wDevID].port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port); - seq_unlock(); - midiCloseSeq(); - - MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L); - MidiInDev[wDevID].midiDesc.hMidi = 0; - MidiInDev[wDevID].seq = NULL; - - return ret; -} - /*======================================================================* * MIDI entry points * *======================================================================*/ @@ -350,11 +72,6 @@ static BOOL ALSA_MidiInit(void) params.err = &err; ALSA_CALL(midi_init, ¶ms);
- if (!err) - { - MIDM_NumDevs = params.num_srcs; - MidiInDev = params.srcs; - } return TRUE; }
@@ -374,10 +91,6 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, case DRVM_INIT: ALSA_MidiInit(); return 0; - case MIDM_OPEN: - return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2); - case MIDM_CLOSE: - return midClose(wDevID); }
params.dev_id = wDevID; diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h index 46f256a1c6a..ad8865a0988 100644 --- a/dlls/winealsa.drv/unixlib.h +++ b/dlls/winealsa.drv/unixlib.h @@ -207,27 +207,9 @@ struct get_prop_value_params unsigned int *buffer_size; };
-#include <alsa/asoundlib.h> -#include "mmddk.h" - -typedef struct midi_src -{ - int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */ - MIDIOPENDESC midiDesc; - WORD wFlags; - MIDIHDR *lpQueueHdr; - UINT startTime; - MIDIINCAPSW caps; - snd_seq_t *seq; - snd_seq_addr_t addr; - int port_in; -} WINE_MIDIIN; - struct midi_init_params { UINT *err; - unsigned int num_srcs; - void *srcs; };
struct notify_context @@ -271,13 +253,6 @@ struct midi_notify_wait_params struct notify_context *notify; };
-struct midi_seq_open_params -{ - int close; - snd_seq_t *seq; - int *port_in; -}; - enum alsa_funcs { alsa_get_endpoint_ids, @@ -308,10 +283,6 @@ enum alsa_funcs alsa_midi_out_message, alsa_midi_in_message, alsa_midi_notify_wait, - - alsa_midi_seq_lock, /* temporary */ - alsa_midi_seq_open, - alsa_midi_handle_event, };
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN; @@ -320,10 +291,6 @@ NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN; NTSTATUS midi_in_message(void *args) DECLSPEC_HIDDEN; NTSTATUS midi_notify_wait(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN; -NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN; -NTSTATUS midi_handle_event(void *args) DECLSPEC_HIDDEN; - extern unixlib_handle_t alsa_handle;
#define ALSA_CALL(func, params) __wine_unix_call(alsa_handle, alsa_ ## func, params)
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Fri, Mar 25, 2022 at 08:42:17AM +0000, Huw Davies wrote:
Signed-off-by: Huw Davies huw@codeweavers.com
dlls/winealsa.drv/Makefile.in | 2 +- dlls/winealsa.drv/alsa.c | 4 - dlls/winealsa.drv/alsamidi.c | 231 ++++++++++++++++++++++++--- dlls/winealsa.drv/midi.c | 287 ---------------------------------- dlls/winealsa.drv/unixlib.h | 33 ---- 5 files changed, 206 insertions(+), 351 deletions(-)
diff --git a/dlls/winealsa.drv/Makefile.in b/dlls/winealsa.drv/Makefile.in index 41be57d8b83..2113594fbe3 100644 --- a/dlls/winealsa.drv/Makefile.in +++ b/dlls/winealsa.drv/Makefile.in @@ -3,7 +3,7 @@ MODULE = winealsa.drv UNIXLIB = winealsa.so IMPORTS = uuid ole32 advapi32 DELAYIMPORTS = winmm -EXTRALIBS = $(ALSA_LIBS) +EXTRALIBS = $(ALSA_LIBS) $(PTHREAD_LIBS)
EXTRADLLFLAGS = -mcygwin
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index b18588ab1c0..e068f6608f3 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -2449,8 +2449,4 @@ unixlib_entry_t __wine_unix_call_funcs[] = midi_out_message, midi_in_message, midi_notify_wait,
- midi_seq_lock, /* temporary */
- midi_seq_open,
- midi_handle_event,
}; diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c index 1633268b533..8ec646281d2 100644 --- a/dlls/winealsa.drv/alsamidi.c +++ b/dlls/winealsa.drv/alsamidi.c @@ -60,6 +60,19 @@ struct midi_dest int port_out; };
+struct midi_src +{
- int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
- MIDIOPENDESC midiDesc;
- WORD wFlags;
- MIDIHDR *lpQueueHdr;
- UINT startTime;
- MIDIINCAPSW caps;
- snd_seq_t *seq;
- snd_seq_addr_t addr;
- int port_in;
+};
static pthread_mutex_t seq_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t in_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -70,6 +83,10 @@ static snd_seq_t *midi_seq; static unsigned int seq_refs; static int port_in = -1;
+static unsigned int num_midi_in_started; +static int rec_cancel_pipe[2]; +static pthread_t rec_thread_id;
static pthread_mutex_t notify_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t notify_cond = PTHREAD_COND_INITIALIZER; static BOOL notify_quit; @@ -87,14 +104,6 @@ static void seq_unlock(void) pthread_mutex_unlock(&seq_mutex); }
-NTSTATUS midi_seq_lock(void *args) -{
- if (args) seq_lock();
- else seq_unlock();
- return STATUS_SUCCESS;
-}
static void in_buffer_lock(void) { pthread_mutex_lock(&in_buffer_mutex); @@ -233,18 +242,6 @@ static void seq_close(void) seq_unlock(); }
-NTSTATUS midi_seq_open(void *args) -{
- struct midi_seq_open_params *params = args;
- if (!params->close)
params->seq = seq_open(params->port_in);
- else
seq_close();
- return STATUS_SUCCESS;
-}
static int alsa_to_win_device_type(unsigned int type) { /* MOD_MIDIPORT output port @@ -458,8 +455,6 @@ NTSTATUS midi_init(void *args) free( pinfo );
*params->err = NOERROR;
params->num_srcs = num_srcs;
params->srcs = srcs;
TRACE("End\n");
@@ -1033,9 +1028,8 @@ static void handle_regular_event(struct midi_src *src, snd_seq_event_t *ev) } }
-NTSTATUS midi_handle_event(void *args) +static void midi_handle_event(snd_seq_event_t *ev) {
snd_seq_event_t *ev = args; struct midi_src *src;
/* Find the target device */
@@ -1043,14 +1037,193 @@ NTSTATUS midi_handle_event(void *args) if ((ev->source.client == src->addr.client) && (ev->source.port == src->addr.port)) break; if ((src == srcs + num_srcs) || (src->state != 1))
return STATUS_SUCCESS;
return;
if (ev->type == SND_SEQ_EVENT_SYSEX) handle_sysex_event(src, ev->data.ext.ptr, ev->data.ext.len); else handle_regular_event(src, ev);
+}
- return STATUS_SUCCESS;
+static void *rec_thread_proc(void *arg) +{
- snd_seq_t *midi_seq = (snd_seq_t *)arg;
- int num_fds;
- struct pollfd *pollfd;
- int ret;
- /* Add on one for the read end of the cancel pipe */
- num_fds = snd_seq_poll_descriptors_count(midi_seq, POLLIN) + 1;
- pollfd = malloc(num_fds * sizeof(struct pollfd));
- while(1)
- {
pollfd[0].fd = rec_cancel_pipe[0];
pollfd[0].events = POLLIN;
seq_lock();
snd_seq_poll_descriptors(midi_seq, pollfd + 1, num_fds - 1, POLLIN);
seq_unlock();
/* Check if an event is present */
if (poll(pollfd, num_fds, -1) <= 0)
continue;
if (pollfd[0].revents & POLLIN) /* cancelled */
break;
do
{
snd_seq_event_t *ev;
seq_lock();
snd_seq_event_input(midi_seq, &ev);
seq_unlock();
if (ev)
{
midi_handle_event(ev);
snd_seq_free_event(ev);
}
seq_lock();
ret = snd_seq_event_input_pending(midi_seq, 0);
seq_unlock();
} while(ret > 0);
- }
- free(pollfd);
- return 0;
+}
+static UINT midi_in_open(WORD dev_id, MIDIOPENDESC *desc, UINT flags, struct notify_context *notify) +{
- struct midi_src *src;
- int ret = 0, port_in;
- snd_seq_t *midi_seq;
- TRACE("(%04X, %p, %08X);\n", dev_id, desc, flags);
- if (!desc)
- {
WARN("Invalid Parameter !\n");
return MMSYSERR_INVALPARAM;
- }
- /* FIXME: check that contents of desc are correct */
- if (dev_id >= num_srcs)
- {
WARN("dev_id too large (%u) !\n", dev_id);
return MMSYSERR_BADDEVICEID;
- }
- src = srcs + dev_id;
- if (src->state == -1)
- {
WARN("device disabled\n");
return MIDIERR_NODEVICE;
- }
- if (src->midiDesc.hMidi)
- {
WARN("device already open !\n");
return MMSYSERR_ALLOCATED;
- }
- if (flags & MIDI_IO_STATUS)
- {
WARN("No support for MIDI_IO_STATUS in flags yet, ignoring it\n");
flags &= ~MIDI_IO_STATUS;
- }
- if (flags & ~CALLBACK_TYPEMASK)
- {
FIXME("Bad flags %08X\n", flags);
return MMSYSERR_INVALFLAG;
- }
- if (!(midi_seq = seq_open(&port_in)))
return MMSYSERR_ERROR;
- src->wFlags = HIWORD(flags & CALLBACK_TYPEMASK);
- src->lpQueueHdr = NULL;
- src->midiDesc = *desc;
- src->state = 0;
- src->startTime = 0;
- src->seq = midi_seq;
- src->port_in = port_in;
- /* Connect our app port to the device port */
- seq_lock();
- ret = snd_seq_connect_from(midi_seq, port_in, src->addr.client, src->addr.port);
- seq_unlock();
- if (ret < 0)
return MMSYSERR_NOTENABLED;
- TRACE("Input port :%d connected %d:%d\n", port_in, src->addr.client, src->addr.port);
- if (num_midi_in_started++ == 0)
- {
pipe(rec_cancel_pipe);
if (pthread_create(&rec_thread_id, NULL, rec_thread_proc, midi_seq))
{
close(rec_cancel_pipe[0]);
close(rec_cancel_pipe[1]);
num_midi_in_started = 0;
WARN("Couldn't create thread for midi-in\n");
seq_close();
return MMSYSERR_ERROR;
}
- }
- set_in_notify(notify, src, dev_id, MIM_OPEN, 0, 0);
- return MMSYSERR_NOERROR;
+}
+static UINT midi_in_close(WORD dev_id, struct notify_context *notify) +{
- struct midi_src *src;
- TRACE("(%04X);\n", dev_id);
- if (dev_id >= num_srcs)
- {
WARN("dev_id too big (%u) !\n", dev_id);
return MMSYSERR_BADDEVICEID;
- }
- src = srcs + dev_id;
- if (!src->midiDesc.hMidi)
- {
WARN("device not opened !\n");
return MMSYSERR_ERROR;
- }
- if (src->lpQueueHdr)
return MIDIERR_STILLPLAYING;
- if (src->seq == NULL)
- {
WARN("ooops !\n");
return MMSYSERR_ERROR;
- }
- if (--num_midi_in_started == 0)
- {
TRACE("Stopping thread for midi-in\n");
write(rec_cancel_pipe[1], "x", 1);
pthread_join(rec_thread_id, NULL);
close(rec_cancel_pipe[0]);
close(rec_cancel_pipe[1]);
TRACE("Stopped thread for midi-in\n");
- }
- seq_lock();
- snd_seq_disconnect_from(src->seq, src->port_in, src->addr.client, src->addr.port);
- seq_unlock();
- seq_close();
- set_in_notify(notify, src, dev_id, MIM_CLOSE, 0, 0);
- src->midiDesc.hMidi = 0;
- src->seq = NULL;
- return MMSYSERR_NOERROR;
}
static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size) @@ -1257,6 +1430,12 @@ NTSTATUS midi_in_message(void *args) /* FIXME: Pretend this is supported */ *params->err = MMSYSERR_NOERROR; break;
- case MIDM_OPEN:
*params->err = midi_in_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify);
break;
- case MIDM_CLOSE:
*params->err = midi_in_close(params->dev_id, params->notify);
case MIDM_ADDBUFFER: *params->err = midi_in_add_buffer(params->dev_id, (MIDIHDR *)params->param_1, params->param_2); break;break;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c index 327d4b7b200..b768517e655 100644 --- a/dlls/winealsa.drv/midi.c +++ b/dlls/winealsa.drv/midi.c @@ -47,26 +47,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(midi);
-static WINE_MIDIIN *MidiInDev;
-/* this is the total number of MIDI out devices found */ -static int MIDM_NumDevs = 0;
-static int numStartedMidiIn = 0;
-static int rec_cancel_pipe[2]; -static HANDLE hThread;
-static void seq_lock(void) -{
- ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)1);
-}
-static void seq_unlock(void) -{
- ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)0);
-}
static void notify_client(struct notify_context *notify) { TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n", notify->dev_id, notify->msg, notify->param_1, notify->param_2); @@ -75,264 +55,6 @@ static void notify_client(struct notify_context *notify) notify->instance, notify->param_1, notify->param_2); }
-/*======================================================================*
Low level MIDI implementation *
- *======================================================================*/
-#if 0 /* Debug Purpose */ -static void error_handler(const char* file, int line, const char* function, int err, const char* fmt, ...) -{
- va_list arg;
- if (err == ENOENT)
return;
- va_start(arg, fmt);
- fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function);
- vfprintf(stderr, fmt, arg);
- if (err)
fprintf(stderr, ": %s", snd_strerror(err));
- putc('\n', stderr);
- va_end(arg);
-} -#endif
-/**************************************************************************
MIDI_NotifyClient [internal]
- */
-static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
-{
- DWORD_PTR dwCallBack;
- UINT uFlags;
- HANDLE hDev;
- DWORD_PTR dwInstance;
- TRACE("wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",
wDevID, wMsg, dwParam1, dwParam2);
- switch (wMsg) {
- case MIM_OPEN:
- case MIM_CLOSE:
- if (wDevID > MIDM_NumDevs) return;
- dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback;
- uFlags = MidiInDev[wDevID].wFlags;
- hDev = MidiInDev[wDevID].midiDesc.hMidi;
- dwInstance = MidiInDev[wDevID].midiDesc.dwInstance;
- break;
- default:
- ERR("Unsupported MSW-MIDI message %u\n", wMsg);
- return;
- }
- DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2);
-}
-/**************************************************************************
midiOpenSeq [internal]
- */
-static snd_seq_t *midiOpenSeq(int *port_in_ret) -{
- struct midi_seq_open_params params;
- params.port_in = port_in_ret;
- params.close = 0;
- ALSA_CALL(midi_seq_open, ¶ms);
- return params.seq;
-}
-/**************************************************************************
midiCloseSeq [internal]
- */
-static int midiCloseSeq(void) -{
- struct midi_seq_open_params params;
- params.port_in = NULL;
- params.close = 1;
- ALSA_CALL(midi_seq_open, ¶ms);
- return 0;
-}
-static DWORD WINAPI midRecThread(void *arg) -{
- snd_seq_t *midi_seq = arg;
- int num_fds;
- struct pollfd *pollfd;
- int ret;
- /* Add on one for the read end of the cancel pipe */
- num_fds = snd_seq_poll_descriptors_count(midi_seq, POLLIN) + 1;
- pollfd = malloc(num_fds * sizeof(struct pollfd));
- while(1) {
pollfd[0].fd = rec_cancel_pipe[0];
pollfd[0].events = POLLIN;
seq_lock();
snd_seq_poll_descriptors(midi_seq, pollfd + 1, num_fds - 1, POLLIN);
seq_unlock();
- /* Check if an event is present */
if (poll(pollfd, num_fds, -1) <= 0)
continue;
if (pollfd[0].revents & POLLIN) /* cancelled */
break;
- do {
snd_seq_event_t *ev;
seq_lock();
snd_seq_event_input(midi_seq, &ev);
seq_unlock();
if (ev) {
ALSA_CALL(midi_handle_event, ev);
snd_seq_free_event(ev);
}
seq_lock();
ret = snd_seq_event_input_pending(midi_seq, 0);
seq_unlock();
- } while(ret > 0);
- }
- free(pollfd);
- return 0;
-}
-/**************************************************************************
midOpen [internal]
- */
-static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) -{
- int ret = 0, port_in;
- snd_seq_t *midi_seq;
- TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
- if (lpDesc == NULL) {
- WARN("Invalid Parameter !\n");
- return MMSYSERR_INVALPARAM;
- }
- /* FIXME :
* how to check that content of lpDesc is correct ?
*/
- if (wDevID >= MIDM_NumDevs) {
- WARN("wDevID too large (%u) !\n", wDevID);
- return MMSYSERR_BADDEVICEID;
- }
- if (MidiInDev[wDevID].state == -1) {
WARN("device disabled\n");
return MIDIERR_NODEVICE;
- }
- if (MidiInDev[wDevID].midiDesc.hMidi != 0) {
- WARN("device already open !\n");
- return MMSYSERR_ALLOCATED;
- }
- if ((dwFlags & MIDI_IO_STATUS) != 0) {
- WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n");
- dwFlags &= ~MIDI_IO_STATUS;
- }
- if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {
- FIXME("Bad dwFlags\n");
- return MMSYSERR_INVALFLAG;
- }
- if (!(midi_seq = midiOpenSeq(&port_in))) {
- return MMSYSERR_ERROR;
- }
- MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- MidiInDev[wDevID].lpQueueHdr = NULL;
- MidiInDev[wDevID].midiDesc = *lpDesc;
- MidiInDev[wDevID].state = 0;
- MidiInDev[wDevID].startTime = 0;
- MidiInDev[wDevID].seq = midi_seq;
- MidiInDev[wDevID].port_in = port_in;
- /* Connect our app port to the device port */
- seq_lock();
- ret = snd_seq_connect_from(midi_seq, port_in, MidiInDev[wDevID].addr.client,
MidiInDev[wDevID].addr.port);
- seq_unlock();
- if (ret < 0)
- return MMSYSERR_NOTENABLED;
- TRACE("Input port :%d connected %d:%d\n",port_in,MidiInDev[wDevID].addr.client,MidiInDev[wDevID].addr.port);
- if (numStartedMidiIn++ == 0) {
- pipe(rec_cancel_pipe);
- hThread = CreateThread(NULL, 0, midRecThread, midi_seq, 0, NULL);
- if (!hThread) {
close(rec_cancel_pipe[0]);
close(rec_cancel_pipe[1]);
numStartedMidiIn = 0;
WARN("Couldn't create thread for midi-in\n");
midiCloseSeq();
return MMSYSERR_ERROR;
- }
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
- TRACE("Created thread for midi-in\n");
- }
- MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L);
- return MMSYSERR_NOERROR;
-}
-/**************************************************************************
midClose [internal]
- */
-static DWORD midClose(WORD wDevID) -{
- int ret = MMSYSERR_NOERROR;
- TRACE("(%04X);\n", wDevID);
- if (wDevID >= MIDM_NumDevs) {
- WARN("wDevID too big (%u) !\n", wDevID);
- return MMSYSERR_BADDEVICEID;
- }
- if (MidiInDev[wDevID].midiDesc.hMidi == 0) {
- WARN("device not opened !\n");
- return MMSYSERR_ERROR;
- }
- if (MidiInDev[wDevID].lpQueueHdr != 0) {
- return MIDIERR_STILLPLAYING;
- }
- if (MidiInDev[wDevID].seq == NULL) {
- WARN("ooops !\n");
- return MMSYSERR_ERROR;
- }
- if (--numStartedMidiIn == 0) {
- TRACE("Stopping thread for midi-in\n");
write(rec_cancel_pipe[1], "x", 1);
- if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) {
WARN("Thread end not signaled, force termination\n");
TerminateThread(hThread, 0);
- }
close(rec_cancel_pipe[0]);
close(rec_cancel_pipe[1]);
TRACE("Stopped thread for midi-in\n");
- }
- seq_lock();
- snd_seq_disconnect_from(MidiInDev[wDevID].seq, MidiInDev[wDevID].port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port);
- seq_unlock();
- midiCloseSeq();
- MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L);
- MidiInDev[wDevID].midiDesc.hMidi = 0;
- MidiInDev[wDevID].seq = NULL;
- return ret;
-}
/*======================================================================*
MIDI entry points *
*======================================================================*/ @@ -350,11 +72,6 @@ static BOOL ALSA_MidiInit(void) params.err = &err; ALSA_CALL(midi_init, ¶ms);
- if (!err)
- {
MIDM_NumDevs = params.num_srcs;
MidiInDev = params.srcs;
- } return TRUE;
}
@@ -374,10 +91,6 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, case DRVM_INIT: ALSA_MidiInit(); return 0;
case MIDM_OPEN:
return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
case MIDM_CLOSE:
return midClose(wDevID); }
params.dev_id = wDevID;
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h index 46f256a1c6a..ad8865a0988 100644 --- a/dlls/winealsa.drv/unixlib.h +++ b/dlls/winealsa.drv/unixlib.h @@ -207,27 +207,9 @@ struct get_prop_value_params unsigned int *buffer_size; };
-#include <alsa/asoundlib.h> -#include "mmddk.h"
-typedef struct midi_src -{
- int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
- MIDIOPENDESC midiDesc;
- WORD wFlags;
- MIDIHDR *lpQueueHdr;
- UINT startTime;
- MIDIINCAPSW caps;
- snd_seq_t *seq;
- snd_seq_addr_t addr;
- int port_in;
-} WINE_MIDIIN;
struct midi_init_params { UINT *err;
- unsigned int num_srcs;
- void *srcs;
};
struct notify_context @@ -271,13 +253,6 @@ struct midi_notify_wait_params struct notify_context *notify; };
-struct midi_seq_open_params -{
- int close;
- snd_seq_t *seq;
- int *port_in;
-};
enum alsa_funcs { alsa_get_endpoint_ids, @@ -308,10 +283,6 @@ enum alsa_funcs alsa_midi_out_message, alsa_midi_in_message, alsa_midi_notify_wait,
- alsa_midi_seq_lock, /* temporary */
- alsa_midi_seq_open,
- alsa_midi_handle_event,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN; @@ -320,10 +291,6 @@ NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN; NTSTATUS midi_in_message(void *args) DECLSPEC_HIDDEN; NTSTATUS midi_notify_wait(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN; -NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN; -NTSTATUS midi_handle_event(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t alsa_handle;
#define ALSA_CALL(func, params) __wine_unix_call(alsa_handle, alsa_ ## func, params)
2.25.1