Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/wineoss.drv/Makefile.in | 2 +- dlls/wineoss.drv/midi.c | 243 ----------------------------------- dlls/wineoss.drv/oss.c | 3 - dlls/wineoss.drv/ossmidi.c | 193 +++++++++++++++++++++++++--- dlls/wineoss.drv/unixlib.h | 35 ----- 5 files changed, 175 insertions(+), 301 deletions(-)
diff --git a/dlls/wineoss.drv/Makefile.in b/dlls/wineoss.drv/Makefile.in index 04b438da71e..13fb18b6004 100644 --- a/dlls/wineoss.drv/Makefile.in +++ b/dlls/wineoss.drv/Makefile.in @@ -3,7 +3,7 @@ MODULE = wineoss.drv UNIXLIB = wineoss.so IMPORTS = uuid ole32 user32 advapi32 DELAYIMPORTS = winmm -EXTRALIBS = $(OSS4_LIBS) +EXTRALIBS = $(OSS4_LIBS) $(PTHREAD_LIBS) EXTRAINCL = $(OSS4_CFLAGS)
EXTRADLLFLAGS = -mcygwin diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c index c83dd55fd6b..84a4fac4b74 100644 --- a/dlls/wineoss.drv/midi.c +++ b/dlls/wineoss.drv/midi.c @@ -63,23 +63,10 @@
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; - /*======================================================================* * Low level MIDI implementation * *======================================================================*/
-static int midiOpenSeq(void); -static int midiCloseSeq(int); - static int MIDI_loadcount; /************************************************************************** * OSS_MidiInit [internal] @@ -100,11 +87,6 @@ static LRESULT OSS_MidiInit(void) params.err = &err; OSS_CALL(midi_init, ¶ms);
- if (!err) - { - MidiInDev = params.srcs; - MIDM_NumDevs = params.num_srcs; - } return err; }
@@ -120,9 +102,6 @@ static LRESULT OSS_MidiExit(void) if (--MIDI_loadcount) return 1;
- MidiInDev = NULL; - MIDM_NumDevs = 0; - return 0; }
@@ -135,224 +114,6 @@ static void notify_client(struct notify_context *notify) notify->instance, notify->param_1, notify->param_2); }
-/************************************************************************** - * 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: - case MIM_DATA: - case MIM_LONGDATA: - case MIM_ERROR: - case MIM_LONGERROR: - case MIM_MOREDATA: - 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 int midiOpenSeq(void) -{ - struct midi_seq_open_params params; - - params.close = 0; - params.fd = -1; - OSS_CALL(midi_seq_open, ¶ms); - - return params.fd; -} - -/************************************************************************** - * midiCloseSeq [internal] - */ -static int midiCloseSeq(int fd) -{ - struct midi_seq_open_params params; - - params.close = 1; - params.fd = fd; - OSS_CALL(midi_seq_open, ¶ms); - - return 0; -} - -static void handle_midi_data(unsigned char *buffer, unsigned int len) -{ - struct midi_handle_data_params params; - - params.buffer = buffer; - params.len = len; - OSS_CALL(midi_handle_data, ¶ms); -} - -static DWORD WINAPI midRecThread(void *arg) -{ - int fd = (int)(INT_PTR)arg; - unsigned char buffer[256]; - int len; - struct pollfd pollfd[2]; - - pollfd[0].fd = rec_cancel_pipe[0]; - pollfd[0].events = POLLIN; - pollfd[1].fd = fd; - pollfd[1].events = POLLIN; - - while (1) - { - /* Check if an event is present */ - if (poll(pollfd, ARRAY_SIZE(pollfd), -1) <= 0) - continue; - - if (pollfd[0].revents & POLLIN) /* cancelled */ - break; - - len = read(fd, buffer, sizeof(buffer)); - - if (len > 0 && len % 4 == 0) - handle_midi_data(buffer, len); - } - return 0; -} - -/************************************************************************** - * midOpen [internal] - */ -static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) -{ - int fd; - - 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; - } - - fd = midiOpenSeq(); - if (fd < 0) { - return MMSYSERR_ERROR; - } - - if (numStartedMidiIn++ == 0) { - pipe(rec_cancel_pipe); - hThread = CreateThread(NULL, 0, midRecThread, (void *)(INT_PTR)fd, 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(fd); - return MMSYSERR_ERROR; - } - SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); - TRACE("Created thread for midi-in\n"); - } - - MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); - - MidiInDev[wDevID].lpQueueHdr = NULL; - MidiInDev[wDevID].midiDesc = *lpDesc; - MidiInDev[wDevID].state = 0; - MidiInDev[wDevID].incLen = 0; - MidiInDev[wDevID].startTime = 0; - MidiInDev[wDevID].fd = fd; - - 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].fd == -1) { - 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"); - } - midiCloseSeq(MidiInDev[wDevID].fd); - MidiInDev[wDevID].fd = -1; - - MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L); - MidiInDev[wDevID].midiDesc.hMidi = 0; - return ret; -} - /*======================================================================* * MIDI entry points * *======================================================================*/ @@ -374,10 +135,6 @@ DWORD WINAPI OSS_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser, return OSS_MidiInit(); case DRVM_EXIT: return OSS_MidiExit(); - case MIDM_OPEN: - return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2); - case MIDM_CLOSE: - return midClose(wDevID); }
params.dev_id = wDevID; diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c index c5b422a60c9..b0a411ecd9b 100644 --- a/dlls/wineoss.drv/oss.c +++ b/dlls/wineoss.drv/oss.c @@ -1410,7 +1410,4 @@ unixlib_entry_t __wine_unix_call_funcs[] = midi_out_message, midi_in_message, midi_notify_wait, - - midi_seq_open, - midi_handle_data, }; diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c index 9c8ca8a8f39..072a9815c35 100644 --- a/dlls/wineoss.drv/ossmidi.c +++ b/dlls/wineoss.drv/ossmidi.c @@ -33,6 +33,7 @@ #include <stdint.h> #include <time.h> #include <unistd.h> +#include <poll.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -45,6 +46,7 @@ #define WIN32_NO_STATUS #include "winternl.h" #include "audioclient.h" +#include "mmddk.h"
#include "wine/debug.h" #include "wine/unixlib.h" @@ -62,12 +64,30 @@ struct midi_dest int fd; };
+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; + unsigned char incoming[3]; + unsigned char incPrev; + char incLen; + UINT startTime; + MIDIINCAPSW caps; + int fd; +}; + static pthread_mutex_t in_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned int num_dests, num_srcs, num_synths, seq_refs; static struct midi_dest dests[MAX_MIDIOUTDRV]; static struct midi_src srcs[MAX_MIDIINDRV];
+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_read_cond = PTHREAD_COND_INITIALIZER; static pthread_cond_t notify_write_cond = PTHREAD_COND_INITIALIZER; @@ -281,18 +301,6 @@ static int seq_close(int fd) return 0; }
-NTSTATUS midi_seq_open(void *args) -{ - struct midi_seq_open_params *params = args; - - if (!params->close) - params->fd = seq_open(); - else - seq_close(params->fd); - - return STATUS_SUCCESS; -} - NTSTATUS midi_init(void *args) { struct midi_init_params *params = args; @@ -499,8 +507,6 @@ wrapup: seq_close(fd);
*params->err = 0; - params->num_srcs = num_srcs; - params->srcs = srcs;
return STATUS_SUCCESS; } @@ -1313,11 +1319,8 @@ static void handle_regular_data(struct midi_src *src, unsigned char value, UINT } }
-NTSTATUS midi_handle_data(void *args) +static void handle_midi_data(unsigned char *buffer, unsigned int len) { - struct midi_handle_data_params *params = args; - unsigned char *buffer = params->buffer; - unsigned int len = params->len; unsigned int time = get_time_msec(), i; struct midi_src *src; unsigned char value; @@ -1339,7 +1342,153 @@ NTSTATUS midi_handle_data(void *args) else handle_regular_data(src, value, time - src->startTime); } - return STATUS_SUCCESS; +} + +static void *rec_thread_proc(void *arg) +{ + int fd = PtrToLong(arg); + unsigned char buffer[256]; + int len; + struct pollfd pollfd[2]; + + pollfd[0].fd = rec_cancel_pipe[0]; + pollfd[0].events = POLLIN; + pollfd[1].fd = fd; + pollfd[1].events = POLLIN; + + while (1) + { + /* Check if an event is present */ + if (poll(pollfd, ARRAY_SIZE(pollfd), -1) <= 0) + continue; + + if (pollfd[0].revents & POLLIN) /* cancelled */ + break; + + len = read(fd, buffer, sizeof(buffer)); + + if (len > 0 && len % 4 == 0) + handle_midi_data(buffer, len); + } + return NULL; +} + +static UINT midi_in_open(WORD dev_id, MIDIOPENDESC *desc, UINT flags, struct notify_context *notify) +{ + struct midi_src *src; + int fd; + + TRACE("(%04X, %p, %08X);\n", dev_id, desc, flags); + + if (desc == NULL) + { + WARN("Invalid Parameter !\n"); + return MMSYSERR_INVALPARAM; + } + + /* FIXME : + * how to check that content of lpDesc is correct ? + */ + if (dev_id >= num_srcs) + { + WARN("wDevID 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 != 0) + { + WARN("device already open !\n"); + return MMSYSERR_ALLOCATED; + } + if ((flags & MIDI_IO_STATUS) != 0) + { + WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n"); + flags &= ~MIDI_IO_STATUS; + } + if ((flags & ~CALLBACK_TYPEMASK) != 0) + { + FIXME("Bad flags\n"); + return MMSYSERR_INVALFLAG; + } + + fd = seq_open(); + if (fd < 0) + return MMSYSERR_ERROR; + + if (num_midi_in_started++ == 0) + { + pipe(rec_cancel_pipe); + if (pthread_create(&rec_thread_id, NULL, rec_thread_proc, LongToPtr(fd))) + { + 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(fd); + return MMSYSERR_ERROR; + } + TRACE("Created thread for midi-in\n"); + } + + src->wFlags = HIWORD(flags & CALLBACK_TYPEMASK); + + src->lpQueueHdr = NULL; + src->midiDesc = *desc; + src->state = 0; + src->incLen = 0; + src->startTime = 0; + src->fd = fd; + + 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 == 0) + { + WARN("device not opened !\n"); + return MMSYSERR_ERROR; + } + if (src->lpQueueHdr != 0) + return MIDIERR_STILLPLAYING; + + if (src->fd == -1) + { + 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_close(src->fd); + src->fd = -1; + + set_in_notify(notify, src, dev_id, MIM_CLOSE, 0, 0); + src->midiDesc.hMidi = 0; + + return MMSYSERR_NOERROR; }
static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size) @@ -1544,6 +1693,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/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h index 90d0c47421c..d3dda7c76f2 100644 --- a/dlls/wineoss.drv/unixlib.h +++ b/dlls/wineoss.drv/unixlib.h @@ -209,27 +209,9 @@ struct is_started_params HRESULT result; };
-#include <mmddk.h> /* temporary */ - -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; - unsigned char incoming[3]; - unsigned char incPrev; - char incLen; - UINT startTime; - MIDIINCAPSW caps; - int fd; -} WINE_MIDIIN; - struct midi_init_params { UINT *err; - unsigned int num_srcs; - struct midi_src *srcs; };
struct notify_context @@ -273,18 +255,6 @@ struct midi_notify_wait_params struct notify_context *notify; };
-struct midi_seq_open_params -{ - int close; - int fd; -}; - -struct midi_handle_data_params -{ - unsigned char *buffer; - unsigned int len; -}; - enum oss_funcs { oss_test_connect, @@ -315,9 +285,6 @@ enum oss_funcs oss_midi_out_message, oss_midi_in_message, oss_midi_notify_wait, - - oss_midi_seq_open, /* temporary */ - oss_midi_handle_data, };
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN; @@ -325,8 +292,6 @@ NTSTATUS midi_release(void *args) DECLSPEC_HIDDEN; 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_open(void *args) DECLSPEC_HIDDEN; -NTSTATUS midi_handle_data(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t oss_handle;