Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/libremidi.examples.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ add_example(midi1_to_midi2)
add_example(midiclock_in)
add_example(midiclock_out)
add_example(midiout)
add_example(client)
# add_example(client)
add_example(midiprobe)
add_example(qmidiin)
add_example(sysextest)
Expand Down
4 changes: 2 additions & 2 deletions cmake/libremidi.sources.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ target_sources(libremidi PRIVATE
include/libremidi/detail/ump_stream.hpp

include/libremidi/api.hpp
include/libremidi/client.cpp
include/libremidi/client.hpp
# include/libremidi/client.cpp
# include/libremidi/client.hpp
include/libremidi/config.hpp
include/libremidi/configurations.hpp
include/libremidi/error.hpp
Expand Down
28 changes: 18 additions & 10 deletions examples/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ inline std::ostream& operator<<(std::ostream& s, const libremidi::device_identif
{
std::ostream& s;
void operator()(const std::string& u) { s << u; }
void operator()(libremidi::usb_device_identifier u)
{
s << u.vendor_id << ":" << u.product_id;
}
void operator()(uint64_t u)
{
auto res = static_cast<uint32_t>(u);
Expand Down Expand Up @@ -160,23 +164,27 @@ inline std::ostream& operator<<(std::ostream& s, const libremidi::port_informati
{
s << "[ client: " << rhs.client;
if (rhs.container.index() > 0)
s << ", container: " << rhs.container;
s << "\n , container: " << rhs.container;
if (rhs.device.index() > 0)
s << ", device_id: " << rhs.device;
s << "\n , device_id: " << rhs.device;

s << ", port: " << rhs.port;
s << "\n , port: " << rhs.port;

if (!rhs.manufacturer.empty())
s << ", manufacturer: " << rhs.manufacturer;
s << "\n , manufacturer: " << rhs.manufacturer;
if (!rhs.product.empty())
s << "\n , product: " << rhs.product;
if (!rhs.serial.empty())
s << "\n , serial: " << rhs.serial;
if (!rhs.device_name.empty())
s << ", device_name: " << rhs.device_name;
s << "\n , device_name: " << rhs.device_name;
if (!rhs.port_name.empty())
s << ", port_name: " << rhs.port_name;
s << "\n , port_name: " << rhs.port_name;
if (!rhs.display_name.empty())
s << ", display_name: " << rhs.display_name;
if (rhs.type != libremidi::port_information::unknown)
s << ", type: " << rhs.type;
return s << "]";
s << "\n , display_name: " << rhs.display_name;
if (rhs.type != libremidi::transport_type::unknown)
s << "\n , type: " << rhs.type;
return s << "\n ]";
}

namespace libremidi::examples
Expand Down
1 change: 1 addition & 0 deletions include/libremidi/backends/alsa_raw/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace alsa_raw
{
struct alsa_raw_port_info
{
// hw:1,2,0
std::string device;
std::string card_name;
std::string device_name;
Expand Down
62 changes: 40 additions & 22 deletions include/libremidi/backends/alsa_raw/observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ class observer_impl_base
explicit observer_impl_base(
observer_configuration&& conf, alsa_raw_observer_configuration&& apiconf)
: configuration{std::move(conf), std::move(apiconf)}
{
}

~observer_impl_base()
{
#if LIBREMIDI_HAS_UDEV
m_termination_event.notify();

if (m_thread.joinable())
m_thread.join();
#endif
}

// Must be called for child classes due to virtual function calls
void finish_init()
{
if (!configuration.has_callbacks())
return;
Expand All @@ -48,16 +63,6 @@ class observer_impl_base
#endif
}

~observer_impl_base()
{
#if LIBREMIDI_HAS_UDEV
m_termination_event.notify();

if (m_thread.joinable())
m_thread.join();
#endif
}

std::vector<libremidi::input_port> get_input_ports() const noexcept override
{
std::vector<libremidi::input_port> ret;
Expand All @@ -84,7 +89,6 @@ class observer_impl_base
return ret;
}

private:
#if LIBREMIDI_HAS_UDEV
void run()
{
Expand All @@ -98,6 +102,12 @@ class observer_impl_base
return;
}

// Check eventfd to see if we need to exit
if (m_fds[1].revents & POLLIN)
{
break;
}

// Check udev
if (m_fds[0].revents & POLLIN)
{
Expand All @@ -122,12 +132,6 @@ class observer_impl_base
m_fds[0].revents = 0;
}

// Check eventfd
if (m_fds[1].revents & POLLIN)
{
break;
}

// Check timer
if (m_fds[2].revents & POLLIN)
{
Expand All @@ -146,26 +150,35 @@ class observer_impl_base
-> std::conditional_t<Input, input_port, output_port>
{
#if LIBREMIDI_HAS_UDEV
auto [container, device, type] = get_udev_soundcard_info(m_udev, p.card);
auto [container, device, type, manufacturer, product, serial]
= get_udev_soundcard_info(m_udev, p.card);
#else
container_identifier container{};
device_identifier device{};
libremidi::port_information::port_type type{};
libremidi::transport_type type{};
std::string manufacturer;
std::string product;
std::string serial;
#endif
std::string display_name = p.subdevice_name;
if (display_name.empty())
display_name = p.device_name;
if (display_name.empty())
display_name = p.card_name;
if (display_name.empty())
display_name = product;
if (display_name.empty())
display_name = "unknown";

return {
{.client = 0,
{.api = get_current_api(),
.client = 0,
.container = container,
.device = device,
.port = raw_to_port_handle({p.card, p.dev, p.sub}),
.manufacturer = p.card_name,
.manufacturer = manufacturer,
.product = product,
.serial = serial,
.device_name = p.device_name,
.port_name = p.subdevice_name,
.display_name = std::move(display_name),
Expand Down Expand Up @@ -247,7 +260,12 @@ namespace libremidi::alsa_raw
{
struct observer_impl : observer_impl_base<alsa_raw::midi1_enumerator>
{
using alsa_raw::observer_impl_base<midi1_enumerator>::observer_impl_base;
observer_impl(observer_configuration&& conf, alsa_raw_observer_configuration&& apiconf)
: observer_impl_base<alsa_raw::midi1_enumerator>{std::move(conf), std::move(apiconf)}
{
finish_init();
}

libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_RAW; }
};
}
11 changes: 8 additions & 3 deletions include/libremidi/backends/alsa_raw_ump/observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

namespace libremidi::alsa_raw_ump
{

class observer_impl : public alsa_raw::observer_impl_base<midi2_enumerator>
{
using alsa_raw::observer_impl_base<midi2_enumerator>::observer_impl_base;
public:
observer_impl(
libremidi::observer_configuration&& conf, alsa_raw_ump::observer_configuration&& apiconf)
: observer_impl_base<alsa_raw_ump::midi2_enumerator>{std::move(conf), std::move(apiconf)}
{
finish_init();
}

libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_RAW_UMP; }
};

}
39 changes: 36 additions & 3 deletions include/libremidi/backends/alsa_seq/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ inline constexpr std::pair<int, int> seq_from_port_handle(port_handle p) noexcep
return {client, port};
}

inline void for_all_clients(
const libasound& snd, snd_seq_t* seq, const std::function<void(snd_seq_client_info_t&)>& func)
{
snd_seq_client_info_t* cinfo{};
snd_seq_client_info_alloca(&cinfo);
snd_seq_port_info_t* pinfo{};
snd_seq_port_info_alloca(&pinfo);

snd.seq.client_info_set_client(cinfo, -1);
while (snd.seq.query_next_client(seq, cinfo) >= 0)
{
int client = snd.seq.client_info_get_client(cinfo);
if (client == 0)
continue;
func(*cinfo);
}
}

inline void for_all_ports(
const libasound& snd, snd_seq_t* seq,
const std::function<void(snd_seq_client_info_t&, snd_seq_port_info_t&)>& func)
Expand All @@ -82,6 +100,21 @@ inline void for_all_ports(
}
}

inline void for_all_ports(
const libasound& snd, snd_seq_t* seq, int client,
const std::function<void(snd_seq_port_info_t&)>& func)
{
snd_seq_port_info_t* pinfo{};
snd_seq_port_info_alloca(&pinfo);

snd.seq.port_info_set_client(pinfo, client);
snd.seq.port_info_set_port(pinfo, -1);
while (snd.seq.query_next_port(seq, pinfo) >= 0)
{
func(*pinfo);
}
}

// This function is used to count or get the pinfo structure for a given port
// number.
inline unsigned int iterate_port_info(
Expand Down Expand Up @@ -159,15 +192,15 @@ struct alsa_data
snd.seq.set_client_name(seq, configuration.client_name.data());

#if __has_include(<alsa/ump.h>)
if (snd.seq.ump.set_client_midi_version)
if (snd.seq.set_client_midi_version)
{
switch (configuration.midi_version)
{
case 1:
snd.seq.ump.set_client_midi_version(seq, SND_SEQ_CLIENT_LEGACY_MIDI);
snd.seq.set_client_midi_version(seq, SND_SEQ_CLIENT_LEGACY_MIDI);
break;
case 2:
snd.seq.ump.set_client_midi_version(seq, SND_SEQ_CLIENT_UMP_MIDI_2_0);
snd.seq.set_client_midi_version(seq, SND_SEQ_CLIENT_UMP_MIDI_2_0);
break;
}
}
Expand Down
Loading
Loading