MackieControlProtocol::MackieControlProtocol (Session& session)
: ControlProtocol (session, X_("Mackie"))
, _current_initial_bank( 0 )
- , connections_back( _connections )
, _surface( 0 )
, _ports_changed( false )
, _polling( true )
#endif
// will start reading from ports, as soon as there are some
pthread_create_and_store (X_("mackie monitor"), &thread, 0, _monitor_work, this);
+
+ // receive punch-in and punch-out
+ Config->ParameterChanged.connect ((mem_fun (*this, &MackieControlProtocol::notify_parameter_changed)));
}
MackieControlProtocol::~MackieControlProtocol()
#endif
}
-Mackie::Surface & MackieControlProtocol::surface()
+Mackie::Surface &
+MackieControlProtocol::surface()
{
- if ( _surface == 0 )
- {
+ if ( _surface == 0 ) {
throw MackieControlException( "_surface is 0 in MackieControlProtocol::surface" );
}
return *_surface;
}
-const Mackie::SurfacePort & MackieControlProtocol::mcu_port() const
+const Mackie::SurfacePort &
+MackieControlProtocol::mcu_port() const
{
- if ( _ports.size() < 1 )
- {
+ if (_ports.size() < 1) {
return _dummy_port;
- }
- else
- {
+ } else {
return dynamic_cast<const MackiePort &>( *_ports[0] );
}
}
-Mackie::SurfacePort & MackieControlProtocol::mcu_port()
+Mackie::SurfacePort &
+MackieControlProtocol::mcu_port()
{
- if ( _ports.size() < 1 )
- {
+ if (_ports.size() < 1) {
return _dummy_port;
- }
- else
- {
+ } else {
return dynamic_cast<MackiePort &>( *_ports[0] );
}
}
// go to the previous track.
// Assume that get_sorted_routes().size() > route_table.size()
-void MackieControlProtocol::prev_track()
+void
+MackieControlProtocol::prev_track()
{
- if ( _current_initial_bank >= 1 )
- {
+ if (_current_initial_bank >= 1) {
session->set_dirty();
switch_banks( _current_initial_bank - 1 );
}
// go to the next track.
// Assume that get_sorted_routes().size() > route_table.size()
-void MackieControlProtocol::next_track()
+void
+MackieControlProtocol::next_track()
{
Sorted sorted = get_sorted_routes();
- if ( _current_initial_bank + route_table.size() < sorted.size() )
- {
+ if ( _current_initial_bank + route_table.size() < sorted.size() ) {
session->set_dirty();
switch_banks( _current_initial_bank + 1 );
}
}
-void MackieControlProtocol::clear_route_signals()
+void
+MackieControlProtocol::clear_route_signals()
{
- for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it )
- {
+ for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it ) {
delete *it;
}
route_signals.clear();
+
+ for (vector<sigc::connection>::iterator c = route_connections.begin(); c != route_connections.end(); ++c) {
+ (*c).disconnect ();
+ }
+ route_connections.clear ();
+
}
// return the port for a given id - 0 based
// throws an exception if no port found
-MackiePort & MackieControlProtocol::port_for_id( uint32_t index )
+MackiePort &
+MackieControlProtocol::port_for_id( uint32_t index )
{
uint32_t current_max = 0;
- for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
- {
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it ) {
current_max += (*it)->strips();
if ( index < current_max ) return **it;
}
// predicate for sort call in get_sorted_routes
struct RouteByRemoteId
{
- bool operator () ( const shared_ptr<Route> & a, const shared_ptr<Route> & b ) const
- {
+ bool operator () ( const shared_ptr<Route> & a, const shared_ptr<Route> & b ) const {
return a->remote_control_id() < b->remote_control_id();
}
- bool operator () ( const Route & a, const Route & b ) const
- {
+ bool operator () ( const Route & a, const Route & b ) const {
return a.remote_control_id() < b.remote_control_id();
}
- bool operator () ( const Route * a, const Route * b ) const
- {
+ bool operator () ( const Route * a, const Route * b ) const {
return a->remote_control_id() < b->remote_control_id();
}
};
-MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
+MackieControlProtocol::Sorted
+MackieControlProtocol::get_sorted_routes()
{
Sorted sorted;
return sorted;
}
-void MackieControlProtocol::refresh_current_bank()
+void
+MackieControlProtocol::refresh_current_bank()
{
switch_banks( _current_initial_bank );
}
-void MackieControlProtocol::switch_banks( int initial )
+void
+MackieControlProtocol::switch_banks( int initial )
{
// DON'T prevent bank switch if initial == _current_initial_bank
// because then this method can't be used as a refresh
_current_initial_bank = initial;
// first clear the signals from old routes
- // taken care of by the RouteSignal destructors
+ // taken care of by the RouteSignal destructors and explicit disconnect from other Route signals such as GoingAway
clear_route_signals();
// now set the signals for new routes
route_table[i] = route;
RouteSignal * rs = new RouteSignal (route, *this, strip, port_for_id(i) );
route_signals.push_back( rs );
+ route_connections.push_back (route->GoingAway.connect (mem_fun (*this, &MackieControlProtocol::route_deleted)));
// update strip from route
rs->notify_all();
}
surface().display_bank_start( mcu_port(), builder, _current_initial_bank );
}
-void MackieControlProtocol::zero_all()
+void
+MackieControlProtocol::route_deleted ()
+{
+ for (vector<sigc::connection>::iterator c = route_connections.begin(); c != route_connections.end(); ++c) {
+ (*c).disconnect ();
+ }
+ route_connections.clear ();
+ update_surface ();
+}
+
+void
+MackieControlProtocol::zero_all()
{
// TODO turn off SMPTE displays
surface().zero_all( mcu_port(), builder );
}
-int MackieControlProtocol::set_active( bool yn )
+int
+MackieControlProtocol::set_active( bool yn )
{
if ( yn != _active )
{
// correctly initialised
initialize_surface();
connect_session_signals();
-
+
// yeehah!
_active = true;
return 0;
}
-bool MackieControlProtocol::handle_strip_button( Control & control, ButtonState bs, boost::shared_ptr<Route> route )
+bool
+MackieControlProtocol::handle_strip_button( Control & control, ButtonState bs, boost::shared_ptr<Route> route )
{
bool state = false;
return state;
}
-void MackieControlProtocol::update_led( Mackie::Button & button, Mackie::LedState ls )
+void
+MackieControlProtocol::update_led( Mackie::Button & button, Mackie::LedState ls )
{
if ( ls != none )
{
}
}
-void MackieControlProtocol::update_smpte_beats_led()
+void
+MackieControlProtocol::update_smpte_beats_led()
{
switch ( _timecode_type )
{
}
}
-void MackieControlProtocol::update_global_button( const string & name, LedState ls )
+void
+MackieControlProtocol::update_global_button( const string & name, LedState ls )
{
if ( surface().controls_by_name.find( name ) != surface().controls_by_name.end() )
{
}
}
-void MackieControlProtocol::update_global_led( const string & name, LedState ls )
+void
+MackieControlProtocol::update_global_led( const string & name, LedState ls )
{
if ( surface().controls_by_name.find( name ) != surface().controls_by_name.end() )
{
}
// send messages to surface to set controls to correct values
-void MackieControlProtocol::update_surface()
+void
+MackieControlProtocol::update_surface()
{
if ( _active )
{
// _current_initial_bank is initialised by set_state
switch_banks( _current_initial_bank );
- // create a RouteSignal for the master route
+ // remove any existing master route RouteSignal by dropping our reference to it
+ master_route_signal.reset ();
+ // if appropriate, create a RouteSignal for the master route
boost::shared_ptr<Route> mr = master_route ();
if (mr) {
- master_route_signal = shared_ptr<RouteSignal> (new RouteSignal (mr, *this, master_strip(), mcu_port()) );
+ master_route_signal.reset (new RouteSignal (mr, *this, master_strip(), mcu_port()));
+ route_connections.push_back (mr->GoingAway.connect (mem_fun (*this, &MackieControlProtocol::route_deleted)));
// update strip from route
master_route_signal->notify_all();
}
update_smpte_beats_led();
}
}
+void
+MackieControlProtocol::disconnect_session_signals ()
+{
+ for (vector<sigc::connection>::iterator i = session_connections.begin(); i != session_connections.end(); ++i) {
+ (*i).disconnect ();
+ }
+ session_connections.clear ();
+}
-void MackieControlProtocol::connect_session_signals()
+void
+MackieControlProtocol::connect_session_signals()
{
// receive routes added
- connections_back = session->RouteAdded.connect( ( mem_fun (*this, &MackieControlProtocol::notify_route_added) ) );
+ session_connections.push_back (session->RouteAdded.connect (mem_fun (*this, &MackieControlProtocol::notify_route_added)));
// receive record state toggled
- connections_back = session->RecordStateChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_record_state_changed) ) );
+ session_connections.push_back (session->RecordStateChanged.connect (mem_fun (*this, &MackieControlProtocol::notify_record_state_changed)));
// receive transport state changed
- connections_back = session->TransportStateChange.connect( ( mem_fun (*this, &MackieControlProtocol::notify_transport_state_changed) ) );
- // receive punch-in and punch-out
- connections_back = Config->ParameterChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_parameter_changed) ) );
- // receive rude solo changed
- connections_back = session->SoloActive.connect( ( mem_fun (*this, &MackieControlProtocol::notify_solo_active_changed) ) );
+ session_connections.push_back (session->TransportStateChange.connect (mem_fun (*this, &MackieControlProtocol::notify_transport_state_changed)));
+ // receive rude solo changed
+ session_connections.push_back (session->SoloActive.connect (mem_fun (*this, &MackieControlProtocol::notify_solo_active_changed)));
// 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 )
- {
- connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
+ for ( Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it ) {
+ session_connections.push_back ((*it)->RemoteControlIDChanged.connect (mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed)));
}
}
-void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
+void
+MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
{
#ifdef DEBUG
cout << "add port " << midi_port.name() << ", " << midi_port.device() << ", " << midi_port.type() << endl;
MackiePort * sport = new MackiePort( *this, midi_port, number );
_ports.push_back( sport );
- connections_back = sport->init_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_init)
- , sport
- )
- );
-
- connections_back = sport->active_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_active)
- , sport
- )
- );
-
- connections_back = sport->inactive_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_inactive)
- , sport
- )
- );
+ sport->init_event.connect(sigc::bind (mem_fun (*this, &MackieControlProtocol::handle_port_init), sport));
+
+ sport->active_event.connect(sigc::bind (mem_fun (*this, &MackieControlProtocol::handle_port_active) , sport));
+
+ sport->inactive_event.connect(sigc::bind (mem_fun (*this, &MackieControlProtocol::handle_port_inactive) , sport));
_ports_changed = true;
}
}
-void MackieControlProtocol::create_ports()
+void
+MackieControlProtocol::create_ports()
{
MIDI::Manager * mm = MIDI::Manager::instance();
}
}
-shared_ptr<Route> MackieControlProtocol::master_route()
+shared_ptr<Route>
+MackieControlProtocol::master_route()
{
boost::shared_ptr<IO> mo = session->master_out ();
return boost::dynamic_pointer_cast<Route>(mo);
}
-Strip & MackieControlProtocol::master_strip()
+Strip &
+MackieControlProtocol::master_strip()
{
return dynamic_cast<Strip&>( *surface().groups["master"] );
}
-void MackieControlProtocol::initialize_surface()
+void
+MackieControlProtocol::initialize_surface()
{
// set up the route table
int strips = 0;
// Connect events. Must be after route table otherwise there will be trouble
for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
{
- connections_back = (*it)->control_event.connect( ( mem_fun (*this, &MackieControlProtocol::handle_control_event) ) );
+ (*it)->control_event.connect (mem_fun (*this, &MackieControlProtocol::handle_control_event));
}
}
-void MackieControlProtocol::close()
+void
+MackieControlProtocol::close()
{
// stop polling, and wait for it...
// must be before other shutdown otherwise polling loop
// TODO disconnect port active/inactive signals
// Or at least put a lock here
- // disconnect global signals from Session
- // TODO Since *this is a sigc::trackable, this shouldn't be necessary
- // but it is for some reason
-#if 0
- for( vector<sigc::connection>::iterator it = _connections.begin(); it != _connections.end(); ++it )
- {
- it->disconnect();
- }
-#endif
-
- if ( _surface != 0 )
- {
+ if ( _surface != 0 ) {
+
// These will fail if the port has gone away.
// So catch the exception and do the rest of the
// close afterwards
// because the bcf doesn't respond to the next 3 sysex messages
- try
- {
+
+ try {
zero_all();
}
- catch ( exception & e )
- {
+ catch (exception & e) {
#ifdef DEBUG
cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
#endif
}
- for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
- {
- try
- {
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it ) {
+ try {
MackiePort & port = **it;
// faders to minimum
port.write_sysex( 0x61 );
// Reset (reboot into offline mode)
port.write_sysex( 0x63 );
}
- catch ( exception & e )
- {
+
+ catch ( exception & e ) {
#ifdef DEBUG
cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
#endif
}
}
-
- // disconnect routes from strips
- clear_route_signals();
-
+
delete _surface;
_surface = 0;
}
+ // disconnect routes from strips
+ clear_route_signals();
+ // drop the route signal for the master route, if it exists
+ master_route_signal.reset ();
+ // drop per-session signal connections
+ disconnect_session_signals ();
// shut down MackiePorts
- for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
- {
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it ) {
delete *it;
}
_ports.clear();
// this is done already in monitor_work. But it's here so we know.
- delete[] pfd;
+ delete [] pfd;
pfd = 0;
nfds = 0;
}
-void* MackieControlProtocol::_monitor_work (void* arg)
+void*
+MackieControlProtocol::_monitor_work (void* arg)
{
return static_cast<MackieControlProtocol*>(arg)->monitor_work ();
}
-XMLNode & MackieControlProtocol::get_state()
+XMLNode &
+MackieControlProtocol::get_state()
{
#ifdef DEBUG
cout << "MackieControlProtocol::get_state" << endl;
return *node;
}
-int MackieControlProtocol::set_state( const XMLNode & node )
+int
+MackieControlProtocol::set_state( const XMLNode & node )
{
#ifdef DEBUG
cout << "MackieControlProtocol::set_state: active " << _active << endl;
int retval = 0;
// fetch current bank
- if ( node.property( X_("bank") ) != 0 )
- {
+ if (node.property( X_("bank") ) != 0) {
string bank = node.property( X_("bank") )->value();
- try
- {
+ try {
set_active( true );
uint32_t new_bank = atoi( bank.c_str() );
if ( _current_initial_bank != new_bank ) switch_banks( new_bank );
}
- catch ( exception & e )
- {
+ catch ( exception & e ) {
#ifdef DEBUG
cout << "exception in MackieControlProtocol::set_state: " << e.what() << endl;
#endif
return retval;
}
-void MackieControlProtocol::handle_control_event( SurfacePort & port, Control & control, const ControlState & state )
+void
+MackieControlProtocol::handle_control_event( SurfacePort & port, Control & control, const ControlState & state )
{
// find the route for the control, if there is one
boost::shared_ptr<Route> route;
- if ( control.group().is_strip() )
- {
- if ( control.group().is_master() )
- {
+ if (control.group().is_strip()) {
+ if ( control.group().is_master() ) {
route = master_route();
- }
- else
- {
+ } else {
uint32_t index = control.ordinal() - 1 + ( port.number() * port.strips() );
if ( index < route_table.size() )
route = route_table[index];
// This handles control element events from the surface
// the state of the controls on the surface is usually updated
// from UI events.
- switch ( control.type() )
- {
+ switch (control.type()) {
case Control::type_fader:
// find the route in the route table for the id
// if the route isn't available, skip it
// 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 )
{
try
{
}
}
-void MackieControlProtocol::notify_mute_changed( RouteSignal * route_signal )
+void
+MackieControlProtocol::notify_mute_changed( RouteSignal * route_signal )
{
try
{
}
}
-void MackieControlProtocol::notify_record_enable_changed( RouteSignal * route_signal )
+void
+MackieControlProtocol::notify_record_enable_changed( RouteSignal * route_signal )
{
try
{
}
}
-void MackieControlProtocol::notify_active_changed( RouteSignal * route_signal )
+void
+MackieControlProtocol::notify_active_changed( RouteSignal * route_signal )
{
try
{
}
}
-void MackieControlProtocol::notify_gain_changed( RouteSignal * route_signal, bool force_update )
+void
+MackieControlProtocol::notify_gain_changed( RouteSignal * route_signal, bool force_update )
{
try
{
}
}
-void MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_signal )
+void
+MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_signal )
{
try
{
}
}
-void MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal, bool force_update )
+void
+MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal, bool force_update )
{
try
{
}
// TODO handle plugin automation polling
-void MackieControlProtocol::update_automation( RouteSignal & rs )
+void
+MackieControlProtocol::update_automation( RouteSignal & rs )
{
ARDOUR::AutoState gain_state = rs.route()->gain_automation_state();
if ( gain_state == Touch || gain_state == Play )
_automation_last.start();
}
-string MackieControlProtocol::format_bbt_timecode( nframes_t now_frame )
+string
+MackieControlProtocol::format_bbt_timecode( nframes_t now_frame )
{
BBT_Time bbt_time;
session->bbt_time( now_frame, bbt_time );
return os.str();
}
-string MackieControlProtocol::format_smpte_timecode( nframes_t now_frame )
+string
+MackieControlProtocol::format_smpte_timecode( nframes_t now_frame )
{
SMPTE::Time smpte;
session->smpte_time( now_frame, smpte );
return os.str();
}
-void MackieControlProtocol::update_timecode_display()
+void
+MackieControlProtocol::update_timecode_display()
{
if ( surface().has_timecode_display() )
{
}
}
-void MackieControlProtocol::poll_session_data()
+void
+MackieControlProtocol::poll_session_data()
{
if ( _active && _automation_last.elapsed() >= 20 )
{
// Transport Buttons
/////////////////////////////////////
-LedState MackieControlProtocol::frm_left_press( Button & button )
+LedState
+MackieControlProtocol::frm_left_press( Button & button )
{
// can use first_mark_before/after as well
unsigned long elapsed = _frm_left_last.restart();
return on;
}
-LedState MackieControlProtocol::frm_left_release( Button & button )
+LedState
+MackieControlProtocol::frm_left_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::frm_right_press( Button & button )
+LedState
+MackieControlProtocol::frm_right_press( Button & button )
{
// can use first_mark_before/after as well
Location * loc = session->locations()->first_location_after (
return on;
}
-LedState MackieControlProtocol::frm_right_release( Button & button )
+LedState
+MackieControlProtocol::frm_right_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::stop_press( Button & button )
+LedState
+MackieControlProtocol::stop_press( Button & button )
{
session->request_stop();
return on;
}
-LedState MackieControlProtocol::stop_release( Button & button )
+LedState
+MackieControlProtocol::stop_release( Button & button )
{
return session->transport_stopped();
}
-LedState MackieControlProtocol::play_press( Button & button )
+LedState
+MackieControlProtocol::play_press( Button & button )
{
session->request_transport_speed( 1.0 );
return on;
}
-LedState MackieControlProtocol::play_release( Button & button )
+LedState
+MackieControlProtocol::play_release( Button & button )
{
return session->transport_rolling();
}
-LedState MackieControlProtocol::record_press( Button & button )
+LedState
+MackieControlProtocol::record_press( Button & button )
{
if ( session->get_record_enabled() )
session->disable_record( false );
return on;
}
-LedState MackieControlProtocol::record_release( Button & button )
+LedState
+MackieControlProtocol::record_release( Button & button )
{
if ( session->get_record_enabled() )
{
return off;
}
-LedState MackieControlProtocol::rewind_press( Button & button )
+LedState
+MackieControlProtocol::rewind_press( Button & button )
{
_jog_wheel.push( JogWheel::speed );
_jog_wheel.transport_direction( -1 );
return on;
}
-LedState MackieControlProtocol::rewind_release( Button & button )
+LedState
+MackieControlProtocol::rewind_release( Button & button )
{
_jog_wheel.pop();
_jog_wheel.transport_direction( 0 );
return off;
}
-LedState MackieControlProtocol::ffwd_press( Button & button )
+LedState
+MackieControlProtocol::ffwd_press( Button & button )
{
_jog_wheel.push( JogWheel::speed );
_jog_wheel.transport_direction( 1 );
return on;
}
-LedState MackieControlProtocol::ffwd_release( Button & button )
+LedState
+MackieControlProtocol::ffwd_release( Button & button )
{
_jog_wheel.pop();
_jog_wheel.transport_direction( 0 );
return off;
}
-LedState MackieControlProtocol::loop_press( Button & button )
+LedState
+MackieControlProtocol::loop_press( Button & button )
{
session->request_play_loop( !session->get_play_loop() );
return on;
}
-LedState MackieControlProtocol::loop_release( Button & button )
+LedState
+MackieControlProtocol::loop_release( Button & button )
{
return session->get_play_loop();
}
-LedState MackieControlProtocol::punch_in_press( Button & button )
+LedState
+MackieControlProtocol::punch_in_press( Button & button )
{
bool state = !Config->get_punch_in();
Config->set_punch_in( state );
return state;
}
-LedState MackieControlProtocol::punch_in_release( Button & button )
+LedState
+MackieControlProtocol::punch_in_release( Button & button )
{
return Config->get_punch_in();
}
-LedState MackieControlProtocol::punch_out_press( Button & button )
+LedState
+MackieControlProtocol::punch_out_press( Button & button )
{
bool state = !Config->get_punch_out();
Config->set_punch_out( state );
return state;
}
-LedState MackieControlProtocol::punch_out_release( Button & button )
+LedState
+MackieControlProtocol::punch_out_release( Button & button )
{
return Config->get_punch_out();
}
-LedState MackieControlProtocol::home_press( Button & button )
+LedState
+MackieControlProtocol::home_press( Button & button )
{
session->goto_start();
return on;
}
-LedState MackieControlProtocol::home_release( Button & button )
+LedState
+MackieControlProtocol::home_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::end_press( Button & button )
+LedState
+MackieControlProtocol::end_press( Button & button )
{
session->goto_end();
return on;
}
-LedState MackieControlProtocol::end_release( Button & button )
+LedState
+MackieControlProtocol::end_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::clicking_press( Button & button )
+LedState
+MackieControlProtocol::clicking_press( Button & button )
{
bool state = !Config->get_clicking();
Config->set_clicking( state );
return state;
}
-LedState MackieControlProtocol::clicking_release( Button & button )
+LedState
+MackieControlProtocol::clicking_release( Button & button )
{
return Config->get_clicking();
}
-LedState MackieControlProtocol::global_solo_press( Button & button )
+LedState
+MackieControlProtocol::global_solo_press( Button & button )
{
bool state = !session->soloing();
session->set_all_solo ( state );
return state;
}
-LedState MackieControlProtocol::global_solo_release( Button & button )
+LedState
+MackieControlProtocol::global_solo_release( Button & button )
{
return session->soloing();
}
// Session signals
///////////////////////////////////////////
-void MackieControlProtocol::notify_parameter_changed( const char * name_str )
+void
+MackieControlProtocol::notify_parameter_changed( const char * name_str )
{
string name( name_str );
if ( name == "punch-in" )
}
// RouteList is the set of routes that have just been added
-void MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl )
+void
+MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl )
{
// currently assigned banks are less than the full set of
// strips, so activate the new strip now.
- if ( route_signals.size() < route_table.size() )
- {
+
+ if ( route_signals.size() < route_table.size() ) {
refresh_current_bank();
}
+
// otherwise route added, but current bank needs no updating
// make sure remote id changes in the new route are handled
+
typedef ARDOUR::Session::RouteList ARS;
- for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it )
- {
- connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
+ for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it ) {
+ session_connections.push_back ((*it)->RemoteControlIDChanged.connect (( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed))));
}
}
-void MackieControlProtocol::notify_solo_active_changed( bool active )
+void
+MackieControlProtocol::notify_solo_active_changed( bool active )
{
Button * rude_solo = reinterpret_cast<Button*>( surface().controls_by_name["solo"] );
mcu_port().write( builder.build_led( *rude_solo, active ? flashing : off ) );
}
-void MackieControlProtocol::notify_remote_id_changed()
+void
+MackieControlProtocol::notify_remote_id_changed()
{
Sorted sorted = get_sorted_routes();
// Transport signals
///////////////////////////////////////////
-void MackieControlProtocol::notify_record_state_changed()
+void
+MackieControlProtocol::notify_record_state_changed()
{
// switch rec button on / off / flashing
Button * rec = reinterpret_cast<Button*>( surface().controls_by_name["record"] );
mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) );
}
-void MackieControlProtocol::notify_transport_state_changed()
+void
+MackieControlProtocol::notify_transport_state_changed()
{
// switch various play and stop buttons on / off
update_global_button( "play", session->transport_rolling() );
/////////////////////////////////////
// Bank Switching
/////////////////////////////////////
-LedState MackieControlProtocol::left_press( Button & button )
+LedState
+MackieControlProtocol::left_press( Button & button )
{
Sorted sorted = get_sorted_routes();
if ( sorted.size() > route_table.size() )
}
}
-LedState MackieControlProtocol::left_release( Button & button )
+LedState
+MackieControlProtocol::left_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::right_press( Button & button )
+LedState
+MackieControlProtocol::right_press( Button & button )
{
Sorted sorted = get_sorted_routes();
if ( sorted.size() > route_table.size() )
}
}
-LedState MackieControlProtocol::right_release( Button & button )
+LedState
+MackieControlProtocol::right_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::channel_left_press( Button & button )
+LedState
+MackieControlProtocol::channel_left_press( Button & button )
{
Sorted sorted = get_sorted_routes();
if ( sorted.size() > route_table.size() )
}
}
-LedState MackieControlProtocol::channel_left_release( Button & button )
+LedState
+MackieControlProtocol::channel_left_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::channel_right_press( Button & button )
+LedState
+MackieControlProtocol::channel_right_press( Button & button )
{
Sorted sorted = get_sorted_routes();
if ( sorted.size() > route_table.size() )
}
}
-LedState MackieControlProtocol::channel_right_release( Button & button )
+LedState
+MackieControlProtocol::channel_right_release( Button & button )
{
return off;
}
/////////////////////////////////////
// Functions
/////////////////////////////////////
-LedState MackieControlProtocol::marker_press( Button & button )
+LedState
+MackieControlProtocol::marker_press( Button & button )
{
// cut'n'paste from LocationUI::add_new_location()
string markername;
return on;
}
-LedState MackieControlProtocol::marker_release( Button & button )
+LedState
+MackieControlProtocol::marker_release( Button & button )
{
return off;
}
}
}
-Mackie::LedState MackieControlProtocol::zoom_press( Mackie::Button & )
+Mackie::LedState
+MackieControlProtocol::zoom_press( Mackie::Button & )
{
_jog_wheel.zoom_state_toggle();
update_global_button( "scrub", _jog_wheel.jog_wheel_state() == JogWheel::scrub );
return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
}
-Mackie::LedState MackieControlProtocol::zoom_release( Mackie::Button & )
+Mackie::LedState
+MackieControlProtocol::zoom_release( Mackie::Button & )
{
return _jog_wheel.jog_wheel_state() == JogWheel::zoom;
}
-Mackie::LedState MackieControlProtocol::scrub_press( Mackie::Button & )
+Mackie::LedState
+MackieControlProtocol::scrub_press( Mackie::Button & )
{
_jog_wheel.scrub_state_cycle();
update_global_button( "zoom", _jog_wheel.jog_wheel_state() == JogWheel::zoom );
;
}
-Mackie::LedState MackieControlProtocol::scrub_release( Mackie::Button & )
+Mackie::LedState
+MackieControlProtocol::scrub_release( Mackie::Button & )
{
return
_jog_wheel.jog_wheel_state() == JogWheel::scrub
;
}
-LedState MackieControlProtocol::drop_press( Button & button )
+LedState
+MackieControlProtocol::drop_press( Button & button )
{
session->remove_last_capture();
return on;
}
-LedState MackieControlProtocol::drop_release( Button & button )
+LedState
+MackieControlProtocol::drop_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::save_press( Button & button )
+LedState
+MackieControlProtocol::save_press( Button & button )
{
session->save_state( "" );
return on;
}
-LedState MackieControlProtocol::save_release( Button & button )
+LedState
+MackieControlProtocol::save_release( Button & button )
{
return off;
}
-LedState MackieControlProtocol::smpte_beats_press( Button & )
+LedState
+MackieControlProtocol::smpte_beats_press( Button & )
{
switch ( _timecode_type )
{
return on;
}
-LedState MackieControlProtocol::smpte_beats_release( Button & )
+LedState
+MackieControlProtocol::smpte_beats_release( Button & )
{
return off;
}
}
/**
- This handles the plugin duties, and the midi encoding and decoding,
- and the signal callbacks, mostly from ARDOUR::Route.
-
- The model of the control surface is handled by classes in controls.h
-
- What happens is that each strip on the control surface has
- a corresponding route in ControlProtocol::route_table. When
- an incoming midi message is signaled, the correct route
- is looked up, and the relevant changes made to it.
-
- For each route currently in route_table, there's a RouteSignal object
- which encapsulates the signals that indicate that there are changes
- to be sent to the surface. The signals are handled by this class.
-
- Calls to signal handlers pass a Route object which is used to look
- up the relevant Strip in Surface. Then the state is retrieved from
- the Route and encoded as the correct midi message.
+ This handles the plugin duties, and the midi encoding and decoding,
+ and the signal callbacks, mostly from ARDOUR::Route.
+
+ The model of the control surface is handled by classes in controls.h
+
+ What happens is that each strip on the control surface has
+ a corresponding route in ControlProtocol::route_table. When
+ an incoming midi message is signaled, the correct route
+ is looked up, and the relevant changes made to it.
+
+ For each route currently in route_table, there's a RouteSignal object
+ which encapsulates the signals that indicate that there are changes
+ to be sent to the surface. The signals are handled by this class.
+
+ Calls to signal handlers pass a Route object which is used to look
+ up the relevant Strip in Surface. Then the state is retrieved from
+ the Route and encoded as the correct midi message.
*/
-class MackieControlProtocol
-: public ARDOUR::ControlProtocol
-, public Mackie::MackieButtonHandler
+
+class MackieControlProtocol : public ARDOUR::ControlProtocol , public Mackie::MackieButtonHandler
{
public:
MackieControlProtocol( ARDOUR::Session & );
virtual ~MackieControlProtocol();
-
+
int set_active (bool yn);
XMLNode& get_state ();
Mackie::Surface & surface();
- // control events
- void handle_control_event( Mackie::SurfacePort & port, Mackie::Control & control, const Mackie::ControlState & state );
-
- // strip/route related stuff
+ // control events
+ void handle_control_event( Mackie::SurfacePort & port, Mackie::Control & control, const Mackie::ControlState & state );
+
+ // strip/route related stuff
public:
/// Signal handler for Route::solo
void notify_solo_changed( Mackie::RouteSignal * );
void notify_remote_id_changed();
/// rebuild the current bank. Called on route added/removed and
- /// remote id changed.
+ /// remote id changed.
void refresh_current_bank();
-
- // global buttons (ie button not part of strips)
+
+ // global buttons (ie button not part of strips)
public:
- // button-related signals
+ // button-related signals
void notify_record_state_changed();
- void notify_transport_state_changed();
- // mainly to pick up punch-in and punch-out
+ void notify_transport_state_changed();
+ // mainly to pick up punch-in and punch-out
void notify_parameter_changed( const char * );
- void notify_solo_active_changed( bool );
-
+ void notify_solo_active_changed( bool );
+
/// Turn smpte on and beats off, or vice versa, depending
/// on state of _timecode_type
void update_smpte_beats_led();
-
+
/// this is called to generate the midi to send in response to a button press.
void update_led( Mackie::Button & button, Mackie::LedState );
-
+
void update_global_button( const std::string & name, Mackie::LedState );
void update_global_led( const std::string & name, Mackie::LedState );
-
- // transport button handler methods from MackieButtonHandler
+
+ // transport button handler methods from MackieButtonHandler
virtual Mackie::LedState frm_left_press( Mackie::Button & );
virtual Mackie::LedState frm_left_release( Mackie::Button & );
-
+
virtual Mackie::LedState frm_right_press( Mackie::Button & );
virtual Mackie::LedState frm_right_release( Mackie::Button & );
-
+
virtual Mackie::LedState stop_press( Mackie::Button & );
virtual Mackie::LedState stop_release( Mackie::Button & );
virtual Mackie::LedState scrub_press( Mackie::Button & );
virtual Mackie::LedState scrub_release( Mackie::Button & );
- /// This is the main MCU port, ie not an extender port
+ /// This is the main MCU port, ie not an extender port
/// Only for use by JogWheel
const Mackie::SurfacePort & mcu_port() const;
Mackie::SurfacePort & mcu_port();
void initialize_surface();
// This sets up the notifications and sets the
- // controls to the correct values
+ // controls to the correct values
void update_surface();
-
- // connects global (not strip) signals from the Session to here
- // so the surface can be notified of changes from the other UIs.
- void connect_session_signals();
-
- // set all controls to their zero position
+
+ // connects global (not strip) signals from the Session to here
+ // so the surface can be notified of changes from the other UIs.
+ void connect_session_signals();
+
+ // disconnect all connections made in connect_session_signals ()
+ std::vector<sigc::connection> session_connections;
+ void disconnect_session_signals ();
+
+ // handle deletion of a route
+ std::vector<sigc::connection> route_connections;
+ void route_deleted ();
+
+ // set all controls to their zero position
void zero_all();
/**
- Fetch the set of routes to be considered for control by the
- surface. Excluding master, hidden and control routes, and inactive routes
+ Fetch the set of routes to be considered for control by the
+ surface. Excluding master, hidden and control routes, and inactive routes
*/
typedef std::vector<boost::shared_ptr<ARDOUR::Route> > Sorted;
Sorted get_sorted_routes();
-
- // bank switching
- void switch_banks( int initial );
- void prev_track();
- void next_track();
-
- // delete all RouteSignal objects connecting Routes to Strips
- void clear_route_signals();
- typedef std::vector<Mackie::RouteSignal*> RouteSignals;
+ // bank switching
+ void switch_banks( int initial );
+ void prev_track();
+ void next_track();
+
+ // delete all RouteSignal objects connecting Routes to Strips
+ void clear_route_signals();
+
+ typedef std::list<Mackie::RouteSignal*> RouteSignals;
RouteSignals route_signals;
- // return which of the ports a particular route_table
- // index belongs to
+ // return which of the ports a particular route_table
+ // index belongs to
Mackie::MackiePort & port_for_id( uint32_t index );
-
+
/**
- Handle a button press for the control and return whether
- the corresponding light should be on or off.
+ Handle a button press for the control and return whether
+ the corresponding light should be on or off.
*/
bool handle_strip_button( Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route> );
-
+
/// thread started. Calls monitor_work.
static void* _monitor_work (void* arg);
void add_port( MIDI::Port &, int number );
/**
- Read session data and send to surface. Includes
- automation from the currently active routes and
- timecode displays.
+ Read session data and send to surface. Includes
+ automation from the currently active routes and
+ timecode displays.
*/
void poll_session_data();
std::string format_smpte_timecode( nframes_t now_frame );
/**
- 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
- for new data.
+ 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
+ for new data.
*/
void handle_port_init( Mackie::SurfacePort * );
private:
boost::shared_ptr<Mackie::RouteSignal> master_route_signal;
- static const char * default_port_name;
+ static const char * default_port_name;
/// The Midi port(s) connected to the units
typedef vector<Mackie::MackiePort*> MackiePorts;
/// Sometimes the real port goes away, and we want to contain the breakage
Mackie::DummyPort _dummy_port;
- // the thread that polls the ports for incoming midi data
+ // the thread that polls the ports for incoming midi data
pthread_t thread;
/// The initial remote_id of the currently switched in bank.
- uint32_t _current_initial_bank;
+ uint32_t _current_initial_bank;
- /// protects the port list, and polling structures
+ /// protects the port list, and polling structures
Glib::Mutex update_mutex;
/// Protects set_active, and allows waiting on the poll thread
Glib::Cond update_cond;
- // because sigc::trackable doesn't seem to be working
- std::vector<sigc::connection> _connections;
- std::back_insert_iterator<std::vector<sigc::connection> > connections_back;
- /// The representation of the physical controls on the surface.
+ /// The representation of the physical controls on the surface.
Mackie::Surface * _surface;
/// If a port is opened or closed, this will be