/* Copyright (C) 2010 Devin Anderson This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __JackMidiRawInputWriteQueue__ #define __JackMidiRawInputWriteQueue__ #include "JackMidiAsyncQueue.h" #include "JackMidiWriteQueue.h" namespace Jack { /** * This queue enqueues raw, unparsed MIDI packets, and outputs complete * MIDI messages to a write queue. * * Use this queue if the MIDI API you're interfacing with gives you raw * MIDI bytes that must be parsed. */ class SERVER_EXPORT JackMidiRawInputWriteQueue: public JackMidiWriteQueue { private: jack_midi_event_t event; jack_midi_data_t event_byte; bool event_pending; size_t expected_bytes; jack_midi_data_t *input_buffer; size_t input_buffer_size; jack_midi_event_t *packet; JackMidiAsyncQueue *packet_queue; jack_midi_data_t status_byte; size_t total_bytes; size_t unbuffered_bytes; JackMidiWriteQueue *write_queue; void Clear(); bool PrepareBufferedEvent(jack_nframes_t time); bool PrepareByteEvent(jack_nframes_t time, jack_midi_data_t byte); void PrepareEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer); bool ProcessByte(jack_nframes_t time, jack_midi_data_t byte); void RecordByte(jack_midi_data_t byte); bool WriteEvent(jack_nframes_t boundary_frame); protected: /** * Override this method to specify what happens when there isn't enough * room in the ringbuffer to contain a parsed event. The default * method outputs an error message. */ virtual void HandleBufferFailure(size_t unbuffered_bytes, size_t total_bytes); /** * Override this method to specify what happens when a parsed event * can't be written to the write queue because the event's size exceeds * the total possible space in the write queue. The default method * outputs an error message. */ virtual void HandleEventLoss(jack_midi_event_t *event); /** * Override this method to specify what happens when an incomplete MIDI * message is parsed. The default method outputs an error message. */ virtual void HandleIncompleteMessage(size_t total_bytes); /** * Override this method to specify what happens when an invalid MIDI * status byte is parsed. The default method outputs an error message. */ virtual void HandleInvalidStatusByte(jack_midi_data_t byte); /** * Override this method to specify what happens when a sysex end byte * is parsed without first parsing a sysex begin byte. The default * method outputs an error message. */ virtual void HandleUnexpectedSysexEnd(size_t total_bytes); public: using JackMidiWriteQueue::EnqueueEvent; /** * Called to create a new raw input write queue. The `write_queue` * argument is the queue to write parsed messages to. The optional * `max_packets` argument specifies the number of packets that can be * enqueued in the internal queue. The optional `max_packet_data` * argument specifies the total number of MIDI bytes that can be put in * the internal queue, AND the maximum size for an event that can be * written to the write queue. */ JackMidiRawInputWriteQueue(JackMidiWriteQueue *write_queue, size_t max_packet_data=4096, size_t max_packets=1024); ~JackMidiRawInputWriteQueue(); EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer); /** * Returns the maximum size event that can be enqueued right *now*. */ size_t GetAvailableSpace(); /** * The `Process()` method should be called each time the * `EnqueueEvent()` method returns `OK`. The `Process()` method will * return the next frame at which an event should be sent. The return * value from `Process()` depends upon the result of writing bytes to * the write queue: * * -If the return value is '0', then all *complete* events have been * sent successfully to the write queue. Don't call `Process()` again * until another event has been enqueued. * * -If the return value is a non-zero value, then it specifies the * frame that a pending event is scheduled to sent at. If the frame is * in the future, then `Process()` should be called again at that time; * otherwise, `Process()` should be called as soon as the write queue * will accept events again. */ jack_nframes_t Process(jack_nframes_t boundary_frame=0); }; } #endif