MMRESULT StopNote( DeviceInfo* device_info, UCHAR note) { HANDLE heap = GetProcessHeap(); NoteNode* node; NoteNode* prev_node = NULL; DPRINT("StopNote\n"); EnterCriticalSection(&device_lock); node = device_info->note_list; while ( node != NULL ) { if ( node->note == note ) { /* Found the note - just remove the node from the list */ DPRINT("Stopping note %d\n", (int) node->note); if ( prev_node != NULL ) prev_node->next = node->next; else device_info->note_list = node->next; HeapFree(heap, 0, node); device_info->playing_notes_count --; DPRINT("Note stopped - now playing %d notes\n", (int) device_info->playing_notes_count); #ifdef CONTINUOUS_NOTES if (device_info->playing_notes_count == 0) ResetEvent(device_info->work_available); #endif LeaveCriticalSection(&device_lock); device_info->refresh_notes = TRUE; return MMSYSERR_NOERROR; } prev_node = node; node = node->next; } LeaveCriticalSection(&device_lock); /* Hmm, a good idea? */ #ifndef CONTINUOUS_NOTES ProcessPlayingNotes((PVOID) device_info); #endif return MMSYSERR_NOERROR; }
MMRESULT PlayNote( DeviceInfo* device_info, UCHAR note, UCHAR velocity) { HANDLE heap = GetProcessHeap(); NoteNode* node; DPRINT("PlayNote\n"); if ( velocity == 0 ) { DPRINT("Zero velocity\n"); /* Velocity zero is effectively a "note off" */ StopNote(device_info, note); } else { /* Start playing the note */ NoteNode* new_node; EnterCriticalSection(&device_lock); node = device_info->note_list; while ( node != NULL ) { #ifndef ALLOW_DUPLICATE_NOTES if ( ( node->note == note ) && ( velocity > 0 ) ) { /* The note is already playing - do nothing */ DPRINT("Duplicate note playback request ignored\n"); LeaveCriticalSection(&device_lock); return MMSYSERR_NOERROR; } #endif node = node->next; } new_node = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(NoteNode)); if ( ! new_node ) { LeaveCriticalSection(&device_lock); return MMSYSERR_NOMEM; } new_node->note = note; new_node->velocity = velocity; /* Prepend to the playing notes list. If exceeding polyphony, remove the oldest note (which will be at the tail.) */ if ( device_info->note_list ) device_info->note_list->previous = new_node; new_node->next = device_info->note_list; new_node->previous = NULL; device_info->note_list = new_node; device_info->playing_notes_count ++; /* if ( device_info->playing_notes_count > POLYPHONY ) { ASSERT(tail_node); DPRINT("Polyphony exceeded\n"); tail_node->previous->next = NULL; HeapFree(heap, 0, tail_node); device_info->playing_notes_count --; } */ LeaveCriticalSection(&device_lock); DPRINT("Note started - now playing %d notes\n", (int) device_info->playing_notes_count); device_info->refresh_notes = TRUE; } #ifndef CONTINUOUS_NOTES ProcessPlayingNotes((PVOID) device_info); #endif return MMSYSERR_NOERROR; }