|
- /*
- Copyright (C) 2011 Devin Anderson
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #include <memory>
-
- #include "JackALSARawMidiInputPort.h"
- #include "JackMidiUtil.h"
-
- using Jack::JackALSARawMidiInputPort;
-
- JackALSARawMidiInputPort::JackALSARawMidiInputPort(snd_rawmidi_info_t *info,
- size_t index,
- size_t max_bytes,
- size_t max_messages):
- JackALSARawMidiPort(info, index)
- {
- alsa_event = 0;
- jack_event = 0;
- receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
- std::auto_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
- thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
- std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
- write_queue = new JackMidiBufferWriteQueue();
- std::auto_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
- raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
- max_messages);
- write_ptr.release();
- thread_ptr.release();
- receive_ptr.release();
- }
-
- JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
- {
- delete raw_queue;
- delete receive_queue;
- delete thread_queue;
- delete write_queue;
- }
-
- jack_nframes_t
- JackALSARawMidiInputPort::EnqueueALSAEvent()
- {
- switch (raw_queue->EnqueueEvent(alsa_event)) {
- case JackMidiWriteQueue::BUFFER_FULL:
- // Processing events early might free up some space in the raw queue.
- raw_queue->Process();
- switch (raw_queue->EnqueueEvent(alsa_event)) {
- case JackMidiWriteQueue::BUFFER_TOO_SMALL:
- jack_error("JackALSARawMidiInputPort::Process - **BUG** "
- "JackMidiRawInputWriteQueue::EnqueueEvent returned "
- "`BUFFER_FULL` and then returned `BUFFER_TOO_SMALL` "
- "after a `Process()` call.");
- // Fallthrough on purpose
- case JackMidiWriteQueue::OK:
- return 0;
- default:
- ;
- }
- break;
- case JackMidiWriteQueue::BUFFER_TOO_SMALL:
- jack_error("JackALSARawMidiInputPort::Execute - The thread queue "
- "couldn't enqueue a %d-byte packet. Dropping event.",
- alsa_event->size);
- // Fallthrough on purpose
- case JackMidiWriteQueue::OK:
- return 0;
- default:
- ;
- }
- jack_nframes_t alsa_time = alsa_event->time;
- jack_nframes_t next_time = raw_queue->Process();
- return (next_time < alsa_time) ? next_time : alsa_time;
- }
-
- bool
- JackALSARawMidiInputPort::ProcessALSA(jack_nframes_t *frame)
- {
- unsigned short revents;
- if (! ProcessPollEvents(&revents)) {
- return false;
- }
- if (alsa_event) {
- *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 true;
- }
- }
- }
- *frame = raw_queue->Process();
- return true;
- }
-
- bool
- JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
- jack_nframes_t frames)
- {
- write_queue->ResetMidiBuffer(port_buffer, frames);
- if (! jack_event) {
- jack_event = thread_queue->DequeueEvent();
- }
- for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
-
- // We add `frames` so that MIDI events align with audio as closely as
- // possible.
- switch (write_queue->EnqueueEvent(jack_event, frames)) {
- case JackMidiWriteQueue::BUFFER_TOO_SMALL:
- jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
- "queue couldn't enqueue a %d-byte event. Dropping "
- "event.", jack_event->size);
- // Fallthrough on purpose
- case JackMidiWriteQueue::OK:
- continue;
- default:
- ;
- }
- break;
- }
- return true;
- }
|