Jack2  1.9.8
JackMidiAsyncQueue.cpp
00001 /*
00002 Copyright (C) 2010 Devin Anderson
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as published by
00006 the Free Software Foundation; either version 2.1 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018 */
00019 
00020 #include <new>
00021 
00022 #include "JackMidiAsyncQueue.h"
00023 
00024 using Jack::JackMidiAsyncQueue;
00025 
00026 JackMidiAsyncQueue::JackMidiAsyncQueue(size_t max_bytes, size_t max_messages)
00027 {
00028     data_buffer = new jack_midi_data_t[max_bytes];
00029     byte_ring = jack_ringbuffer_create((max_bytes * sizeof(jack_midi_data_t)) +
00030                                        1);
00031     if (byte_ring) {
00032         info_ring = jack_ringbuffer_create((max_messages * INFO_SIZE) + 1);
00033         if (info_ring) {
00034             jack_ringbuffer_mlock(byte_ring);
00035             jack_ringbuffer_mlock(info_ring);
00036             this->max_bytes = max_bytes;
00037             return;
00038         }
00039         jack_ringbuffer_free(byte_ring);
00040     }
00041     delete data_buffer;
00042     throw std::bad_alloc();
00043 }
00044 
00045 JackMidiAsyncQueue::~JackMidiAsyncQueue()
00046 {
00047     jack_ringbuffer_free(byte_ring);
00048     jack_ringbuffer_free(info_ring);
00049     delete[] data_buffer;
00050 }
00051 
00052 jack_midi_event_t *
00053 JackMidiAsyncQueue::DequeueEvent()
00054 {
00055     jack_midi_event_t *event = 0;
00056     if (jack_ringbuffer_read_space(info_ring) >= INFO_SIZE) {
00057         size_t size;
00058         event = &dequeue_event;
00059         jack_ringbuffer_read(info_ring, (char *) &(event->time),
00060                              sizeof(jack_nframes_t));
00061         jack_ringbuffer_read(info_ring, (char *) &size,
00062                              sizeof(size_t));
00063         jack_ringbuffer_read(byte_ring, (char *) data_buffer,
00064                              size * sizeof(jack_midi_data_t));
00065         event->buffer = data_buffer;
00066         event->size = size;
00067     }
00068     return event;
00069 }
00070 
00071 Jack::JackMidiWriteQueue::EnqueueResult
00072 JackMidiAsyncQueue::EnqueueEvent(jack_nframes_t time, size_t size,
00073                                  jack_midi_data_t *buffer)
00074 {
00075     if (size > max_bytes) {
00076         return BUFFER_TOO_SMALL;
00077     }
00078     if (! ((jack_ringbuffer_write_space(info_ring) >= INFO_SIZE) &&
00079            (jack_ringbuffer_write_space(byte_ring) >=
00080             (size * sizeof(jack_midi_data_t))))) {
00081         return BUFFER_FULL;
00082     }
00083     jack_ringbuffer_write(byte_ring, (const char *) buffer,
00084                           size * sizeof(jack_midi_data_t));
00085     jack_ringbuffer_write(info_ring, (const char *) (&time),
00086                           sizeof(jack_nframes_t));
00087     jack_ringbuffer_write(info_ring, (const char *) (&size), sizeof(size_t));
00088     return OK;
00089 }
00090 
00091 size_t
00092 JackMidiAsyncQueue::GetAvailableSpace()
00093 {
00094     return jack_ringbuffer_write_space(info_ring) < INFO_SIZE ? 0 :
00095         max_bytes - jack_ringbuffer_read_space(byte_ring);
00096 }