Stop trying to talk to device on startup. Remap some bcf buttons.

git-svn-id: svn://localhost/ardour2/trunk@1568 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
John Anderson 2007-03-09 20:46:46 +00:00
parent 765d0f4785
commit 7182cd75e3
13 changed files with 291 additions and 187 deletions

View file

@ -3,8 +3,7 @@
if the handler is not called in the "correct thread", it will use a pseudo-RT-safe-enough technique to get the correct thread to recall "handler" later on, and return. if the handler is not called in the "correct thread", it will use a pseudo-RT-safe-enough technique to get the correct thread to recall "handler" later on, and return.
* jog with transport rolling doesn't work properly. My use of ScrollTimeline also doesn't work. * jog with transport rolling doesn't work properly. My use of ScrollTimeline also doesn't work.
* finish button mapping. Click on/off. start/end locate. punch in/out * finish button mapping.
* discuss button mapping for Ardour
* concurrency for bank switching? And make sure "old" events aren't sent to "new" faders * concurrency for bank switching? And make sure "old" events aren't sent to "new" faders
* TODOs in code * TODOs in code
* removal of a route results in a strip that isn't dead, but doesn't have any effect on the session * removal of a route results in a strip that isn't dead, but doesn't have any effect on the session

View file

@ -405,29 +405,29 @@ void Mackie::BcfSurface::init_controls()
group->add( *control ); group->add( *control );
group = groups["assignment"]; group = groups["assignment"];
control = new Button ( 41, 1, "sends", *group ); control = new Button ( 90, 1, "sends", *group );
buttons[0x29] = control; buttons[0x5a] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["sends"] = control; controls_by_name["sends"] = control;
group->add( *control ); group->add( *control );
group = groups["assignment"]; group = groups["assignment"];
control = new Button ( 42, 1, "pan", *group ); control = new Button ( 89, 1, "pan", *group );
buttons[0x2a] = control; buttons[0x59] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["pan"] = control; controls_by_name["pan"] = control;
group->add( *control ); group->add( *control );
group = groups["assignment"]; group = groups["assignment"];
control = new Button ( 43, 1, "plugin", *group ); control = new Button ( 87, 1, "plugin", *group );
buttons[0x2b] = control; buttons[0x57] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["plugin"] = control; controls_by_name["plugin"] = control;
group->add( *control ); group->add( *control );
group = groups["assignment"]; group = groups["assignment"];
control = new Button ( 44, 1, "eq", *group ); control = new Button ( 88, 1, "eq", *group );
buttons[0x2c] = control; buttons[0x58] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["eq"] = control; controls_by_name["eq"] = control;
group->add( *control ); group->add( *control );
@ -475,8 +475,8 @@ void Mackie::BcfSurface::init_controls()
group->add( *control ); group->add( *control );
group = groups["none"]; group = groups["none"];
control = new Button ( 51, 1, "edit", *group ); control = new Button ( 86, 1, "edit", *group );
buttons[0x33] = control; buttons[0x56] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["edit"] = control; controls_by_name["edit"] = control;
group->add( *control ); group->add( *control );
@ -607,11 +607,11 @@ void Mackie::BcfSurface::init_controls()
controls_by_name["F16"] = control; controls_by_name["F16"] = control;
group->add( *control ); group->add( *control );
group = groups["modifiers"]; group = groups["none"];
control = new Button ( 70, 1, "shift", *group ); control = new Button ( 39, 1, "global_solo", *group );
buttons[0x46] = control; buttons[0x27] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["shift"] = control; controls_by_name["global_solo"] = control;
group->add( *control ); group->add( *control );
group = groups["modifiers"]; group = groups["modifiers"];
@ -720,36 +720,36 @@ void Mackie::BcfSurface::init_controls()
group->add( *control ); group->add( *control );
group = groups["transport"]; group = groups["transport"];
control = new Button ( 86, 1, "loop", *group ); control = new Button ( 70, 1, "loop", *group );
buttons[0x56] = control; buttons[0x46] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["loop"] = control; controls_by_name["loop"] = control;
group->add( *control ); group->add( *control );
group = groups["transport"]; group = groups["transport"];
control = new Button ( 87, 1, "punch_in", *group ); control = new Button ( 44, 1, "punch_in", *group );
buttons[0x57] = control; buttons[0x2c] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["punch_in"] = control; controls_by_name["punch_in"] = control;
group->add( *control ); group->add( *control );
group = groups["transport"]; group = groups["transport"];
control = new Button ( 88, 1, "punch_out", *group ); control = new Button ( 43, 1, "punch_out", *group );
buttons[0x58] = control; buttons[0x2b] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["punch_out"] = control; controls_by_name["punch_out"] = control;
group->add( *control ); group->add( *control );
group = groups["transport"]; group = groups["transport"];
control = new Button ( 89, 1, "home", *group ); control = new Button ( 42, 1, "home", *group );
buttons[0x59] = control; buttons[0x2a] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["home"] = control; controls_by_name["home"] = control;
group->add( *control ); group->add( *control );
group = groups["transport"]; group = groups["transport"];
control = new Button ( 90, 1, "end", *group ); control = new Button ( 41, 1, "end", *group );
buttons[0x5a] = control; buttons[0x29] = control;
controls.push_back( control ); controls.push_back( control );
controls_by_name["end"] = control; controls_by_name["end"] = control;
group->add( *control ); group->add( *control );
@ -899,6 +899,13 @@ void Mackie::BcfSurface::init_controls()
controls.push_back( control ); controls.push_back( control );
group->add( *control ); group->add( *control );
group = groups["none"];
control = new Button ( 51, 1, "clicking", *group );
buttons[0x33] = control;
controls.push_back( control );
controls_by_name["clicking"] = control;
group->add( *control );
group = groups["none"]; group = groups["none"];
control = new Led ( 113, 1, "smpte", *group ); control = new Led ( 113, 1, "smpte", *group );
leds[0x71] = control; leds[0x71] = control;
@ -949,7 +956,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x29: // sends case 0x5a: // sends
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.sends_press( button ); break; case press: ls = mbh.sends_press( button ); break;
case release: ls = mbh.sends_release( button ); break; case release: ls = mbh.sends_release( button ); break;
@ -957,7 +964,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x2a: // pan case 0x59: // pan
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.pan_press( button ); break; case press: ls = mbh.pan_press( button ); break;
case release: ls = mbh.pan_release( button ); break; case release: ls = mbh.pan_release( button ); break;
@ -965,7 +972,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x2b: // plugin case 0x57: // plugin
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.plugin_press( button ); break; case press: ls = mbh.plugin_press( button ); break;
case release: ls = mbh.plugin_release( button ); break; case release: ls = mbh.plugin_release( button ); break;
@ -973,7 +980,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x2c: // eq case 0x58: // eq
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.eq_press( button ); break; case press: ls = mbh.eq_press( button ); break;
case release: ls = mbh.eq_release( button ); break; case release: ls = mbh.eq_release( button ); break;
@ -1029,7 +1036,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x33: // edit case 0x56: // edit
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.edit_press( button ); break; case press: ls = mbh.edit_press( button ); break;
case release: ls = mbh.edit_release( button ); break; case release: ls = mbh.edit_release( button ); break;
@ -1181,10 +1188,10 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x46: // shift case 0x27: // global_solo
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.shift_press( button ); break; case press: ls = mbh.global_solo_press( button ); break;
case release: ls = mbh.shift_release( button ); break; case release: ls = mbh.global_solo_release( button ); break;
case neither: break; case neither: break;
} }
break; break;
@ -1309,7 +1316,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x56: // loop case 0x46: // loop
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.loop_press( button ); break; case press: ls = mbh.loop_press( button ); break;
case release: ls = mbh.loop_release( button ); break; case release: ls = mbh.loop_release( button ); break;
@ -1317,7 +1324,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x57: // punch_in case 0x2c: // punch_in
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.punch_in_press( button ); break; case press: ls = mbh.punch_in_press( button ); break;
case release: ls = mbh.punch_in_release( button ); break; case release: ls = mbh.punch_in_release( button ); break;
@ -1325,7 +1332,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x58: // punch_out case 0x2b: // punch_out
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.punch_out_press( button ); break; case press: ls = mbh.punch_out_press( button ); break;
case release: ls = mbh.punch_out_release( button ); break; case release: ls = mbh.punch_out_release( button ); break;
@ -1333,7 +1340,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x59: // home case 0x2a: // home
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.home_press( button ); break; case press: ls = mbh.home_press( button ); break;
case release: ls = mbh.home_release( button ); break; case release: ls = mbh.home_release( button ); break;
@ -1341,7 +1348,7 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x5a: // end case 0x29: // end
switch ( bs ) { switch ( bs ) {
case press: ls = mbh.end_press( button ); break; case press: ls = mbh.end_press( button ); break;
case release: ls = mbh.end_release( button ); break; case release: ls = mbh.end_release( button ); break;
@ -1453,6 +1460,14 @@ void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState b
} }
break; break;
case 0x33: // clicking
switch ( bs ) {
case press: ls = mbh.clicking_press( button ); break;
case release: ls = mbh.clicking_release( button ); break;
case neither: break;
}
break;
} }
mbh.update_led( button, ls ); mbh.update_led( button, ls );
} }

View file

@ -18,27 +18,47 @@
#include <control_protocol/control_protocol.h> #include <control_protocol/control_protocol.h>
#include "mackie_control_protocol.h" #include "mackie_control_protocol.h"
#include <pbd/error.h>
#include <stdexcept> #include <stdexcept>
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD;
using namespace std; using namespace std;
ControlProtocol* ControlProtocol*
new_mackie_protocol (ControlProtocolDescriptor* descriptor, Session* s) new_mackie_protocol (ControlProtocolDescriptor* descriptor, Session* s)
{ {
MackieControlProtocol * mcp = 0; if ( Config->get_mmc_port_name().substr(0,3) == "mcu" )
try
{ {
mcp = new MackieControlProtocol (*s); error << "mcu already used as mmc port" << endmsg;
mcp->set_active( true );
} }
catch( exception & e ) else if ( Config->get_mtc_port_name().substr(0,3) == "mcu" )
{ {
cout << "Error instantiating MackieControlProtocol: " << e.what() << endl; error << "mcu already used as mtc port" << endmsg;
delete mcp;
mcp = 0;
} }
return mcp; else if ( Config->get_midi_port_name().substr(0,3) == "mcu" )
{
error << "mcu already used as midi port" << endmsg;
}
else
{
// no one else is using the port, so try instantiate the object
MackieControlProtocol * mcp = 0;
try
{
mcp = new MackieControlProtocol (*s);
mcp->set_active( true );
}
catch( exception & e )
{
error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg;
delete mcp;
mcp = 0;
}
return mcp;
}
return 0;
} }
void void

View file

@ -20,7 +20,6 @@ LedState MackieButtonHandler::default_button_release( Button & button )
return off; return off;
} }
LedState MackieButtonHandler::io_press( Button & button ) LedState MackieButtonHandler::io_press( Button & button )
{ {
return default_button_press( button ); return default_button_press( button );
@ -671,3 +670,22 @@ LedState MackieButtonHandler::fader_touch_release( Button & button )
return default_button_release( button ); return default_button_release( button );
} }
LedState MackieButtonHandler::clicking_press( Button & button )
{
return default_button_press( button );
}
LedState MackieButtonHandler::clicking_release( Button & button )
{
return default_button_press( button );
}
LedState MackieButtonHandler::global_solo_press( Button & button )
{
return default_button_press( button );
}
LedState MackieButtonHandler::global_solo_release( Button & button )
{
return default_button_press( button );
}

View file

@ -215,6 +215,11 @@ public:
virtual LedState fader_touch_press( Button & ); virtual LedState fader_touch_press( Button & );
virtual LedState fader_touch_release( Button & ); virtual LedState fader_touch_release( Button & );
virtual LedState clicking_press( Button & );
virtual LedState clicking_release( Button & );
virtual LedState global_solo_press( Button & );
virtual LedState global_solo_release( Button & );
}; };
} }

View file

@ -117,6 +117,7 @@ MackieControlProtocol::~MackieControlProtocol()
{ {
cout << "~MackieControlProtocol caught unknown" << endl; cout << "~MackieControlProtocol caught unknown" << endl;
} }
cout << "finished ~MackieControlProtocol::MackieControlProtocol" << endl;
} }
Mackie::Surface & MackieControlProtocol::surface() Mackie::Surface & MackieControlProtocol::surface()
@ -370,6 +371,9 @@ int MackieControlProtocol::set_active (bool yn)
create_ports(); create_ports();
} }
// make sure the ports are being listened to
update_ports();
// wait until poll thread is running, with ports to poll // wait until poll thread is running, with ports to poll
// the mutex is only there because conditions require a mutex // the mutex is only there because conditions require a mutex
{ {
@ -402,6 +406,7 @@ int MackieControlProtocol::set_active (bool yn)
// send current control positions to surface // send current control positions to surface
// must come after _active = true otherwise it won't run // must come after _active = true otherwise it won't run
cout << "update_surface in set_active" << endl;
update_surface(); update_surface();
} }
else else
@ -555,17 +560,15 @@ void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
connections_back = sport->active_event.connect( connections_back = sport->active_event.connect(
sigc::bind ( sigc::bind (
mem_fun (*this, &MackieControlProtocol::handle_port_changed) mem_fun (*this, &MackieControlProtocol::handle_port_active)
, sport , sport
, true
) )
); );
connections_back = sport->inactive_event.connect( connections_back = sport->inactive_event.connect(
sigc::bind ( sigc::bind (
mem_fun (*this, &MackieControlProtocol::handle_port_changed) mem_fun (*this, &MackieControlProtocol::handle_port_inactive)
, sport , sport
, false
) )
); );
@ -895,29 +898,11 @@ void MackieControlProtocol::handle_control_event( SurfacePort & port, Control &
} }
} }
/////////////////////////////////////////////////////////
// Notifications from UI
/////////////////////////////////////////////////////////
struct RouteSignalByRoute
{
RouteSignalByRoute( Route & route ): _route( route ) {}
bool operator () ( const RouteSignal & rs ) const
{
return rs.route().id() == _route.id();
}
bool operator () ( const RouteSignal * rs ) const
{
return rs->route().id() == _route.id();
}
Route & _route;
};
///////////////////////////////////////////////// /////////////////////////////////////////////////
// handlers for Route signals // handlers for Route signals
// TODO should these be part of RouteSignal? // TODO should these be part of RouteSignal?
// They started off as sigc handlers for signals
// from Route, but they're also used in polling for automation
///////////////////////////////////////////////// /////////////////////////////////////////////////
void MackieControlProtocol::notify_solo_changed( RouteSignal * route_signal ) void MackieControlProtocol::notify_solo_changed( RouteSignal * route_signal )
@ -1038,7 +1023,7 @@ void MackieControlProtocol::poll_automation()
} }
// and the master strip // and the master strip
update_automation( *master_route_signal ); if ( master_route_signal != 0 ) update_automation( *master_route_signal );
} }
} }
@ -1135,6 +1120,14 @@ void MackieControlProtocol::notify_parameter_changed( const char * name_str )
{ {
update_global_button( "punch_out", Config->get_punch_out() ); update_global_button( "punch_out", Config->get_punch_out() );
} }
else if ( name == "clicking" )
{
update_global_button( "clicking", Config->get_clicking() );
}
else
{
cout << "parameter changed: " << name << endl;
}
} }
// RouteList is the set of routes that have just been added // RouteList is the set of routes that have just been added
@ -1260,6 +1253,18 @@ LedState MackieControlProtocol::end_release( Button & button )
return off; return off;
} }
LedState MackieControlProtocol::clicking_press( Button & button )
{
bool state = !Config->get_clicking();
Config->set_clicking( state );
return state;
}
LedState MackieControlProtocol::clicking_release( Button & button )
{
return Config->get_clicking();
}
///////////////////////////////////// /////////////////////////////////////
// Bank Switching // Bank Switching
///////////////////////////////////// /////////////////////////////////////

View file

@ -167,6 +167,9 @@ class MackieControlProtocol
virtual Mackie::LedState channel_right_press( Mackie::Button & ); virtual Mackie::LedState channel_right_press( Mackie::Button & );
virtual Mackie::LedState channel_right_release( Mackie::Button & ); virtual Mackie::LedState channel_right_release( Mackie::Button & );
virtual Mackie::LedState clicking_press( Mackie::Button & );
virtual Mackie::LedState clicking_release( Mackie::Button & );
protected: protected:
// create instances of MackiePort, depending on what's found in ardour.rc // create instances of MackiePort, depending on what's found in ardour.rc
void create_ports(); void create_ports();
@ -222,13 +225,18 @@ class MackieControlProtocol
*/ */
bool handle_strip_button( Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route> ); bool handle_strip_button( Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route> );
// Polling midi port(s) for incoming messages /// thread started. Calls monitor_work.
static void* _monitor_work (void* arg); static void* _monitor_work (void* arg);
/// Polling midi port(s) for incoming messages
void* monitor_work (); void* monitor_work ();
/// rebuild the set of ports for this surface /// rebuild the set of ports for this surface
void update_ports(); void update_ports();
/// Returns true if there is pending data, false otherwise /// Returns true if there is pending data, false otherwise
bool poll_ports(); bool poll_ports();
/// Trigger the MIDI::Parser /// Trigger the MIDI::Parser
void read_ports(); void read_ports();
@ -240,15 +248,18 @@ class MackieControlProtocol
// called from poll_automation to figure out which automations need to be sent // called from poll_automation to figure out which automations need to be sent
void update_automation( Mackie::RouteSignal & ); void update_automation( Mackie::RouteSignal & );
/// notification from the MackiePorts that their status has changed
void handle_port_changed( Mackie::SurfacePort *, bool active );
/** /**
notification that the port is about to start it's init sequence. notification that the port is about to start it's init sequence.
We must make sure that before this exits, the port is being polled We must make sure that before this exits, the port is being polled
for new data. for new data.
*/ */
void handle_port_init( Mackie::SurfacePort * ); void handle_port_init( Mackie::SurfacePort * );
/// notification from a MackiePort that it's now active
void handle_port_active( Mackie::SurfacePort * );
/// notification from a MackiePort that it's now inactive
void handle_port_inactive( Mackie::SurfacePort * );
boost::shared_ptr<ARDOUR::Route> master_route(); boost::shared_ptr<ARDOUR::Route> master_route();
Mackie::Strip & master_strip(); Mackie::Strip & master_strip();

View file

@ -34,49 +34,39 @@ bool MackieControlProtocol::probe()
void * MackieControlProtocol::monitor_work() void * MackieControlProtocol::monitor_work()
{ {
cout << "MackieControlProtocol::monitor_work" << endl;
// What does ThreadCreatedWithRequestSize do? // What does ThreadCreatedWithRequestSize do?
PBD::ThreadCreated (pthread_self(), X_("Mackie")); PBD::ThreadCreated (pthread_self(), X_("Mackie"));
#if 0
// it seems to do the "block" on poll less often
// with this code disabled
struct sched_param rtparam;
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
int err;
if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
// do we care? not particularly.
PBD::info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror( errno )) << endmsg;
}
#endif
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0); pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
// read from midi ports // read from midi ports
cout << "start poll cycle" << endl;
while ( true ) while ( true )
{ {
update_ports(); try
if ( poll_ports() )
{ {
try { read_ports(); } if ( poll_ports() )
catch ( exception & e ) { {
cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl; try { read_ports(); }
_ports_changed = true; catch ( exception & e ) {
update_ports(); cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
_ports_changed = true;
update_ports();
}
} }
// poll for automation data from the routes
poll_automation();
} }
catch ( exception & e )
{
cout << "caught exception in MackieControlProtocol::monitor_work " << e.what() << endl;
}
// provide a cancellation point // provide a cancellation point
pthread_testcancel(); pthread_testcancel();
// poll for automation data from the routes
poll_automation();
} }
// these never get called // these never get called because of cancellation point above
cout << "MackieControlProtocol::poll_ports exiting" << endl; cout << "MackieControlProtocol::poll_ports exiting" << endl;
delete[] pfd; delete[] pfd;
@ -86,16 +76,14 @@ void * MackieControlProtocol::monitor_work()
void MackieControlProtocol::update_ports() void MackieControlProtocol::update_ports()
{ {
// create pollfd structures if necessary
if ( _ports_changed ) if ( _ports_changed )
{ {
cout << "MackieControlProtocol::update_ports changed 1" << endl;
Glib::Mutex::Lock ul( update_mutex ); Glib::Mutex::Lock ul( update_mutex );
// yes, this is a double-test locking paradigm, or whatever it's called // yes, this is a double-test locking paradigm, or whatever it's called
// because we don't *always* need to acquire the lock for the first test // because we don't *always* need to acquire the lock for the first test
if ( _ports_changed ) if ( _ports_changed )
{ {
cout << "MackieControlProtocol::update_ports updating" << endl; // create new pollfd structures
if ( pfd != 0 ) delete[] pfd; if ( pfd != 0 ) delete[] pfd;
// TODO This might be a memory leak. How does thread cancellation cleanup work? // TODO This might be a memory leak. How does thread cancellation cleanup work?
pfd = new pollfd[_ports.size()]; pfd = new pollfd[_ports.size()];
@ -110,9 +98,7 @@ void MackieControlProtocol::update_ports()
} }
_ports_changed = false; _ports_changed = false;
} }
cout << "MackieControlProtocol::update_ports signalling" << endl;
update_cond.signal(); update_cond.signal();
cout << "MackieControlProtocol::update_ports finished" << endl;
} }
} }
@ -125,9 +111,11 @@ void MackieControlProtocol::read_ports()
// this will cause handle_midi_any in the MackiePort to be triggered // this will cause handle_midi_any in the MackiePort to be triggered
if ( pfd[p].revents & POLLIN > 0 ) if ( pfd[p].revents & POLLIN > 0 )
{ {
lock.release(); // avoid deadlocking?
// doesn't seem to make a difference
//lock.release();
_ports[p]->read(); _ports[p]->read();
lock.acquire(); //lock.acquire();
} }
} }
} }
@ -161,36 +149,42 @@ bool MackieControlProtocol::poll_ports()
return retval > 0; return retval > 0;
} }
void MackieControlProtocol::handle_port_changed( SurfacePort * port, bool active ) void MackieControlProtocol::handle_port_inactive( SurfacePort * port )
{ {
cout << "MackieControlProtocol::handle_port_changed port: " << *port << " active: " << active << endl; // port gone away. So stop polling it ASAP
if ( active == false )
{ {
// port gone away. So stop polling it ASAP // delete the port instance
Glib::Mutex::Lock lock( update_mutex );
MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
if ( it != _ports.end() )
{ {
// delete the port instance delete *it;
Glib::Mutex::Lock lock( update_mutex ); _ports.erase( it );
MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
if ( it != _ports.end() )
{
delete *it;
_ports.erase( it );
}
} }
_ports_changed = true;
update_ports();
}
else
{
_ports_changed = true;
// port added
update_ports();
update_surface();
// TODO update bank size
// rebuild surface
} }
_ports_changed = true;
update_ports();
// TODO all the rebuilding of surfaces and so on
}
void MackieControlProtocol::handle_port_active( SurfacePort * port )
{
// no need to re-add port because it was already added
// during the init phase. So just update the local surface
// representation and send the representation to
// all existing ports
// TODO update bank size
// TODO rebuild surface, to have new units
// finally update session state to the surface
// TODO but this is also done in set_active, and
// in fact update_surface won't execute unless
// _active == true
cout << "update_surface in handle_port_active" << endl;
update_surface();
} }
void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport ) void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport )
@ -198,5 +192,4 @@ void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport )
cout << "MackieControlProtocol::handle_port_init" << endl; cout << "MackieControlProtocol::handle_port_init" << endl;
_ports_changed = true; _ports_changed = true;
update_ports(); update_ports();
cout << "MackieControlProtocol::handle_port_init finished" << endl;
} }

View file

@ -233,26 +233,7 @@ void MackiePort::probe_emulation( const MidiByteArray & bytes )
return; return;
} }
// probing doesn't work very well, so just use a config variable finalise_init( true );
// to set the emulation mode
bool emulation_ok = false;
if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
{
_emulation = bcf2000;
emulation_ok = true;
}
else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
{
_emulation = mackie;
emulation_ok = true;
}
else
{
cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
emulation_ok = false;
}
finalise_init( emulation_ok );
} }
void MackiePort::init() void MackiePort::init()
@ -266,12 +247,42 @@ void MackiePort::init()
init_event(); init_event();
// kick off initialisation. See docs in header file for init() // kick off initialisation. See docs in header file for init()
write_sysex ( MidiByteArray (2, 0x13, 0x00 ));
// bypass the init sequence because sometimes the first
// message doesn't get to the unit, and there's no way
// to do a timed lock in Glib.
//write_sysex ( MidiByteArray ( 2, 0x13, 0x00 ) );
finalise_init( true );
} }
void MackiePort::finalise_init( bool yn ) void MackiePort::finalise_init( bool yn )
{ {
cout << "MackiePort::finalise_init" << endl; cout << "MackiePort::finalise_init" << endl;
bool emulation_ok = false;
// probing doesn't work very well, so just use a config variable
// to set the emulation mode
if ( _emulation == none )
{
if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
{
_emulation = bcf2000;
emulation_ok = true;
}
else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
{
_emulation = mackie;
emulation_ok = true;
}
else
{
cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
emulation_ok = false;
}
}
yn = yn && emulation_ok;
SurfacePort::active( yn ); SurfacePort::active( yn );

View file

@ -17,17 +17,17 @@ button,7,strip,vselect,1,0,0x08
# overlay buttons # overlay buttons
button,1,assignment,io,1,1,0x28 button,1,assignment,io,1,1,0x28
button,1,assignment,sends,1,1,0x29 button,1,assignment,sends,1,1,0x5a
button,1,assignment,pan,1,1,0x2a button,1,assignment,pan,1,1,0x59
button,1,assignment,plugin,1,1,0x2b button,1,assignment,plugin,1,1,0x57
button,1,assignment,eq,1,1,0x2c button,1,assignment,eq,1,1,0x58
button,1,assignment,dyn,1,1,0x2d button,1,assignment,dyn,1,1,0x2d
button,1,bank,left,1,0,0x2e button,1,bank,left,1,0,0x2e
button,1,bank,right,1,0,0x2f button,1,bank,right,1,0,0x2f
button,1,bank,channel_left,1,0,0x30 button,1,bank,channel_left,1,0,0x30
button,1,bank,channel_right,1,0,0x31 button,1,bank,channel_right,1,0,0x31
button,1,,flip,1,1,0x32 button,1,,flip,1,1,0x32
button,1,,edit,1,1,0x33 button,1,,edit,1,1,0x56
button,1,display,name_value,1,0,0x34 button,1,display,name_value,1,0,0x34
button,1,display,smpte_beats,1,0,0x35 button,1,display,smpte_beats,1,0,0x35
@ -47,7 +47,8 @@ button,1,,F13,1,0,0x42
button,1,,F14,1,0,0x43 button,1,,F14,1,0,0x43
button,1,,F15,1,0,0x44 button,1,,F15,1,0,0x44
button,1,,F16,1,0,0x45 button,1,,F16,1,0,0x45
button,1,modifiers,shift,1,0,0x46 # turn on/off all solos
button,1,,global_solo,1,0,0x27
button,1,modifiers,option,1,0,0x47 button,1,modifiers,option,1,0,0x47
button,1,modifiers,control,1,0,0x48 button,1,modifiers,control,1,0,0x48
button,1,modifiers,cmd_alt,1,0,0x49 button,1,modifiers,cmd_alt,1,0,0x49
@ -63,11 +64,11 @@ button,1,functions,cancel,1,0,0x52
button,1,functions,mixer,1,0,0x53 button,1,functions,mixer,1,0,0x53
button,1,transport,frm_left,1,1,0x54 button,1,transport,frm_left,1,1,0x54
button,1,transport,frm_right,1,1,0x55 button,1,transport,frm_right,1,1,0x55
button,1,transport,loop,1,1,0x56 button,1,transport,loop,1,1,0x46
button,1,transport,punch_in,1,1,0x57 button,1,transport,punch_in,1,1,0x2c
button,1,transport,punch_out,1,1,0x58 button,1,transport,punch_out,1,1,0x2b
button,1,transport,home,1,1,0x59 button,1,transport,home,1,1,0x2a
button,1,transport,end,1,1,0x5a button,1,transport,end,1,1,0x29
# transport buttons # transport buttons
button,1,transport,"rewind",1,1,0x5b button,1,transport,"rewind",1,1,0x5b
@ -87,6 +88,7 @@ button,1,user,"user_b",1,0,0x67
button,7,strip,"fader_touch",1,0,0x68 button,7,strip,"fader_touch",1,0,0x68
button,1,master,"fader_touch",1,0,0x6f button,1,master,"fader_touch",1,0,0x6f
button,1,master,mute,1,0,0x17 button,1,master,mute,1,0,0x17
button,1,,clicking,1,1,0x33
button,1,,"smpte",0,1,0x71 button,1,,"smpte",0,1,0x71
button,1,,"beats",0,1,0x72 button,1,,"beats",0,1,0x72

Can't render this file because it has a wrong number of fields in line 2.

View file

@ -1,17 +1,18 @@
#! /usr/bin/ruby #! /usr/bin/ruby
require 'erb' require 'erb'
require 'controls.rb'
require File.dirname(__FILE__) + '/controls.rb'
cc_template = '' cc_template = ''
File.open("surface-cc-template.erb", "r") { |f| cc_template = f.read } File.open( File.dirname(__FILE__) + "/surface-cc-template.erb", "r" ) { |f| cc_template = f.read }
h_template = '' h_template = ''
File.open("surface-h-template.erb", "r") { |f| h_template = f.read } File.open( File.dirname(__FILE__) + "/surface-h-template.erb", "r" ) { |f| h_template = f.read }
sf = Surface.new( ARGV[0] ) sf = Surface.new( ARGV[0] )
control_data = '' control_data = ''
File.open("#{sf.name.downcase}-controls.csv", "r") { |f| control_data = f.read } File.open( File.dirname(__FILE__) + "/#{sf.name.downcase}-controls.csv", "r") { |f| control_data = f.read }
sf.parse control_data sf.parse control_data
@result = "" @result = ""

View file

@ -22,6 +22,11 @@ while !File.exist? ARGV[0]
sleep 0.010 sleep 0.010
end end
#mapping_csv = ARGV[1] || "mackie-controls.csv"
mapping_csv = ARGV[1]
puts "mapping_csv: #{mapping_csv}"
puts ""
file = File.open ARGV[0], 'r+' file = File.open ARGV[0], 'r+'
mck = Mackie.new( file ) mck = Mackie.new( file )
@ -94,7 +99,7 @@ puts "version: #{version.map{|x| x.chr}}"
sf = Surface.new sf = Surface.new
control_data = "" control_data = ""
File.open( "mackie-controls.csv" ) { |f| control_data = f.read } File.open( mapping_csv ) { |f| control_data = f.read }
sf.parse( control_data ) sf.parse( control_data )
# send all faders to 0, but bounce them first # send all faders to 0, but bounce them first
@ -122,7 +127,7 @@ while bytes = mck.file.read( 3 )
print " Control Type: %-7s, " % sf.types[midi_type] print " Control Type: %-7s, " % sf.types[midi_type]
print "id: %4i" % control_id print "id: %4i" % control_id
print ", control: %15s" % control.name print ", control: %15s" % ( control ? control.name : "nil control" )
print ", %15s" % control.group.name print ", %15s" % ( control ? control.group.name : "nil group" )
print "\n" print "\n"
end end

View file

@ -28,6 +28,8 @@
#include "i18n.h" #include "i18n.h"
#include <sstream> #include <sstream>
#include <cstring>
#include <cerrno>
using namespace std; using namespace std;
using namespace Mackie; using namespace Mackie;
@ -45,7 +47,11 @@ MidiByteArray SurfacePort::read()
// return nothing read if the lock isn't acquired // return nothing read if the lock isn't acquired
Glib::RecMutex::Lock lock( _rwlock, Glib::TRY_LOCK ); Glib::RecMutex::Lock lock( _rwlock, Glib::TRY_LOCK );
if ( !lock.locked() ) return retval; if ( !lock.locked() )
{
cout << "SurfacePort::read not locked" << endl;
return retval;
}
// read port and copy to return value // read port and copy to return value
int nread = port().read( buf, sizeof (buf) ); int nread = port().read( buf, sizeof (buf) );
@ -59,11 +65,17 @@ MidiByteArray SurfacePort::read()
} }
else else
{ {
ostringstream os; if ( errno != EAGAIN )
os << "error reading from port: " << port().name() << " nread: " << nread; {
cout << os.str() << endl; char buf[512];
//inactive_event(); char * msg = strerror_r( errno, buf, 512 );
//throw MackieControlException( os.str() );
ostringstream os;
os << "Surface: error reading from port: " << port().name() << ": " << errno << " " << msg;
cout << os.str() << endl;
inactive_event();
throw MackieControlException( os.str() );
}
} }
return retval; return retval;
} }
@ -76,10 +88,17 @@ void SurfacePort::write( const MidiByteArray & mba )
int count = port().write( mba.bytes().get(), mba.size() ); int count = port().write( mba.bytes().get(), mba.size() );
if ( count != (int)mba.size() ) if ( count != (int)mba.size() )
{ {
inactive_event(); if ( errno != EAGAIN )
ostringstream os; {
os << _("Surface: couldn't write to port ") << port().name(); char buf[512];
throw MackieControlException( os.str() ); char * msg = strerror_r( errno, buf, 512 );
ostringstream os;
os << "Surface: couldn't write to port " << port().name() << ": " << errno << " " << msg;
cout << os.str();
inactive_event();
throw MackieControlException( os.str() );
}
} }
//if ( mba[0] == 0xf0 ) cout << "SurfacePort::write " << count << endl; //if ( mba[0] == 0xf0 ) cout << "SurfacePort::write " << count << endl;
} }