Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/winealsa.drv/alsa.c | 1 + dlls/winealsa.drv/alsamidi.c | 133 +++++++++++++++++++++++++++++++++++ dlls/winealsa.drv/midi.c | 127 +++++++-------------------------- dlls/winealsa.drv/unixlib.h | 26 +++++++ 4 files changed, 186 insertions(+), 101 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index 16c0c7c387d..6d307eb84bf 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -2445,6 +2445,7 @@ unixlib_entry_t __wine_unix_call_funcs[] = is_started, get_prop_value, midi_init, + midi_out_message,
midi_seq_lock, /* temporary */ midi_seq_open, diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c index e1fca85b3b4..a7a5a211484 100644 --- a/dlls/winealsa.drv/alsamidi.c +++ b/dlls/winealsa.drv/alsamidi.c @@ -362,3 +362,136 @@ NTSTATUS midi_init(void *args)
return STATUS_SUCCESS; } + +static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg, + UINT_PTR param_1, UINT_PTR param_2) +{ + notify->send_notify = TRUE; + notify->dev_id = dev_id; + notify->msg = msg; + notify->param_1 = param_1; + notify->param_2 = param_2; + notify->callback = dest->midiDesc.dwCallback; + notify->flags = dest->wFlags; + notify->device = dest->midiDesc.hMidi; + notify->instance = dest->midiDesc.dwInstance; +} + +static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, struct notify_context *notify) +{ + int ret; + int port_out; + char port_out_name[32]; + snd_seq_t *midi_seq; + struct midi_dest *dest; + + TRACE("(%04X, %p, %08X);\n", dev_id, midi_desc, flags); + + if (midi_desc == NULL) + { + WARN("Invalid Parameter !\n"); + return MMSYSERR_INVALPARAM; + } + if (dev_id >= num_dests) + { + TRACE("MAX_MIDIOUTDRV reached !\n"); + return MMSYSERR_BADDEVICEID; + } + dest = dests + dev_id; + if (dest->midiDesc.hMidi != 0) + { + WARN("device already open !\n"); + return MMSYSERR_ALLOCATED; + } + if (!dest->bEnabled) + { + WARN("device disabled !\n"); + return MIDIERR_NODEVICE; + } + if ((flags & ~CALLBACK_TYPEMASK) != 0) + { + WARN("bad dwFlags\n"); + return MMSYSERR_INVALFLAG; + } + + switch (dest->caps.wTechnology) + { + case MOD_FMSYNTH: + case MOD_MIDIPORT: + case MOD_SYNTH: + if (!(midi_seq = seq_open(NULL))) + return MMSYSERR_ALLOCATED; + break; + default: + WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology); + return MMSYSERR_NOTENABLED; + } + + dest->wFlags = HIWORD(flags & CALLBACK_TYPEMASK); + dest->midiDesc = *midi_desc; + dest->seq = midi_seq; + + seq_lock(); + /* Create a port dedicated to a specific device */ + /* Keep the old name without a number for the first port */ + if (dev_id) + sprintf(port_out_name, "WINE ALSA Output #%d", dev_id); + + port_out = snd_seq_create_simple_port(midi_seq, dev_id ? port_out_name : "WINE ALSA Output", + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_SUBS_WRITE, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + + if (port_out < 0) + { + TRACE("Unable to create output port\n"); + dest->port_out = -1; + } + else + { + TRACE("Output port %d created successfully\n", port_out); + dest->port_out = port_out; + + /* Connect our app port to the device port */ + ret = snd_seq_connect_to(midi_seq, port_out, dest->addr.client, dest->addr.port); + + /* usually will happen when the port is already connected */ + /* other errors should not be fatal either */ + if (ret < 0) + WARN("Could not connect port %d to %d:%d: %s\n", dev_id, dest->addr.client, + dest->addr.port, snd_strerror(ret)); + } + seq_unlock(); + + if (port_out < 0) + return MMSYSERR_NOTENABLED; + + TRACE("Output port :%d connected %d:%d\n", port_out, dest->addr.client, dest->addr.port); + + set_out_notify(notify, dest, dev_id, MOM_OPEN, 0, 0); + return MMSYSERR_NOERROR; +} + +NTSTATUS midi_out_message(void *args) +{ + struct midi_out_message_params *params = args; + + params->notify->send_notify = FALSE; + + switch (params->msg) + { + case DRVM_EXIT: + case DRVM_ENABLE: + case DRVM_DISABLE: + /* FIXME: Pretend this is supported */ + *params->err = MMSYSERR_NOERROR; + break; + case MODM_OPEN: + *params->err = midi_out_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify); + break; + default: + TRACE("Unsupported message\n"); + *params->err = MMSYSERR_NOTSUPPORTED; + } + + return STATUS_SUCCESS; +} diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c index 535f3dbd348..c77d479162b 100644 --- a/dlls/winealsa.drv/midi.c +++ b/dlls/winealsa.drv/midi.c @@ -79,6 +79,14 @@ 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); + + DriverCallback(notify->callback, notify->flags, notify->device, notify->msg, + notify->instance, notify->param_1, notify->param_2); +} + /*======================================================================* * Low level MIDI implementation * *======================================================================*/ @@ -114,7 +122,6 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg, wDevID, wMsg, dwParam1, dwParam2);
switch (wMsg) { - case MOM_OPEN: case MOM_CLOSE: case MOM_DONE: case MOM_POSITIONCB: @@ -624,96 +631,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize) return MMSYSERR_NOERROR; }
-/************************************************************************** - * modOpen [internal] - */ -static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) -{ - int ret; - int port_out; - char port_out_name[32]; - snd_seq_t *midi_seq; - - TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags); - if (lpDesc == NULL) { - WARN("Invalid Parameter !\n"); - return MMSYSERR_INVALPARAM; - } - if (wDevID >= MODM_NumDevs) { - TRACE("MAX_MIDIOUTDRV reached !\n"); - return MMSYSERR_BADDEVICEID; - } - if (MidiOutDev[wDevID].midiDesc.hMidi != 0) { - WARN("device already open !\n"); - return MMSYSERR_ALLOCATED; - } - if (!MidiOutDev[wDevID].bEnabled) { - WARN("device disabled !\n"); - return MIDIERR_NODEVICE; - } - if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) { - WARN("bad dwFlags\n"); - return MMSYSERR_INVALFLAG; - } - - switch (MidiOutDev[wDevID].caps.wTechnology) { - case MOD_FMSYNTH: - case MOD_MIDIPORT: - case MOD_SYNTH: - if (!(midi_seq = midiOpenSeq(NULL))) { - return MMSYSERR_ALLOCATED; - } - break; - default: - WARN("Technology not supported (yet) %d !\n", - MidiOutDev[wDevID].caps.wTechnology); - return MMSYSERR_NOTENABLED; - } - - MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); - MidiOutDev[wDevID].midiDesc = *lpDesc; - MidiOutDev[wDevID].seq = midi_seq; - - seq_lock(); - /* Create a port dedicated to a specific device */ - /* Keep the old name without a number for the first port */ - if (wDevID) - sprintf(port_out_name, "WINE ALSA Output #%d", wDevID); - - port_out = snd_seq_create_simple_port(midi_seq, wDevID?port_out_name:"WINE ALSA Output", - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION); - - if (port_out < 0) { - TRACE("Unable to create output port\n"); - MidiOutDev[wDevID].port_out = -1; - } else { - TRACE("Output port %d created successfully\n", port_out); - MidiOutDev[wDevID].port_out = port_out; - - /* Connect our app port to the device port */ - ret = snd_seq_connect_to(midi_seq, port_out, MidiOutDev[wDevID].addr.client, - MidiOutDev[wDevID].addr.port); - - /* usually will happen when the port is already connected */ - /* other errors should not be fatal either */ - if (ret < 0) - WARN("Could not connect port %d to %d:%d: %s\n", - wDevID, MidiOutDev[wDevID].addr.client, - MidiOutDev[wDevID].addr.port, snd_strerror(ret)); - } - seq_unlock(); - - if (port_out < 0) - return MMSYSERR_NOTENABLED; - - TRACE("Output port :%d connected %d:%d\n",port_out,MidiOutDev[wDevID].addr.client,MidiOutDev[wDevID].addr.port); - - MIDI_NotifyClient(wDevID, MOM_OPEN, 0L, 0L); - return MMSYSERR_NOERROR; -} - - /************************************************************************** * modClose [internal] */ @@ -1123,6 +1040,10 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { + struct midi_out_message_params params; + struct notify_context notify; + UINT err; + TRACE("(%04X, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);
@@ -1130,13 +1051,6 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, case DRVM_INIT: ALSA_MidiInit(); return 0; - case DRVM_EXIT: - case DRVM_ENABLE: - case DRVM_DISABLE: - /* FIXME: Pretend this is supported */ - return 0; - case MODM_OPEN: - return modOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2); case MODM_CLOSE: return modClose(wDevID); case MODM_DATA: @@ -1157,10 +1071,21 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, return 0; case MODM_RESET: return modReset(wDevID); - default: - TRACE("Unsupported message\n"); } - return MMSYSERR_NOTSUPPORTED; + + params.dev_id = wDevID; + params.msg = wMsg; + params.user = dwUser; + params.param_1 = dwParam1; + params.param_2 = dwParam2; + params.err = &err; + params.notify = ¬ify; + + ALSA_CALL(midi_out_message, ¶ms); + + if (!err && notify.send_notify) notify_client(¬ify); + + return err; }
/************************************************************************** diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h index d69ab980f42..e3cd7123101 100644 --- a/dlls/winealsa.drv/unixlib.h +++ b/dlls/winealsa.drv/unixlib.h @@ -241,6 +241,30 @@ struct midi_init_params void *dests, *srcs; };
+struct notify_context +{ + BOOL send_notify; + WORD dev_id; + WORD msg; + UINT_PTR param_1; + UINT_PTR param_2; + UINT_PTR callback; + UINT flags; + HANDLE device; + UINT_PTR instance; +}; + +struct midi_out_message_params +{ + UINT dev_id; + UINT msg; + UINT_PTR user; + UINT_PTR param_1; + UINT_PTR param_2; + UINT *err; + struct notify_context *notify; +}; + struct midi_seq_open_params { int close; @@ -274,12 +298,14 @@ enum alsa_funcs alsa_is_started, alsa_get_prop_value, alsa_midi_init, + alsa_midi_out_message,
alsa_midi_seq_lock, /* temporary */ alsa_midi_seq_open, };
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN; +NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN; NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;