ReactOS 0.4.15-dev-7968-g24a56f8
beepmidi.c
Go to the documentation of this file.
1/*
2 BeepMidi :: beep.sys MIDI player
3
4 (c) Andrew Greenwood, 2007.
5
6 Released as open-source software. You may copy, re-distribute and modify
7 this software, provided this copyright notice remains intact.
8
9 Please see the included README.TXT for more information
10
11 HISTORY :
12 16th January 2007 Started
13 17th January 2007 Polyphony support and threading added
14 18th January 2007 Made threading optional, added comments
15*/
16
17/* The timeslice to allocate for all playing notes (in milliseconds) */
18#define TIMESLICE_SIZE 60
19
20/*
21 If this is defined, notes are added to the playing list, even if
22 they already exist. As a result, the note will sound twice during
23 each timeslice. Also each note on will require a corresponding note
24 off event.
25*/
26#define ALLOW_DUPLICATE_NOTES
27
28/*
29 The maximum number of notes that may be playing at any one time.
30 Higher values result in a messier sound as all the frequencies get
31 mashed together. Do not set this below 2. Recommended = 4
32*/
33#define POLYPHONY 3
34
35/*
36 Define CONTINUOUS_NOTES to perform note playback in a separate thread.
37 This was originally the intended behaviour, but after experimentation
38 doesn't sound as good for MIDI files which have a lot going on. If not
39 defined, all playing notes are output in sequence as a new note starts.
40*/
41#define CONTINUOUS_NOTES
42
43#define WIN32_NO_STATUS
44#define _INC_WINDOWS
45#define COM_NO_WINDOWS_H
46#include <stdarg.h>
47#include <windef.h>
48#include <winbase.h>
49#define NTOS_MODE_USER
50#include <ndk/iofuncs.h>
51#include <ndk/obfuncs.h>
52#include <ndk/rtlfuncs.h>
53#include <ntddbeep.h>
54#include <math.h>
55#include <mmddk.h>
56
57/*#define DPRINT printf*/
58#define DPRINT FakePrintf
59
60/* A few MIDI command categories */
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
67
68/* Specific commands */
69#define MIDI_RESET 0xFF
70
71
72typedef struct _NoteNode
73{
74 struct _NoteNode* next;
76
78 UCHAR velocity; /* 0 is note-off */
80
81typedef struct _DeviceInfo
82{
85
89
91
95
100
103
104void
105FakePrintf(char* str, ...)
106{
107 /* Just to shut the compiler up */
108}
109
110
111/*
112 This is designed to be treated as a thread, however it behaves as a
113 normal function if CONTINUOUS_NOTES is not defined.
114*/
115
118 LPVOID parameter)
119{
120 DeviceInfo* device_info = (DeviceInfo*) parameter;
122 IO_STATUS_BLOCK io_status_block;
123 DWORD arp_notes;
124
125 DPRINT("Note processing started\n");
126
127 /* We lock the note list only while accessing it */
128
129#ifdef CONTINUOUS_NOTES
130 while ( WaitForSingleObject(the_device->work_available, INFINITE), !device_info->terminate_thread )
131#endif
132 {
133 NoteNode* node;
134
135 /* Number of notes being arpeggiated */
136 arp_notes = 1;
137
139
140 /* Calculate how much time to allocate to each playing note */
141
142 DPRINT("%d notes active\n", (int) device_info->playing_notes_count);
143
144 node = device_info->note_list;
145
146 while ( ( node != NULL ) && ( arp_notes <= POLYPHONY ) )
147 {
148 BEEP_SET_PARAMETERS beep_data;
149 DWORD actually_playing = 0;
150
151 double frequency = node->note;
152
153 DPRINT("playing..\n");
154
155 frequency = frequency / 12;
156 frequency = pow(2, frequency);
157 frequency = 8.1758 * frequency;
158
159 if (device_info->playing_notes_count > POLYPHONY)
160 actually_playing = POLYPHONY;
161 else
162 actually_playing = device_info->playing_notes_count;
163
164 DPRINT("Frequency %f\n", frequency);
165
166 // TODO
167 beep_data.Frequency = (DWORD) frequency;
168 beep_data.Duration = TIMESLICE_SIZE / actually_playing; /* device_info->playing_notes_count; */
169
170 status = NtDeviceIoControlFile(device_info->kernel_device,
171 NULL,
172 NULL,
173 NULL,
174 &io_status_block,
176 &beep_data,
177 sizeof(BEEP_SET_PARAMETERS),
178 NULL,
179 0);
180
181 if ( ! NT_SUCCESS(status) )
182 {
183 DPRINT("ERROR %d\n", (int) GetLastError());
184 }
185
186 SleepEx(beep_data.Duration, TRUE);
187
188 if ( device_info->refresh_notes )
189 {
190 device_info->refresh_notes = FALSE;
191 break;
192 }
193
194 arp_notes ++;
195 node = node->next;
196 }
197
199 }
200
201 return 0;
202}
203
204
205/*
206 Fills a MIDIOUTCAPS structure with information about our device.
207*/
208
211 MIDIOUTCAPS* caps)
212{
213 /* These are ignored for now */
214 caps->wMid = 0;
215 caps->wPid = 0;
216
217 caps->vDriverVersion = 0x0100;
218
219 memset(caps->szPname, 0, sizeof(caps->szPname));
220 wcscpy(caps->szPname, L"PC speaker");
221
222 caps->wTechnology = MOD_SQSYNTH;
223
224 caps->wVoices = 1; /* We only have one voice */
225 caps->wNotes = POLYPHONY;
226 caps->wChannelMask = 0xFFBF; /* Ignore channel 10 */
227
228 caps->dwSupport = 0;
229
230 return MMSYSERR_NOERROR;
231}
232
233
234/*
235 Helper function that just simplifies calling the application making use
236 of us.
237*/
238
239BOOL
241 DeviceInfo* device_info,
243 DWORD_PTR parameter1,
244 DWORD_PTR parameter2)
245{
246 DPRINT("Calling client - callback 0x%x mmhandle 0x%x\n", device_info->callback, device_info->mme_handle);
247 return DriverCallback(device_info->callback,
248 HIWORD(device_info->flags),
249 device_info->mme_handle,
250 message,
251 device_info->instance,
252 parameter1,
253 parameter2);
254
255}
256
257
258/*
259 Open the kernel-mode device and allocate resources. This opens the
260 BEEP.SYS kernel device.
261*/
262
265 DeviceInfo** private_data,
266 MIDIOPENDESC* open_desc,
267 DWORD flags)
268{
270 HANDLE heap;
271 HANDLE kernel_device;
272 UNICODE_STRING beep_device_name;
274 IO_STATUS_BLOCK status_block;
275
276 /* One at a time.. */
277 if ( the_device )
278 {
279 DPRINT("Already allocated\n");
280 return MMSYSERR_ALLOCATED;
281 }
282
283 /* Make the device name into a unicode string and open it */
284
285 RtlInitUnicodeString(&beep_device_name,
286 L"\\Device\\Beep");
287
289 &beep_device_name,
290 0,
291 NULL,
292 NULL);
293
294 status = NtCreateFile(&kernel_device,
296 &attribs,
297 &status_block,
298 NULL,
299 0,
302 0,
303 NULL,
304 0);
305
306 if ( ! NT_SUCCESS(status) )
307 {
308 DPRINT("Could not connect to BEEP device - %d\n", (int) GetLastError());
309 return MMSYSERR_ERROR;
310 }
311
312 DPRINT("Opened!\n");
313
314 /* Allocate and initialize the device info */
315
317
319
320 if ( ! the_device )
321 {
322 DPRINT("Out of memory\n");
323 return MMSYSERR_NOMEM;
324 }
325
326 /* Initialize */
327 the_device->kernel_device = kernel_device;
328 the_device->playing_notes_count = 0;
329 the_device->note_list = NULL;
330 the_device->thread_handle = 0;
331 the_device->terminate_thread = FALSE;
332 the_device->running_status = 0;
333
334 // TODO
335 the_device->mme_handle = (HDRVR) open_desc->hMidi;
336 the_device->callback = open_desc->dwCallback;
337 the_device->instance = open_desc->dwInstance;
338 the_device->flags = flags;
339
340 /* Store the pointer in the user data */
341 *private_data = the_device;
342
343 /* This is threading-related code */
344#ifdef CONTINUOUS_NOTES
345 the_device->work_available = CreateEvent(NULL, TRUE, FALSE, NULL);
346
347 if ( ! the_device->work_available )
348 {
349 DPRINT("CreateEvent failed\n");
351 return MMSYSERR_NOMEM;
352 }
353
354 the_device->thread_handle = CreateThread(NULL,
355 0,
358 0,
359 NULL);
360
361 if ( ! the_device->thread_handle )
362 {
363 DPRINT("CreateThread failed\n");
364 CloseHandle(the_device->work_available);
366 return MMSYSERR_NOMEM;
367 }
368#endif
369
370 /* Now we call the client application to say the device is open */
371 DPRINT("Sending MOM_OPEN\n");
372 DPRINT("Success? %d\n", (int) CallClient(the_device, MOM_OPEN, 0, 0));
373
374 return MMSYSERR_NOERROR;
375}
376
377
378/*
379 Close the kernel-mode device.
380*/
381
384{
386
387 /* If we're working in threaded mode we need to wait for thread to die */
388#ifdef CONTINUOUS_NOTES
389 the_device->terminate_thread = TRUE;
390 SetEvent(device_info->work_available);
391
392 WaitForSingleObject(the_device->thread_handle, INFINITE);
393 CloseHandle(the_device->thread_handle);
394 CloseHandle(the_device->work_available);
395#endif
396
397 /* Let the client application know the device is closing */
398 DPRINT("Sending MOM_CLOSE\n");
399 CallClient(device_info, MOM_CLOSE, 0, 0);
400
401 NtClose(device_info->kernel_device);
402
403 /* Free resources */
404 HeapFree(heap, 0, device_info);
405
407
408 return MMSYSERR_NOERROR;
409}
410
411
412/*
413 Removes a note from the playing notes list. If the note is not playing,
414 we just pretend nothing happened.
415*/
416
419 DeviceInfo* device_info,
420 UCHAR note)
421{
423 NoteNode* node;
424 NoteNode* prev_node = NULL;
425
426 DPRINT("StopNote\n");
427
429
430 node = device_info->note_list;
431
432 while ( node != NULL )
433 {
434 if ( node->note == note )
435 {
436 /* Found the note - just remove the node from the list */
437
438 DPRINT("Stopping note %d\n", (int) node->note);
439
440 if ( prev_node != NULL )
441 prev_node->next = node->next;
442 else
443 device_info->note_list = node->next;
444
445 HeapFree(heap, 0, node);
446
447 device_info->playing_notes_count --;
448
449 DPRINT("Note stopped - now playing %d notes\n", (int) device_info->playing_notes_count);
450
451#ifdef CONTINUOUS_NOTES
452 if (device_info->playing_notes_count == 0)
453 ResetEvent(device_info->work_available);
454#endif
455
457 device_info->refresh_notes = TRUE;
458
459 return MMSYSERR_NOERROR;
460 }
461
462 prev_node = node;
463 node = node->next;
464 }
465
467
468 /* Hmm, a good idea? */
469#ifndef CONTINUOUS_NOTES
470 ProcessPlayingNotes((PVOID) device_info);
471#endif
472
473 return MMSYSERR_NOERROR;
474}
475
476
477/*
478 Adds a note to the playing notes list. If the note is already playing,
479 the definition of ALLOW_DUPLICATE_NOTES determines if an existing note
480 may be duplicated. Otherwise, duplicate notes are ignored.
481*/
482
485 DeviceInfo* device_info,
486 UCHAR note,
487 UCHAR velocity)
488{
490
491 NoteNode* node;
492
493 DPRINT("PlayNote\n");
494
495 if ( velocity == 0 )
496 {
497 DPRINT("Zero velocity\n");
498
499 /* Velocity zero is effectively a "note off" */
500 StopNote(device_info, note);
501 }
502 else
503 {
504 /* Start playing the note */
505 NoteNode* new_node;
506
508
509 node = device_info->note_list;
510
511 while ( node != NULL )
512 {
513#ifndef ALLOW_DUPLICATE_NOTES
514 if ( ( node->note == note ) && ( velocity > 0 ) )
515 {
516 /* The note is already playing - do nothing */
517 DPRINT("Duplicate note playback request ignored\n");
519 return MMSYSERR_NOERROR;
520 }
521#endif
522
523 node = node->next;
524 }
525
526 new_node = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(NoteNode));
527
528 if ( ! new_node )
529 {
531 return MMSYSERR_NOMEM;
532 }
533
534 new_node->note = note;
535 new_node->velocity = velocity;
536
537 /*
538 Prepend to the playing notes list. If exceeding polyphony,
539 remove the oldest note (which will be at the tail.)
540 */
541
542 if ( device_info->note_list )
543 device_info->note_list->previous = new_node;
544
545 new_node->next = device_info->note_list;
546 new_node->previous = NULL;
547
548 device_info->note_list = new_node;
549 device_info->playing_notes_count ++;
550
551/*
552 if ( device_info->playing_notes_count > POLYPHONY )
553 {
554 ASSERT(tail_node);
555
556 DPRINT("Polyphony exceeded\n");
557
558 tail_node->previous->next = NULL;
559
560 HeapFree(heap, 0, tail_node);
561
562 device_info->playing_notes_count --;
563 }
564*/
565
566#ifdef CONTINUOUS_NOTES
567 SetEvent(device_info->work_available);
568#endif
569
571
572 DPRINT("Note started - now playing %d notes\n", (int) device_info->playing_notes_count);
573 device_info->refresh_notes = TRUE;
574 }
575
576#ifndef CONTINUOUS_NOTES
577 ProcessPlayingNotes((PVOID) device_info);
578#endif
579
580 return MMSYSERR_NOERROR;
581}
582
583/*
584 Decipher a short MIDI message (which is a MIDI message packed into a DWORD.)
585 This will set "running status", but does not take this into account when
586 processing messages (is this necessary?)
587*/
588
591 DeviceInfo* device_info,
593{
595
597 DWORD channel;
599
600 status = message & 0x000000FF;
601
602 /* Deal with running status */
603
604 if ( status < MIDI_NOTE_OFF )
605 {
606 status = device_info->running_status;
607 }
608
609 /* Ensure the status is sane! */
610
611 if ( status < MIDI_NOTE_OFF )
612 {
613 /* It's garbage, ignore it */
614 return MMSYSERR_NOERROR;
615 }
616
617 /* Figure out the message category and channel */
618
619 category = status & 0xF0;
620 channel = status & 0x0F; /* we don't use this */
621
622 data1 = (message & 0x0000FF00) >> 8;
623 data2 = (message & 0x00FF0000) >> 16;
624
625 DPRINT("0x%x, %d, %d\n", (int) status, (int) data1, (int) data2);
626
627 /* Filter drums (which are *usually* on channel 10) */
628 if ( channel == 10 )
629 {
630 return MMSYSERR_NOERROR;
631 }
632
633 /* Pass to the appropriate message handler */
634
635 switch ( category )
636 {
637 case MIDI_NOTE_ON :
638 {
639 PlayNote(device_info, data1, data2);
640 break;
641 }
642
643 case MIDI_NOTE_OFF :
644 {
645 StopNote(device_info, data1);
646 break;
647 }
648 }
649
650 return MMSYSERR_NOERROR;
651}
652
653
654#define PACK_MIDI(b1, b2, b3) \
655 ((b3 * 65536) + (b2 * 256) + b1);
656
657
658/*
659 Processes a "long" MIDI message (ie, a MIDI message contained within a
660 buffer.) This is intended for supporting SysEx data, or blocks of MIDI
661 events. However in our case we're only interested in short MIDI messages,
662 so we scan the buffer, and each time we encounter a valid status byte
663 we start recording it as a new event. Once 3 bytes or a new status is
664 received, the event is passed to the short message handler.
665*/
666
669 DeviceInfo* device_info,
671{
672 unsigned int index = 0;
673 UCHAR* midi_bytes = (UCHAR*) header->lpData;
674
675 unsigned int msg_index = 0;
676 UCHAR msg[3];
677
678 /* Initialize the buffer */
679 msg[0] = msg[1] = msg[2] = 0;
680
681 if ( ! ( header->dwFlags & MHDR_PREPARED ) )
682 {
683 DPRINT("Not prepared!\n");
684 return MIDIERR_UNPREPARED;
685 }
686
687 DPRINT("Processing %d bytes of MIDI\n", (int) header->dwBufferLength);
688
689 while ( index < header->dwBufferLength )
690 {
691 /* New status byte? ( = new event) */
692 if ( midi_bytes[index] & 0x80 )
693 {
694 DWORD short_msg;
695
696 /* Deal with the existing event */
697
698 if ( msg[0] & 0x80 )
699 {
700 short_msg = PACK_MIDI(msg[0], msg[1], msg[2]);
701
702 DPRINT("Complete msg is 0x%x %d %d\n", (int) msg[0], (int) msg[1], (int) msg[2]);
703 ProcessShortMidiMessage(device_info, short_msg);
704 }
705
706 /* Set new running status and start recording the event */
707 DPRINT("Set new running status\n");
708 device_info->running_status = midi_bytes[index];
709 msg[0] = midi_bytes[index];
710 msg_index = 1;
711 }
712
713 /* Unexpected data byte? ( = re-use previous status) */
714 else if ( msg_index == 0 )
715 {
716 if ( device_info->running_status & 0x80 )
717 {
718 DPRINT("Retrieving running status\n");
719 msg[0] = device_info->running_status;
720 msg[1] = midi_bytes[index];
721 msg_index = 2;
722 }
723 else
724 DPRINT("garbage\n");
725 }
726
727 /* Expected data ( = append to message until buffer full) */
728 else
729 {
730 DPRINT("Next byte...\n");
731 msg[msg_index] = midi_bytes[index];
732 msg_index ++;
733
734 if ( msg_index > 2 )
735 {
736 DWORD short_msg;
737
738 short_msg = PACK_MIDI(msg[0], msg[1], msg[2]);
739
740 DPRINT("Complete msg is 0x%x %d %d\n", (int) msg[0], (int) msg[1], (int) msg[2]);
741 ProcessShortMidiMessage(device_info, short_msg);
742
743 /* Reinit */
744 msg_index = 0;
745 msg[0] = msg[1] = msg[2] = 0;
746 }
747 }
748
749 index ++;
750 }
751
752 /*
753 We're meant to clear MHDR_DONE and set MHDR_INQUEUE but since we
754 deal with everything here and now we might as well just say so.
755 */
756 header->dwFlags |= MHDR_DONE;
757 header->dwFlags &= ~ MHDR_INQUEUE;
758
759 DPRINT("Success? %d\n", CallClient(the_device, MOM_DONE, (DWORD_PTR) header, 0));
760
761 return MMSYSERR_NOERROR;
762}
763
764
765/*
766 Exported function that receives messages from WINMM (the MME API.)
767*/
768
772 UINT device_id,
774 DWORD_PTR private_data,
775 DWORD_PTR parameter1,
776 DWORD_PTR parameter2)
777{
778 switch ( message )
779 {
780 case MODM_GETNUMDEVS :
781 {
782 /* Only one internal PC speaker device (and even that's too much) */
783 DPRINT("MODM_GETNUMDEVS\n");
784 return 1;
785 }
786
787 case MODM_GETDEVCAPS :
788 {
789 DPRINT("MODM_GETDEVCAPS\n");
790 return GetDeviceCapabilities((MIDIOUTCAPS*) parameter1);
791 }
792
793 case MODM_OPEN :
794 {
795 DPRINT("MODM_OPEN\n");
796
797 return OpenDevice((DeviceInfo**) private_data,
798 (MIDIOPENDESC*) parameter1,
799 parameter2);
800 }
801
802 case MODM_CLOSE :
803 {
804 DPRINT("MODM_CLOSE\n");
805 return CloseDevice((DeviceInfo*) private_data);
806 }
807
808 case MODM_DATA :
809 {
810 return ProcessShortMidiMessage((DeviceInfo*) private_data, parameter1);
811 }
812
813 case MODM_PREPARE :
814 {
815 /* We don't bother with this */
816 MIDIHDR* hdr = (MIDIHDR*) parameter1;
817 hdr->dwFlags |= MHDR_PREPARED;
818 return MMSYSERR_NOERROR;
819 }
820
821 case MODM_UNPREPARE :
822 {
823 MIDIHDR* hdr = (MIDIHDR*) parameter1;
824 hdr->dwFlags &= ~MHDR_PREPARED;
825 return MMSYSERR_NOERROR;
826 }
827
828 case MODM_LONGDATA :
829 {
830 DPRINT("LONGDATA\n");
831 return ProcessLongMidiMessage((DeviceInfo*) private_data, (MIDIHDR*) parameter1);
832 }
833
834 case MODM_RESET :
835 {
836 /* TODO */
837 break;
838 }
839 }
840
841 DPRINT("Not supported %d\n", message);
842
844}
845
846
847/*
848 Driver entrypoint.
849*/
850
851LONG
854 DWORD driver_id,
855 HDRVR driver_handle,
857 LONG parameter1,
858 LONG parameter2)
859{
860 switch ( message )
861 {
862 case DRV_LOAD :
863 DPRINT("DRV_LOAD\n");
865 return 1L;
866
867 case DRV_FREE :
868 DPRINT("DRV_FREE\n");
869 return 1L;
870
871 case DRV_OPEN :
872 DPRINT("DRV_OPEN\n");
874 return 1L;
875
876 case DRV_CLOSE :
877 DPRINT("DRV_CLOSE\n");
878 return 1L;
879
880 case DRV_ENABLE :
881 DPRINT("DRV_ENABLE\n");
882 return 1L;
883
884 case DRV_DISABLE :
885 DPRINT("DRV_DISABLE\n");
886 return 1L;
887
888 /*
889 We don't provide configuration capabilities. This used to be
890 for things like I/O port, IRQ, DMA settings, etc.
891 */
892
893 case DRV_QUERYCONFIGURE :
894 DPRINT("DRV_QUERYCONFIGURE\n");
895 return 0L;
896
897 case DRV_CONFIGURE :
898 DPRINT("DRV_CONFIGURE\n");
899 return 0L;
900
901 case DRV_INSTALL :
902 DPRINT("DRV_INSTALL\n");
903 return DRVCNF_RESTART;
904 };
905
906 DPRINT("???\n");
907
908 return DefDriverProc(driver_id,
909 driver_handle,
910 message,
911 parameter1,
912 parameter2);
913}
#define msg(x)
Definition: auth_time.c:54
LONG NTSTATUS
Definition: precomp.h:26
#define index(s, c)
Definition: various.h:29
int note(char *format,...)
Definition: util.c:12
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210
#define CONTINUOUS_NOTES
Definition: beepmidi.c:41
#define DPRINT
Definition: beepmidi.c:58
MMRESULT CloseDevice(DeviceInfo *device_info)
Definition: beepmidi.c:383
DeviceInfo * the_device
Definition: beepmidi.c:101
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
Definition: beepmidi.c:418
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
Definition: beepmidi.c:590
MMRESULT PlayNote(DeviceInfo *device_info, UCHAR note, UCHAR velocity)
Definition: beepmidi.c:484
void FakePrintf(char *str,...)
Definition: beepmidi.c:105
#define TIMESLICE_SIZE
Definition: beepmidi.c:18
struct _DeviceInfo DeviceInfo
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:240
LONG FAR PASCAL DriverProc(DWORD driver_id, HDRVR driver_handle, UINT message, LONG parameter1, LONG parameter2)
Definition: beepmidi.c:853
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
#define PACK_MIDI(b1, b2, b3)
Definition: beepmidi.c:654
MMRESULT FAR PASCAL modMessage(UINT device_id, UINT message, DWORD_PTR private_data, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:771
#define POLYPHONY
Definition: beepmidi.c:33
MMRESULT ProcessLongMidiMessage(DeviceInfo *device_info, MIDIHDR *header)
Definition: beepmidi.c:668
struct _NoteNode NoteNode
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define FAR
Definition: zlib.h:34
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)
Definition: thread.c:137
#define MODM_GETDEVCAPS
Definition: mmddk.h:155
#define MODM_PREPARE
Definition: mmddk.h:158
#define MODM_RESET
Definition: mmddk.h:162
#define MODM_GETNUMDEVS
Definition: mmddk.h:154
#define MODM_DATA
Definition: mmddk.h:160
#define MODM_OPEN
Definition: mmddk.h:156
#define MODM_UNPREPARE
Definition: mmddk.h:159
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
#define MODM_LONGDATA
Definition: mmddk.h:161
#define MODM_CLOSE
Definition: mmddk.h:157
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
double pow(double x, double y)
Definition: freeldr.c:112
#define FILE_OPEN_IF
Definition: from_kernel.h:56
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
const GLint * attribs
Definition: glext.h:10538
#define DRV_LOAD(x)
char hdr[14]
Definition: iptest.cpp:33
if(dx< 0)
Definition: linetemp.h:194
#define DRV_CLOSE
Definition: mmsystem.h:122
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
UINT MMRESULT
Definition: mmsystem.h:962
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define MIDIERR_UNPREPARED
Definition: mmsystem.h:231
#define MHDR_PREPARED
Definition: mmsystem.h:269
#define DRV_ENABLE
Definition: mmsystem.h:120
#define MOM_DONE
Definition: mmsystem.h:249
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define DRV_OPEN
Definition: mmsystem.h:121
#define MOD_SQSYNTH
Definition: mmsystem.h:261
#define MOM_CLOSE
Definition: mmsystem.h:248
#define DRV_INSTALL
Definition: mmsystem.h:127
#define MOM_OPEN
Definition: mmsystem.h:247
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
#define MHDR_DONE
Definition: mmsystem.h:268
#define DRV_FREE
Definition: mmsystem.h:124
#define DRV_DISABLE
Definition: mmsystem.h:123
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static LARGE_INTEGER * frequency
Definition: time.c:106
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
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)
Definition: obhandle.c:3402
#define DWORD
Definition: nt_native.h:44
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)
#define IOCTL_BEEP_SET
Definition: ntddbeep.h:31
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
const WCHAR * str
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static HANDLE heap
Definition: heap.c:65
#define memset(x, y, z)
Definition: compat.h:39
HMIDI hMidi
Definition: mmddk.h:412
DWORD dwInstance
Definition: mmddk.h:414
DWORD dwCallback
Definition: mmddk.h:413
BOOL refresh_notes
Definition: beepmidi.c:94
HDRVR mme_handle
Definition: beepmidi.c:83
HANDLE work_available
Definition: beepmidi.c:98
UCHAR running_status
Definition: beepmidi.c:90
DWORD flags
Definition: beepmidi.c:88
DWORD_PTR callback
Definition: beepmidi.c:86
HANDLE thread_handle
Definition: beepmidi.c:96
NoteNode * note_list
Definition: beepmidi.c:93
DWORD playing_notes_count
Definition: beepmidi.c:92
BOOL terminate_thread
Definition: beepmidi.c:97
HANDLE kernel_device
Definition: beepmidi.c:84
DWORD instance
Definition: beepmidi.c:87
UCHAR note
Definition: beepmidi.c:77
struct _NoteNode * previous
Definition: beepmidi.c:75
UCHAR velocity
Definition: beepmidi.c:78
struct _NoteNode * next
Definition: beepmidi.c:74
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: tftpd.h:60
Definition: ps.c:97
MMVERSION vDriverVersion
Definition: mmsystem.h:1113
CHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1114
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define HIWORD(l)
Definition: typedefs.h:247
Definition: dlist.c:348
void * next
Definition: dlist.c:360
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define CreateEvent
Definition: winbase.h:3748
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define PASCAL
Definition: windef.h:133
#define WINAPI
Definition: msvc.h:6
unsigned char UCHAR
Definition: xmlstorage.h:181