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

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

◆ CloseDevice()

MMRESULT CloseDevice ( DeviceInfo device_info)

Definition at line 383 of file beepmidi.c.

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}
DeviceInfo * the_device
Definition: beepmidi.c:101
BOOL CallClient(DeviceInfo *device_info, DWORD_PTR message, DWORD_PTR parameter1, DWORD_PTR parameter2)
Definition: beepmidi.c:240
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define HeapFree(x, y, z)
Definition: compat.h:735
#define INFINITE
Definition: serial.h:102
#define MOM_CLOSE
Definition: mmsystem.h:248
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
static HANDLE heap
Definition: heap.c:65
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733

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");
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}
CRITICAL_SECTION device_lock
Definition: beepmidi.c:102
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
#define DRV_LOAD(x)
#define DRV_CLOSE
Definition: mmsystem.h:122
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define DRV_ENABLE
Definition: mmsystem.h:120
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define DRV_OPEN
Definition: mmsystem.h:121
#define DRV_INSTALL
Definition: mmsystem.h:127
#define DRV_FREE
Definition: mmsystem.h:124
#define DRV_DISABLE
Definition: mmsystem.h:123
#define L(x)
Definition: ntvdm.h:50
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751

◆ 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}
#define POLYPHONY
Definition: beepmidi.c:33
#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)
#define memset(x, y, z)
Definition: compat.h:39
MMVERSION vDriverVersion
Definition: mmsystem.h:1113
CHAR szPname[MAXPNAMELEN]
Definition: mmsystem.h:1114

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
844}
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210
MMRESULT CloseDevice(DeviceInfo *device_info)
Definition: beepmidi.c:383
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
MMRESULT ProcessShortMidiMessage(DeviceInfo *device_info, DWORD message)
Definition: beepmidi.c:590
MMRESULT ProcessLongMidiMessage(DeviceInfo *device_info, MIDIHDR *header)
Definition: beepmidi.c:668
#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
#define MODM_LONGDATA
Definition: mmddk.h:161
#define MODM_CLOSE
Definition: mmddk.h:157
char hdr[14]
Definition: iptest.cpp:33
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MHDR_PREPARED
Definition: mmsystem.h:269

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,
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}
LONG NTSTATUS
Definition: precomp.h:26
#define CONTINUOUS_NOTES
Definition: beepmidi.c:41
DWORD WINAPI ProcessPlayingNotes(LPVOID parameter)
Definition: beepmidi.c:117
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define HeapAlloc
Definition: compat.h:733
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
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 FILE_OPEN_IF
Definition: from_kernel.h:56
GLbitfield flags
Definition: glext.h:7161
const GLint * attribs
Definition: glext.h:10538
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define MOM_OPEN
Definition: mmsystem.h:247
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#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)
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)
HMIDI hMidi
Definition: mmddk.h:412
DWORD dwInstance
Definition: mmddk.h:414
DWORD dwCallback
Definition: mmddk.h:413
Definition: ps.c:97
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CreateEvent
Definition: winbase.h:3748

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{
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}
int note(char *format,...)
Definition: util.c:12
MMRESULT StopNote(DeviceInfo *device_info, UCHAR note)
Definition: beepmidi.c:418
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: dlist.c:348
void * next
Definition: dlist.c:360
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)

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}
#define msg(x)
Definition: auth_time.c:54
#define index(s, c)
Definition: various.h:29
#define PACK_MIDI(b1, b2, b3)
Definition: beepmidi.c:654
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint index
Definition: glext.h:6031
if(dx< 0)
Definition: linetemp.h:194
#define MIDIERR_UNPREPARED
Definition: mmsystem.h:231
#define MOM_DONE
Definition: mmsystem.h:249
#define MHDR_DONE
Definition: mmsystem.h:268
uint32_t DWORD_PTR
Definition: typedefs.h:65
unsigned char UCHAR
Definition: xmlstorage.h:181

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 TIMESLICE_SIZE
Definition: beepmidi.c:18
double pow(double x, double y)
Definition: freeldr.c:112
static LARGE_INTEGER * frequency
Definition: time.c:106
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 DWORD
Definition: nt_native.h:44
#define IOCTL_BEEP_SET
Definition: ntddbeep.h:31
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802

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

◆ ProcessShortMidiMessage()

MMRESULT ProcessShortMidiMessage ( DeviceInfo device_info,
DWORD  message 
)

Definition at line 590 of file beepmidi.c.

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}
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
MMRESULT PlayNote(DeviceInfo *device_info, UCHAR note, UCHAR velocity)
Definition: beepmidi.c:484
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
Definition: tftpd.h:126
Definition: tftpd.h:138

Referenced by modMessage(), and ProcessLongMidiMessage().

◆ StopNote()

MMRESULT StopNote ( DeviceInfo device_info,
UCHAR  note 
)

Definition at line 418 of file beepmidi.c.

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}
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714

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