ALSA backend RT-safe MIDI buffer allocation
This commit is contained in:
parent
2b7c585dba
commit
59a63a08f9
@ -77,6 +77,8 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
|
||||
pthread_mutex_init (&_port_callback_mutex, 0);
|
||||
_input_audio_device_info.valid = false;
|
||||
_output_audio_device_info.valid = false;
|
||||
|
||||
_port_connection_queue.reserve (128);
|
||||
}
|
||||
|
||||
AlsaAudioBackend::~AlsaAudioBackend ()
|
||||
@ -1693,11 +1695,11 @@ AlsaAudioBackend::midi_event_get (
|
||||
if (event_index >= source.size ()) {
|
||||
return -1;
|
||||
}
|
||||
AlsaMidiEvent * const event = source[event_index].get ();
|
||||
AlsaMidiEvent const& event = source[event_index];
|
||||
|
||||
timestamp = event->timestamp ();
|
||||
size = event->size ();
|
||||
*buf = event->data ();
|
||||
timestamp = event.timestamp ();
|
||||
size = event.size ();
|
||||
*buf = event.data ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1708,15 +1710,18 @@ AlsaAudioBackend::midi_event_put (
|
||||
const uint8_t* buffer, size_t size)
|
||||
{
|
||||
assert (buffer && port_buffer);
|
||||
if (size >= MaxAlsaMidiEventSize) {
|
||||
return -1;
|
||||
}
|
||||
AlsaMidiBuffer& dst = * static_cast<AlsaMidiBuffer*>(port_buffer);
|
||||
if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
|
||||
#ifndef NDEBUG
|
||||
if (dst.size () && (pframes_t)dst.back ().timestamp () > timestamp) {
|
||||
// nevermind, ::get_buffer() sorts events
|
||||
fprintf (stderr, "AlsaMidiBuffer: it's too late for this event. %d > %d\n",
|
||||
(pframes_t)dst.back ()->timestamp (), timestamp);
|
||||
#endif
|
||||
(pframes_t)dst.back ().timestamp (), timestamp);
|
||||
}
|
||||
dst.push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (timestamp, buffer, size)));
|
||||
#endif
|
||||
dst.push_back (AlsaMidiEvent (timestamp, buffer, size));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1949,7 +1954,7 @@ AlsaAudioBackend::main_process_thread ()
|
||||
AlsaMidiIn *rm = _rmidi_in.at(i);
|
||||
void *bptr = (*it)->get_buffer(0);
|
||||
pframes_t time;
|
||||
uint8_t data[64]; // match MaxAlsaEventSize in alsa_rawmidi.cc
|
||||
uint8_t data[MaxAlsaMidiEventSize];
|
||||
size_t size = sizeof(data);
|
||||
midi_clear(bptr);
|
||||
while (rm->recv_event (time, data, size)) {
|
||||
@ -1983,7 +1988,7 @@ AlsaAudioBackend::main_process_thread ()
|
||||
AlsaMidiOut *rm = _rmidi_out.at(i);
|
||||
rm->sync_time (clock1);
|
||||
for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
|
||||
rm->send_event ((*mit)->timestamp(), (*mit)->data(), (*mit)->size());
|
||||
rm->send_event (mit->timestamp (), mit->data (), mit->size ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2321,13 +2326,18 @@ AlsaMidiPort::AlsaMidiPort (AlsaAudioBackend &b, const std::string& name, PortFl
|
||||
{
|
||||
_buffer[0].clear ();
|
||||
_buffer[1].clear ();
|
||||
_buffer[2].clear ();
|
||||
|
||||
_buffer[0].reserve(256);
|
||||
_buffer[1].reserve(256);
|
||||
_buffer[2].reserve(256);
|
||||
}
|
||||
|
||||
AlsaMidiPort::~AlsaMidiPort () { }
|
||||
|
||||
struct MidiEventSorter {
|
||||
bool operator() (const boost::shared_ptr<AlsaMidiEvent>& a, const boost::shared_ptr<AlsaMidiEvent>& b) {
|
||||
return *a < *b;
|
||||
bool operator() (AlsaMidiEvent const& a, AlsaMidiEvent const& b) {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
@ -2341,7 +2351,7 @@ void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
|
||||
++i) {
|
||||
const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*i)->const_buffer ();
|
||||
for (AlsaMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
|
||||
(_buffer[_bufperiod]).push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (**it)));
|
||||
(_buffer[_bufperiod]).push_back (*it);
|
||||
}
|
||||
}
|
||||
std::stable_sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
|
||||
@ -2352,10 +2362,8 @@ void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
|
||||
AlsaMidiEvent::AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
|
||||
: _size (size)
|
||||
, _timestamp (timestamp)
|
||||
, _data (0)
|
||||
{
|
||||
if (size > 0) {
|
||||
_data = (uint8_t*) malloc (size);
|
||||
if (size > 0 && size < MaxAlsaMidiEventSize) {
|
||||
memcpy (_data, data, size);
|
||||
}
|
||||
}
|
||||
@ -2363,14 +2371,9 @@ AlsaMidiEvent::AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, si
|
||||
AlsaMidiEvent::AlsaMidiEvent (const AlsaMidiEvent& other)
|
||||
: _size (other.size ())
|
||||
, _timestamp (other.timestamp ())
|
||||
, _data (0)
|
||||
{
|
||||
if (other.size () && other.const_data ()) {
|
||||
_data = (uint8_t*) malloc (other.size ());
|
||||
memcpy (_data, other.const_data (), other.size ());
|
||||
if (other._size > 0) {
|
||||
assert (other._size < MaxAlsaMidiEventSize);
|
||||
memcpy (_data, other._data, other._size);
|
||||
}
|
||||
};
|
||||
|
||||
AlsaMidiEvent::~AlsaMidiEvent () {
|
||||
free (_data);
|
||||
};
|
||||
|
@ -50,19 +50,17 @@ class AlsaMidiEvent {
|
||||
public:
|
||||
AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size);
|
||||
AlsaMidiEvent (const AlsaMidiEvent& other);
|
||||
~AlsaMidiEvent ();
|
||||
size_t size () const { return _size; };
|
||||
pframes_t timestamp () const { return _timestamp; };
|
||||
const unsigned char* const_data () const { return _data; };
|
||||
unsigned char* data () { return _data; };
|
||||
const uint8_t* data () const { return _data; };
|
||||
bool operator< (const AlsaMidiEvent &other) const { return timestamp () < other.timestamp (); };
|
||||
private:
|
||||
size_t _size;
|
||||
pframes_t _timestamp;
|
||||
uint8_t *_data;
|
||||
uint8_t _data[MaxAlsaMidiEventSize];
|
||||
};
|
||||
|
||||
typedef std::vector<boost::shared_ptr<AlsaMidiEvent> > AlsaMidiBuffer;
|
||||
typedef std::vector<AlsaMidiEvent> AlsaMidiBuffer;
|
||||
|
||||
class AlsaPort {
|
||||
protected:
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "pbd/ringbuffer.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
/* max bytes per individual midi-event
|
||||
* events larger than this are ignored */
|
||||
#define MaxAlsaMidiEventSize (64)
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class AlsaMidiIO {
|
||||
|
@ -28,10 +28,6 @@
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
/* max bytes per individual midi-event
|
||||
* events larger than this are ignored */
|
||||
#define MaxAlsaRawEventSize (64)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define _DEBUGPRINT(STR) fprintf(stderr, STR);
|
||||
#else
|
||||
@ -123,7 +119,7 @@ AlsaRawMidiOut::main_process_thread ()
|
||||
while (_running) {
|
||||
bool have_data = false;
|
||||
struct MidiEventHeader h(0,0);
|
||||
uint8_t data[MaxAlsaRawEventSize];
|
||||
uint8_t data[MaxAlsaMidiEventSize];
|
||||
|
||||
const uint32_t read_space = _rb->read_space();
|
||||
|
||||
@ -133,7 +129,7 @@ AlsaRawMidiOut::main_process_thread ()
|
||||
break;
|
||||
}
|
||||
assert (read_space >= h.size);
|
||||
if (h.size > MaxAlsaRawEventSize) {
|
||||
if (h.size > MaxAlsaMidiEventSize) {
|
||||
_rb->increment_read_idx (h.size);
|
||||
_DEBUGPRINT("AlsaRawMidiOut: MIDI event too large!\n");
|
||||
continue;
|
||||
@ -280,7 +276,7 @@ AlsaRawMidiIn::main_process_thread ()
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t data[MaxAlsaRawEventSize];
|
||||
uint8_t data[MaxAlsaMidiEventSize];
|
||||
uint64_t time = g_get_monotonic_time();
|
||||
ssize_t err = snd_rawmidi_read (_device, data, sizeof(data));
|
||||
|
||||
|
@ -27,10 +27,6 @@
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
/* max bytes per individual midi-event
|
||||
* events larger than this are ignored */
|
||||
#define MaxAlsaSeqEventSize (64)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define _DEBUGPRINT(STR) fprintf(stderr, STR);
|
||||
#else
|
||||
@ -130,12 +126,12 @@ AlsaSeqMidiOut::main_process_thread ()
|
||||
_running = true;
|
||||
bool need_drain = false;
|
||||
snd_midi_event_t *alsa_codec = NULL;
|
||||
snd_midi_event_new (MaxAlsaSeqEventSize, &alsa_codec);
|
||||
snd_midi_event_new (MaxAlsaMidiEventSize, &alsa_codec);
|
||||
pthread_mutex_lock (&_notify_mutex);
|
||||
while (_running) {
|
||||
bool have_data = false;
|
||||
struct MidiEventHeader h(0,0);
|
||||
uint8_t data[MaxAlsaSeqEventSize];
|
||||
uint8_t data[MaxAlsaMidiEventSize];
|
||||
|
||||
const uint32_t read_space = _rb->read_space();
|
||||
|
||||
@ -145,7 +141,7 @@ AlsaSeqMidiOut::main_process_thread ()
|
||||
break;
|
||||
}
|
||||
assert (read_space >= h.size);
|
||||
if (h.size > MaxAlsaSeqEventSize) {
|
||||
if (h.size > MaxAlsaMidiEventSize) {
|
||||
_rb->increment_read_idx (h.size);
|
||||
_DEBUGPRINT("AlsaSeqMidiOut: MIDI event too large!\n");
|
||||
continue;
|
||||
@ -240,7 +236,7 @@ AlsaSeqMidiIn::main_process_thread ()
|
||||
_running = true;
|
||||
bool do_poll = true;
|
||||
snd_midi_event_t *alsa_codec = NULL;
|
||||
snd_midi_event_new (MaxAlsaSeqEventSize, &alsa_codec);
|
||||
snd_midi_event_new (MaxAlsaMidiEventSize, &alsa_codec);
|
||||
|
||||
while (_running) {
|
||||
|
||||
@ -275,7 +271,7 @@ AlsaSeqMidiIn::main_process_thread ()
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t data[MaxAlsaSeqEventSize];
|
||||
uint8_t data[MaxAlsaMidiEventSize];
|
||||
snd_midi_event_reset_decode (alsa_codec);
|
||||
ssize_t size = snd_midi_event_decode (alsa_codec, data, sizeof(data), event);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user