static int process_callback(jack_nframes_t nframes, void *notused) { #ifdef MEASURE_TIME if (get_delta_time() > MAX_TIME_BETWEEN_CALLBACKS) { warn_from_jack_thread_context("Had to wait too long for JACK callback; scheduling problem?"); } #endif /* Check for impossible condition that actually happened to me, caused by some problem between jackd and OSS4. */ if (nframes <= 0) { warn_from_jack_thread_context("Process callback called with nframes = 0; bug in JACK?"); return 0; } if (pthread_mutex_trylock(&mutex) == 0) { if ((smf = smf_vol) != NULL) { process_midi_output(nframes); } pthread_mutex_unlock(&mutex); } #ifdef MEASURE_TIME if (get_delta_time() > MAX_PROCESSING_TIME) { warn_from_jack_thread_context("Processing took too long; scheduling problem?"); } #endif return 0; }
static void send_all_sound_off(void *port_buffers[MAX_NUMBER_OF_TRACKS], jack_nframes_t nframes) { int i, channel; unsigned char *buffer; for (i = 0; i <= smf->number_of_tracks; i++) { for (channel = 0; channel < 16; channel++) { #ifdef JACK_MIDI_NEEDS_NFRAMES buffer = jack_midi_event_reserve(port_buffers[i], 0, 3, nframes); #else buffer = jack_midi_event_reserve(port_buffers[i], 0, 3); #endif if (buffer == NULL) { warn_from_jack_thread_context("jack_midi_event_reserve failed, cannot send All Sound Off."); break; } buffer[0] = MIDI_CONTROLLER | channel; buffer[1] = MIDI_ALL_SOUND_OFF; buffer[2] = 0; } if (just_one_output) break; } }
void process_midi_input (jack_nframes_t nframes) { static int time_of_first_event = -1; int /*read,*/ events, i, channel; jack_midi_event_t event; int last_frame_time = jack_last_frame_time(jack_client); void * port_buffer = jack_port_get_buffer(input_port, nframes); if (port_buffer == NULL) { warn_from_jack_thread_context ( "jack_port_get_buffer failed, cannot receive anything." ); return; } #ifdef JACK_MIDI_NEEDS_NFRAMES events = jack_midi_get_event_count(port_buffer, nframes); #else events = jack_midi_get_event_count(port_buffer); #endif for (i = 0; i < events; ++i) { smf_event_t * smf_event; #ifdef JACK_MIDI_NEEDS_NFRAMES int read = jack_midi_event_get(&event, port_buffer, i, nframes); #else int read = jack_midi_event_get(&event, port_buffer, i); #endif if (read) { warn_from_jack_thread_context("jack_midi_event_get failed, RECEIVED NOTE LOST."); continue; } if (event.buffer[0] >= 0xF8) /* Ignore realtime messages. */ continue; if (time_of_first_event == -1) /* First event received? */ time_of_first_event = last_frame_time + event.time; smf_event = smf_event_new_from_pointer(event.buffer, event.size); if (smf_event == NULL) { warn_from_jack_thread_context ( "smf_event_from_pointer failed, RECEIVED NOTE LOST." ); continue; } // assert(smf_event->midi_buffer_length >= 1); channel = smf_event->midi_buffer[0] & 0x0F; smf_track_add_event_seconds ( tracks[channel], smf_event, nframes_to_seconds ( jack_last_frame_time(jack_client) + event.time - time_of_first_event ) ); } }
static void process_midi_output(jack_nframes_t nframes) { int i, t, bytes_remaining, track_number; unsigned char *buffer, tmp_status; void *port_buffers[MAX_NUMBER_OF_TRACKS]; jack_nframes_t last_frame_time; jack_transport_state_t transport_state; static jack_transport_state_t previous_transport_state = JackTransportStopped; static int previous_playback_started = -1; static int previous_playback_paused = 0; for (i = 0; i <= smf->number_of_tracks; i++) { port_buffers[i] = jack_port_get_buffer(output_ports[i], nframes); if (port_buffers[i] == NULL) { warn_from_jack_thread_context("jack_port_get_buffer failed, cannot send anything."); return; } #ifdef JACK_MIDI_NEEDS_NFRAMES jack_midi_clear_buffer(port_buffers[i], nframes); #else jack_midi_clear_buffer(port_buffers[i]); #endif if (just_one_output) break; } if (ctrl_c_pressed) { send_all_sound_off(port_buffers, nframes); /* The idea here is to exit at the second time process_midi_output gets called. Otherwise, All Sound Off won't be delivered. */ ctrl_c_pressed++; if (ctrl_c_pressed >= 3) exit(0); return; } // g_debug("PROCESS CALLBACK!!!"); if (playback_paused) { if (!previous_playback_paused) { send_all_sound_off(port_buffers, nframes); } previous_playback_paused = playback_paused; return; } previous_playback_paused = playback_paused; if (use_transport) { // if (!ready_to_roll) return; transport_state = jack_transport_query(jack_client, NULL); if (transport_state == JackTransportStopped) { if (previous_transport_state == JackTransportRolling) { send_all_sound_off(port_buffers, nframes); } playback_started = -1; } if (transport_state == JackTransportStarting) { playback_started = -1; } if (transport_state == JackTransportRolling) { if (previous_transport_state != JackTransportRolling) { jack_position_t position; jack_transport_query(jack_client, &position); song_position = position.frame; playback_started = jack_last_frame_time(jack_client); } } previous_transport_state = transport_state; } else { if (playback_started == -1) { if (previous_playback_started >= 0) { send_all_sound_off(port_buffers, nframes); send_sond_end(); } } previous_playback_started = playback_started; } /* End of song already? */ if (playback_started < 0) return; last_frame_time = jack_last_frame_time(jack_client); /* We may push at most one byte per 0.32ms to stay below 31.25 Kbaud limit. */ bytes_remaining = nframes_to_ms(nframes) * rate_limit; double loop_offset = loop_song(smf); for (;;) { smf_event_t *event = smf_peek_next_event(smf); int end_of_song = 0; int is_meta_event = 0; if (event == NULL) { end_of_song = 1; } else if (smf_event_is_metadata(event)) { is_meta_event = 1; char *decoded = smf_event_decode(event); if (decoded) { if (!be_quiet) g_debug("Metadata: %s", decoded); end_of_song = process_meta_event(decoded); free(decoded); } } if (end_of_song) { if (!be_quiet) g_debug("End of song."); playback_started = -1; if (!use_transport) ctrl_c_pressed = 1; break; } if (is_meta_event) { smf_event_t *ret = smf_get_next_event(smf); assert(ret != 0); continue; } bytes_remaining -= event->midi_buffer_length; if (rate_limit > 0.0 && bytes_remaining <= 0) { warn_from_jack_thread_context("Rate limiting in effect."); break; } // t = seconds_to_nframes(event->time_seconds) + playback_started - song_position + nframes - last_frame_time; t = seconds_to_nframes(event->time_seconds + loop_offset) + playback_started - song_position - last_frame_time; /* If computed time is too much into the future, we'll need to send it later. */ if (t >= (int)nframes) break; /* If computed time is < 0, we missed a cycle because of xrun. */ if (t < 0) t = 0; assert(event->track->track_number >= 0 && event->track->track_number <= MAX_NUMBER_OF_TRACKS); /* We will send this event; remove it from the queue. */ smf_event_t *ret = smf_get_next_event(smf); assert(ret != 0); /* First, send it via midi_out. */ track_number = 0; #ifdef JACK_MIDI_NEEDS_NFRAMES buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length, nframes); #else buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length); #endif if (buffer == NULL) { warn_from_jack_thread_context("jack_midi_event_reserve failed, NOTE LOST."); break; } memcpy(buffer, event->midi_buffer, event->midi_buffer_length); /* Ignore per-track outputs? */ if (just_one_output) continue; /* Send it via proper output port. */ track_number = event->track->track_number; #ifdef JACK_MIDI_NEEDS_NFRAMES buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length, nframes); #else buffer = jack_midi_event_reserve(port_buffers[track_number], t, event->midi_buffer_length); #endif if (buffer == NULL) { warn_from_jack_thread_context("jack_midi_event_reserve failed, NOTE LOST."); break; } /* Before sending, reset channel to 0. XXX: Not very pretty. */ assert(event->midi_buffer_length >= 1); tmp_status = event->midi_buffer[0]; if (event->midi_buffer[0] >= 0x80 && event->midi_buffer[0] <= 0xEF) event->midi_buffer[0] &= 0xF0; memcpy(buffer, event->midi_buffer, event->midi_buffer_length); event->midi_buffer[0] = tmp_status; } }