diff --git a/common/JackMidiWriteQueue.h b/common/JackMidiWriteQueue.h index 8a51bafa..a39776c9 100644 --- a/common/JackMidiWriteQueue.h +++ b/common/JackMidiWriteQueue.h @@ -63,13 +63,16 @@ namespace Jack { jack_midi_data_t *buffer) = 0; /** - * A wrapper method for the `EnqueueEvent` method above. + * A wrapper method for the `EnqueueEvent` method above. The optional + * 'frame_offset' argument is an amount of frames to add to the event's + * time. */ inline EnqueueResult - EnqueueEvent(jack_midi_event_t *event) + EnqueueEvent(jack_midi_event_t *event, jack_nframes_t frame_offset=0) { - return EnqueueEvent(event->time, event->size, event->buffer); + return EnqueueEvent(event->time + frame_offset, event->size, + event->buffer); } }; diff --git a/linux/alsarawmidi/JackALSARawMidiDriver.cpp b/linux/alsarawmidi/JackALSARawMidiDriver.cpp index 7bbae0a1..3f4761e0 100755 --- a/linux/alsarawmidi/JackALSARawMidiDriver.cpp +++ b/linux/alsarawmidi/JackALSARawMidiDriver.cpp @@ -134,32 +134,44 @@ JackALSARawMidiDriver::Execute() } revents = poll_fds[0].revents; if (revents & POLLHUP) { - close(fds[0]); - fds[0] = -1; + // Driver is being stopped. break; } - if (revents & (~(POLLHUP | POLLIN))) { + if (revents & (~ POLLIN)) { jack_error("JackALSARawMidiDriver::Execute - unexpected poll " "event on pipe file descriptor."); break; } - handle_ports: timeout_frame = 0; for (int i = 0; i < fCaptureChannels; i++) { - process_frame = input_ports[i]->ProcessALSA(); + if (! input_ports[i]->ProcessALSA(&process_frame)) { + jack_error("JackALSARawMidiDriver::Execute - a fatal error " + "occurred while processing ALSA input events."); + goto cleanup; + } if (process_frame && ((! timeout_frame) || (process_frame < timeout_frame))) { timeout_frame = process_frame; } } for (int i = 0; i < fPlaybackChannels; i++) { - process_frame = output_ports[i]->ProcessALSA(fds[0]); + if (! output_ports[i]->ProcessALSA(fds[0], &process_frame)) { + jack_error("JackALSARawMidiDriver::Execute - a fatal error " + "occurred while processing ALSA output events."); + goto cleanup; + } if (process_frame && ((! timeout_frame) || (process_frame < timeout_frame))) { timeout_frame = process_frame; } } } + cleanup: + close(fds[0]); + fds[0] = -1; + + jack_info("JackALSARawMidiDriver::Execute - ALSA thread exiting."); + return false; } @@ -402,7 +414,9 @@ JackALSARawMidiDriver::Read() { jack_nframes_t buffer_size = fEngineControl->fBufferSize; for (int i = 0; i < fCaptureChannels; i++) { - input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size); + if (! input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size)) { + return -1; + } } return 0; } @@ -539,8 +553,10 @@ JackALSARawMidiDriver::Write() jack_nframes_t buffer_size = fEngineControl->fBufferSize; int write_fd = fds[1]; for (int i = 0; i < fPlaybackChannels; i++) { - output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size, - write_fd); + if (! output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size, + write_fd)) { + return -1; + } } return 0; } diff --git a/linux/alsarawmidi/JackALSARawMidiInputPort.cpp b/linux/alsarawmidi/JackALSARawMidiInputPort.cpp index 94ae8c4a..7167c8b8 100755 --- a/linux/alsarawmidi/JackALSARawMidiInputPort.cpp +++ b/linux/alsarawmidi/JackALSARawMidiInputPort.cpp @@ -69,30 +69,33 @@ JackALSARawMidiInputPort::EnqueueALSAEvent() return (next_time < alsa_time) ? next_time : alsa_time; } -jack_nframes_t -JackALSARawMidiInputPort::ProcessALSA() +bool +JackALSARawMidiInputPort::ProcessALSA(jack_nframes_t *frame) { - unsigned short revents = ProcessPollEvents(); - jack_nframes_t frame; + unsigned short revents; + if (! ProcessPollEvents(&revents)) { + return false; + } if (alsa_event) { - frame = EnqueueALSAEvent(); - if (frame) { - return frame; + *frame = EnqueueALSAEvent(); + if (*frame) { + return true; } } if (revents & POLLIN) { for (alsa_event = receive_queue->DequeueEvent(); alsa_event; alsa_event = receive_queue->DequeueEvent()) { - frame = EnqueueALSAEvent(); - if (frame) { - return frame; + *frame = EnqueueALSAEvent(); + if (*frame) { + return true; } } } - return raw_queue->Process(); + *frame = raw_queue->Process(); + return true; } -void +bool JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames) { @@ -119,4 +122,5 @@ JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer, } break; } + return true; } diff --git a/linux/alsarawmidi/JackALSARawMidiInputPort.h b/linux/alsarawmidi/JackALSARawMidiInputPort.h index a5d5a2da..38b8985b 100755 --- a/linux/alsarawmidi/JackALSARawMidiInputPort.h +++ b/linux/alsarawmidi/JackALSARawMidiInputPort.h @@ -30,10 +30,10 @@ namespace Jack { size_t max_messages=1024); ~JackALSARawMidiInputPort(); - jack_nframes_t - ProcessALSA(); + bool + ProcessALSA(jack_nframes_t *frame); - void + bool ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames); }; diff --git a/linux/alsarawmidi/JackALSARawMidiOutputPort.cpp b/linux/alsarawmidi/JackALSARawMidiOutputPort.cpp index df1fc268..c1a2bfb8 100755 --- a/linux/alsarawmidi/JackALSARawMidiOutputPort.cpp +++ b/linux/alsarawmidi/JackALSARawMidiOutputPort.cpp @@ -54,13 +54,17 @@ JackALSARawMidiOutputPort::DequeueALSAEvent(int read_fd) return event; } -jack_nframes_t -JackALSARawMidiOutputPort::ProcessALSA(int read_fd) +bool +JackALSARawMidiOutputPort::ProcessALSA(int read_fd, jack_nframes_t *frame) { - unsigned short revents = ProcessPollEvents(); + unsigned short revents; + if (! ProcessPollEvents(&revents)) { + return false; + } if (blocked) { if (! (revents & POLLOUT)) { - return 0; + *frame = 0; + return true; } blocked = false; } @@ -98,7 +102,7 @@ JackALSARawMidiOutputPort::ProcessALSA(int read_fd) break; } process_events: - jack_nframes_t next_frame = raw_queue->Process(); + *frame = raw_queue->Process(); blocked = send_queue->IsBlocked(); if (blocked) { @@ -106,13 +110,14 @@ JackALSARawMidiOutputPort::ProcessALSA(int read_fd) "blocked"); SetPollEventMask(POLLERR | POLLNVAL | POLLOUT); - return 0; + *frame = 0; + } else { + SetPollEventMask(POLLERR | POLLNVAL); } - SetPollEventMask(POLLERR | POLLNVAL); - return next_frame; + return true; } -void +bool JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames, int write_fd) { @@ -128,20 +133,21 @@ JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer, char c = 1; ssize_t result = write(write_fd, &c, 1); assert(result <= 1); + if (result < 0) { + jack_error("JackALSARawMidiOutputPort::ProcessJack - error " + "writing a byte to the pipe file descriptor: %s", + strerror(errno)); + return false; + } if (! result) { + // Recoverable. jack_error("JackALSARawMidiOutputPort::ProcessJack - Couldn't " "write a byte to the pipe file descriptor. Dropping " "event."); - } else if (result < 0) { - jack_error("JackALSARawMidiOutputPort::ProcessJack - error " - "writing a byte to the pipe file descriptor: %s", - strerror(errno)); - } else if (thread_queue->EnqueueEvent(event->time + frames, - event->size, event->buffer) != - JackMidiWriteQueue::OK) { - jack_error("JackALSARawMidiOutputPort::ProcessJack - **BUG** The " - "thread queue said it had enough space to enqueue a " - "%d-byte event, but failed to enqueue the event."); + } else { + assert(thread_queue->EnqueueEvent(event, frames) == + JackMidiWriteQueue::OK); } } + return true; } diff --git a/linux/alsarawmidi/JackALSARawMidiOutputPort.h b/linux/alsarawmidi/JackALSARawMidiOutputPort.h index aea8f2ea..816ab6a2 100755 --- a/linux/alsarawmidi/JackALSARawMidiOutputPort.h +++ b/linux/alsarawmidi/JackALSARawMidiOutputPort.h @@ -30,10 +30,10 @@ namespace Jack { size_t max_messages=1024); ~JackALSARawMidiOutputPort(); - jack_nframes_t - ProcessALSA(int read_fd); + bool + ProcessALSA(int read_fd, jack_nframes_t *frame); - void + bool ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames, int write_fd); diff --git a/linux/alsarawmidi/JackALSARawMidiPort.cpp b/linux/alsarawmidi/JackALSARawMidiPort.cpp index a2d3d8fc..a37f9d93 100755 --- a/linux/alsarawmidi/JackALSARawMidiPort.cpp +++ b/linux/alsarawmidi/JackALSARawMidiPort.cpp @@ -126,27 +126,28 @@ JackALSARawMidiPort::PopulatePollDescriptors(struct pollfd *poll_fd) return result; } -int -JackALSARawMidiPort::ProcessPollEvents() +bool +JackALSARawMidiPort::ProcessPollEvents(unsigned short *revents) { - unsigned short revents = 0; int code = snd_rawmidi_poll_descriptors_revents(rawmidi, poll_fds, num_fds, - &revents); + revents); if (code) { jack_error("JackALSARawMidiPort::ProcessPollEvents - " "snd_rawmidi_poll_descriptors_revents: %s", snd_strerror(code)); - return 0; + return false; } - if (revents & POLLNVAL) { + if ((*revents) & POLLNVAL) { jack_error("JackALSARawMidiPort::ProcessPollEvents - the file " "descriptor is invalid."); + return false; } - if (revents & POLLERR) { + if ((*revents) & POLLERR) { jack_error("JackALSARawMidiPort::ProcessPollEvents - an error has " "occurred on the device or stream."); + return false; } - return revents; + return true; } void diff --git a/linux/alsarawmidi/JackALSARawMidiPort.h b/linux/alsarawmidi/JackALSARawMidiPort.h index 564e5b7b..07fb4c0f 100755 --- a/linux/alsarawmidi/JackALSARawMidiPort.h +++ b/linux/alsarawmidi/JackALSARawMidiPort.h @@ -21,8 +21,8 @@ namespace Jack { snd_rawmidi_t *rawmidi; - int - ProcessPollEvents(); + bool + ProcessPollEvents(unsigned short *revents); void SetPollEventMask(unsigned short events);