Skip to content

Commit fede74d

Browse files
committed
port information: add more metadata
1 parent 0f04ab4 commit fede74d

24 files changed

Lines changed: 334 additions & 127 deletions

File tree

examples/utils.hpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ inline std::ostream& operator<<(std::ostream& s, const libremidi::device_identif
5959
{
6060
std::ostream& s;
6161
void operator()(const std::string& u) { s << u; }
62+
void operator()(libremidi::usb_device_identifier u)
63+
{
64+
s << u.vendor_id << ":" << u.product_id;
65+
}
6266
void operator()(uint64_t u)
6367
{
6468
auto res = static_cast<uint32_t>(u);
@@ -160,23 +164,27 @@ inline std::ostream& operator<<(std::ostream& s, const libremidi::port_informati
160164
{
161165
s << "[ client: " << rhs.client;
162166
if (rhs.container.index() > 0)
163-
s << ", container: " << rhs.container;
167+
s << "\n , container: " << rhs.container;
164168
if (rhs.device.index() > 0)
165-
s << ", device_id: " << rhs.device;
169+
s << "\n , device_id: " << rhs.device;
166170

167-
s << ", port: " << rhs.port;
171+
s << "\n , port: " << rhs.port;
168172

169173
if (!rhs.manufacturer.empty())
170-
s << ", manufacturer: " << rhs.manufacturer;
174+
s << "\n , manufacturer: " << rhs.manufacturer;
175+
if (!rhs.product.empty())
176+
s << "\n , product: " << rhs.product;
177+
if (!rhs.serial.empty())
178+
s << "\n , serial: " << rhs.serial;
171179
if (!rhs.device_name.empty())
172-
s << ", device_name: " << rhs.device_name;
180+
s << "\n , device_name: " << rhs.device_name;
173181
if (!rhs.port_name.empty())
174-
s << ", port_name: " << rhs.port_name;
182+
s << "\n , port_name: " << rhs.port_name;
175183
if (!rhs.display_name.empty())
176-
s << ", display_name: " << rhs.display_name;
177-
if (rhs.type != libremidi::port_information::unknown)
178-
s << ", type: " << rhs.type;
179-
return s << "]";
184+
s << "\n , display_name: " << rhs.display_name;
185+
if (rhs.type != libremidi::transport_type::unknown)
186+
s << "\n , type: " << rhs.type;
187+
return s << "\n ]";
180188
}
181189

182190
namespace libremidi::examples

include/libremidi/backends/alsa_raw/helpers.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace alsa_raw
5353
{
5454
struct alsa_raw_port_info
5555
{
56+
// hw:1,2,0
5657
std::string device;
5758
std::string card_name;
5859
std::string device_name;

include/libremidi/backends/alsa_raw/observer.hpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ class observer_impl_base
2828
explicit observer_impl_base(
2929
observer_configuration&& conf, alsa_raw_observer_configuration&& apiconf)
3030
: configuration{std::move(conf), std::move(apiconf)}
31+
{
32+
}
33+
34+
~observer_impl_base()
35+
{
36+
#if LIBREMIDI_HAS_UDEV
37+
m_termination_event.notify();
38+
39+
if (m_thread.joinable())
40+
m_thread.join();
41+
#endif
42+
}
43+
44+
// Must be called for child classes due to virtual function calls
45+
void finish_init()
3146
{
3247
if (!configuration.has_callbacks())
3348
return;
@@ -48,16 +63,6 @@ class observer_impl_base
4863
#endif
4964
}
5065

51-
~observer_impl_base()
52-
{
53-
#if LIBREMIDI_HAS_UDEV
54-
m_termination_event.notify();
55-
56-
if (m_thread.joinable())
57-
m_thread.join();
58-
#endif
59-
}
60-
6166
std::vector<libremidi::input_port> get_input_ports() const noexcept override
6267
{
6368
std::vector<libremidi::input_port> ret;
@@ -84,7 +89,6 @@ class observer_impl_base
8489
return ret;
8590
}
8691

87-
private:
8892
#if LIBREMIDI_HAS_UDEV
8993
void run()
9094
{
@@ -98,6 +102,12 @@ class observer_impl_base
98102
return;
99103
}
100104

105+
// Check eventfd to see if we need to exit
106+
if (m_fds[1].revents & POLLIN)
107+
{
108+
break;
109+
}
110+
101111
// Check udev
102112
if (m_fds[0].revents & POLLIN)
103113
{
@@ -122,12 +132,6 @@ class observer_impl_base
122132
m_fds[0].revents = 0;
123133
}
124134

125-
// Check eventfd
126-
if (m_fds[1].revents & POLLIN)
127-
{
128-
break;
129-
}
130-
131135
// Check timer
132136
if (m_fds[2].revents & POLLIN)
133137
{
@@ -146,26 +150,35 @@ class observer_impl_base
146150
-> std::conditional_t<Input, input_port, output_port>
147151
{
148152
#if LIBREMIDI_HAS_UDEV
149-
auto [container, device, type] = get_udev_soundcard_info(m_udev, p.card);
153+
auto [container, device, type, manufacturer, product, serial]
154+
= get_udev_soundcard_info(m_udev, p.card);
150155
#else
151156
container_identifier container{};
152157
device_identifier device{};
153-
libremidi::port_information::port_type type{};
158+
libremidi::transport_type type{};
159+
std::string manufacturer;
160+
std::string product;
161+
std::string serial;
154162
#endif
155163
std::string display_name = p.subdevice_name;
156164
if (display_name.empty())
157165
display_name = p.device_name;
158166
if (display_name.empty())
159167
display_name = p.card_name;
168+
if (display_name.empty())
169+
display_name = product;
160170
if (display_name.empty())
161171
display_name = "unknown";
162172

163173
return {
164-
{.client = 0,
174+
{.api = get_current_api(),
175+
.client = 0,
165176
.container = container,
166177
.device = device,
167178
.port = raw_to_port_handle({p.card, p.dev, p.sub}),
168-
.manufacturer = p.card_name,
179+
.manufacturer = manufacturer,
180+
.product = product,
181+
.serial = serial,
169182
.device_name = p.device_name,
170183
.port_name = p.subdevice_name,
171184
.display_name = std::move(display_name),
@@ -247,7 +260,12 @@ namespace libremidi::alsa_raw
247260
{
248261
struct observer_impl : observer_impl_base<alsa_raw::midi1_enumerator>
249262
{
250-
using alsa_raw::observer_impl_base<midi1_enumerator>::observer_impl_base;
263+
observer_impl(observer_configuration&& conf, alsa_raw_observer_configuration&& apiconf)
264+
: observer_impl_base<alsa_raw::midi1_enumerator>{std::move(conf), std::move(apiconf)}
265+
{
266+
finish_init();
267+
}
268+
251269
libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_RAW; }
252270
};
253271
}

include/libremidi/backends/alsa_raw_ump/observer.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
namespace libremidi::alsa_raw_ump
66
{
7-
87
class observer_impl : public alsa_raw::observer_impl_base<midi2_enumerator>
98
{
10-
using alsa_raw::observer_impl_base<midi2_enumerator>::observer_impl_base;
9+
public:
10+
observer_impl(
11+
libremidi::observer_configuration&& conf, alsa_raw_ump::observer_configuration&& apiconf)
12+
: observer_impl_base<alsa_raw_ump::midi2_enumerator>{std::move(conf), std::move(apiconf)}
13+
{
14+
finish_init();
15+
}
16+
1117
libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_RAW_UMP; }
1218
};
13-
1419
}

include/libremidi/backends/alsa_seq/observer.hpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,22 +153,31 @@ class observer_impl
153153

154154
container_identifier container{};
155155
device_identifier device{};
156-
libremidi::port_information::port_type type = p.type;
156+
libremidi::transport_type type = p.type;
157+
std::string manufacturer;
158+
std::string product;
159+
std::string serial;
157160
#if LIBREMIDI_HAS_UDEV
158161
if (p.card)
159162
{
160163
auto res = get_udev_soundcard_info(m_udev, *p.card);
161164
container = res.container;
162165
device = res.path;
163166
type = res.type;
167+
manufacturer = res.vendor;
168+
product = res.product;
169+
serial = res.serial;
164170
}
165171
#endif
166172
return {
167-
{.client = std::uintptr_t(this->seq),
173+
{.api = get_current_api(),
174+
.client = std::uintptr_t(this->seq),
168175
.container = container,
169176
.device = device,
170177
.port = alsa_seq::seq_to_port_handle(p.client, p.port),
171-
.manufacturer = "",
178+
.manufacturer = manufacturer,
179+
.product = product,
180+
.serial = serial,
172181
.device_name = p.client_name,
173182
.port_name = p.port_name,
174183
.display_name = p.port_name,

include/libremidi/backends/android/observer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class observer final
5353
for (size_t i = 0; i < context::midi_devices.size(); ++i)
5454
{
5555
libremidi::input_port port;
56+
port.api = libremidi::API::ANDROID_AMIDI;
5657
port.port_name = context::port_name(env, i);
5758
port.port = i;
5859
ports.push_back(std::move(port));

include/libremidi/backends/coremidi/observer.hpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class observer_core
2222

2323
explicit observer_core(observer_configuration&& conf, coremidi_observer_configuration&& apiconf)
2424
: configuration{std::move(conf), std::move(apiconf)}
25+
{
26+
}
27+
28+
void finish_init()
2529
{
2630
if (configuration.client_name.empty())
2731
configuration.client_name = "libremidi observer";
@@ -77,7 +81,7 @@ class observer_core
7781
return {};
7882

7983
// Get the MIDI device from the entity
80-
libremidi::port_information::port_type type{};
84+
libremidi::transport_type type{};
8185
libremidi::container_identifier usb_location_id{};
8286
libremidi::device_identifier usb_vendor_product{};
8387
{
@@ -86,37 +90,38 @@ class observer_core
8690
{
8791
if (device)
8892
{
89-
using enum libremidi::port_information::port_type;
93+
using enum libremidi::transport_type;
9094
SInt32 devid_res{};
9195
if (MIDIObjectGetIntegerProperty(device, CFSTR("USBLocationID"), &devid_res) == noErr)
9296
{
93-
type = (libremidi::port_information::port_type)(hardware | usb);
97+
type = (libremidi::transport_type)(hardware | usb);
9498
usb_location_id = (uint64_t)devid_res;
9599
}
96100

97101
SInt32 vendor_res{};
98102
if (MIDIObjectGetIntegerProperty(device, CFSTR("USBVendorProduct"), &vendor_res)
99103
== noErr)
100104
{
101-
type = (libremidi::port_information::port_type)(hardware | usb);
105+
type = (libremidi::transport_type)(hardware | usb);
102106
usb_vendor_product = (uint64_t)vendor_res;
103107
}
104108

105109
const auto driver = get_string_property(device, kMIDIPropertyDriverOwner);
106110
if (driver == "com.apple.AppleMIDIUSBDriver")
107-
type = (libremidi::port_information::port_type)(hardware | usb);
111+
type = (libremidi::transport_type)(hardware | usb);
108112
if (driver == "com.apple.AppleMIDIBluetoothDriver")
109-
type = (libremidi::port_information::port_type)(hardware | bluetooth);
113+
type = (libremidi::transport_type)(hardware | bluetooth);
110114
if (driver == "com.apple.AppleMIDIIACDriver")
111-
type = (libremidi::port_information::port_type)(software);
115+
type = (libremidi::transport_type)(software);
112116
if (driver == "com.apple.AppleMIDIRTPDriver")
113-
type = (libremidi::port_information::port_type)(network);
117+
type = (libremidi::transport_type)(network);
114118
}
115119
}
116120
}
117121

118122
return std::conditional_t<Input, input_port, output_port>{
119-
{.client = (std::uintptr_t)this->client,
123+
{.api = get_current_api(),
124+
.client = (std::uintptr_t)this->client,
120125
.container = usb_location_id,
121126
.device = usb_vendor_product,
122127
.port = std::bit_cast<uint32_t>(get_int_property(obj, kMIDIPropertyUniqueID)),
@@ -213,3 +218,17 @@ class observer_core
213218
MIDIClientRef client{};
214219
};
215220
}
221+
222+
namespace libremidi::coremidi
223+
{
224+
struct observer_impl : observer_core
225+
{
226+
observer_impl(observer_configuration&& conf, coremidi_observer_configuration&& apiconf)
227+
: observer_core{std::move(conf), std::move(apiconf)}
228+
{
229+
finish_init();
230+
}
231+
232+
libremidi::API get_current_api() const noexcept override { return libremidi::API::COREMIDI; }
233+
};
234+
}

include/libremidi/backends/coremidi_ump/observer.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class observer_impl final : public libremidi::observer_core
1414
std::move(conf),
1515
coremidi_observer_configuration{apiconf.client_name, apiconf.on_create_context}}
1616
{
17+
finish_init();
1718
}
1819

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

include/libremidi/backends/emscripten/observer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ static auto to_port_info(int index, const webmidi_helpers::device_information& d
4242
-> std::conditional_t<Input, input_port, output_port>
4343
{
4444
return {
45-
{.client = 0,
45+
{.api = libremidi::API::WEBMIDI,
46+
.client = 0,
4647
.port = (uint64_t)index,
4748
.manufacturer = "",
4849
.device_name = "",

include/libremidi/backends/jack/helpers.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ struct jack_client
4141
}
4242
}
4343

44-
template <bool Input>
44+
template <bool Input, libremidi::API Api>
4545
static auto to_port_info(jack_client_t* client, jack_port_t* port)
4646
-> std::conditional_t<Input, input_port, output_port>
4747
{
4848
return {{
49+
.api = Api,
4950
.client = reinterpret_cast<std::uintptr_t>(client),
5051
.port = 0,
5152
.manufacturer = "",
@@ -55,7 +56,7 @@ struct jack_client
5556
}};
5657
}
5758

58-
template <bool Input>
59+
template <bool Input, libremidi::API Api>
5960
static auto get_ports(
6061
jack_client_t* client, const char* pattern, const char* type, const JackPortFlags flags,
6162
bool midi2) noexcept -> std::vector<std::conditional_t<Input, input_port, output_port>>
@@ -78,7 +79,7 @@ struct jack_client
7879
if (port)
7980
{
8081
if (bool(midi2) == bool(jack_port_flags(port) & 0x20))
81-
ret.push_back(to_port_info<Input>(client, port));
82+
ret.push_back(to_port_info<Input, Api>(client, port));
8283
}
8384
i++;
8485
}

0 commit comments

Comments
 (0)