Skip to content

Commit

Permalink
[cleanup] Split the data so that every in/out only has relevant members
Browse files Browse the repository at this point in the history
Also clean all use of std::ostringstream and put all std::cerr beehind __LIBREMIDI_DEBUG__
  • Loading branch information
jcelerier committed Jul 17, 2023
1 parent 40e3012 commit bd0e4cb
Show file tree
Hide file tree
Showing 18 changed files with 216 additions and 181 deletions.
2 changes: 0 additions & 2 deletions include/libremidi/backends/alsa_raw/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@
#include <libremidi/libremidi.hpp>

#include <atomic>
#include <ostream>
#include <sstream>
#include <thread>
20 changes: 12 additions & 8 deletions include/libremidi/backends/alsa_raw/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#include <alsa/asoundlib.h>

#include <functional>
#include <ostream>
#include <sstream>
#include <vector>

// Credits: greatly inspired from
Expand Down Expand Up @@ -69,9 +67,9 @@ struct raw_alsa_helpers
template <typename... Args>
void error(Args&&... args)
{
std::ostringstream s;
((s << args), ...);
error_callback(s.str());
std::string s;
((s += args), ...);
error_callback(std::move(s));
}

// 1: is an input / output
Expand Down Expand Up @@ -116,9 +114,15 @@ struct raw_alsa_helpers

static std::string device_identifier(int card, int device, int sub)
{
std::ostringstream s;
s << "hw:" << card << "," << device << "," << sub;
return s.str();
std::string s;
s.reserve(12);
s += "hw:";
s += std::to_string(card);
s += ",";
s += std::to_string(device);
s += ",";
s += std::to_string(sub);
return s;
}

void enumerate_cards()
Expand Down
39 changes: 36 additions & 3 deletions include/libremidi/backends/alsa_seq/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <atomic>
#include <map>
#include <sstream>
#include <thread>

namespace libremidi
Expand Down Expand Up @@ -55,6 +54,28 @@ portInfo(snd_seq_t* seq, snd_seq_port_info_t* pinfo, unsigned int type, int port
return count;
return 0;
}

inline std::string portName(snd_seq_t* seq, snd_seq_port_info_t* pinfo)
{
snd_seq_client_info_t* cinfo;
snd_seq_client_info_alloca(&cinfo);

int cnum = snd_seq_port_info_get_client(pinfo);
snd_seq_get_any_client_info(seq, cnum, cinfo);

std::string str;
str.reserve(64);
str += snd_seq_client_info_get_name(cinfo);
str += ":";
str += snd_seq_port_info_get_name(pinfo);
str += " "; // These lines added to make sure devices are listed
str += std::to_string(
snd_seq_port_info_get_client(pinfo)); // with full portnames added to ensure individual
// device names
str += ":";
str += std::to_string(snd_seq_port_info_get_port(pinfo));
return str;
}
}

struct alsa_configuration
Expand All @@ -69,15 +90,27 @@ struct alsa_data
{
snd_seq_t* seq{};
int vport{};

snd_seq_port_subscribe_t* subscription{};
snd_midi_event_t* coder{};

unsigned int bufferSize{};
std::vector<unsigned char> buffer;
};

struct alsa_in_data : alsa_data
{
pthread_t thread{};
pthread_t dummy_thread_id{};
snd_seq_real_time_t lastTime{};
int queue_id{}; // an input queue is needed to get timestamped events
int trigger_fds[2]{};
std::vector<unsigned char> buffer;
snd_seq_real_time_t lastTime{};

bool doInput{false};
};

struct alsa_out_data : alsa_data
{
};

}
69 changes: 29 additions & 40 deletions include/libremidi/backends/alsa_seq/midi_in.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ class midi_in_alsa final : public midi_in_api
midi_in_alsa::close_port();

// Shutdown the input thread.
if (inputData_.doInput)
if (data.doInput)
{
inputData_.doInput = false;
write(data.trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput));
data.doInput = false;
write(data.trigger_fds[1], &data.doInput, sizeof(data.doInput));

if (!pthread_equal(data.thread, data.dummy_thread_id))
pthread_join(data.thread, nullptr);
Expand Down Expand Up @@ -105,10 +105,8 @@ class midi_in_alsa final : public midi_in_api
(int)portNumber)
== 0)
{
std::ostringstream ost;
ost << "midi_in_alsa::open_port: the 'portNumber' argument (" << portNumber
<< ") is invalid.";
error<invalid_parameter_error>(ost.str());
error<invalid_parameter_error>(
"midi_in_alsa::open_port: invalid 'portNumber' argument: " + std::to_string(portNumber));
return;
}

Expand Down Expand Up @@ -165,7 +163,7 @@ class midi_in_alsa final : public midi_in_api
}
}

if (inputData_.doInput == false)
if (data.doInput == false)
{
// Start the input queue
#ifndef LIBREMIDI_ALSA_AVOID_TIMESTAMPING
Expand All @@ -178,15 +176,15 @@ class midi_in_alsa final : public midi_in_api
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);

inputData_.doInput = true;
data.doInput = true;
int err = pthread_create(&data.thread, &attr, alsaMidiHandler, &inputData_);
pthread_attr_destroy(&attr);
if (err)
{
snd_seq_unsubscribe_port(data.seq, data.subscription);
snd_seq_port_subscribe_free(data.subscription);
data.subscription = nullptr;
inputData_.doInput = false;
data.doInput = false;
error<thread_error>("midi_in_alsa::open_port: error starting MIDI input thread!");
return;
}
Expand Down Expand Up @@ -222,7 +220,7 @@ class midi_in_alsa final : public midi_in_api
data.vport = snd_seq_port_info_get_port(pinfo);
}

if (inputData_.doInput == false)
if (data.doInput == false)
{
// Wait for old thread to stop, if still running
if (!pthread_equal(data.thread, data.dummy_thread_id))
Expand All @@ -239,7 +237,7 @@ class midi_in_alsa final : public midi_in_api
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);

inputData_.doInput = true;
data.doInput = true;
int err = pthread_create(&data.thread, &attr, alsaMidiHandler, &inputData_);
pthread_attr_destroy(&attr);
if (err)
Expand All @@ -250,7 +248,7 @@ class midi_in_alsa final : public midi_in_api
snd_seq_port_subscribe_free(data.subscription);
data.subscription = nullptr;
}
inputData_.doInput = false;
data.doInput = false;
error<thread_error>("midi_in_alsa::open_virtual_port: error starting MIDI input thread!");
return;
}
Expand All @@ -277,10 +275,10 @@ class midi_in_alsa final : public midi_in_api

// Stop thread to avoid triggering the callback, while the port is intended
// to be closed
if (inputData_.doInput)
if (data.doInput)
{
inputData_.doInput = false;
write(data.trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput));
data.doInput = false;
write(data.trigger_fds[1], &data.doInput, sizeof(data.doInput));

if (!pthread_equal(data.thread, data.dummy_thread_id))
pthread_join(data.thread, nullptr);
Expand Down Expand Up @@ -311,45 +309,30 @@ class midi_in_alsa final : public midi_in_api

std::string get_port_name(unsigned int portNumber) override
{
snd_seq_client_info_t* cinfo;
snd_seq_port_info_t* pinfo;
snd_seq_client_info_alloca(&cinfo);
snd_seq_port_info_alloca(&pinfo);

std::string stringName;
if (portInfo(
data.seq, pinfo, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, (int)portNumber))
{
int cnum = snd_seq_port_info_get_client(pinfo);
snd_seq_get_any_client_info(data.seq, cnum, cinfo);
std::ostringstream os;
os << snd_seq_client_info_get_name(cinfo);
os << ":";
os << snd_seq_port_info_get_name(pinfo);
os << " "; // These lines added to make sure devices are listed
os << snd_seq_port_info_get_client(pinfo); // with full portnames added to ensure individual
// device names
os << ":";
os << snd_seq_port_info_get_port(pinfo);
stringName = os.str();
return stringName;
return portName(data.seq, pinfo);
}

// If we get here, we didn't find a match.
warning("midi_in_alsa::get_port_name: error looking for port name!");
return stringName;
return {};
}

private:
static void* alsaMidiHandler(void* ptr)
{
auto& data = *static_cast<midi_in_api::in_data*>(ptr);
auto& apidata = *static_cast<alsa_data*>(data.apiData);
auto& apidata = *static_cast<alsa_in_data*>(data.apiData);

double time{};
bool continueSysex = false;
bool doDecode = false;
message message{};
message& message = data.message;
int poll_fd_count{};
pollfd* poll_fds{};

Expand All @@ -359,9 +342,11 @@ class midi_in_alsa final : public midi_in_api
int result = snd_midi_event_new(0, &apidata.coder);
if (result < 0)
{
data.doInput = false;
apidata.doInput = false;
#if defined(__LIBREMIDI_DEBUG__)
std::cerr << "\nmidi_in_alsa::alsaMidiHandler: error initializing MIDI "
"event parser!\n\n";
#endif
return nullptr;
}

Expand All @@ -378,7 +363,7 @@ class midi_in_alsa final : public midi_in_api
poll_fds[0].fd = apidata.trigger_fds[0];
poll_fds[0].events = POLLIN;

while (data.doInput)
while (apidata.doInput)
{
if (snd_seq_event_input_pending(apidata.seq, 1) == 0)
{
Expand All @@ -398,13 +383,17 @@ class midi_in_alsa final : public midi_in_api
result = snd_seq_event_input(apidata.seq, &ev);
if (result == -ENOSPC)
{
#if defined(__LIBREMIDI_DEBUG__)
std::cerr << "\nmidi_in_alsa::alsaMidiHandler: MIDI input buffer overrun!\n\n";
#endif
continue;
}
else if (result <= 0)
{
#if defined(__LIBREMIDI_DEBUG__)
std::cerr << "\nmidi_in_alsa::alsaMidiHandler: unknown MIDI input error!\n";
perror("System reports");
#endif
continue;
}

Expand All @@ -419,14 +408,14 @@ class midi_in_alsa final : public midi_in_api

case SND_SEQ_EVENT_PORT_SUBSCRIBED:
#if defined(__LIBREMIDI_DEBUG__)
std::cout << "midi_in_alsa::alsaMidiHandler: port connection made!\n";
std::cerr << "midi_in_alsa::alsaMidiHandler: port connection made!\n";
#endif
break;

case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
#if defined(__LIBREMIDI_DEBUG__)
std::cerr << "midi_in_alsa::alsaMidiHandler: port connection has closed!\n";
std::cout << "sender = " << (int)ev->data.connect.sender.client << ":"
std::cerr << "sender = " << (int)ev->data.connect.sender.client << ":"
<< (int)ev->data.connect.sender.port
<< ", dest = " << (int)ev->data.connect.dest.client << ":"
<< (int)ev->data.connect.dest.port << std::endl;
Expand Down Expand Up @@ -551,7 +540,7 @@ class midi_in_alsa final : public midi_in_api
apidata.thread = apidata.dummy_thread_id;
return nullptr;
}
alsa_data data;
alsa_in_data data;
};

}
31 changes: 7 additions & 24 deletions include/libremidi/backends/alsa_seq/midi_out.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ class midi_out_alsa final : public midi_out_api
{
// Set up the ALSA sequencer client.
snd_seq_t* seq{};
int result1 = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK);
if (result1 < 0)
if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK) < 0)
{
error<driver_error>(
"midi_out_alsa::initialize: error creating ALSA sequencer client "
Expand Down Expand Up @@ -75,10 +74,9 @@ class midi_out_alsa final : public midi_out_api
data.seq, pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, (int)portNumber)
== 0)
{
std::ostringstream ost;
ost << "midi_out_alsa::open_port: the 'portNumber' argument (" << portNumber
<< ") is invalid.";
error<invalid_parameter_error>(ost.str());
error<invalid_parameter_error>(
"midi_out_alsa::open_port: invalid 'portNumber' argument: "
+ std::to_string(portNumber));
return;
}

Expand Down Expand Up @@ -171,34 +169,19 @@ class midi_out_alsa final : public midi_out_api

std::string get_port_name(unsigned int portNumber) override
{
snd_seq_client_info_t* cinfo;
snd_seq_port_info_t* pinfo;
snd_seq_client_info_alloca(&cinfo);
snd_seq_port_info_alloca(&pinfo);

std::string stringName;
if (portInfo(
data.seq, pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
(int)portNumber))
{
int cnum = snd_seq_port_info_get_client(pinfo);
snd_seq_get_any_client_info(data.seq, cnum, cinfo);
std::ostringstream os;
os << snd_seq_client_info_get_name(cinfo);
os << ":";
os << snd_seq_port_info_get_name(pinfo);
os << " "; // These lines added to make sure devices are listed
os << snd_seq_port_info_get_client(pinfo); // with full portnames added to ensure individual
// device names
os << ":";
os << snd_seq_port_info_get_port(pinfo);
stringName = os.str();
return stringName;
return portName(data.seq, pinfo);
}

// If we get here, we didn't find a match.
warning("midi_out_alsa::get_port_name: error looking for port name!");
return stringName;
return {};
}

void send_message(const unsigned char* message, std::size_t size) override
Expand Down Expand Up @@ -257,6 +240,6 @@ class midi_out_alsa final : public midi_out_api
}

private:
alsa_data data;
alsa_out_data data;
};
}
Loading

0 comments on commit bd0e4cb

Please sign in to comment.