give MackieControlProtocol its own thread and make it parse incoming MIDI in that thread, as well as doing timeouts there too
git-svn-id: svn://localhost/ardour2/branches/3.0@11872 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
893b468858
commit
01c1eeb279
|
@ -135,6 +135,7 @@ MidiControlUI::reset_ports ()
|
|||
for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
|
||||
|
||||
if (!(*i)->centrally_parsed()) {
|
||||
cerr << "Skip MIDI port " << (*i)->name() << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "ardour/dB.h"
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/location.h"
|
||||
#include "ardour/midi_ui.h"
|
||||
#include "ardour/meter.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
|
@ -71,22 +70,23 @@ using namespace ARDOUR;
|
|||
using namespace std;
|
||||
using namespace Mackie;
|
||||
using namespace PBD;
|
||||
using namespace Glib;
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#include "pbd/abstract_ui.cc" // instantiate template
|
||||
|
||||
#define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
|
||||
#define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
|
||||
|
||||
extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
|
||||
#define invalidator(x) __invalidator (*(MidiControlUI::instance()), __FILE__, __LINE__)
|
||||
#define invalidator() __invalidator ((*this), __FILE__, __LINE__)
|
||||
|
||||
const int MackieControlProtocol::MODIFIER_OPTION = 0x1;
|
||||
const int MackieControlProtocol::MODIFIER_CONTROL = 0x2;
|
||||
const int MackieControlProtocol::MODIFIER_SHIFT = 0x3;
|
||||
const int MackieControlProtocol::MODIFIER_CMDALT = 0x4;
|
||||
|
||||
MackieControlProtocol* MackieControlProtocol::_instance = 0;
|
||||
|
||||
bool MackieControlProtocol::probe()
|
||||
{
|
||||
return true;
|
||||
|
@ -107,9 +107,11 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
|
|||
DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
|
||||
|
||||
AudioEngine::instance()->PortConnectedOrDisconnected.connect (
|
||||
audio_engine_connections, invalidator (*this), ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
|
||||
midi_ui_context ()
|
||||
audio_engine_connections, invalidator (), ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
|
||||
this
|
||||
);
|
||||
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
MackieControlProtocol::~MackieControlProtocol()
|
||||
|
@ -129,13 +131,26 @@ MackieControlProtocol::~MackieControlProtocol()
|
|||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "finished ~MackieControlProtocol::MackieControlProtocol\n");
|
||||
|
||||
_instance = 0;
|
||||
}
|
||||
|
||||
void
|
||||
MackieControlProtocol::thread_init ()
|
||||
{
|
||||
struct sched_param rtparam;
|
||||
|
||||
pthread_set_name (X_("MackieControl"));
|
||||
|
||||
PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
|
||||
ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
|
||||
|
||||
memset (&rtparam, 0, sizeof (rtparam));
|
||||
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
|
||||
|
||||
if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
|
||||
// do we care? not particularly.
|
||||
}
|
||||
}
|
||||
|
||||
// go to the previous track.
|
||||
|
@ -307,6 +322,10 @@ MackieControlProtocol::set_active (bool yn)
|
|||
{
|
||||
if (yn) {
|
||||
|
||||
/* start event loop */
|
||||
|
||||
BaseUI::run ();
|
||||
|
||||
create_surfaces ();
|
||||
connect_session_signals ();
|
||||
|
||||
|
@ -432,23 +451,23 @@ void
|
|||
MackieControlProtocol::connect_session_signals()
|
||||
{
|
||||
// receive routes added
|
||||
session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_route_added, this, _1), midi_ui_context());
|
||||
session->RouteAdded.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_route_added, this, _1), this);
|
||||
// receive record state toggled
|
||||
session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_record_state_changed, this), midi_ui_context());
|
||||
session->RecordStateChanged.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_record_state_changed, this), this);
|
||||
// receive transport state changed
|
||||
session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), midi_ui_context());
|
||||
session->TransportStateChange.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_transport_state_changed, this), this);
|
||||
// receive punch-in and punch-out
|
||||
Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), midi_ui_context());
|
||||
Config->ParameterChanged.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
|
||||
session->config.ParameterChanged.connect (session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
|
||||
// receive rude solo changed
|
||||
session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), midi_ui_context());
|
||||
session->SoloActive.connect(session_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), this);
|
||||
|
||||
// make sure remote id changed signals reach here
|
||||
// see also notify_route_added
|
||||
Sorted sorted = get_sorted_routes();
|
||||
|
||||
for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, invalidator(), ui_bind(&MackieControlProtocol::notify_remote_id_changed, this), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,12 +499,29 @@ MackieControlProtocol::create_surfaces ()
|
|||
ARDOUR::DataType::MIDI,
|
||||
session->engine().make_port_name_non_relative (surface->port().output_port().name())
|
||||
);
|
||||
|
||||
int fd;
|
||||
MIDI::Port& input_port (surface->port().input_port());
|
||||
|
||||
if ((fd = input_port.selectable ()) >= 0) {
|
||||
Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
|
||||
|
||||
psrc->connect (sigc::bind (sigc::mem_fun (this, &MackieControlProtocol::midi_input_handler), &input_port));
|
||||
psrc->attach (main_loop()->get_context());
|
||||
|
||||
// glibmm hack: for now, store only the GSource*
|
||||
|
||||
port_sources.push_back (psrc->gobj());
|
||||
g_source_ref (psrc->gobj());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MackieControlProtocol::close()
|
||||
{
|
||||
clear_ports ();
|
||||
|
||||
port_connections.drop_connections ();
|
||||
session_connections.drop_connections ();
|
||||
route_connections.drop_connections ();
|
||||
|
@ -658,7 +694,7 @@ MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
|
|||
typedef ARDOUR::RouteList ARS;
|
||||
|
||||
for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), midi_ui_context());
|
||||
(*it)->RemoteControlIDChanged.connect (route_connections, invalidator(), ui_bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,7 +793,7 @@ MackieControlProtocol::do_request (MackieControlUIRequest* req)
|
|||
{
|
||||
if (req->type == CallSlot) {
|
||||
|
||||
call_slot (MISSING_INVALIDATOR, req->the_slot);
|
||||
call_slot (invalidator(), req->the_slot);
|
||||
|
||||
} else if (req->type == Quit) {
|
||||
|
||||
|
@ -787,7 +823,7 @@ MackieControlProtocol::add_in_use_timeout (Surface& surface, Control& in_use_con
|
|||
sigc::bind (sigc::mem_fun (*this, &MackieControlProtocol::control_in_use_timeout), &surface, &in_use_control, touch_control));
|
||||
in_use_control.in_use_touch_control = touch_control;
|
||||
|
||||
timeout->attach (MidiControlUI::instance()->main_loop()->get_context());
|
||||
timeout->attach (main_loop()->get_context());
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("timeout queued for surface %1, control %2 touch control %3\n",
|
||||
surface.number(), &in_use_control, touch_control));}
|
||||
|
@ -1369,3 +1405,35 @@ MackieControlProtocol::select_track (boost::shared_ptr<Route> r)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
|
||||
|
||||
if (ioc & ~IO_IN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioc & IO_IN) {
|
||||
|
||||
CrossThreadChannel::drain (port->selectable());
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
|
||||
framepos_t now = session->engine().frame_time();
|
||||
port->parse (now);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MackieControlProtocol::clear_ports ()
|
||||
{
|
||||
for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
|
||||
g_source_destroy (*i);
|
||||
g_source_unref (*i);
|
||||
}
|
||||
|
||||
port_sources.clear ();
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,8 @@ class MackieControlProtocol
|
|||
MackieControlProtocol(ARDOUR::Session &);
|
||||
virtual ~MackieControlProtocol();
|
||||
|
||||
static MackieControlProtocol* instance() { return _instance; }
|
||||
|
||||
int set_active (bool yn);
|
||||
|
||||
XMLNode& get_state ();
|
||||
|
@ -315,6 +317,8 @@ class MackieControlProtocol
|
|||
|
||||
private:
|
||||
|
||||
static MackieControlProtocol* _instance;
|
||||
|
||||
void create_surfaces ();
|
||||
void port_connected_or_disconnected (std::string, std::string, bool);
|
||||
bool control_in_use_timeout (Mackie::Surface*, Mackie::Control *, Mackie::Control *);
|
||||
|
@ -364,6 +368,13 @@ class MackieControlProtocol
|
|||
int _modifier_state;
|
||||
|
||||
Mackie::MackieMidiBuilder builder;
|
||||
|
||||
typedef std::list<GSource*> PortSources;
|
||||
PortSources port_sources;
|
||||
|
||||
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
|
||||
void clear_ports ();
|
||||
|
||||
};
|
||||
|
||||
#endif // ardour_mackie_control_protocol_h
|
||||
|
|
|
@ -51,11 +51,11 @@ using namespace std;
|
|||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
#define midi_ui_context() ARDOUR::MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
|
||||
#define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
|
||||
#define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
|
||||
|
||||
extern PBD::EventLoop::InvalidationRecord* __invalidator (sigc::trackable& trackable, const char*, int);
|
||||
#define invalidator(x) __invalidator (*(MidiControlUI::instance()), __FILE__, __LINE__)
|
||||
#define invalidator() __invalidator (*(MackieControlProtocol::instance()), __FILE__, __LINE__)
|
||||
|
||||
Strip::Strip (Surface& s, const std::string& name, int index, StripControlDefinition* ctls)
|
||||
: Group (name)
|
||||
|
@ -237,34 +237,34 @@ Strip::set_route (boost::shared_ptr<Route> r)
|
|||
|
||||
|
||||
if (has_solo()) {
|
||||
_route->solo_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_solo_changed, this), midi_ui_context());
|
||||
_route->solo_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_solo_changed, this), ui_context());
|
||||
}
|
||||
if (has_mute()) {
|
||||
_route->mute_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_mute_changed, this), midi_ui_context());
|
||||
_route->mute_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_mute_changed, this), ui_context());
|
||||
}
|
||||
|
||||
if (has_gain()) {
|
||||
_route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_gain_changed, this, false), midi_ui_context());
|
||||
_route->gain_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_gain_changed, this, false), ui_context());
|
||||
}
|
||||
|
||||
_route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_property_changed, this, _1), midi_ui_context());
|
||||
_route->PropertyChanged.connect (route_connections, invalidator(), ui_bind (&Strip::notify_property_changed, this, _1), ui_context());
|
||||
|
||||
if (_route->pannable()) {
|
||||
_route->pannable()->pan_azimuth_control->Changed.connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_panner_changed, this, false), midi_ui_context());
|
||||
_route->pannable()->pan_width_control->Changed.connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_panner_changed, this, false), midi_ui_context());
|
||||
_route->pannable()->pan_azimuth_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
|
||||
_route->pannable()->pan_width_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
|
||||
}
|
||||
|
||||
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
|
||||
|
||||
if (trk) {
|
||||
trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_record_enable_changed, this), midi_ui_context());
|
||||
trk->rec_enable_control()->Changed .connect(route_connections, invalidator(), ui_bind (&Strip::notify_record_enable_changed, this), ui_context());
|
||||
}
|
||||
|
||||
// TODO this works when a currently-banked route is made inactive, but not
|
||||
// when a route is activated which should be currently banked.
|
||||
|
||||
_route->active_changed.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_active_changed, this), midi_ui_context());
|
||||
_route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, ui_bind (&Strip::notify_route_deleted, this), midi_ui_context());
|
||||
_route->active_changed.connect (route_connections, invalidator(), ui_bind (&Strip::notify_active_changed, this), ui_context());
|
||||
_route->DropReferences.connect (route_connections, invalidator(), ui_bind (&Strip::notify_route_deleted, this), ui_context());
|
||||
|
||||
// TODO
|
||||
// SelectedChanged
|
||||
|
|
|
@ -59,8 +59,15 @@ Surface::Surface (MackieControlProtocol& mcp, jack_client_t* jack, const std::st
|
|||
DEBUG_TRACE (DEBUG::MackieControl, "Surface::init\n");
|
||||
|
||||
MIDI::Manager * mm = MIDI::Manager::instance();
|
||||
MIDI::Port * input = mm->add_port (new MIDI::Port (string_compose (_("%1 in"), device_name), MIDI::Port::IsInput, jack));
|
||||
MIDI::Port * output = mm->add_port (new MIDI::Port (string_compose (_("%1 out"), device_name), MIDI::Port::IsOutput, jack));
|
||||
|
||||
MIDI::Port * input = new MIDI::Port (string_compose (_("%1 in"), device_name), MIDI::Port::IsInput, jack);
|
||||
MIDI::Port * output =new MIDI::Port (string_compose (_("%1 out"), device_name), MIDI::Port::IsOutput, jack);
|
||||
|
||||
input->set_centrally_parsed (false);
|
||||
output->set_centrally_parsed (false);
|
||||
|
||||
mm->add_port (input);
|
||||
mm->add_port (output);
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has ports named %1 and %2\n",
|
||||
input->name(), output->name()));
|
||||
|
|
Loading…
Reference in New Issue
Block a user