ReactOS  0.4.13-dev-92-gf251225
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 
72 typedef struct _NoteNode
73 {
74  struct _NoteNode* next;
76 
78  UCHAR velocity; /* 0 is note-off */
79 } NoteNode;
80 
81 typedef struct _DeviceInfo
82 {
83  HDRVR mme_handle;
85 
89 
91 
95 
99 } DeviceInfo;
100 
103 
104 void
105 FakePrintf(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 
209 MMRESULT
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 
239 BOOL
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 
263 MMRESULT
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,
301  FILE_OPEN_IF,
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 
316  heap = GetProcessHeap();
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");
350  HeapFree(heap, 0, the_device);
351  return MMSYSERR_NOMEM;
352  }
353 
354  the_device->thread_handle = CreateThread(NULL,
355  0,
357  (PVOID) the_device,
358  0,
359  NULL);
360 
361  if ( ! the_device->thread_handle )
362  {
363  DPRINT("CreateThread failed\n");
364  CloseHandle(the_device->work_available);
365  HeapFree(heap, 0, the_device);
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 
382 MMRESULT
383 CloseDevice(DeviceInfo* device_info)
384 {
385  HANDLE heap = GetProcessHeap();
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 
406  the_device = NULL;
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 
417 MMRESULT
419  DeviceInfo* device_info,
420  UCHAR note)
421 {
422  HANDLE heap = GetProcessHeap();
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 
483 MMRESULT
485  DeviceInfo* device_info,
486  UCHAR note,
487  UCHAR velocity)
488 {
489  HANDLE heap = GetProcessHeap();
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 
589 MMRESULT
591  DeviceInfo* device_info,
592  DWORD message)
593 {
594  DWORD status;
595 
596  DWORD category;
597  DWORD channel;
598  DWORD data1, data2;
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 
667 MMRESULT
669  DeviceInfo* device_info,
670  MIDIHDR* header)
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 
769 MMRESULT
770 FAR PASCAL
772  UINT device_id,
773  UINT message,
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 
843  return MMSYSERR_NOTSUPPORTED;
844 }
845 
846 
847 /*
848  Driver entrypoint.
849 */
850 
851 LONG
852 FAR PASCAL
854  DWORD driver_id,
855  HDRVR driver_handle,
856  UINT message,
857  LONG parameter1,
858  LONG parameter2)
859 {
860  switch ( message )
861  {
862  case DRV_LOAD :
863  DPRINT("DRV_LOAD\n");
864  the_device = NULL;
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 CreateEvent
Definition: winbase.h:3562
#define DRV_DISABLE
Definition: mmsystem.h:123
DWORD instance
Definition: beepmidi.c:87
MMRESULT CloseDevice(DeviceInfo *device_info)
Definition: beepmidi.c:383
DWORD dwCallback
Definition: mmddk.h:413
Definition: tftpd.h:59
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
char hdr[14]
Definition: iptest.cpp:33
#define FILE_OPEN_IF
Definition: from_kernel.h:56
DWORD dwInstance
Definition: mmddk.h:414
const GLint * attribs
Definition: glext.h:10538
DWORD flags
Definition: beepmidi.c:88
#define CONTINUOUS_NOTES
Definition: beepmidi.c:41
MMRESULT PlayNote(DeviceInfo *device_info, UCHAR note, UCHAR velocity)
Definition: beepmidi.c:484
LONG NTSTATUS
Definition: precomp.h:26
#define MODM_LONGDATA
Definition: mmddk.h:161
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
void * next
Definition: dlist.c:360
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:240
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
UINT MMRESULT
Definition: mmsystem.h:962
Definition: tftpd.h:125
struct _NoteNode * previous
Definition: beepmidi.c:75
#define DRV_CLOSE
Definition: mmsystem.h:122
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)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
MMVERSION vDriverVersion
Definition: mmsystem.h:1113
BOOL terminate_thread
Definition: beepmidi.c:97
#define TIMESLICE_SIZE
Definition: beepmidi.c:18
HANDLE work_available
Definition: beepmidi.c:98
#define MODM_GETDEVCAPS
Definition: mmddk.h:155
#define DWORD
Definition: nt_native.h:44
CHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1114
struct _NoteNode * next
Definition: beepmidi.c:74
#define FILE_SHARE_READ
Definition: compat.h:125
struct _NoteNode NoteNode
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define DRV_OPEN
Definition: mmsystem.h:121
struct node node
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define MODM_PREPARE
Definition: mmddk.h:158
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
MMRESULT FAR PASCAL modMessage(UINT device_id, UINT message, DWORD_PTR private_data, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:771
#define MIDIERR_UNPREPARED
Definition: mmsystem.h:231
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
BOOL refresh_notes
Definition: beepmidi.c:94
unsigned int BOOL
Definition: ntddk_ex.h:94
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
long LONG
Definition: pedump.c:60
float pow(float __x, int __y)
Definition: _cmath.h:458
#define FILE_READ_DATA
Definition: nt_native.h:628
DWORD callback
Definition: beepmidi.c:86
#define FAR
Definition: guiddef.h:36
const WCHAR * str
int note(char *format,...)
Definition: util.c:12
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:112
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
#define DRV_LOAD(x)
LONG FAR PASCAL DriverProc(DWORD driver_id, HDRVR driver_handle, UINT message, LONG parameter1, LONG parameter2)
Definition: beepmidi.c:853
GLuint index
Definition: glext.h:6031
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define MOM_DONE
Definition: mmsystem.h:249
#define MODM_GETNUMDEVS
Definition: mmddk.h:154
#define MODM_UNPREPARE
Definition: mmddk.h:159
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
Definition: beepmidi.c:418
MMRESULT ProcessLongMidiMessage(DeviceInfo *device_info, MIDIHDR *header)
Definition: beepmidi.c:668
#define MODM_CLOSE
Definition: mmddk.h:157
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:748
#define POLYPHONY
Definition: beepmidi.c:33
#define MOM_OPEN
Definition: mmsystem.h:247
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
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 MMSYSERR_ERROR
Definition: mmsystem.h:97
#define DRV_CONFIGURE
Definition: mmsystem.h:125
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
#define MOD_SQSYNTH
Definition: mmsystem.h:261
UCHAR running_status
Definition: beepmidi.c:90
HMIDI hMidi
Definition: mmddk.h:412
#define WINAPI
Definition: msvc.h:8
struct _DeviceInfo DeviceInfo
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DRV_FREE
Definition: mmsystem.h:124
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MODM_OPEN
Definition: mmddk.h:156
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
GLbitfield flags
Definition: glext.h:7161
#define MOM_CLOSE
Definition: mmsystem.h:248
unsigned char UCHAR
Definition: xmlstorage.h:181
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
DeviceInfo * the_device
Definition: beepmidi.c:101
#define index(s, c)
Definition: various.h:29
static const WCHAR L[]
Definition: oid.c:1250
#define MODM_RESET
Definition: mmddk.h:162
#define PACK_MIDI(b1, b2, b3)
Definition: beepmidi.c:654
#define PASCAL
Definition: windef.h:133
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define MHDR_DONE
Definition: mmsystem.h:268
UCHAR velocity
Definition: beepmidi.c:78
static LARGE_INTEGER * frequency
Definition: time.c:106
#define DRV_ENABLE
Definition: mmsystem.h:120
HANDLE kernel_device
Definition: beepmidi.c:84
#define MODM_DATA
Definition: mmddk.h:160
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
Definition: beepmidi.c:590
static const WCHAR data1[]
Definition: db.c:2967
static const WCHAR data2[]
Definition: db.c:2971
HDRVR mme_handle
Definition: beepmidi.c:83
UCHAR note
Definition: beepmidi.c:77
NoteNode * note_list
Definition: beepmidi.c:93
void FakePrintf(char *str,...)
Definition: beepmidi.c:105
#define MHDR_INQUEUE
Definition: mmsystem.h:270
unsigned int UINT
Definition: ndis.h:50
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:660
#define DPRINT
Definition: beepmidi.c:58
#define msg(x)
Definition: auth_time.c:54
#define HIWORD(l)
Definition: typedefs.h:246
#define IOCTL_BEEP_SET
Definition: ntddbeep.h:31
#define DRV_INSTALL
Definition: mmsystem.h:127
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
#define MHDR_PREPARED
Definition: mmsystem.h:269
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HANDLE thread_handle
Definition: beepmidi.c:96
#define INFINITE
Definition: serial.h:102
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210
#define HeapFree(x, y, z)
Definition: compat.h:394
struct CFHEADER header
Definition: fdi.c:109
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
Definition: dlist.c:348
Definition: tftpd.h:137
DWORD playing_notes_count
Definition: beepmidi.c:92
Definition: ps.c:97