summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-08-05 15:03:06 +0200
committerRobin Gareus <robin@gareus.org>2017-08-05 15:36:36 +0200
commit59a63a08f99e1cb17ba5775afa4ad514cc5b163f (patch)
tree5e74512a65a16d4ac6711d2381feea005acee3b8 /libs
parent2b7c585dbae9c989d35e2884060aad4b0270f90e (diff)
ALSA backend RT-safe MIDI buffer allocation
Diffstat (limited to 'libs')
-rw-r--r--libs/backends/alsa/alsa_audiobackend.cc51
-rw-r--r--libs/backends/alsa/alsa_audiobackend.h8
-rw-r--r--libs/backends/alsa/alsa_midi.h4
-rw-r--r--libs/backends/alsa/alsa_rawmidi.cc10
-rw-r--r--libs/backends/alsa/alsa_sequencer.cc14
5 files changed, 42 insertions, 45 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc
index 9d3dc96f43..e7cdfedcb9 100644
--- a/libs/backends/alsa/alsa_audiobackend.cc
+++ b/libs/backends/alsa/alsa_audiobackend.cc
@@ -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);
-};
diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h
index 97cba16ba5..c175a1950b 100644
--- a/libs/backends/alsa/alsa_audiobackend.h
+++ b/libs/backends/alsa/alsa_audiobackend.h
@@ -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:
diff --git a/libs/backends/alsa/alsa_midi.h b/libs/backends/alsa/alsa_midi.h
index 254835591f..7aa2af95c3 100644
--- a/libs/backends/alsa/alsa_midi.h
+++ b/libs/backends/alsa/alsa_midi.h
@@ -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 {
diff --git a/libs/backends/alsa/alsa_rawmidi.cc b/libs/backends/alsa/alsa_rawmidi.cc
index 8d2420a6cb..68d8808679 100644
--- a/libs/backends/alsa/alsa_rawmidi.cc
+++ b/libs/backends/alsa/alsa_rawmidi.cc
@@ -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));
diff --git a/libs/backends/alsa/alsa_sequencer.cc b/libs/backends/alsa/alsa_sequencer.cc
index a9c3adf4fa..036ea5abc6 100644
--- a/libs/backends/alsa/alsa_sequencer.cc
+++ b/libs/backends/alsa/alsa_sequencer.cc
@@ -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);