18#define TIMESLICE_SIZE 60
26#define ALLOW_DUPLICATE_NOTES
41#define CONTINUOUS_NOTES
43#define WIN32_NO_STATUS
45#define COM_NO_WINDOWS_H
58#define DPRINT FakePrintf
61#define MIDI_NOTE_OFF 0x80
62#define MIDI_NOTE_ON 0x90
63#define MIDI_CONTROL_CHANGE 0xB0
64#define MIDI_PROGRAM 0xC0
65#define MIDI_PITCH_BEND 0xE0
66#define MIDI_SYSTEM 0xFF
69#define MIDI_RESET 0xFF
125 DPRINT(
"Note processing started\n");
129#ifdef CONTINUOUS_NOTES
142 DPRINT(
"%d notes active\n", (
int) device_info->playing_notes_count);
144 node = device_info->note_list;
149 DWORD actually_playing = 0;
159 if (device_info->playing_notes_count >
POLYPHONY)
162 actually_playing = device_info->playing_notes_count;
188 if ( device_info->refresh_notes )
190 device_info->refresh_notes =
FALSE;
246 DPRINT(
"Calling client - callback 0x%x mmhandle 0x%x\n", device_info->callback, device_info->mme_handle);
248 HIWORD(device_info->flags),
249 device_info->mme_handle,
251 device_info->instance,
279 DPRINT(
"Already allocated\n");
322 DPRINT(
"Out of memory\n");
349 DPRINT(
"CreateEvent failed\n");
363 DPRINT(
"CreateThread failed\n");
371 DPRINT(
"Sending MOM_OPEN\n");
388#ifdef CONTINUOUS_NOTES
390 SetEvent(device_info->work_available);
398 DPRINT(
"Sending MOM_CLOSE\n");
401 NtClose(device_info->kernel_device);
430 node = device_info->note_list;
438 DPRINT(
"Stopping note %d\n", (
int)
node->note);
440 if ( prev_node !=
NULL )
443 device_info->note_list =
node->
next;
447 device_info->playing_notes_count --;
449 DPRINT(
"Note stopped - now playing %d notes\n", (
int) device_info->playing_notes_count);
451#ifdef CONTINUOUS_NOTES
452 if (device_info->playing_notes_count == 0)
457 device_info->refresh_notes =
TRUE;
469#ifndef CONTINUOUS_NOTES
497 DPRINT(
"Zero velocity\n");
509 node = device_info->note_list;
513#ifndef ALLOW_DUPLICATE_NOTES
514 if ( (
node->note ==
note ) && ( velocity > 0 ) )
517 DPRINT(
"Duplicate note playback request ignored\n");
542 if ( device_info->note_list )
543 device_info->note_list->previous = new_node;
545 new_node->
next = device_info->note_list;
548 device_info->note_list = new_node;
549 device_info->playing_notes_count ++;
566#ifdef CONTINUOUS_NOTES
567 SetEvent(device_info->work_available);
572 DPRINT(
"Note started - now playing %d notes\n", (
int) device_info->playing_notes_count);
573 device_info->refresh_notes =
TRUE;
576#ifndef CONTINUOUS_NOTES
606 status = device_info->running_status;
654#define PACK_MIDI(b1, b2, b3) \
655 ((b3 * 65536) + (b2 * 256) + b1);
672 unsigned int index = 0;
675 unsigned int msg_index = 0;
683 DPRINT(
"Not prepared!\n");
687 DPRINT(
"Processing %d bytes of MIDI\n", (
int)
header->dwBufferLength);
689 while ( index < header->dwBufferLength )
692 if ( midi_bytes[
index] & 0x80 )
702 DPRINT(
"Complete msg is 0x%x %d %d\n", (
int)
msg[0], (
int)
msg[1], (
int)
msg[2]);
707 DPRINT(
"Set new running status\n");
708 device_info->running_status = midi_bytes[
index];
714 else if ( msg_index == 0 )
716 if ( device_info->running_status & 0x80 )
718 DPRINT(
"Retrieving running status\n");
719 msg[0] = device_info->running_status;
740 DPRINT(
"Complete msg is 0x%x %d %d\n", (
int)
msg[0], (
int)
msg[1], (
int)
msg[2]);
757 header->dwFlags &= ~ MHDR_INQUEUE;
783 DPRINT(
"MODM_GETNUMDEVS\n");
789 DPRINT(
"MODM_GETDEVCAPS\n");
824 hdr->dwFlags &= ~MHDR_PREPARED;
894 DPRINT(
"DRV_QUERYCONFIGURE\n");
898 DPRINT(
"DRV_CONFIGURE\n");
int note(char *format,...)
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
MMRESULT CloseDevice(DeviceInfo *device_info)
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
MMRESULT PlayNote(DeviceInfo *device_info, UCHAR note, UCHAR velocity)
void FakePrintf(char *str,...)
struct _DeviceInfo DeviceInfo
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
CRITICAL_SECTION device_lock
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
LONG FAR PASCAL DriverProc(DWORD driver_id, HDRVR driver_handle, UINT message, LONG parameter1, LONG parameter2)
#define PACK_MIDI(b1, b2, b3)
MMRESULT FAR PASCAL modMessage(UINT device_id, UINT message, DWORD_PTR private_data, DWORD_PTR parameter1, DWORD_PTR parameter2)
MMRESULT ProcessLongMidiMessage(DeviceInfo *device_info, MIDIHDR *header)
struct _NoteNode NoteNode
#define NT_SUCCESS(StatCode)
#define HeapFree(x, y, z)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
double pow(double x, double y)
#define DRV_QUERYCONFIGURE
#define MMSYSERR_NOTSUPPORTED
#define MIDIERR_UNPREPARED
#define MMSYSERR_ALLOCATED
#define InitializeObjectAttributes(p, n, a, r, s)
static LARGE_INTEGER * frequency
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
DWORD playing_notes_count
struct _NoteNode * previous
CHAR szPname[MAXPNAMELEN]
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
DWORD WINAPI GetLastError(void)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)