Skip to content

Commit

Permalink
Merge branch 'sadguitarius-long-sysex'
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmoreno committed Sep 25, 2024
2 parents e280c88 + bd1a897 commit cbd42c6
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 32 deletions.
4 changes: 2 additions & 2 deletions lib/rtppeer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ void rtppeer_t::parse_midi(io_bytes_reader &buffer) {
if ((header & 0x80) != 0) {
length <<= 8;
length += buffer.read_uint8();
DEBUG("Long header, {} bytes long", length);
// DEBUG("Long header, {} bytes long", length);
}
buffer.check_enough(length);
auto remaining = length;
Expand Down Expand Up @@ -675,7 +675,7 @@ void rtppeer_t::send_midi(const io_bytes_reader &events) {
buffer.write_uint8(events_size);
} else {
// Long header, 2 octets
DEBUG("Send long message: message_size={} bytes", events_size);
// DEBUG("Send long message: message_size={} bytes", events_size);
if (events_size > 1400) {
WARNING("MIDI message too long, may fail on UDP. message_size={} . If "
"find any problem report an issue to "
Expand Down
96 changes: 80 additions & 16 deletions src/aseq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,33 @@ snd_seq_addr_t *get_my_ev_client_port(snd_seq_event_t *ev, uint8_t client_id) {
}
aseq_t::aseq_t(std::string _name) : name(std::move(_name)), seq(nullptr) {
snd_lib_error_set_handler(error_handler);
if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) <
0) {
throw alsa_connect_exception(
"Can't open sequencer. Maybe user has no permissions.");
}
snd_seq_set_client_name(seq, name.c_str());
snd_seq_nonblock(seq, 1);

// Increase seq client pool sizes to 2000, which is the maximum allowed by the
// kernel
// TODO: make this configurable?
snd_seq_client_pool_alloca(&pool);
int result;
if ((result = snd_seq_get_client_pool(seq, pool)) < 0) {
ERROR("Failed to get pool: {}", snd_strerror(result));
} else {
snd_seq_client_pool_set_input_pool(pool, 2000);
snd_seq_client_pool_set_output_pool(pool, 2000);

if ((result = snd_seq_set_client_pool(seq, pool)) < 0) {
ERROR("Failed to set pool: {}", snd_strerror(result));
}
}

// TODO: these buffer sizes should probably be configurable or pinned to pool
// size in bytes
snd_seq_set_input_buffer_size(seq, 65536);
snd_seq_set_output_buffer_size(seq, 65536);

snd_seq_client_info_t *info = nullptr;
snd_seq_client_info_malloc(&info);
Expand Down Expand Up @@ -603,8 +624,12 @@ void aseq_t::for_connections(const port_t &port,
snd_seq_query_subscribe_free(subs);
}

mididata_to_alsaevents_t::mididata_to_alsaevents_t() : buffer(nullptr) {
snd_midi_event_new(1024, &buffer);
// TODO: these buffer sizes should probably be configurable or pinned to pool
// size in bytes
mididata_to_alsaevents_t::mididata_to_alsaevents_t()
: buffer(nullptr), decode_buffer_data(65536, 0),
decode_buffer(&decode_buffer_data[0], 65536) {
snd_midi_event_new(65536, &buffer);
}
mididata_to_alsaevents_t::~mididata_to_alsaevents_t() {
if (buffer)
Expand All @@ -620,7 +645,6 @@ void mididata_to_alsaevents_t::mididata_to_evs_f(

while (data.position < data.end) {
// DEBUG("mididata to snd_ev, left {}", data);
snd_seq_ev_clear(&ev);
auto used = snd_midi_event_encode(buffer, data.position,
data.end - data.position, &ev);
if (used <= 0) {
Expand All @@ -633,18 +657,58 @@ void mididata_to_alsaevents_t::mididata_to_evs_f(
}
}

void mididata_to_alsaevents_t::ev_to_mididata(snd_seq_event_t *ev,
rtpmidid::io_bytes_writer &data) {
snd_midi_event_reset_decode(buffer);
auto ret = snd_midi_event_decode(buffer, data.position,
data.end - data.position, ev);
if (ret < 0) {
ERROR("Could not translate alsa seq event. Do nothing.");
return;
}
void mididata_to_alsaevents_t::ev_to_mididata_f(
snd_seq_event_t *ev, rtpmidid::io_bytes_writer &data,
std::function<void(const mididata_t &)> func) {
if (ev->type != SND_SEQ_EVENT_SYSEX) {
snd_midi_event_reset_decode(buffer);
auto ret = snd_midi_event_decode(buffer, data.position,
data.end - data.position, ev);
if (ret < 0) {
ERROR("Could not translate alsa seq event. Do nothing.");
return;
}

data.position += ret;
// DEBUG("ev to mididata, left: {}, {}", ret, data);
data.position += ret;
const auto mididata = mididata_t(data);
func(mididata);
} else {
snd_midi_event_reset_decode(buffer);
auto total_bytes = snd_midi_event_decode(buffer, &decode_buffer_data[0],
ev->data.ext.len, ev);
if (total_bytes < 0) {
ERROR("Could not translate alsa seq event. Do nothing.");
return;
}
bool start = true;

while (true) {
rtpmidid::io_bytes_writer_static<258> out_buffer;
if (start) {
decode_buffer.position += 1;
out_buffer.write_uint8(0xF0);
start = false;
} else {
out_buffer.write_uint8(0xF7);
}
auto bytes_left =
total_bytes - (decode_buffer.position - decode_buffer.start) - 1;
if (bytes_left <= 256) {
out_buffer.copy_from(decode_buffer, bytes_left);
out_buffer.write_uint8(0xF7);
const auto mididata = mididata_t(out_buffer);
func(mididata);
decode_buffer.position = decode_buffer.start;
return;
} else {
out_buffer.copy_from(decode_buffer, 256); // Don't copy 0xF7
out_buffer.write_uint8(0xF0);
const auto mididata = mididata_t(out_buffer);
func(mididata);
decode_buffer.position += 256;
}
}
}
}

} // namespace rtpmididns
Expand Down
10 changes: 9 additions & 1 deletion src/aseq.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <rtpmidid/iobytes.hpp>
#include <rtpmidid/poller.hpp>
#include <rtpmidid/signal.hpp>
#include <mididata.hpp>

namespace rtpmididns {
class aseq_t : public std::enable_shared_from_this<aseq_t> {
Expand Down Expand Up @@ -95,6 +96,7 @@ class aseq_t : public std::enable_shared_from_this<aseq_t> {

std::string name;
snd_seq_t *seq;
snd_seq_client_pool_t *pool;
// std::vector<int> fds; // Normally 1?
std::map<int, rtpmidid::signal_t<port_t, const std::string &>>
subscribe_event;
Expand Down Expand Up @@ -149,7 +151,13 @@ class mididata_to_alsaevents_t {
// Gets a data bunch of bytes, and calls a callback with all found events.
void mididata_to_evs_f(rtpmidid::io_bytes_reader &data,
std::function<void(snd_seq_event_t *)>);
void ev_to_mididata(snd_seq_event_t *, rtpmidid::io_bytes_writer &data);

void ev_to_mididata_f(snd_seq_event_t *ev, rtpmidid::io_bytes_writer &data,
std::function<void(const mididata_t &)> func);

private:
std::vector<uint8_t> decode_buffer_data;
rtpmidid::io_bytes decode_buffer;
};

class alsa_connect_exception : public rtpmidid::exception {
Expand Down
20 changes: 16 additions & 4 deletions src/local_alsa_listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ local_alsa_listener_t::local_alsa_listener_t(const std::string &name_,
aseq->midi_event[alsaport].connect([this](snd_seq_event_t *ev) {
rtpmidid::io_bytes_static<1024> data;
auto datawriter = rtpmidid::io_bytes_writer(data);
mididata_decoder.ev_to_mididata(ev, datawriter);
auto mididata = mididata_t(datawriter);
router->send_midi(peer_id, mididata);
mididata_decoder.ev_to_mididata_f(
ev, datawriter, [this](const mididata_t &mididata) {
router->send_midi(peer_id, mididata);
});
});
}

Expand Down Expand Up @@ -142,7 +143,18 @@ void local_alsa_listener_t::send_midi(midipeer_id_t from,
snd_seq_ev_set_source(ev, alsaport);
snd_seq_ev_set_subs(ev); // to all subscribers
snd_seq_ev_set_direct(ev);
snd_seq_event_output_direct(aseq->seq, ev);
auto result = snd_seq_event_output(aseq->seq, ev);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(aseq->seq);
snd_seq_drop_output(aseq->seq);
}
result = snd_seq_drain_output(aseq->seq);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(aseq->seq);
snd_seq_drop_output(aseq->seq);
}
});
}

Expand Down
21 changes: 16 additions & 5 deletions src/local_alsa_multi_listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ void local_alsa_multi_listener_t::alsaseq_event(snd_seq_event_t *event) {
return;
}
rtpmidid::io_bytes_writer_static<1024> writer;
alsatrans_decoder.ev_to_mididata(event, writer);
auto midi = mididata_t(writer);

router->send_midi(peer_id, peerI->second, midi);
alsatrans_decoder.ev_to_mididata_f(event, writer,
[this](const mididata_t &mididata) {
router->send_midi(peer_id, mididata);
});
}

void local_alsa_multi_listener_t::send_midi(midipeer_id_t from,
Expand All @@ -155,7 +155,18 @@ void local_alsa_multi_listener_t::send_midi(midipeer_id_t from,
snd_seq_ev_set_source(ev, this->port);
snd_seq_ev_set_dest(ev, port.client, port.port);
snd_seq_ev_set_direct(ev);
snd_seq_event_output_direct(seq->seq, ev);
auto result = snd_seq_event_output(seq->seq, ev);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(seq->seq);
snd_seq_drop_output(seq->seq);
}
result = snd_seq_drain_output(seq->seq);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(seq->seq);
snd_seq_drop_output(seq->seq);
}
});
}
}
Expand Down
20 changes: 16 additions & 4 deletions src/local_alsa_peer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ local_alsa_peer_t::local_alsa_peer_t(const std::string &name_,
midi_connection = seq->midi_event[port].connect([this](snd_seq_event *ev) {
rtpmidid::io_bytes_static<1024> data;
auto datawriter = rtpmidid::io_bytes_writer(data);
mididata_decoder.ev_to_mididata(ev, datawriter);
auto mididata = mididata_t(datawriter);
router->send_midi(peer_id, mididata);
mididata_decoder.ev_to_mididata_f(ev, datawriter,
[this](const mididata_t &mididata) {
router->send_midi(peer_id, mididata);
});
});
}

Expand All @@ -50,7 +51,18 @@ void local_alsa_peer_t::send_midi(midipeer_id_t from, const mididata_t &data) {
snd_seq_ev_set_source(ev, this->port);
snd_seq_ev_set_subs(ev); // to all subscribers
snd_seq_ev_set_direct(ev);
snd_seq_event_output_direct(seq->seq, ev);
auto result = snd_seq_event_output(seq->seq, ev);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(seq->seq);
snd_seq_drop_output(seq->seq);
}
result = snd_seq_drain_output(seq->seq);
if (result < 0) {
ERROR("Error: {}", snd_strerror(result));
snd_seq_drop_input(seq->seq);
snd_seq_drop_output(seq->seq);
}
});
}

Expand Down

0 comments on commit cbd42c6

Please sign in to comment.