@@ -17,6 +17,55 @@ namespace advss {
17
17
std::map<std::pair<MidiDeviceType, std::string>, MidiDeviceInstance *>
18
18
MidiDeviceInstance::devices = {};
19
19
20
+ static bool setupDeviceObservers ()
21
+ {
22
+ static std::vector<libremidi::observer> observers;
23
+ for (auto api : libremidi::available_apis ()) {
24
+ libremidi::observer_configuration cbs;
25
+ cbs.input_added = [=](const libremidi::input_port &p) {
26
+ auto dev = MidiDeviceInstance::GetDevice (p);
27
+ if (!dev) {
28
+ return ;
29
+ }
30
+ blog (LOG_INFO, " MIDI input connected: %s" ,
31
+ p.port_name .c_str ());
32
+ dev->ClosePort ();
33
+ dev->OpenPort ();
34
+ };
35
+ cbs.input_removed = [=](const libremidi::input_port &p) {
36
+ auto dev = MidiDeviceInstance::GetDevice (p);
37
+ if (!dev) {
38
+ return ;
39
+ }
40
+ blog (LOG_INFO, " MIDI input removed: %s" ,
41
+ p.port_name .c_str ());
42
+ };
43
+ cbs.output_added = [=](const libremidi::output_port &p) {
44
+ auto dev = MidiDeviceInstance::GetDevice (p);
45
+ if (!dev) {
46
+ return ;
47
+ }
48
+ blog (LOG_INFO, " MIDI output connected: %s" ,
49
+ p.port_name .c_str ());
50
+ dev->ClosePort ();
51
+ dev->OpenPort ();
52
+ };
53
+ cbs.output_removed = [=](const libremidi::output_port &p) {
54
+ auto dev = MidiDeviceInstance::GetDevice (p);
55
+ if (!dev) {
56
+ return ;
57
+ }
58
+ blog (LOG_INFO, " MIDI output removed: %s" ,
59
+ p.port_name .c_str ());
60
+ };
61
+ observers.emplace_back (
62
+ cbs, libremidi::observer_configuration_for (api));
63
+ }
64
+ return true ;
65
+ }
66
+
67
+ static bool deviceObserversAreSetup = setupDeviceObservers();
68
+
20
69
void MidiDeviceInstance::ResetAllDevices ()
21
70
{
22
71
for (auto const &[_, device] : MidiDeviceInstance::devices) {
@@ -212,8 +261,9 @@ bool MidiMessage::Matches(const MidiMessage &m) const
212
261
return channelMatch && noteMatch && valueMatch && typeMatch;
213
262
}
214
263
215
- MidiDeviceInstance *MidiDeviceInstance::GetDevice (MidiDeviceType type,
216
- const std::string &name)
264
+ MidiDeviceInstance *
265
+ MidiDeviceInstance::GetDeviceAndOpen (MidiDeviceType type,
266
+ const std::string &name)
217
267
{
218
268
if (name.empty ()) {
219
269
return nullptr ;
@@ -252,6 +302,30 @@ getNameFromPortInformation(const libremidi::port_information &info)
252
302
return " [" + name;
253
303
}
254
304
305
+ MidiDeviceInstance *
306
+ advss::MidiDeviceInstance::GetDevice (const libremidi::input_port &p)
307
+ {
308
+ auto key = std::make_pair (MidiDeviceType::INPUT,
309
+ getNameFromPortInformation (p));
310
+ auto it = MidiDeviceInstance::devices.find (key);
311
+ if (it == devices.end ()) {
312
+ return nullptr ;
313
+ }
314
+ return it->second ;
315
+ }
316
+
317
+ MidiDeviceInstance *
318
+ advss::MidiDeviceInstance::GetDevice (const libremidi::output_port &p)
319
+ {
320
+ auto key = std::make_pair (MidiDeviceType::OUTPUT,
321
+ getNameFromPortInformation (p));
322
+ auto it = MidiDeviceInstance::devices.find (key);
323
+ if (it == devices.end ()) {
324
+ return nullptr ;
325
+ }
326
+ return it->second ;
327
+ }
328
+
255
329
static inline QStringList getInputDeviceNames ()
256
330
{
257
331
QStringList devices;
@@ -305,10 +379,11 @@ static std::string getPortNameFromNumber(MidiDeviceType type, int port)
305
379
return devices.at (port).toStdString ();
306
380
}
307
381
308
- MidiDeviceInstance *MidiDeviceInstance::GetDevice (MidiDeviceType type, int port)
382
+ MidiDeviceInstance *MidiDeviceInstance::GetDeviceAndOpen (MidiDeviceType type,
383
+ int port)
309
384
{
310
385
std::string name = getPortNameFromNumber (type, port);
311
- return GetDevice (type, name);
386
+ return GetDeviceAndOpen (type, name);
312
387
}
313
388
314
389
void MidiDevice::Save (obs_data_t *obj) const
@@ -327,13 +402,13 @@ void MidiDevice::Load(obs_data_t *obj)
327
402
// TODO: Remove this fallback at some point
328
403
if (obs_data_has_user_value (data, " port" )) {
329
404
auto port = obs_data_get_int (data, " port" );
330
- _dev = MidiDeviceInstance::GetDevice (_type, port);
405
+ _dev = MidiDeviceInstance::GetDeviceAndOpen (_type, port);
331
406
if (_dev) {
332
407
_name = _dev->_name ;
333
408
}
334
409
} else {
335
410
_name = obs_data_get_string (data, " portName" );
336
- _dev = MidiDeviceInstance::GetDevice (_type, _name);
411
+ _dev = MidiDeviceInstance::GetDeviceAndOpen (_type, _name);
337
412
}
338
413
}
339
414
@@ -372,8 +447,7 @@ getInPortFromName(const std::string &name)
372
447
373
448
bool MidiDeviceInstance::OpenPort ()
374
449
{
375
- if ((_type == MidiDeviceType::INPUT && _in.is_port_open ()) ||
376
- (_type == MidiDeviceType::OUTPUT && _out.is_port_open ())) {
450
+ if (IsOpened ()) {
377
451
return true ;
378
452
}
379
453
@@ -437,10 +511,15 @@ bool MidiDeviceInstance::OpenPort()
437
511
return false ;
438
512
}
439
513
514
+ bool MidiDeviceInstance::IsOpened () const
515
+ {
516
+ return (_type == MidiDeviceType::INPUT && _in.is_port_open ()) ||
517
+ (_type == MidiDeviceType::OUTPUT && _out.is_port_open ());
518
+ }
519
+
440
520
void MidiDeviceInstance::ClosePort ()
441
521
{
442
- if ((_type == MidiDeviceType::INPUT && !_in.is_port_open ()) ||
443
- (_type == MidiDeviceType::OUTPUT && !_out.is_port_open ())) {
522
+ if (!IsOpened ()) {
444
523
return ;
445
524
}
446
525
@@ -542,7 +621,6 @@ MidiMessageBuffer MidiDeviceInstance::RegisterForMidiMessages()
542
621
543
622
void MidiDeviceInstance::ReceiveMidiMessage (libremidi::message &&msg)
544
623
{
545
- auto lock = LockContext ();
546
624
_dispatcher.DispatchMessage (msg);
547
625
vblog (LOG_INFO, " received midi: %s" ,
548
626
MidiMessage::ToString (msg).c_str ());
@@ -590,7 +668,7 @@ void MidiDeviceSelection::IdxChangedHelper(int idx)
590
668
}
591
669
592
670
auto name = currentText ().toStdString ();
593
- auto devInstance = MidiDeviceInstance::GetDevice (_type, name);
671
+ auto devInstance = MidiDeviceInstance::GetDeviceAndOpen (_type, name);
594
672
if (!devInstance) {
595
673
DisplayMessage (obs_module_text (
596
674
" AdvSceneSwitcher.midi.deviceOpenFail" ));
0 commit comments