CPM: Activate hotplugged libusb ctrl-surface
This commit is contained in:
parent
161d82869a
commit
97272481b8
@ -75,6 +75,7 @@ class LIBARDOUR_API ControlProtocolManager : public PBD::Stateful, public ARDOUR
|
||||
void midi_connectivity_established ();
|
||||
void drop_protocols ();
|
||||
void probe_midi_control_protocols ();
|
||||
void probe_usb_control_protocols (bool, uint16_t, uint16_t);
|
||||
|
||||
int activate (ControlProtocolInfo&);
|
||||
int deactivate (ControlProtocolInfo&);
|
||||
|
@ -21,6 +21,19 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_USB
|
||||
#include <libusb.h>
|
||||
/* ControlProtocolManager is a singleton, so we can use static
|
||||
* here. This has the advantage that libusb.h does not need
|
||||
* to be used in ardour/control_protocol_manager.h which
|
||||
* is included by various UIs
|
||||
*/
|
||||
static libusb_hotplug_callback_handle _hpcp = 0;
|
||||
static libusb_context* _usb_ctx = NULL;
|
||||
static pthread_t _hotplug_thread;
|
||||
static bool _hotplug_thread_run = false;
|
||||
#endif
|
||||
|
||||
#include <glibmm/module.h>
|
||||
|
||||
#include <glibmm/fileutils.h>
|
||||
@ -29,6 +42,7 @@
|
||||
#include "pbd/event_loop.h"
|
||||
#include "pbd/file_utils.h"
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/stacktrace.h"
|
||||
|
||||
#include "control_protocol/control_protocol.h"
|
||||
|
||||
@ -49,6 +63,33 @@ ControlProtocolManager* ControlProtocolManager::_instance = 0;
|
||||
const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
|
||||
PBD::Signal1<void,StripableNotificationListPtr> ControlProtocolManager::StripableSelectionChanged;
|
||||
|
||||
#ifdef HAVE_USB
|
||||
static int
|
||||
usb_hotplug_cb (libusb_context* ctx, libusb_device* device, libusb_hotplug_event event, void* user_data)
|
||||
{
|
||||
ControlProtocolManager* cpm = static_cast<ControlProtocolManager*> (user_data);
|
||||
struct libusb_device_descriptor desc;
|
||||
if (LIBUSB_SUCCESS == libusb_get_device_descriptor (device, &desc)) {
|
||||
DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("USB Hotplug: %1 vendor: %2 product: %3\n",
|
||||
(event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) ? "arrived" : "removed", std::hex, desc.idVendor, desc.idProduct));
|
||||
cpm->probe_usb_control_protocols (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, desc.idVendor, desc.idProduct);
|
||||
}
|
||||
|
||||
return _hotplug_thread_run ? 0 : 1;
|
||||
}
|
||||
|
||||
static void*
|
||||
usb_hotplug_thread (void* user_data)
|
||||
{
|
||||
while (_hotplug_thread_run) {
|
||||
if (libusb_handle_events (_usb_ctx) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ControlProtocolInfo::~ControlProtocolInfo ()
|
||||
{
|
||||
if (protocol && descriptor) {
|
||||
@ -62,6 +103,9 @@ ControlProtocolInfo::~ControlProtocolInfo ()
|
||||
delete (Glib::Module*) descriptor->module;
|
||||
descriptor = 0;
|
||||
}
|
||||
#ifdef HAVE_USB
|
||||
assert (!_hotplug_thread_run);
|
||||
#endif
|
||||
}
|
||||
|
||||
ControlProtocolManager::ControlProtocolManager ()
|
||||
@ -93,6 +137,17 @@ ControlProtocolManager::set_session (Session* s)
|
||||
SessionHandlePtr::set_session (s);
|
||||
|
||||
if (!_session) {
|
||||
#ifdef HAVE_USB
|
||||
if (_hotplug_thread_run) {
|
||||
_hotplug_thread_run = false;
|
||||
libusb_hotplug_deregister_callback (_usb_ctx, _hpcp);
|
||||
pthread_join (_hotplug_thread, NULL);
|
||||
}
|
||||
if (_usb_ctx) {
|
||||
libusb_exit (_usb_ctx);
|
||||
_usb_ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,6 +171,24 @@ ControlProtocolManager::set_session (Session* s)
|
||||
StripableSelectionChanged (v); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_USB
|
||||
if (LIBUSB_SUCCESS == libusb_init (&_usb_ctx) && libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
|
||||
if (LIBUSB_SUCCESS == libusb_hotplug_register_callback (_usb_ctx,
|
||||
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
|
||||
LIBUSB_HOTPLUG_ENUMERATE,
|
||||
LIBUSB_HOTPLUG_MATCH_ANY,
|
||||
LIBUSB_HOTPLUG_MATCH_ANY,
|
||||
LIBUSB_HOTPLUG_MATCH_ANY,
|
||||
usb_hotplug_cb, this,
|
||||
&_hpcp)) {
|
||||
_hotplug_thread_run = true;
|
||||
if (pthread_create (&_hotplug_thread, NULL, usb_hotplug_thread, this)) {
|
||||
_hotplug_thread_run = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -586,6 +659,38 @@ ControlProtocolManager::probe_midi_control_protocols ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocolManager::probe_usb_control_protocols (bool arrived, uint16_t vendor, uint16_t product)
|
||||
{
|
||||
if (!Config->get_auto_enable_surfaces ()) {
|
||||
return;
|
||||
}
|
||||
for (auto const& cpi : control_protocol_info) {
|
||||
/* Note: manual teardown deletes the descriptor */
|
||||
if (!cpi->descriptor) {
|
||||
cpi->automatic = false;
|
||||
continue;
|
||||
}
|
||||
if (!cpi->descriptor->match_usb || !cpi->descriptor->match_usb (vendor, product)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool active = 0 != cpi->protocol;
|
||||
|
||||
if (!active && arrived) {
|
||||
cpi->automatic = true;
|
||||
activate (*cpi);
|
||||
} else if (active && cpi->automatic && !arrived) {
|
||||
cpi->automatic = false;
|
||||
deactivate (*cpi);
|
||||
/* allow to auto-enable again */
|
||||
if (!cpi->descriptor) {
|
||||
cpi->descriptor = get_descriptor (cpi->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
|
||||
{
|
||||
|
@ -391,7 +391,7 @@ def build(bld):
|
||||
obj.includes = ['.', '../vst3/', '../ctrl-interface/control_protocol', '..']
|
||||
obj.name = 'libardour'
|
||||
obj.target = 'ardour'
|
||||
obj.uselib = ['GLIBMM','GTHREAD','AUBIO','SIGCPP','XML','UUID', 'LO',
|
||||
obj.uselib = ['GLIBMM','GTHREAD','AUBIO','SIGCPP','XML','UUID', 'LO', 'USB',
|
||||
'SNDFILE','SAMPLERATE','LRDF','AUDIOUNITS', 'GIOMM', 'FFTW3F',
|
||||
'OSX','BOOST','CURL','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
|
||||
obj.use = ['libpbd','libmidipp','libevoral',
|
||||
@ -591,7 +591,7 @@ def build(bld):
|
||||
testcommon.includes = obj.includes + ['test', '../pbd', '..']
|
||||
testcommon.source = ['test/testrunner.cc', 'test/test_needing_session.cc',
|
||||
'test/dummy_lxvst.cc', 'test/audio_region_test.cc', 'test/test_util.cc', 'test/test_ui.cc']
|
||||
testcommon.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', 'OSX', 'FFTW3F',
|
||||
testcommon.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', 'OSX', 'FFTW3F', 'USB',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
|
||||
testcommon.use = ['libpbd', 'libmidipp', 'libevoral', 'libaudiographer', 'libardour']
|
||||
if bld.is_defined('USE_EXTERNAL_LIBS'):
|
||||
@ -711,7 +711,7 @@ def create_ardour_test_program(bld, includes, name, target, sources):
|
||||
testobj = bld(features = 'cxx cxxprogram')
|
||||
testobj.includes = includes + ['test', '../pbd', '..']
|
||||
testobj.source = sources
|
||||
testobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', 'FFTW3F', 'OSX',
|
||||
testobj.uselib = ['CPPUNIT','SIGCPP','GLIBMM','GTHREAD', 'FFTW3F', 'OSX', 'USB',
|
||||
'SAMPLERATE','XML','LRDF','COREAUDIO','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND']
|
||||
testobj.use = [ 'testcommon' ]
|
||||
testobj.name = name
|
||||
|
@ -42,7 +42,6 @@ def configure(conf):
|
||||
|
||||
autowaf.set_recursive()
|
||||
|
||||
autowaf.check_pkg(conf, 'libusb-1.0', uselib_store='USB', mandatory=False)
|
||||
#if Options.options.tranzport and conf.is_defined('HAVE_USB'):
|
||||
# conf.define('BUILD_TRANZPORT', 1)
|
||||
|
||||
|
2
wscript
2
wscript
@ -1201,6 +1201,8 @@ def configure(conf):
|
||||
autowaf.check_pkg(conf, 'vamp-hostsdk', uselib_store='VAMPHOSTSDK', atleast_version='2.1', mandatory=True)
|
||||
autowaf.check_pkg(conf, 'rubberband', uselib_store='RUBBERBAND', mandatory=True)
|
||||
|
||||
autowaf.check_pkg(conf, 'libusb-1.0', uselib_store='USB', atleast_version='1.0.16', mandatory=False)
|
||||
|
||||
# we cannot rely on pkg-config - https://lists.linuxaudio.org/archives/linux-audio-dev/2022-July/038395.html
|
||||
conf.check_cc(
|
||||
features = 'cxx',
|
||||
|
Loading…
Reference in New Issue
Block a user