ReactOS  0.4.14-dev-57-g333b8f1
beepmidi.c File Reference
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <ndk/iofuncs.h>
#include <ndk/obfuncs.h>
#include <ndk/rtlfuncs.h>
#include <ntddbeep.h>
#include <math.h>
#include <mmddk.h>
Include dependency graph for beepmidi.c:

Go to the source code of this file.

Classes

struct  _NoteNode
 
struct  _DeviceInfo
 

Macros

#define TIMESLICE_SIZE   60
 
#define ALLOW_DUPLICATE_NOTES
 
#define POLYPHONY   3
 
#define CONTINUOUS_NOTES
 
#define WIN32_NO_STATUS
 
#define _INC_WINDOWS
 
#define COM_NO_WINDOWS_H
 
#define NTOS_MODE_USER
 
#define DPRINT   FakePrintf
 
#define MIDI_NOTE_OFF   0x80
 
#define MIDI_NOTE_ON   0x90
 
#define MIDI_CONTROL_CHANGE   0xB0
 
#define MIDI_PROGRAM   0xC0
 
#define MIDI_PITCH_BEND   0xE0
 
#define MIDI_SYSTEM   0xFF
 
#define MIDI_RESET   0xFF
 
#define PACK_MIDI(b1, b2, b3)   ((b3 * 65536) + (b2 * 256) + b1);
 

Typedefs

typedef struct _NoteNode NoteNode
 
typedef struct _DeviceInfo DeviceInfo
 

Functions

void FakePrintf (char *str,...)
 
DWORD WINAPI ProcessPlayingNotes (LPVOID parameter)
 
MMRESULT GetDeviceCapabilities (MIDIOUTCAPS *caps)
 
BOOL CallClient (DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
 
MMRESULT OpenDevice (DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
 
MMRESULT CloseDevice (DeviceInfo *device_info)
 
MMRESULT StopNote (DeviceInfo *device_info, UCHAR note)
 
MMRESULT PlayNote (DeviceInfo *device_info, UCHAR note, UCHAR velocity)
 
MMRESULT ProcessShortMidiMessage (DeviceInfo *device_info, DWORD message)
 
MMRESULT ProcessLongMidiMessage (DeviceInfo *device_info, MIDIHDR *header)
 
MMRESULT FAR PASCAL modMessage (UINT device_id, UINT message, DWORD_PTR private_data, DWORD_PTR parameter1, DWORD_PTR parameter2)
 
LONG FAR PASCAL DriverProc (DWORD driver_id, HDRVR driver_handle, UINT message, LONG parameter1, LONG parameter2)
 

Variables

DeviceInfothe_device
 
CRITICAL_SECTION device_lock
 

Macro Definition Documentation

◆ _INC_WINDOWS

#define _INC_WINDOWS

Definition at line 44 of file beepmidi.c.

◆ ALLOW_DUPLICATE_NOTES

#define ALLOW_DUPLICATE_NOTES

Definition at line 26 of file beepmidi.c.

◆ COM_NO_WINDOWS_H

#define COM_NO_WINDOWS_H

Definition at line 45 of file beepmidi.c.

◆ CONTINUOUS_NOTES

#define CONTINUOUS_NOTES

Definition at line 41 of file beepmidi.c.

◆ DPRINT

#define DPRINT   FakePrintf

Definition at line 58 of file beepmidi.c.

◆ MIDI_CONTROL_CHANGE

#define MIDI_CONTROL_CHANGE   0xB0

Definition at line 63 of file beepmidi.c.

◆ MIDI_NOTE_OFF

#define MIDI_NOTE_OFF   0x80

Definition at line 61 of file beepmidi.c.

◆ MIDI_NOTE_ON

#define MIDI_NOTE_ON   0x90

Definition at line 62 of file beepmidi.c.

◆ MIDI_PITCH_BEND

#define MIDI_PITCH_BEND   0xE0

Definition at line 65 of file beepmidi.c.

◆ MIDI_PROGRAM

#define MIDI_PROGRAM   0xC0

Definition at line 64 of file beepmidi.c.

◆ MIDI_RESET

#define MIDI_RESET   0xFF

Definition at line 69 of file beepmidi.c.

◆ MIDI_SYSTEM

#define MIDI_SYSTEM   0xFF

Definition at line 66 of file beepmidi.c.

◆ NTOS_MODE_USER

#define NTOS_MODE_USER

Definition at line 49 of file beepmidi.c.

◆ PACK_MIDI

#define PACK_MIDI (   b1,
  b2,
  b3 
)    ((b3 * 65536) + (b2 * 256) + b1);

Definition at line 654 of file beepmidi.c.

◆ POLYPHONY

#define POLYPHONY   3

Definition at line 33 of file beepmidi.c.

◆ TIMESLICE_SIZE

#define TIMESLICE_SIZE   60

Definition at line 18 of file beepmidi.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 43 of file beepmidi.c.

Typedef Documentation

◆ DeviceInfo

◆ NoteNode

Function Documentation

◆ CallClient()

BOOL CallClient ( DeviceInfo device_info,
DWORD_PTR  message,
DWORD_PTR  parameter1,
DWORD_PTR  parameter2 
)

Definition at line 240 of file beepmidi.c.

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 }
Definition: tftpd.h:59
#define DPRINT
Definition: beepmidi.c:58
#define HIWORD(l)
Definition: typedefs.h:246
BOOL WINAPI DriverCallback(DWORD dwCallBack, UINT uFlags, HDRVR hDev, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)

Referenced by CloseDevice(), OpenDevice(), and ProcessLongMidiMessage().

◆ CloseDevice()

MMRESULT CloseDevice ( DeviceInfo device_info)

Definition at line 383 of file beepmidi.c.

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 }
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
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:733
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
smooth NULL
Definition: ftsmooth.c:416
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define MOM_CLOSE
Definition: mmsystem.h:248
DeviceInfo * the_device
Definition: beepmidi.c:101
#define DPRINT
Definition: beepmidi.c:58
#define INFINITE
Definition: serial.h:102
#define HeapFree(x, y, z)
Definition: compat.h:394

Referenced by modMessage(), and wodMessage().

◆ DriverProc()

LONG FAR PASCAL DriverProc ( DWORD  driver_id,
HDRVR  driver_handle,
UINT  message,
LONG  parameter1,
LONG  parameter2 
)

Definition at line 853 of file beepmidi.c.

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 DRV_DISABLE
Definition: mmsystem.h:123
Definition: tftpd.h:59
#define DRV_CLOSE
Definition: mmsystem.h:122
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define DRV_OPEN
Definition: mmsystem.h:121
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
#define DRV_LOAD(x)
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define DRV_FREE
Definition: mmsystem.h:124
DeviceInfo * the_device
Definition: beepmidi.c:101
static const WCHAR L[]
Definition: oid.c:1250
#define DRV_ENABLE
Definition: mmsystem.h:120
#define DPRINT
Definition: beepmidi.c:58
#define DRV_INSTALL
Definition: mmsystem.h:127
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102

◆ FakePrintf()

void FakePrintf ( char str,
  ... 
)

Definition at line 105 of file beepmidi.c.

106 {
107  /* Just to shut the compiler up */
108 }

◆ GetDeviceCapabilities()

MMRESULT GetDeviceCapabilities ( MIDIOUTCAPS caps)

Definition at line 210 of file beepmidi.c.

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 }
MMVERSION vDriverVersion
Definition: mmsystem.h:1113
CHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1114
#define POLYPHONY
Definition: beepmidi.c:33
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MOD_SQSYNTH
Definition: mmsystem.h:261
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
#define memset(x, y, z)
Definition: compat.h:39

Referenced by auxMessage(), midMessage(), modMessage(), and wodMessage().

◆ modMessage()

MMRESULT FAR PASCAL modMessage ( UINT  device_id,
UINT  message,
DWORD_PTR  private_data,
DWORD_PTR  parameter1,
DWORD_PTR  parameter2 
)

Definition at line 771 of file beepmidi.c.

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 }
MMRESULT CloseDevice(DeviceInfo *device_info)
Definition: beepmidi.c:383
Definition: tftpd.h:59
char hdr[14]
Definition: iptest.cpp:33
#define MODM_LONGDATA
Definition: mmddk.h:161
#define MODM_GETDEVCAPS
Definition: mmddk.h:155
#define MODM_PREPARE
Definition: mmddk.h:158
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
#define MODM_GETNUMDEVS
Definition: mmddk.h:154
#define MODM_UNPREPARE
Definition: mmddk.h:159
MMRESULT ProcessLongMidiMessage(DeviceInfo *device_info, MIDIHDR *header)
Definition: beepmidi.c:668
#define MODM_CLOSE
Definition: mmddk.h:157
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MODM_OPEN
Definition: mmddk.h:156
#define MODM_RESET
Definition: mmddk.h:162
#define MODM_DATA
Definition: mmddk.h:160
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
Definition: beepmidi.c:590
#define DPRINT
Definition: beepmidi.c:58
#define MHDR_PREPARED
Definition: mmsystem.h:269
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210

Referenced by MMDRV_Install().

◆ OpenDevice()

MMRESULT OpenDevice ( DeviceInfo **  private_data,
MIDIOPENDESC open_desc,
DWORD  flags 
)

Definition at line 264 of file beepmidi.c.

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 }
#define CreateEvent
Definition: winbase.h:3565
DWORD dwCallback
Definition: mmddk.h:413
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define FILE_OPEN_IF
Definition: from_kernel.h:56
DWORD dwInstance
Definition: mmddk.h:414
const GLint * attribs
Definition: glext.h:10538
#define CONTINUOUS_NOTES
Definition: beepmidi.c:41
LONG NTSTATUS
Definition: precomp.h:26
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:240
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:125
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define FILE_READ_DATA
Definition: nt_native.h:628
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:136
smooth NULL
Definition: ftsmooth.c:416
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#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 NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
HMIDI hMidi
Definition: mmddk.h:412
GLbitfield flags
Definition: glext.h:7161
DeviceInfo * the_device
Definition: beepmidi.c:101
static const WCHAR L[]
Definition: oid.c:1250
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define DPRINT
Definition: beepmidi.c:58
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static SERVICE_STATUS status
Definition: service.c:31
#define HeapFree(x, y, z)
Definition: compat.h:394
Definition: ps.c:97

Referenced by AuxGetAudio(), AuxSetAudio(), Enum(), modMessage(), OpenMidiDevice(), SysAudioOpenKMixer(), and wodMessage().

◆ PlayNote()

MMRESULT PlayNote ( DeviceInfo device_info,
UCHAR  note,
UCHAR  velocity 
)

Definition at line 484 of file beepmidi.c.

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 }
#define TRUE
Definition: types.h:120
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
void * next
Definition: dlist.c:360
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
struct _NoteNode * previous
Definition: beepmidi.c:75
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
struct _NoteNode * next
Definition: beepmidi.c:74
struct node node
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
int note(char *format,...)
Definition: util.c:12
smooth NULL
Definition: ftsmooth.c:416
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
Definition: beepmidi.c:418
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
UCHAR velocity
Definition: beepmidi.c:78
UCHAR note
Definition: beepmidi.c:77
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define DPRINT
Definition: beepmidi.c:58
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
Definition: dlist.c:348

Referenced by ProcessShortMidiMessage().

◆ ProcessLongMidiMessage()

MMRESULT ProcessLongMidiMessage ( DeviceInfo device_info,
MIDIHDR header 
)

Definition at line 668 of file beepmidi.c.

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 }
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:240
#define MIDIERR_UNPREPARED
Definition: mmsystem.h:231
GLuint index
Definition: glext.h:6031
#define MOM_DONE
Definition: mmsystem.h:249
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
if(!(yy_init))
Definition: macro.lex.yy.c:714
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned char UCHAR
Definition: xmlstorage.h:181
DeviceInfo * the_device
Definition: beepmidi.c:101
#define index(s, c)
Definition: various.h:29
#define PACK_MIDI(b1, b2, b3)
Definition: beepmidi.c:654
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define MHDR_DONE
Definition: mmsystem.h:268
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
Definition: beepmidi.c:590
#define MHDR_INQUEUE
Definition: mmsystem.h:270
#define DPRINT
Definition: beepmidi.c:58
#define msg(x)
Definition: auth_time.c:54
#define MHDR_PREPARED
Definition: mmsystem.h:269
struct CFHEADER header
Definition: fdi.c:109

Referenced by modMessage().

◆ ProcessPlayingNotes()

DWORD WINAPI ProcessPlayingNotes ( LPVOID  parameter)

Definition at line 117 of file beepmidi.c.

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 }
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
void * next
Definition: dlist.c:360
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
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)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define TIMESLICE_SIZE
Definition: beepmidi.c:18
#define DWORD
Definition: nt_native.h:44
struct node node
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
float pow(float __x, int __y)
Definition: _cmath.h:458
smooth NULL
Definition: ftsmooth.c:416
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802
#define POLYPHONY
Definition: beepmidi.c:33
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
DeviceInfo * the_device
Definition: beepmidi.c:101
static LARGE_INTEGER * frequency
Definition: time.c:106
#define DPRINT
Definition: beepmidi.c:58
#define IOCTL_BEEP_SET
Definition: ntddbeep.h:31
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define INFINITE
Definition: serial.h:102
static SERVICE_STATUS status
Definition: service.c:31
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
Definition: dlist.c:348
Definition: ps.c:97

Referenced by OpenDevice(), PlayNote(), and StopNote().

◆ ProcessShortMidiMessage()

MMRESULT ProcessShortMidiMessage ( DeviceInfo device_info,
DWORD  message 
)

Definition at line 590 of file beepmidi.c.

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 }
Definition: tftpd.h:59
MMRESULT PlayNote(DeviceInfo *device_info, UCHAR note, UCHAR velocity)
Definition: beepmidi.c:484
Definition: tftpd.h:125
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
Definition: beepmidi.c:418
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
unsigned long DWORD
Definition: ntddk_ex.h:95
static const WCHAR data1[]
Definition: db.c:2967
static const WCHAR data2[]
Definition: db.c:2971
#define DPRINT
Definition: beepmidi.c:58
static SERVICE_STATUS status
Definition: service.c:31
Definition: tftpd.h:137
Definition: ps.c:97

Referenced by modMessage(), and ProcessLongMidiMessage().

◆ StopNote()

MMRESULT StopNote ( DeviceInfo device_info,
UCHAR  note 
)

Definition at line 418 of file beepmidi.c.

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 }
#define TRUE
Definition: types.h:120
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
void * next
Definition: dlist.c:360
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
struct _NoteNode * next
Definition: beepmidi.c:74
struct node node
int note(char *format,...)
Definition: util.c:12
smooth NULL
Definition: ftsmooth.c:416
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
#define DPRINT
Definition: beepmidi.c:58
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define HeapFree(x, y, z)
Definition: compat.h:394
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
Definition: dlist.c:348

Referenced by PlayNote(), and ProcessShortMidiMessage().

Variable Documentation

◆ device_lock

CRITICAL_SECTION device_lock

Definition at line 102 of file beepmidi.c.

Referenced by DriverProc(), PlayNote(), ProcessPlayingNotes(), and StopNote().

◆ the_device

DeviceInfo* the_device