wineoss: Move the midi in data handlers to the unixlib.
The syscall itself is temporary. Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
31c5a82b5f
commit
60f9750442
|
@ -126,16 +126,6 @@ static LRESULT OSS_MidiExit(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void in_buffer_lock(void)
|
||||
{
|
||||
OSS_CALL(midi_in_lock, ULongToPtr(1));
|
||||
}
|
||||
|
||||
static void in_buffer_unlock(void)
|
||||
{
|
||||
OSS_CALL(midi_in_lock, ULongToPtr(0));
|
||||
}
|
||||
|
||||
static void notify_client(struct notify_context *notify)
|
||||
{
|
||||
TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n",
|
||||
|
@ -210,123 +200,13 @@ static int midiCloseSeq(int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void handle_sysex_data(struct midi_src *src, unsigned char value, UINT time)
|
||||
{
|
||||
MIDIHDR *hdr;
|
||||
BOOL done = FALSE;
|
||||
|
||||
src->state |= 2;
|
||||
src->incLen = 0;
|
||||
|
||||
in_buffer_lock();
|
||||
|
||||
hdr = src->lpQueueHdr;
|
||||
if (hdr)
|
||||
{
|
||||
BYTE *data = (BYTE *)hdr->lpData;
|
||||
|
||||
data[hdr->dwBytesRecorded++] = value;
|
||||
if (hdr->dwBytesRecorded == hdr->dwBufferLength)
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
if (value == 0xf7) /* end */
|
||||
{
|
||||
src->state &= ~2;
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
if (done && hdr)
|
||||
{
|
||||
src->lpQueueHdr = hdr->lpNext;
|
||||
hdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
hdr->dwFlags |= MHDR_DONE;
|
||||
MIDI_NotifyClient(src - MidiInDev, MIM_LONGDATA, (UINT_PTR)hdr, time);
|
||||
}
|
||||
|
||||
in_buffer_unlock();
|
||||
}
|
||||
|
||||
static void handle_regular_data(struct midi_src *src, unsigned char value, UINT time)
|
||||
{
|
||||
UINT to_send = 0;
|
||||
|
||||
#define IS_CMD(_x) (((_x) & 0x80) == 0x80)
|
||||
#define IS_SYS_CMD(_x) (((_x) & 0xF0) == 0xF0)
|
||||
|
||||
if (!IS_CMD(value) && src->incLen == 0) /* try to reuse old cmd */
|
||||
{
|
||||
if (IS_CMD(src->incPrev) && !IS_SYS_CMD(src->incPrev))
|
||||
{
|
||||
src->incoming[0] = src->incPrev;
|
||||
src->incLen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: should generate MIM_ERROR notification */
|
||||
return;
|
||||
}
|
||||
}
|
||||
src->incoming[(int)src->incLen++] = value;
|
||||
if (src->incLen == 1 && !IS_SYS_CMD(src->incoming[0]))
|
||||
/* store new cmd, just in case */
|
||||
src->incPrev = src->incoming[0];
|
||||
|
||||
#undef IS_CMD
|
||||
#undef IS_SYS_CMD
|
||||
|
||||
switch (src->incoming[0] & 0xF0)
|
||||
{
|
||||
case MIDI_NOTEOFF:
|
||||
case MIDI_NOTEON:
|
||||
case MIDI_KEY_PRESSURE:
|
||||
case MIDI_CTL_CHANGE:
|
||||
case MIDI_PITCH_BEND:
|
||||
if (src->incLen == 3)
|
||||
to_send = (src->incoming[2] << 16) | (src->incoming[1] << 8) |
|
||||
src->incoming[0];
|
||||
break;
|
||||
case MIDI_PGM_CHANGE:
|
||||
case MIDI_CHN_PRESSURE:
|
||||
if (src->incLen == 2)
|
||||
to_send = (src->incoming[1] << 8) | src->incoming[0];
|
||||
break;
|
||||
case MIDI_SYSTEM_PREFIX:
|
||||
if (src->incLen == 1)
|
||||
to_send = src->incoming[0];
|
||||
break;
|
||||
}
|
||||
|
||||
if (to_send)
|
||||
{
|
||||
src->incLen = 0;
|
||||
MIDI_NotifyClient(src - MidiInDev, MIM_DATA, to_send, time);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_midi_data(unsigned char *buffer, unsigned int len)
|
||||
{
|
||||
unsigned int time = GetTickCount(), i;
|
||||
struct midi_src *src;
|
||||
unsigned char value;
|
||||
WORD dev_id;
|
||||
struct midi_handle_data_params params;
|
||||
|
||||
for (i = 0; i < len; i += (buffer[i] & 0x80) ? 8 : 4)
|
||||
{
|
||||
if (buffer[i] != SEQ_MIDIPUTC) continue;
|
||||
|
||||
dev_id = buffer[i + 2];
|
||||
value = buffer[i + 1];
|
||||
|
||||
if (dev_id >= MIDM_NumDevs) continue;
|
||||
src = MidiInDev + dev_id;
|
||||
if (src->state <= 0) continue;
|
||||
|
||||
if (value == 0xf0 || src->state & 2) /* system exclusive */
|
||||
handle_sysex_data(src, value, time - src->startTime);
|
||||
else
|
||||
handle_regular_data(src, value, time - src->startTime);
|
||||
}
|
||||
params.buffer = buffer;
|
||||
params.len = len;
|
||||
OSS_CALL(midi_handle_data, ¶ms);
|
||||
}
|
||||
|
||||
static DWORD WINAPI midRecThread(void *arg)
|
||||
|
@ -565,6 +445,7 @@ static DWORD WINAPI notify_thread(void *p)
|
|||
{
|
||||
OSS_CALL(midi_notify_wait, ¶ms);
|
||||
if (quit) break;
|
||||
if (notify.send_notify) notify_client(¬ify);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1412,5 +1412,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
|
|||
midi_notify_wait,
|
||||
|
||||
midi_seq_open,
|
||||
midi_in_lock,
|
||||
midi_handle_data,
|
||||
};
|
||||
|
|
|
@ -68,7 +68,11 @@ static struct midi_src srcs[MAX_MIDIINDRV];
|
|||
|
||||
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;
|
||||
static BOOL notify_quit;
|
||||
#define NOTIFY_BUFFER_SIZE 64 + 1 /* + 1 for the sentinel */
|
||||
static struct notify_context notify_buffer[NOTIFY_BUFFER_SIZE];
|
||||
static struct notify_context *notify_read = notify_buffer, *notify_write = notify_buffer;
|
||||
|
||||
typedef struct sVoice
|
||||
{
|
||||
|
@ -151,19 +155,59 @@ static void in_buffer_unlock(void)
|
|||
pthread_mutex_unlock(&in_buffer_mutex);
|
||||
}
|
||||
|
||||
NTSTATUS midi_in_lock(void *args)
|
||||
/*
|
||||
* notify buffer: The notification ring buffer is implemented so that
|
||||
* there is always at least one unused sentinel before the current
|
||||
* read position in order to allow detection of the full vs empty
|
||||
* state.
|
||||
*/
|
||||
static struct notify_context *notify_buffer_next(struct notify_context *notify)
|
||||
{
|
||||
if (args) in_buffer_lock();
|
||||
else in_buffer_unlock();
|
||||
if (++notify >= notify_buffer + ARRAY_SIZE(notify_buffer))
|
||||
notify = notify_buffer;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return notify;
|
||||
}
|
||||
|
||||
static BOOL notify_buffer_empty(void)
|
||||
{
|
||||
return notify_read == notify_write;
|
||||
}
|
||||
|
||||
static BOOL notify_buffer_full(void)
|
||||
{
|
||||
return notify_buffer_next(notify_write) == notify_read;
|
||||
}
|
||||
|
||||
static BOOL notify_buffer_add(struct notify_context *notify)
|
||||
{
|
||||
if (notify_buffer_full()) return FALSE;
|
||||
|
||||
*notify_write = *notify;
|
||||
notify_write = notify_buffer_next(notify_write);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL notify_buffer_remove(struct notify_context *notify)
|
||||
{
|
||||
if (notify_buffer_empty()) return FALSE;
|
||||
|
||||
*notify = *notify_read;
|
||||
notify_read = notify_buffer_next(notify_read);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void notify_post(struct notify_context *notify)
|
||||
{
|
||||
pthread_mutex_lock(¬ify_mutex);
|
||||
|
||||
if (notify) FIXME("Not yet handled\n");
|
||||
if (notify)
|
||||
{
|
||||
while (notify_buffer_full())
|
||||
pthread_cond_wait(¬ify_write_cond, ¬ify_mutex);
|
||||
|
||||
notify_buffer_add(notify);
|
||||
}
|
||||
else notify_quit = TRUE;
|
||||
pthread_cond_signal(¬ify_read_cond);
|
||||
|
||||
|
@ -1157,6 +1201,133 @@ static UINT midi_out_reset(WORD dev_id)
|
|||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
static void handle_sysex_data(struct midi_src *src, unsigned char value, UINT time)
|
||||
{
|
||||
struct notify_context notify;
|
||||
MIDIHDR *hdr;
|
||||
BOOL done = FALSE;
|
||||
|
||||
src->state |= 2;
|
||||
src->incLen = 0;
|
||||
|
||||
in_buffer_lock();
|
||||
|
||||
hdr = src->lpQueueHdr;
|
||||
if (hdr)
|
||||
{
|
||||
BYTE *data = (BYTE *)hdr->lpData;
|
||||
|
||||
data[hdr->dwBytesRecorded++] = value;
|
||||
if (hdr->dwBytesRecorded == hdr->dwBufferLength)
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
if (value == 0xf7) /* end */
|
||||
{
|
||||
src->state &= ~2;
|
||||
done = TRUE;
|
||||
}
|
||||
|
||||
if (done && hdr)
|
||||
{
|
||||
src->lpQueueHdr = hdr->lpNext;
|
||||
hdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
hdr->dwFlags |= MHDR_DONE;
|
||||
set_in_notify(¬ify, src, src - srcs, MIM_LONGDATA, (UINT_PTR)hdr, time);
|
||||
notify_post(¬ify);
|
||||
}
|
||||
|
||||
in_buffer_unlock();
|
||||
}
|
||||
|
||||
static void handle_regular_data(struct midi_src *src, unsigned char value, UINT time)
|
||||
{
|
||||
struct notify_context notify;
|
||||
UINT to_send = 0;
|
||||
|
||||
#define IS_CMD(_x) (((_x) & 0x80) == 0x80)
|
||||
#define IS_SYS_CMD(_x) (((_x) & 0xF0) == 0xF0)
|
||||
|
||||
if (!IS_CMD(value) && src->incLen == 0) /* try to reuse old cmd */
|
||||
{
|
||||
if (IS_CMD(src->incPrev) && !IS_SYS_CMD(src->incPrev))
|
||||
{
|
||||
src->incoming[0] = src->incPrev;
|
||||
src->incLen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: should generate MIM_ERROR notification */
|
||||
return;
|
||||
}
|
||||
}
|
||||
src->incoming[(int)src->incLen++] = value;
|
||||
if (src->incLen == 1 && !IS_SYS_CMD(src->incoming[0]))
|
||||
/* store new cmd, just in case */
|
||||
src->incPrev = src->incoming[0];
|
||||
|
||||
#undef IS_CMD
|
||||
#undef IS_SYS_CMD
|
||||
|
||||
switch (src->incoming[0] & 0xF0)
|
||||
{
|
||||
case MIDI_NOTEOFF:
|
||||
case MIDI_NOTEON:
|
||||
case MIDI_KEY_PRESSURE:
|
||||
case MIDI_CTL_CHANGE:
|
||||
case MIDI_PITCH_BEND:
|
||||
if (src->incLen == 3)
|
||||
to_send = (src->incoming[2] << 16) | (src->incoming[1] << 8) |
|
||||
src->incoming[0];
|
||||
break;
|
||||
case MIDI_PGM_CHANGE:
|
||||
case MIDI_CHN_PRESSURE:
|
||||
if (src->incLen == 2)
|
||||
to_send = (src->incoming[1] << 8) | src->incoming[0];
|
||||
break;
|
||||
case MIDI_SYSTEM_PREFIX:
|
||||
if (src->incLen == 1)
|
||||
to_send = src->incoming[0];
|
||||
break;
|
||||
}
|
||||
|
||||
if (to_send)
|
||||
{
|
||||
src->incLen = 0;
|
||||
set_in_notify(¬ify, src, src - srcs, MIM_DATA, to_send, time);
|
||||
notify_post(¬ify);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS midi_handle_data(void *args)
|
||||
{
|
||||
struct midi_handle_data_params *params = args;
|
||||
unsigned char *buffer = params->buffer;
|
||||
unsigned int len = params->len;
|
||||
unsigned int time = NtGetTickCount(), i;
|
||||
struct midi_src *src;
|
||||
unsigned char value;
|
||||
WORD dev_id;
|
||||
|
||||
for (i = 0; i < len; i += (buffer[i] & 0x80) ? 8 : 4)
|
||||
{
|
||||
if (buffer[i] != SEQ_MIDIPUTC) continue;
|
||||
|
||||
dev_id = buffer[i + 2];
|
||||
value = buffer[i + 1];
|
||||
|
||||
if (dev_id >= num_srcs) continue;
|
||||
src = srcs + dev_id;
|
||||
if (src->state <= 0) continue;
|
||||
|
||||
if (value == 0xf0 || src->state & 2) /* system exclusive */
|
||||
handle_sysex_data(src, value, time - src->startTime);
|
||||
else
|
||||
handle_regular_data(src, value, time - src->startTime);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
|
||||
{
|
||||
struct midi_src *src;
|
||||
|
@ -1397,11 +1568,15 @@ NTSTATUS midi_notify_wait(void *args)
|
|||
|
||||
pthread_mutex_lock(¬ify_mutex);
|
||||
|
||||
while (!notify_quit)
|
||||
while (!notify_quit && notify_buffer_empty())
|
||||
pthread_cond_wait(¬ify_read_cond, ¬ify_mutex);
|
||||
|
||||
*params->quit = notify_quit;
|
||||
|
||||
if (!notify_quit)
|
||||
{
|
||||
notify_buffer_remove(params->notify);
|
||||
pthread_cond_signal(¬ify_write_cond);
|
||||
}
|
||||
pthread_mutex_unlock(¬ify_mutex);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -279,6 +279,12 @@ struct midi_seq_open_params
|
|||
int fd;
|
||||
};
|
||||
|
||||
struct midi_handle_data_params
|
||||
{
|
||||
unsigned char *buffer;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
enum oss_funcs
|
||||
{
|
||||
oss_test_connect,
|
||||
|
@ -311,7 +317,7 @@ enum oss_funcs
|
|||
oss_midi_notify_wait,
|
||||
|
||||
oss_midi_seq_open, /* temporary */
|
||||
oss_midi_in_lock,
|
||||
oss_midi_handle_data,
|
||||
};
|
||||
|
||||
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
|
||||
|
@ -320,7 +326,7 @@ 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_in_lock(void *args) DECLSPEC_HIDDEN;
|
||||
NTSTATUS midi_handle_data(void *args) DECLSPEC_HIDDEN;
|
||||
|
||||
extern unixlib_handle_t oss_handle;
|
||||
|
||||
|
|
Loading…
Reference in New Issue