2008-06-02 17:41:35 -04:00
/*
Copyright ( C ) 2006 , 2007 John Anderson
2012-04-21 22:15:24 -04:00
Copyright ( C ) 2012 Paul Davis
2008-06-02 17:41:35 -04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2009-12-20 11:49:55 -05:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2008-06-02 17:41:35 -04:00
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2010-07-07 19:47:31 -04:00
# include <fcntl.h>
2008-06-02 17:41:35 -04:00
# include <iostream>
# include <algorithm>
# include <cmath>
# include <sstream>
# include <vector>
2008-12-12 17:55:03 -05:00
# include <iomanip>
2008-06-02 17:41:35 -04:00
# include <inttypes.h>
# include <float.h>
# include <sys/time.h>
# include <errno.h>
# include <boost/shared_array.hpp>
2015-12-09 00:12:19 -05:00
# include <glibmm/miscutils.h>
2008-06-02 17:41:35 -04:00
2009-10-29 20:21:40 -04:00
# include "midi++/types.h"
# include "midi++/port.h"
2012-04-25 17:21:36 -04:00
# include "midi++/ipmidi_port.h"
2009-10-29 20:21:40 -04:00
# include "pbd/pthread_utils.h"
# include "pbd/error.h"
# include "pbd/memento_command.h"
# include "pbd/convert.h"
2015-10-18 22:55:56 -04:00
# include "ardour/audio_track.h"
2012-04-12 17:02:43 -04:00
# include "ardour/automation_control.h"
2014-11-23 10:37:13 -05:00
# include "ardour/async_midi_port.h"
2009-10-29 20:21:40 -04:00
# include "ardour/dB.h"
2009-12-20 11:49:55 -05:00
# include "ardour/debug.h"
# include "ardour/location.h"
2012-04-08 20:03:58 -04:00
# include "ardour/meter.h"
2015-10-18 21:13:16 -04:00
# include "ardour/midi_track.h"
2009-10-29 20:21:40 -04:00
# include "ardour/panner.h"
2011-01-26 20:31:03 -05:00
# include "ardour/panner_shell.h"
2015-12-10 09:17:05 -05:00
# include "ardour/profile.h"
2009-12-20 11:49:55 -05:00
# include "ardour/route.h"
2015-11-26 09:55:25 -05:00
# include "ardour/route_group.h"
2009-12-20 11:49:55 -05:00
# include "ardour/session.h"
2009-10-29 20:21:40 -04:00
# include "ardour/tempo.h"
2012-04-13 17:46:26 -04:00
# include "ardour/track.h"
2009-10-29 20:21:40 -04:00
# include "ardour/types.h"
2010-07-07 19:47:31 -04:00
# include "ardour/audioengine.h"
2008-06-02 17:41:35 -04:00
# include "mackie_control_protocol.h"
# include "midi_byte_array.h"
# include "mackie_control_exception.h"
2012-04-17 16:41:31 -04:00
# include "device_profile.h"
2008-06-02 17:41:35 -04:00
# include "surface_port.h"
# include "surface.h"
2012-04-09 09:59:35 -04:00
# include "strip.h"
# include "control_group.h"
# include "meter.h"
# include "button.h"
# include "fader.h"
# include "pot.h"
2008-06-02 17:41:35 -04:00
using namespace ARDOUR ;
using namespace std ;
using namespace PBD ;
2012-04-10 13:13:55 -04:00
using namespace Glib ;
2015-04-15 20:37:20 -04:00
using namespace ArdourSurface ;
using namespace Mackie ;
2008-06-02 17:41:35 -04:00
# include "i18n.h"
2011-10-20 07:56:21 -04:00
# include "pbd/abstract_ui.cc" // instantiate template
2012-04-09 13:48:16 -04:00
const int MackieControlProtocol : : MODIFIER_OPTION = 0x1 ;
const int MackieControlProtocol : : MODIFIER_CONTROL = 0x2 ;
2012-04-17 23:24:59 -04:00
const int MackieControlProtocol : : MODIFIER_SHIFT = 0x4 ;
const int MackieControlProtocol : : MODIFIER_CMDALT = 0x8 ;
2015-10-02 07:31:31 -04:00
const int MackieControlProtocol : : MODIFIER_ZOOM = 0x10 ;
const int MackieControlProtocol : : MODIFIER_SCRUB = 0x20 ;
const int MackieControlProtocol : : MAIN_MODIFIER_MASK = ( MackieControlProtocol : : MODIFIER_OPTION |
2015-10-07 13:17:42 -04:00
MackieControlProtocol : : MODIFIER_CONTROL |
MackieControlProtocol : : MODIFIER_SHIFT |
MackieControlProtocol : : MODIFIER_CMDALT ) ;
2012-04-09 13:48:16 -04:00
2012-04-10 13:13:55 -04:00
MackieControlProtocol * MackieControlProtocol : : _instance = 0 ;
2012-04-10 10:27:44 -04:00
bool MackieControlProtocol : : probe ( )
{
return true ;
}
2008-06-02 17:41:35 -04:00
MackieControlProtocol : : MackieControlProtocol ( Session & session )
2012-04-23 06:54:34 -04:00
: ControlProtocol ( session , X_ ( " Mackie " ) )
2015-12-28 10:14:17 -05:00
, AbstractUI < MackieControlUIRequest > ( name ( ) )
2009-12-20 11:49:55 -05:00
, _current_initial_bank ( 0 )
2015-12-11 15:57:24 -05:00
, _frame_last ( 0 )
2009-12-20 11:49:55 -05:00
, _timecode_type ( ARDOUR : : AnyTime : : BBT )
2011-05-04 05:22:11 -04:00
, _gui ( 0 )
2012-04-09 15:47:06 -04:00
, _scrub_mode ( false )
2013-08-24 11:45:31 -04:00
, _flip_mode ( Normal )
2012-04-12 17:02:43 -04:00
, _view_mode ( Mixer )
2015-12-11 11:05:57 -05:00
, _subview_mode ( None )
2015-10-08 00:36:16 -04:00
, _pot_mode ( Pan )
2012-04-09 12:15:55 -04:00
, _current_selected_track ( - 1 )
2012-04-13 13:06:35 -04:00
, _modifier_state ( 0 )
2012-04-25 17:21:36 -04:00
, _ipmidi_base ( MIDI : : IPMIDIPort : : lowest_ipmidi_port_default )
, needs_ipmidi_restart ( false )
2012-06-01 08:56:20 -04:00
, _metering_active ( true )
2012-06-06 08:20:57 -04:00
, _initialized ( false )
2015-10-13 07:33:20 -04:00
, configuration_state ( 0 )
, state_version ( 0 )
2009-12-20 11:49:55 -05:00
{
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::MackieControlProtocol \n " ) ;
2011-09-26 18:22:21 -04:00
2012-04-12 08:58:42 -04:00
DeviceInfo : : reload_device_info ( ) ;
2012-04-17 16:41:31 -04:00
DeviceProfile : : reload_device_profiles ( ) ;
2015-10-22 18:30:34 -04:00
for ( int i = 0 ; i < 9 ; i + + ) {
_last_bank [ i ] = 0 ;
}
_last_bank [ Mixer ] = _current_selected_track ;
2012-04-27 21:43:38 -04:00
TrackSelectionChanged . connect ( gui_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : gui_track_selection_changed , this , _1 , true ) , this ) ;
2012-04-12 10:34:03 -04:00
2012-04-10 13:13:55 -04:00
_instance = this ;
2012-04-10 23:13:19 -04:00
build_button_map ( ) ;
2008-06-02 17:41:35 -04:00
}
MackieControlProtocol : : ~ MackieControlProtocol ( )
{
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol init \n " ) ;
2015-10-02 21:57:12 -04:00
for ( Surfaces : : const_iterator si = surfaces . begin ( ) ; si ! = surfaces . end ( ) ; + + si ) {
( * si ) - > reset ( ) ;
}
2015-10-03 14:03:29 -04:00
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol drop_connections () \n " ) ;
2012-05-12 10:12:51 -04:00
drop_connections ( ) ;
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol tear_down_gui () \n " ) ;
2012-05-12 10:12:51 -04:00
tear_down_gui ( ) ;
2015-10-13 07:33:20 -04:00
delete configuration_state ;
2012-04-09 09:59:35 -04:00
2012-04-23 22:28:51 -04:00
/* stop event loop */
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol BaseUI::quit () \n " ) ;
2012-04-23 22:28:51 -04:00
BaseUI : : quit ( ) ;
2009-12-20 11:49:55 -05:00
try {
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol close() \n " ) ;
2008-06-02 17:41:35 -04:00
close ( ) ;
}
2009-12-20 11:49:55 -05:00
catch ( exception & e ) {
2008-06-02 17:41:35 -04:00
cout < < " ~MackieControlProtocol caught " < < e . what ( ) < < endl ;
}
2009-12-20 11:49:55 -05:00
catch ( . . . ) {
2008-06-02 17:41:35 -04:00
cout < < " ~MackieControlProtocol caught unknown " < < endl ;
}
2009-12-20 11:49:55 -05:00
2012-04-10 13:13:55 -04:00
_instance = 0 ;
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::~MackieControlProtocol done \n " ) ;
2008-06-02 17:41:35 -04:00
}
2012-04-09 12:26:44 -04:00
void
MackieControlProtocol : : thread_init ( )
{
2012-04-10 13:13:55 -04:00
struct sched_param rtparam ;
2015-12-28 10:14:17 -05:00
pthread_set_name ( event_loop_name ( ) . c_str ( ) ) ;
2012-04-10 13:13:55 -04:00
2015-12-28 10:14:17 -05:00
PBD : : notify_event_loops_about_thread_creation ( pthread_self ( ) , event_loop_name ( ) , 2048 ) ;
ARDOUR : : SessionEvent : : create_per_thread_pool ( event_loop_name ( ) , 128 ) ;
2012-04-10 13:13:55 -04:00
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.
}
2012-04-09 12:26:44 -04:00
}
2012-04-21 22:15:24 -04:00
void
2015-10-07 13:17:42 -04:00
MackieControlProtocol : : ping_devices ( )
2012-04-21 22:15:24 -04:00
{
2015-10-07 13:17:42 -04:00
/* should not be called if surfaces are not connected, but will not
* malfunction if it is .
*/
2013-03-06 15:15:28 -05:00
2015-10-07 13:17:42 -04:00
for ( Surfaces : : const_iterator si = surfaces . begin ( ) ; si ! = surfaces . end ( ) ; + + si ) {
( * si ) - > connected ( ) ;
2013-03-06 15:15:28 -05:00
}
2012-04-21 22:15:24 -04:00
}
2008-06-02 17:41:35 -04:00
// go to the previous track.
// Assume that get_sorted_routes().size() > route_table.size()
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : prev_track ( )
2008-06-02 17:41:35 -04:00
{
2009-12-20 11:49:55 -05:00
if ( _current_initial_bank > = 1 ) {
switch_banks ( _current_initial_bank - 1 ) ;
2008-06-02 17:41:35 -04:00
}
}
// go to the next track.
// Assume that get_sorted_routes().size() > route_table.size()
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : next_track ( )
2008-06-02 17:41:35 -04:00
{
Sorted sorted = get_sorted_routes ( ) ;
2012-04-10 10:27:44 -04:00
if ( _current_initial_bank + n_strips ( ) < sorted . size ( ) ) {
2009-12-20 11:49:55 -05:00
switch_banks ( _current_initial_bank + 1 ) ;
2008-06-02 17:41:35 -04:00
}
}
2012-04-26 10:28:41 -04:00
bool
MackieControlProtocol : : route_is_locked_to_strip ( boost : : shared_ptr < Route > r ) const
{
for ( Surfaces : : const_iterator si = surfaces . begin ( ) ; si ! = surfaces . end ( ) ; + + si ) {
if ( ( * si ) - > route_is_locked_to_strip ( r ) ) {
return true ;
}
}
return false ;
}
2008-06-02 17:41:35 -04:00
// predicate for sort call in get_sorted_routes
struct RouteByRemoteId
{
2010-11-29 17:39:21 -05:00
bool operator ( ) ( const boost : : shared_ptr < Route > & a , const boost : : shared_ptr < Route > & b ) const
2008-06-02 17:41:35 -04:00
{
return a - > remote_control_id ( ) < b - > remote_control_id ( ) ;
}
2009-12-20 11:49:55 -05:00
bool operator ( ) ( const Route & a , const Route & b ) const
2008-06-02 17:41:35 -04:00
{
return a . remote_control_id ( ) < b . remote_control_id ( ) ;
}
2009-12-20 11:49:55 -05:00
bool operator ( ) ( const Route * a , const Route * b ) const
2008-06-02 17:41:35 -04:00
{
return a - > remote_control_id ( ) < b - > remote_control_id ( ) ;
}
} ;
2015-10-03 14:03:29 -04:00
MackieControlProtocol : : Sorted
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : get_sorted_routes ( )
2008-06-02 17:41:35 -04:00
{
Sorted sorted ;
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// fetch all routes
2009-01-30 02:40:13 -05:00
boost : : shared_ptr < RouteList > routes = session - > get_routes ( ) ;
2008-06-02 17:41:35 -04:00
set < uint32_t > remote_ids ;
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// routes with remote_id 0 should never be added
// TODO verify this with ardour devs
2009-12-20 11:49:55 -05:00
// remote_ids.insert (0);
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// sort in remote_id order, and exclude master, control and hidden routes
// and any routes that are already set.
2012-04-11 15:16:49 -04:00
2011-09-26 18:32:24 -04:00
for ( RouteList : : iterator it = routes - > begin ( ) ; it ! = routes - > end ( ) ; + + it ) {
2012-04-11 15:16:49 -04:00
2012-04-26 10:28:41 -04:00
boost : : shared_ptr < Route > route = * it ;
2012-04-11 15:16:49 -04:00
2012-04-26 10:28:41 -04:00
if ( remote_ids . find ( route - > remote_control_id ( ) ) ! = remote_ids . end ( ) ) {
2012-04-11 15:16:49 -04:00
continue ;
}
2013-04-06 16:04:02 -04:00
if ( route - > is_auditioner ( ) | | route - > is_master ( ) | | route - > is_monitor ( ) ) {
2012-04-26 10:28:41 -04:00
continue ;
}
/* don't include locked routes */
if ( route_is_locked_to_strip ( route ) ) {
2012-04-11 15:16:49 -04:00
continue ;
}
2015-10-13 15:34:53 -04:00
2012-04-11 15:16:49 -04:00
switch ( _view_mode ) {
2012-04-12 17:02:43 -04:00
case Mixer :
2015-11-26 09:55:25 -05:00
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
2016-01-15 16:16:24 -05:00
if ( ! is_hidden ( route ) ) {
sorted . push_back ( route ) ;
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
2012-04-11 15:16:49 -04:00
break ;
case AudioTracks :
2016-01-16 10:32:30 -05:00
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
2016-01-15 16:16:24 -05:00
if ( is_audio_track ( route ) & & ! is_hidden ( route ) ) {
2015-11-26 09:55:25 -05:00
sorted . push_back ( route ) ;
2015-10-18 22:55:56 -04:00
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
2012-04-11 15:16:49 -04:00
break ;
case Busses :
2016-01-16 10:32:30 -05:00
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
2015-12-10 09:17:05 -05:00
if ( Profile - > get_mixbus ( ) ) {
2015-12-16 06:31:06 -05:00
# ifdef MIXBUS
2015-12-10 09:17:05 -05:00
if ( route - > mixbus ( ) ) {
sorted . push_back ( route ) ;
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
2015-12-16 06:31:06 -05:00
# endif
2015-12-10 09:17:05 -05:00
} else {
2016-01-15 16:16:24 -05:00
if ( ! is_track ( route ) & & ! is_hidden ( route ) ) {
2015-12-10 09:17:05 -05:00
sorted . push_back ( route ) ;
remote_ids . insert ( route - > remote_control_id ( ) ) ;
2015-11-26 09:55:25 -05:00
}
2015-10-18 22:55:56 -04:00
}
2012-04-11 15:16:49 -04:00
break ;
2015-11-26 09:55:25 -05:00
case MidiTracks :
2016-01-16 10:32:30 -05:00
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
2016-01-15 16:16:24 -05:00
if ( is_midi_track ( route ) & & ! is_hidden ( route ) ) {
2015-11-26 09:55:25 -05:00
sorted . push_back ( route ) ;
2015-10-18 21:13:16 -04:00
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
2012-04-11 15:16:49 -04:00
break ;
2015-10-13 15:34:53 -04:00
case Plugins :
break ;
2015-12-10 09:17:05 -05:00
case Auxes : // in ardour, for now aux and buss are same. for mixbus, see "Busses" case above
2016-01-16 10:32:30 -05:00
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
2016-01-15 16:16:24 -05:00
if ( ! is_track ( route ) & & ! is_hidden ( route ) ) {
2016-01-16 10:32:30 -05:00
sorted . push_back ( route ) ;
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
break ;
case Hidden : // Show all the tracks we have hidden
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( true , this ) ;
}
if ( is_hidden ( route ) ) {
// maybe separate groups
2015-11-26 09:55:25 -05:00
sorted . push_back ( route ) ;
2015-10-20 21:54:56 -04:00
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
break ;
2016-01-15 16:16:24 -05:00
case Selected : // For example: a group (this is USER)
if ( selected ( route ) & & ! is_hidden ( route ) ) {
2015-11-26 09:55:25 -05:00
/* Selected may be a group in which case we want to
* control each track separately .
*/
if ( route - > route_group ( ) ) {
route - > route_group ( ) - > set_active ( false , this ) ;
}
sorted . push_back ( route ) ;
2015-10-20 21:54:56 -04:00
remote_ids . insert ( route - > remote_control_id ( ) ) ;
}
2012-04-11 15:16:49 -04:00
break ;
2008-06-02 17:41:35 -04:00
}
2012-04-11 15:16:49 -04:00
2008-06-02 17:41:35 -04:00
}
2012-04-11 15:16:49 -04:00
2009-12-20 11:49:55 -05:00
sort ( sorted . begin ( ) , sorted . end ( ) , RouteByRemoteId ( ) ) ;
2008-06-02 17:41:35 -04:00
return sorted ;
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : refresh_current_bank ( )
2008-06-02 17:41:35 -04:00
{
2012-04-10 10:27:44 -04:00
switch_banks ( _current_initial_bank , true ) ;
}
uint32_t
2012-04-26 10:28:41 -04:00
MackieControlProtocol : : n_strips ( bool with_locked_strips ) const
2012-04-10 10:27:44 -04:00
{
uint32_t strip_count = 0 ;
for ( Surfaces : : const_iterator si = surfaces . begin ( ) ; si ! = surfaces . end ( ) ; + + si ) {
2012-04-26 10:28:41 -04:00
strip_count + = ( * si ) - > n_strips ( with_locked_strips ) ;
2012-04-10 10:27:44 -04:00
}
return strip_count ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2012-04-10 10:27:44 -04:00
MackieControlProtocol : : switch_banks ( uint32_t initial , bool force )
2008-06-02 17:41:35 -04:00
{
2012-04-10 11:13:37 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " switch banking to start at %1 force ? %2 current = %3 \n " , initial , force , _current_initial_bank ) ) ;
2012-04-10 10:27:44 -04:00
if ( initial = = _current_initial_bank & & ! force ) {
return ;
}
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
Sorted sorted = get_sorted_routes ( ) ;
2012-04-26 10:28:41 -04:00
uint32_t strip_cnt = n_strips ( false ) ; // do not include locked strips
// in this count
2012-04-10 10:27:44 -04:00
2012-04-27 16:35:45 -04:00
if ( sorted . size ( ) < = strip_cnt & & _current_initial_bank = = 0 & & ! force ) {
/* no banking - not enough routes to fill all strips and we're
* not at the first one .
*/
2012-04-10 10:27:44 -04:00
return ;
}
2012-04-08 16:44:36 -04:00
_current_initial_bank = initial ;
2012-04-09 12:15:55 -04:00
_current_selected_track = - 1 ;
2012-04-10 10:27:44 -04:00
// Map current bank of routes onto each surface(+strip)
2009-12-20 11:49:55 -05:00
2012-04-10 10:27:44 -04:00
if ( _current_initial_bank < = sorted . size ( ) ) {
2009-10-20 20:15:42 -04:00
2015-10-03 14:03:29 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " switch to %1, %2, available routes %3 on %4 surfaces \n " ,
2014-02-19 12:50:28 -05:00
_current_initial_bank , strip_cnt , sorted . size ( ) ,
surfaces . size ( ) ) ) ;
2011-05-23 06:03:14 -04:00
2008-06-02 17:41:35 -04:00
// link routes to strips
2012-04-08 16:44:36 -04:00
2012-04-10 11:13:37 -04:00
Sorted : : iterator r = sorted . begin ( ) + _current_initial_bank ;
2015-10-03 14:03:29 -04:00
2012-04-10 11:13:37 -04:00
for ( Surfaces : : iterator si = surfaces . begin ( ) ; si ! = surfaces . end ( ) ; + + si ) {
vector < boost : : shared_ptr < Route > > routes ;
uint32_t added = 0 ;
2009-10-20 20:15:42 -04:00
2012-04-26 10:28:41 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " surface has %1 unlockedstrips \n " , ( * si ) - > n_strips ( false ) ) ) ;
2009-10-20 20:15:42 -04:00
2012-04-26 10:28:41 -04:00
for ( ; r ! = sorted . end ( ) & & added < ( * si ) - > n_strips ( false ) ; + + r , + + added ) {
2012-04-10 11:13:37 -04:00
routes . push_back ( * r ) ;
2012-04-10 10:27:44 -04:00
}
2008-06-02 17:41:35 -04:00
2012-04-10 11:13:37 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " give surface %1 routes \n " , routes . size ( ) ) ) ;
2009-10-20 20:15:42 -04:00
2012-04-10 11:13:37 -04:00
( * si ) - > map_routes ( routes ) ;
2008-06-02 17:41:35 -04:00
}
}
2008-12-12 17:55:03 -05:00
2012-04-26 17:22:36 -04:00
/* make sure selection is correct */
2015-10-03 14:03:29 -04:00
2015-12-14 22:22:34 -05:00
_gui_track_selection_changed ( & _last_selected_routes , false , false ) ;
2015-10-03 14:03:29 -04:00
2012-04-11 16:48:51 -04:00
/* current bank has not been saved */
session - > set_dirty ( ) ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
int
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : set_active ( bool yn )
2008-06-02 17:41:35 -04:00
{
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " MackieControlProtocol::set_active init with yn: '%1' \n " , yn ) ) ;
2013-12-21 15:30:07 -05:00
if ( yn = = active ( ) ) {
2011-09-26 18:32:24 -04:00
return 0 ;
}
2012-04-08 19:14:36 -04:00
2012-04-25 17:21:36 -04:00
if ( yn ) {
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
/* start event loop */
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
BaseUI : : run ( ) ;
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
connect_session_signals ( ) ;
2015-10-10 17:13:04 -04:00
if ( ! _device_info . name ( ) . empty ( ) ) {
set_device ( _device_info . name ( ) , true ) ;
}
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
/* set up periodic task for metering and automation
*/
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
Glib : : RefPtr < Glib : : TimeoutSource > periodic_timeout = Glib : : TimeoutSource : : create ( 100 ) ; // milliseconds
periodic_connection = periodic_timeout - > connect ( sigc : : mem_fun ( * this , & MackieControlProtocol : : periodic ) ) ;
periodic_timeout - > attach ( main_loop ( ) - > get_context ( ) ) ;
2015-10-02 22:03:17 -04:00
/* a faster periodic task used to display parameter updates */
2015-10-03 14:03:29 -04:00
2015-10-02 22:03:17 -04:00
Glib : : RefPtr < Glib : : TimeoutSource > redisplay_timeout = Glib : : TimeoutSource : : create ( 10 ) ; // milliseconds
redisplay_connection = redisplay_timeout - > connect ( sigc : : mem_fun ( * this , & MackieControlProtocol : : redisplay ) ) ;
redisplay_timeout - > attach ( main_loop ( ) - > get_context ( ) ) ;
2012-04-25 17:21:36 -04:00
} else {
2012-04-08 20:03:58 -04:00
2012-04-25 17:21:36 -04:00
BaseUI : : quit ( ) ;
close ( ) ;
2011-09-26 18:32:24 -04:00
}
2008-06-02 17:41:35 -04:00
2013-12-21 15:30:07 -05:00
ControlProtocol : : set_active ( yn ) ;
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " MackieControlProtocol::set_active done with yn: '%1' \n " , yn ) ) ;
2008-06-02 17:41:35 -04:00
return 0 ;
}
2015-10-03 12:03:07 -04:00
bool
MackieControlProtocol : : hui_heartbeat ( )
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > hui_heartbeat ( ) ;
}
return true ;
}
2015-10-03 14:03:29 -04:00
2012-04-08 20:03:58 -04:00
bool
2012-04-09 09:59:35 -04:00
MackieControlProtocol : : periodic ( )
2012-04-08 20:03:58 -04:00
{
2013-12-21 15:30:07 -05:00
if ( ! active ( ) ) {
2012-04-09 09:59:35 -04:00
return false ;
}
2012-04-08 20:32:13 -04:00
2012-04-25 17:21:36 -04:00
if ( needs_ipmidi_restart ) {
ipmidi_restart ( ) ;
return true ;
}
2015-10-03 14:03:29 -04:00
2012-06-06 08:20:57 -04:00
if ( ! _initialized ) {
initialize ( ) ;
}
2012-04-25 17:21:36 -04:00
2015-10-08 12:49:58 -04:00
ARDOUR : : microseconds_t now_usecs = ARDOUR : : get_microseconds ( ) ;
2012-04-13 12:11:55 -04:00
2012-12-31 11:04:46 -05:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > periodic ( now_usecs ) ;
}
2012-04-08 20:03:58 -04:00
}
2012-04-18 14:27:06 -04:00
update_timecode_display ( ) ;
2015-10-03 14:03:29 -04:00
2012-04-09 09:59:35 -04:00
return true ;
2012-04-08 20:03:58 -04:00
}
2015-10-02 22:03:17 -04:00
bool
MackieControlProtocol : : redisplay ( )
{
if ( ! active ( ) ) {
return false ;
}
if ( needs_ipmidi_restart ) {
ipmidi_restart ( ) ;
return true ;
}
if ( ! _initialized ) {
initialize ( ) ;
}
2015-10-08 12:49:58 -04:00
ARDOUR : : microseconds_t now = ARDOUR : : get_microseconds ( ) ;
2015-10-02 22:03:17 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
2015-10-08 12:49:58 -04:00
( * s ) - > redisplay ( now ) ;
2015-10-02 22:03:17 -04:00
}
}
return true ;
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : update_timecode_beats_led ( )
2008-12-12 17:55:03 -05:00
{
2012-06-09 15:06:52 -04:00
if ( ! _device_info . has_timecode_display ( ) ) {
return ;
}
2012-06-06 08:20:57 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " MackieControlProtocol::update_timecode_beats_led(): %1 \n " , _timecode_type ) ) ;
2011-09-26 18:32:24 -04:00
switch ( _timecode_type ) {
2008-12-12 17:55:03 -05:00
case ARDOUR : : AnyTime : : BBT :
2012-04-14 15:02:54 -04:00
update_global_led ( Led : : Beats , on ) ;
update_global_led ( Led : : Timecode , off ) ;
2008-12-12 17:55:03 -05:00
break ;
2009-10-26 10:38:58 -04:00
case ARDOUR : : AnyTime : : Timecode :
2012-04-14 15:02:54 -04:00
update_global_led ( Led : : Timecode , on ) ;
update_global_led ( Led : : Beats , off ) ;
2008-12-12 17:55:03 -05:00
break ;
default :
ostringstream os ;
os < < " Unknown Anytime::Type " < < _timecode_type ;
2009-12-20 11:49:55 -05:00
throw runtime_error ( os . str ( ) ) ;
2008-06-02 17:41:35 -04:00
}
}
2015-10-03 14:03:29 -04:00
void
2012-04-14 15:02:54 -04:00
MackieControlProtocol : : update_global_button ( int id , LedState ls )
2008-06-02 17:41:35 -04:00
{
2015-10-13 15:34:53 -04:00
boost : : shared_ptr < Surface > surface ;
2012-12-31 11:04:46 -05:00
2015-10-13 15:34:53 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-10 17:13:04 -04:00
2015-10-13 15:34:53 -04:00
if ( surfaces . empty ( ) ) {
return ;
}
if ( ! _device_info . has_global_controls ( ) ) {
return ;
}
// surface needs to be master surface
surface = _master_surface ;
2012-04-10 10:27:44 -04:00
}
2012-06-09 15:06:52 -04:00
2012-04-14 15:02:54 -04:00
map < int , Control * > : : iterator x = surface - > controls_by_device_independent_id . find ( id ) ;
if ( x ! = surface - > controls_by_device_independent_id . end ( ) ) {
Button * button = dynamic_cast < Button * > ( x - > second ) ;
2012-04-11 15:47:41 -04:00
surface - > write ( button - > set_state ( ls ) ) ;
2011-09-26 18:32:24 -04:00
} else {
2012-04-14 15:02:54 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Button %1 not found \n " , id ) ) ;
2008-12-12 17:55:03 -05:00
}
}
2015-10-03 14:03:29 -04:00
void
2012-04-14 15:02:54 -04:00
MackieControlProtocol : : update_global_led ( int id , LedState ls )
2008-12-12 17:55:03 -05:00
{
2012-12-31 11:04:46 -05:00
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-10 17:13:04 -04:00
if ( surfaces . empty ( ) ) {
return ;
}
2012-06-09 15:06:52 -04:00
if ( ! _device_info . has_global_controls ( ) ) {
2012-04-10 10:27:44 -04:00
return ;
}
2015-08-13 16:00:04 -04:00
boost : : shared_ptr < Surface > surface = _master_surface ;
2012-06-09 15:06:52 -04:00
2012-04-14 15:02:54 -04:00
map < int , Control * > : : iterator x = surface - > controls_by_device_independent_id . find ( id ) ;
2012-06-09 15:06:52 -04:00
2012-04-14 15:02:54 -04:00
if ( x ! = surface - > controls_by_device_independent_id . end ( ) ) {
Led * led = dynamic_cast < Led * > ( x - > second ) ;
2012-06-06 08:20:57 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " Writing LedState \n " ) ;
2012-04-11 00:02:46 -04:00
surface - > write ( led - > set_state ( ls ) ) ;
2011-09-26 18:32:24 -04:00
} else {
2012-04-14 15:02:54 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Led %1 not found \n " , id ) ) ;
2008-12-12 17:55:03 -05:00
}
2008-06-02 17:41:35 -04:00
}
2014-02-19 12:50:28 -05:00
void
MackieControlProtocol : : device_ready ( )
{
/* this is not required to be called, but for devices which do
* handshaking , it can be called once the device has verified the
* connection .
*/
2015-10-03 14:03:29 -04:00
2014-02-19 12:50:28 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " device ready init (active=%1) \n " , active ( ) ) ) ;
update_surfaces ( ) ;
2015-11-06 22:28:24 -05:00
set_pot_mode ( _pot_mode ) ;
2014-02-19 12:50:28 -05:00
}
2008-06-02 17:41:35 -04:00
// send messages to surface to set controls to correct values
2015-10-03 14:03:29 -04:00
void
2012-04-10 10:27:44 -04:00
MackieControlProtocol : : update_surfaces ( )
2008-06-02 17:41:35 -04:00
{
2014-02-19 12:50:28 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " MackieControlProtocol::update_surfaces() init (active=%1) \n " , active ( ) ) ) ;
2013-12-21 15:30:07 -05:00
if ( ! active ( ) ) {
2011-09-26 18:32:24 -04:00
return ;
}
2009-10-20 20:15:42 -04:00
2011-09-26 18:32:24 -04:00
// do the initial bank switch to connect signals
// _current_initial_bank is initialised by set_state
2012-04-10 10:27:44 -04:00
switch_banks ( _current_initial_bank , true ) ;
2015-10-03 14:03:29 -04:00
2012-06-06 08:20:57 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::update_surfaces() finished \n " ) ;
}
void
MackieControlProtocol : : initialize ( )
{
2013-03-06 15:15:28 -05:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-03 14:03:29 -04:00
2013-03-06 15:15:28 -05:00
if ( surfaces . empty ( ) ) {
return ;
}
2015-10-03 14:03:29 -04:00
2015-09-08 23:47:16 -04:00
if ( ! _master_surface - > active ( ) ) {
2013-03-06 15:15:28 -05:00
return ;
}
2015-10-03 14:03:29 -04:00
2013-03-06 15:15:28 -05:00
// sometimes the jog wheel is a pot
if ( _device_info . has_jog_wheel ( ) ) {
2015-09-08 23:47:16 -04:00
_master_surface - > blank_jog_ring ( ) ;
2013-03-06 15:15:28 -05:00
}
2012-06-06 08:20:57 -04:00
}
2012-06-09 15:06:52 -04:00
2011-09-26 18:32:24 -04:00
// update global buttons and displays
2012-04-10 10:27:44 -04:00
2011-09-26 18:32:24 -04:00
notify_record_state_changed ( ) ;
notify_transport_state_changed ( ) ;
update_timecode_beats_led ( ) ;
2015-10-03 14:03:29 -04:00
2012-06-06 08:20:57 -04:00
_initialized = true ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : connect_session_signals ( )
2008-06-02 17:41:35 -04:00
{
// receive routes added
2012-04-25 00:42:01 -04:00
session - > RouteAdded . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_route_added , this , _1 ) , this ) ;
2015-12-13 08:33:02 -05:00
session - > RouteAddedOrRemoved . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_route_added_or_removed , this ) , this ) ;
2008-06-02 17:41:35 -04:00
// receive record state toggled
2012-04-25 00:42:01 -04:00
session - > RecordStateChanged . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_record_state_changed , this ) , this ) ;
2008-06-02 17:41:35 -04:00
// receive transport state changed
2012-04-25 00:42:01 -04:00
session - > TransportStateChange . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_transport_state_changed , this ) , this ) ;
session - > TransportLooped . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_loop_state_changed , this ) , this ) ;
2008-06-02 17:41:35 -04:00
// receive punch-in and punch-out
2012-04-25 00:42:01 -04:00
Config - > ParameterChanged . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_parameter_changed , this , _1 ) , this ) ;
session - > config . ParameterChanged . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_parameter_changed , this , _1 ) , this ) ;
2008-06-02 17:41:35 -04:00
// receive rude solo changed
2012-04-25 00:42:01 -04:00
session - > SoloActive . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_solo_active_changed , this , _1 ) , this ) ;
2016-01-15 19:19:15 -05:00
// need to know if group parameters change... might be hidden.
session - > RouteGroupPropertyChanged . connect ( session_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_remote_id_changed , this ) , this ) ;
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// make sure remote id changed signals reach here
// see also notify_route_added
Sorted sorted = get_sorted_routes ( ) ;
2009-12-20 11:49:55 -05:00
for ( Sorted : : iterator it = sorted . begin ( ) ; it ! = sorted . end ( ) ; + + it ) {
2012-04-25 00:42:01 -04:00
( * it ) - > RemoteControlIDChanged . connect ( route_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_remote_id_changed , this ) , this ) ;
2008-06-02 17:41:35 -04:00
}
}
2012-04-17 16:41:31 -04:00
void
MackieControlProtocol : : set_profile ( const string & profile_name )
{
map < string , DeviceProfile > : : iterator d = DeviceProfile : : device_profiles . find ( profile_name ) ;
if ( d = = DeviceProfile : : device_profiles . end ( ) ) {
2015-12-09 00:12:19 -05:00
_device_profile = DeviceProfile ( profile_name ) ;
2012-04-17 16:41:31 -04:00
return ;
}
2015-10-03 14:03:29 -04:00
2012-04-17 16:41:31 -04:00
_device_profile = d - > second ;
2015-10-03 14:03:29 -04:00
}
2012-04-17 16:41:31 -04:00
2013-09-06 10:39:14 -04:00
int
2013-12-21 15:30:07 -05:00
MackieControlProtocol : : set_device_info ( const string & device_name )
2012-04-12 12:41:07 -04:00
{
map < string , DeviceInfo > : : iterator d = DeviceInfo : : device_info . find ( device_name ) ;
2013-12-21 15:30:07 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " new device chosen %1 \n " , device_name ) ) ;
2012-12-31 11:04:46 -05:00
2012-04-12 12:41:07 -04:00
if ( d = = DeviceInfo : : device_info . end ( ) ) {
2013-09-06 10:39:14 -04:00
return - 1 ;
2012-04-12 12:41:07 -04:00
}
2015-10-03 14:03:29 -04:00
2013-12-21 15:30:07 -05:00
_device_info = d - > second ;
return 0 ;
}
int
2015-10-09 14:01:22 -04:00
MackieControlProtocol : : set_device ( const string & device_name , bool force )
2013-12-21 15:30:07 -05:00
{
2015-10-09 14:01:22 -04:00
if ( device_name = = device_info ( ) . name ( ) & & ! force ) {
2015-10-08 21:23:48 -04:00
/* already using that device, nothing to do */
return 0 ;
}
2015-10-11 11:58:00 -04:00
/* get state from the current setup, and make sure it is stored in
2015-10-13 07:33:20 -04:00
the configuration_states node so that if we switch back to this device ,
2015-10-11 11:58:00 -04:00
we will have its state available .
*/
2015-10-13 15:34:53 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
if ( ! surfaces . empty ( ) ) {
update_configuration_state ( ) ;
}
}
2015-10-11 11:58:00 -04:00
2013-12-21 15:30:07 -05:00
if ( set_device_info ( device_name ) ) {
return - 1 ;
2012-04-25 00:42:01 -04:00
}
2013-12-21 15:30:07 -05:00
clear_surfaces ( ) ;
2015-10-09 14:01:22 -04:00
port_connection . disconnect ( ) ;
2015-10-05 12:23:51 -04:00
hui_connection . disconnect ( ) ;
if ( _device_info . device_type ( ) = = DeviceInfo : : HUI ) {
Glib : : RefPtr < Glib : : TimeoutSource > hui_timeout = Glib : : TimeoutSource : : create ( 1000 ) ; // milliseconds
hui_connection = hui_timeout - > connect ( sigc : : mem_fun ( * this , & MackieControlProtocol : : hui_heartbeat ) ) ;
hui_timeout - > attach ( main_loop ( ) - > get_context ( ) ) ;
}
2012-04-12 12:41:07 -04:00
2015-10-09 14:01:22 -04:00
if ( ! _device_info . uses_ipmidi ( ) ) {
2015-10-10 17:13:04 -04:00
/* notice that the handler for this will execute in our event
loop , not in the thread where the
PortConnectedOrDisconnected signal is emitted .
*/
2015-10-09 14:01:22 -04:00
ARDOUR : : AudioEngine : : instance ( ) - > PortConnectedOrDisconnected . connect ( port_connection , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : connection_handler , this , _1 , _2 , _3 , _4 , _5 ) , this ) ;
}
2015-10-10 17:13:04 -04:00
if ( create_surfaces ( ) ) {
return - 1 ;
}
2013-12-21 15:30:07 -05:00
2015-10-08 21:53:05 -04:00
DeviceChanged ( ) ;
2015-10-08 21:23:48 -04:00
2013-09-06 10:39:14 -04:00
return 0 ;
2012-04-12 12:41:07 -04:00
}
2015-10-03 14:03:29 -04:00
gboolean
2015-04-15 20:37:20 -04:00
ArdourSurface : : ipmidi_input_handler ( GIOChannel * , GIOCondition condition , void * data )
2014-12-03 20:57:58 -05:00
{
2015-04-15 20:37:20 -04:00
ArdourSurface : : MackieControlProtocol : : ipMIDIHandler * ipm = static_cast < ArdourSurface : : MackieControlProtocol : : ipMIDIHandler * > ( data ) ;
2015-10-07 13:17:42 -04:00
return ipm - > mcp - > midi_input_handler ( Glib : : IOCondition ( condition ) , ipm - > port ) ;
2014-12-03 20:57:58 -05:00
}
2013-09-06 10:39:14 -04:00
int
2012-04-10 10:27:44 -04:00
MackieControlProtocol : : create_surfaces ( )
2008-06-02 17:41:35 -04:00
{
2012-04-12 14:16:16 -04:00
string device_name ;
2015-08-13 16:00:04 -04:00
surface_type_t stype = mcu ; // type not yet determined
2008-06-02 17:41:35 -04:00
2015-10-10 17:13:04 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Create %1 surfaces for %2 \n " , 1 + _device_info . extenders ( ) , _device_info . name ( ) ) ) ;
2008-06-02 17:41:35 -04:00
2015-10-11 11:58:00 -04:00
if ( ! _device_info . uses_ipmidi ( ) ) {
_input_bundle . reset ( new ARDOUR : : Bundle ( _ ( " Mackie Control In " ) , true ) ) ;
_output_bundle . reset ( new ARDOUR : : Bundle ( _ ( " Mackie Control Out " ) , false ) ) ;
} else {
_input_bundle . reset ( ) ;
_output_bundle . reset ( ) ;
}
2012-04-12 12:41:07 -04:00
for ( uint32_t n = 0 ; n < 1 + _device_info . extenders ( ) ; + + n ) {
2015-10-11 11:58:00 -04:00
bool is_master = false ;
2015-10-12 00:37:04 -04:00
if ( n = = _device_info . master_position ( ) ) {
2015-10-11 11:58:00 -04:00
is_master = true ;
if ( _device_info . extenders ( ) = = 0 ) {
device_name = _device_info . name ( ) ;
} else {
device_name = X_ ( " mackie control " ) ;
}
2009-10-20 20:15:42 -04:00
2015-10-11 11:58:00 -04:00
}
if ( ! is_master ) {
device_name = string_compose ( X_ ( " mackie control ext %1 " ) , n + 1 ) ;
2015-10-10 17:13:04 -04:00
}
2015-10-13 07:33:20 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Port Name for surface %1 is %2 \n " , n , device_name ) ) ;
2015-10-10 17:13:04 -04:00
2013-09-06 10:39:14 -04:00
boost : : shared_ptr < Surface > surface ;
2015-10-12 00:37:04 -04:00
if ( is_master ) {
2015-08-13 16:00:04 -04:00
stype = mcu ;
} else {
stype = ext ;
}
2013-09-06 10:39:14 -04:00
try {
surface . reset ( new Surface ( * this , device_name , n , stype ) ) ;
} catch ( . . . ) {
return - 1 ;
}
2012-12-31 11:04:46 -05:00
2015-10-11 11:58:00 -04:00
if ( is_master ) {
2015-08-13 16:00:04 -04:00
_master_surface = surface ;
}
2015-10-13 07:33:20 -04:00
if ( configuration_state ) {
XMLNode * this_device = 0 ;
XMLNodeList const & devices = configuration_state - > children ( ) ;
for ( XMLNodeList : : const_iterator d = devices . begin ( ) ; d ! = devices . end ( ) ; + + d ) {
XMLProperty * prop = ( * d ) - > property ( X_ ( " name " ) ) ;
2015-10-14 01:19:36 -04:00
if ( prop & & prop - > value ( ) = = _device_info . name ( ) ) {
2015-10-13 07:33:20 -04:00
this_device = * d ;
break ;
}
}
if ( this_device ) {
2015-10-13 15:34:53 -04:00
XMLNode * snode = this_device - > child ( X_ ( " Surfaces " ) ) ;
if ( snode ) {
surface - > set_state ( * snode , state_version ) ;
2015-10-13 07:33:20 -04:00
}
}
2013-12-14 10:35:18 -05:00
}
2013-12-13 16:00:08 -05:00
2012-12-31 11:04:46 -05:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
surfaces . push_back ( surface ) ;
}
2015-10-03 14:03:29 -04:00
2012-04-23 22:28:51 -04:00
if ( ! _device_info . uses_ipmidi ( ) ) {
2013-12-21 15:30:07 -05:00
2012-04-23 22:28:51 -04:00
_input_bundle - > add_channel (
surface - > port ( ) . input_port ( ) . name ( ) ,
ARDOUR : : DataType : : MIDI ,
session - > engine ( ) . make_port_name_non_relative ( surface - > port ( ) . input_port ( ) . name ( ) )
) ;
2015-10-03 14:03:29 -04:00
2012-04-23 22:28:51 -04:00
_output_bundle - > add_channel (
surface - > port ( ) . output_port ( ) . name ( ) ,
ARDOUR : : DataType : : MIDI ,
session - > engine ( ) . make_port_name_non_relative ( surface - > port ( ) . output_port ( ) . name ( ) )
) ;
}
2012-04-10 13:13:55 -04:00
MIDI : : Port & input_port ( surface - > port ( ) . input_port ( ) ) ;
2014-11-23 10:37:13 -05:00
AsyncMIDIPort * asp = dynamic_cast < AsyncMIDIPort * > ( & input_port ) ;
2014-12-03 20:57:58 -05:00
2014-11-23 10:37:13 -05:00
if ( asp ) {
/* async MIDI port */
2014-12-03 20:57:58 -05:00
asp - > xthread ( ) . set_receive_handler ( sigc : : bind ( sigc : : mem_fun ( this , & MackieControlProtocol : : midi_input_handler ) , & input_port ) ) ;
asp - > xthread ( ) . attach ( main_loop ( ) - > get_context ( ) ) ;
2014-11-23 10:37:13 -05:00
} else {
/* ipMIDI port, no IOSource method at this time */
2012-04-23 22:28:51 -04:00
2014-11-23 10:37:13 -05:00
int fd ;
if ( ( fd = input_port . selectable ( ) ) > = 0 ) {
2015-10-08 21:53:05 -04:00
GIOChannel * ioc = g_io_channel_unix_new ( fd ) ;
surface - > input_source = g_io_create_watch ( ioc , GIOCondition ( G_IO_IN | G_IO_HUP | G_IO_ERR ) ) ;
/* make surface's input source now hold the
* only reference on the IO channel
*/
g_io_channel_unref ( ioc ) ;
2015-10-03 14:03:29 -04:00
2015-10-07 13:17:42 -04:00
/* hack up an object so that in the callback from the event loop
we have both the MackieControlProtocol and the input port .
2015-10-03 14:03:29 -04:00
2015-10-07 13:17:42 -04:00
If we were using C + + for this stuff we wouldn ' t need this
but a nasty , not - fixable bug in the binding between C
and C + + makes it necessary to avoid C + + for the IO
callback setup .
*/
2014-12-03 20:57:58 -05:00
2015-10-07 13:17:42 -04:00
ipMIDIHandler * ipm = new ipMIDIHandler ( ) ; /* we will leak this sizeof(pointer)*2 sized object */
ipm - > mcp = this ;
ipm - > port = & input_port ;
2014-12-03 20:57:58 -05:00
2015-10-08 21:23:48 -04:00
g_source_set_callback ( surface - > input_source , ( GSourceFunc ) ipmidi_input_handler , ipm , NULL ) ;
g_source_attach ( surface - > input_source , main_loop ( ) - > get_context ( ) - > gobj ( ) ) ;
2014-11-23 10:37:13 -05:00
}
2012-04-10 13:13:55 -04:00
}
2008-06-02 17:41:35 -04:00
}
2013-09-06 10:39:14 -04:00
2015-10-11 11:58:00 -04:00
if ( ! _device_info . uses_ipmidi ( ) ) {
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > port ( ) . reconnect ( ) ;
}
}
session - > BundleAddedOrRemoved ( ) ;
assert ( _master_surface ) ;
2013-09-06 10:39:14 -04:00
return 0 ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : close ( )
2008-06-02 17:41:35 -04:00
{
2015-10-10 17:13:04 -04:00
port_connection . disconnect ( ) ;
2009-12-17 13:24:23 -05:00
session_connections . drop_connections ( ) ;
route_connections . drop_connections ( ) ;
2012-04-09 09:59:35 -04:00
periodic_connection . disconnect ( ) ;
2009-10-20 20:15:42 -04:00
2012-12-31 11:04:46 -05:00
clear_surfaces ( ) ;
2008-06-02 17:41:35 -04:00
}
2015-10-13 07:33:20 -04:00
/** Ensure that the configuration_state XML node contains an up-to-date
* copy of the state node the current device . If configuration_state already
* contains a state node for the device , it will deleted and replaced .
2015-10-11 11:58:00 -04:00
*/
void
2015-10-13 07:33:20 -04:00
MackieControlProtocol : : update_configuration_state ( )
2015-10-11 11:58:00 -04:00
{
2015-10-13 15:34:53 -04:00
/* CALLER MUST HOLD SURFACES LOCK */
2015-10-13 07:33:20 -04:00
if ( ! configuration_state ) {
configuration_state = new XMLNode ( X_ ( " Configurations " ) ) ;
}
XMLNode * devnode = new XMLNode ( X_ ( " Configuration " ) ) ;
devnode - > add_property ( X_ ( " name " ) , _device_info . name ( ) ) ;
configuration_state - > remove_nodes_and_delete ( X_ ( " name " ) , _device_info . name ( ) ) ;
configuration_state - > add_child_nocopy ( * devnode ) ;
XMLNode * snode = new XMLNode ( X_ ( " Surfaces " ) ) ;
2015-10-13 15:34:53 -04:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
snode - > add_child_nocopy ( ( * s ) - > get_state ( ) ) ;
2015-10-13 07:33:20 -04:00
}
2015-10-13 15:34:53 -04:00
devnode - > add_child_nocopy ( * snode ) ;
2015-10-11 11:58:00 -04:00
}
2015-10-03 14:03:29 -04:00
XMLNode &
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : get_state ( )
2008-06-02 17:41:35 -04:00
{
2013-12-21 15:30:07 -05:00
XMLNode & node ( ControlProtocol : : get_state ( ) ) ;
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::get_state init \n " ) ;
2012-04-25 17:21:36 -04:00
char buf [ 16 ] ;
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// add current bank
2012-04-25 17:21:36 -04:00
snprintf ( buf , sizeof ( buf ) , " %d " , _current_initial_bank ) ;
2013-12-21 15:30:07 -05:00
node . add_property ( X_ ( " bank " ) , buf ) ;
2012-04-25 17:21:36 -04:00
// ipMIDI base port (possibly not used)
snprintf ( buf , sizeof ( buf ) , " %d " , _ipmidi_base ) ;
2013-12-21 15:30:07 -05:00
node . add_property ( X_ ( " ipmidi-base " ) , buf ) ;
2012-04-25 17:21:36 -04:00
2013-12-21 15:30:07 -05:00
node . add_property ( X_ ( " device-profile " ) , _device_profile . name ( ) ) ;
node . add_property ( X_ ( " device-name " ) , _device_info . name ( ) ) ;
2009-10-20 20:15:42 -04:00
2015-10-13 15:34:53 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
update_configuration_state ( ) ;
}
2013-12-13 16:00:08 -05:00
2015-10-11 11:58:00 -04:00
/* force a copy of the _surfaces_state node, because we want to retain ownership */
2015-10-13 07:33:20 -04:00
node . add_child_copy ( * configuration_state ) ;
2013-12-13 16:00:08 -05:00
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::get_state done \n " ) ;
2013-12-21 15:30:07 -05:00
return node ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
int
2013-12-13 16:00:08 -05:00
MackieControlProtocol : : set_state ( const XMLNode & node , int version )
2008-06-02 17:41:35 -04:00
{
2013-12-21 15:30:07 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " MackieControlProtocol::set_state: active %1 \n " , active ( ) ) ) ;
2009-12-20 11:49:55 -05:00
2008-06-02 17:41:35 -04:00
int retval = 0 ;
2012-04-11 13:13:20 -04:00
const XMLProperty * prop ;
2012-06-13 11:38:15 -04:00
uint32_t bank = 0 ;
2012-04-25 17:21:36 -04:00
2015-06-24 13:46:07 -04:00
if ( ControlProtocol : : set_state ( node , version ) ) {
return - 1 ;
}
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
if ( ( prop = node . property ( X_ ( " ipmidi-base " ) ) ) ! = 0 ) {
set_ipmidi_base ( atoi ( prop - > value ( ) ) ) ;
}
2009-12-20 11:49:55 -05:00
2012-04-12 08:16:55 -04:00
// fetch current bank
2012-04-11 13:13:20 -04:00
if ( ( prop = node . property ( X_ ( " bank " ) ) ) ! = 0 ) {
2012-04-25 17:21:36 -04:00
bank = atoi ( prop - > value ( ) ) ;
}
2015-10-03 14:03:29 -04:00
2012-04-25 17:21:36 -04:00
if ( ( prop = node . property ( X_ ( " device-name " ) ) ) ! = 0 ) {
2013-12-21 15:30:07 -05:00
set_device_info ( prop - > value ( ) ) ;
2012-04-25 17:21:36 -04:00
}
if ( ( prop = node . property ( X_ ( " device-profile " ) ) ) ! = 0 ) {
2015-12-09 00:12:19 -05:00
if ( prop - > value ( ) . empty ( ) ) {
string default_profile_name ;
default_profile_name = Glib : : get_user_name ( ) ;
default_profile_name + = ' ' ;
default_profile_name + = _device_info . name ( ) ;
set_profile ( default_profile_name ) ;
} else {
set_profile ( prop - > value ( ) ) ;
}
2012-04-25 17:21:36 -04:00
}
2015-10-03 14:03:29 -04:00
2015-10-13 07:33:20 -04:00
XMLNode * dnode = node . child ( X_ ( " Configurations " ) ) ;
2015-10-03 14:03:29 -04:00
2015-10-13 07:33:20 -04:00
delete configuration_state ;
configuration_state = 0 ;
2013-12-13 16:00:08 -05:00
2015-10-13 07:33:20 -04:00
if ( dnode ) {
configuration_state = new XMLNode ( * dnode ) ;
state_version = version ;
2013-12-13 16:00:08 -05:00
}
2012-04-25 17:21:36 -04:00
2013-12-21 15:30:07 -05:00
switch_banks ( bank , true ) ;
2015-10-03 14:03:29 -04:00
2012-06-12 23:07:50 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MackieControlProtocol::set_state done \n " ) ;
2008-06-02 17:41:35 -04:00
return retval ;
}
2015-10-03 14:03:29 -04:00
string
2010-12-03 17:26:29 -05:00
MackieControlProtocol : : format_bbt_timecode ( framepos_t now_frame )
2008-12-12 09:43:24 -05:00
{
2010-12-14 13:13:37 -05:00
Timecode : : BBT_Time bbt_time ;
2012-05-29 19:44:34 -04:00
2009-12-20 11:49:55 -05:00
session - > bbt_time ( now_frame , bbt_time ) ;
2009-10-20 20:15:42 -04:00
2012-05-29 19:44:34 -04:00
// The Mackie protocol spec is built around a BBT time display of
//
// digits: 888/88/88/888
// semantics: BBB/bb/ss/ttt
//
// The third field is "subdivisions" which is a concept found in Logic
// but not present in Ardour. Instead Ardour displays a 4 digit tick
// count, which we need to spread across the 5 digits of ss/ttt.
2008-12-12 09:43:24 -05:00
ostringstream os ;
2012-05-29 19:44:34 -04:00
2008-12-12 09:43:24 -05:00
os < < setw ( 3 ) < < setfill ( ' 0 ' ) < < bbt_time . bars ;
os < < setw ( 2 ) < < setfill ( ' 0 ' ) < < bbt_time . beats ;
2012-06-02 10:51:53 -04:00
os < < ' ' ;
os < < setw ( 1 ) < < setfill ( ' 0 ' ) < < bbt_time . ticks / 1000 ;
2012-05-29 19:44:34 -04:00
os < < setw ( 3 ) < < setfill ( ' 0 ' ) < < bbt_time . ticks % 1000 ;
2009-10-20 20:15:42 -04:00
2008-12-12 09:43:24 -05:00
return os . str ( ) ;
}
2015-10-03 14:03:29 -04:00
string
2010-12-03 17:26:29 -05:00
MackieControlProtocol : : format_timecode_timecode ( framepos_t now_frame )
2008-12-12 09:43:24 -05:00
{
2009-10-26 10:38:58 -04:00
Timecode : : Time timecode ;
2009-12-20 11:49:55 -05:00
session - > timecode_time ( now_frame , timecode ) ;
2008-12-12 09:43:24 -05:00
// According to the Logic docs
// digits: 888/88/88/888
2009-10-26 10:38:58 -04:00
// Timecode mode: Hours/Minutes/Seconds/Frames
2008-12-12 09:43:24 -05:00
ostringstream os ;
2012-06-02 10:51:53 -04:00
os < < setw ( 2 ) < < setfill ( ' 0 ' ) < < timecode . hours ;
2012-06-12 23:09:46 -04:00
os < < ' ' ;
2009-10-26 10:38:58 -04:00
os < < setw ( 2 ) < < setfill ( ' 0 ' ) < < timecode . minutes ;
os < < setw ( 2 ) < < setfill ( ' 0 ' ) < < timecode . seconds ;
2012-06-06 08:20:57 -04:00
os < < ' ' ;
2012-06-12 23:09:46 -04:00
os < < setw ( 2 ) < < setfill ( ' 0 ' ) < < timecode . frames ;
2009-10-20 20:15:42 -04:00
2008-12-12 09:43:24 -05:00
return os . str ( ) ;
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : update_timecode_display ( )
2008-12-12 09:43:24 -05:00
{
2012-12-31 11:04:46 -05:00
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2012-04-18 14:27:06 -04:00
if ( surfaces . empty ( ) ) {
return ;
}
2015-08-13 16:00:04 -04:00
boost : : shared_ptr < Surface > surface = _master_surface ;
2012-04-10 10:27:44 -04:00
2012-06-02 10:51:53 -04:00
if ( surface - > type ( ) ! = mcu | | ! _device_info . has_timecode_display ( ) | | ! surface - > active ( ) ) {
2012-04-10 10:27:44 -04:00
return ;
2008-06-02 17:41:35 -04:00
}
2012-04-10 10:27:44 -04:00
// do assignment here so current_frame is fixed
framepos_t current_frame = session - > transport_frame ( ) ;
string timecode ;
2015-12-11 15:57:24 -05:00
// For large jumps in play head possition do full reset
int moved = ( current_frame - _frame_last ) / session - > frame_rate ( ) ;
if ( moved ) {
DEBUG_TRACE ( DEBUG : : MackieControl , " Timecode reset \n " ) ;
_timecode_last = string ( 10 , ' ' ) ;
}
_frame_last = current_frame ;
2012-04-10 10:27:44 -04:00
switch ( _timecode_type ) {
case ARDOUR : : AnyTime : : BBT :
timecode = format_bbt_timecode ( current_frame ) ;
break ;
case ARDOUR : : AnyTime : : Timecode :
timecode = format_timecode_timecode ( current_frame ) ;
break ;
default :
return ;
}
2015-10-03 14:03:29 -04:00
2012-04-10 10:27:44 -04:00
// only write the timecode string to the MCU if it's changed
// since last time. This is to reduce midi bandwidth used.
if ( timecode ! = _timecode_last ) {
surface - > display_timecode ( timecode , _timecode_last ) ;
_timecode_last = timecode ;
}
}
2008-12-12 17:55:03 -05:00
2008-06-02 17:41:35 -04:00
///////////////////////////////////////////
// Session signals
///////////////////////////////////////////
2009-05-25 13:56:34 -04:00
void MackieControlProtocol : : notify_parameter_changed ( std : : string const & p )
2008-06-02 17:41:35 -04:00
{
2011-09-26 18:32:24 -04:00
if ( p = = " punch-in " ) {
2015-10-07 13:17:42 -04:00
// no such button right now
2015-06-04 18:02:51 -04:00
// update_global_button (Button::PunchIn, session->config.get_punch_in());
2011-09-26 18:32:24 -04:00
} else if ( p = = " punch-out " ) {
2015-10-07 13:17:42 -04:00
// no such button right now
2015-06-04 18:02:51 -04:00
// update_global_button (Button::PunchOut, session->config.get_punch_out());
2011-09-26 18:32:24 -04:00
} else if ( p = = " clicking " ) {
2015-10-02 07:31:48 -04:00
update_global_button ( Button : : Click , Config - > get_clicking ( ) ) ;
2011-09-26 18:32:24 -04:00
} else {
2009-12-20 11:49:55 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " parameter changed: %1 \n " , p ) ) ;
2008-06-02 17:41:35 -04:00
}
}
2015-12-13 08:33:02 -05:00
void
MackieControlProtocol : : notify_route_added_or_removed ( )
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > master_monitor_may_have_changed ( ) ;
}
}
2008-06-02 17:41:35 -04:00
// RouteList is the set of routes that have just been added
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : notify_route_added ( ARDOUR : : RouteList & rl )
2008-06-02 17:41:35 -04:00
{
2015-10-10 17:13:04 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
if ( surfaces . empty ( ) ) {
return ;
}
}
2015-12-13 08:33:02 -05:00
/* special case: single route, and it is the monitor or master out */
if ( rl . size ( ) = = 1 & & ( rl . front ( ) - > is_monitor ( ) | | rl . front ( ) - > is_master ( ) ) ) {
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > master_monitor_may_have_changed ( ) ;
}
}
2008-06-02 17:41:35 -04:00
// currently assigned banks are less than the full set of
// strips, so activate the new strip now.
2012-04-08 20:32:13 -04:00
2012-04-10 10:27:44 -04:00
refresh_current_bank ( ) ;
2012-04-08 20:32:13 -04:00
2008-06-02 17:41:35 -04:00
// otherwise route added, but current bank needs no updating
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// make sure remote id changes in the new route are handled
2009-01-30 02:40:13 -05:00
typedef ARDOUR : : RouteList ARS ;
2009-12-17 13:24:23 -05:00
for ( ARS : : iterator it = rl . begin ( ) ; it ! = rl . end ( ) ; + + it ) {
2012-04-25 00:42:01 -04:00
( * it ) - > RemoteControlIDChanged . connect ( route_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_remote_id_changed , this ) , this ) ;
2008-06-02 17:41:35 -04:00
}
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : notify_solo_active_changed ( bool active )
2008-06-02 17:41:35 -04:00
{
2012-12-31 11:04:46 -05:00
boost : : shared_ptr < Surface > surface ;
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-10 17:13:04 -04:00
if ( surfaces . empty ( ) ) {
return ;
}
2015-08-13 16:00:04 -04:00
surface = _master_surface ;
2012-12-31 11:04:46 -05:00
}
2015-10-03 14:03:29 -04:00
2012-04-14 15:02:54 -04:00
map < int , Control * > : : iterator x = surface - > controls_by_device_independent_id . find ( Led : : RudeSolo ) ;
if ( x ! = surface - > controls_by_device_independent_id . end ( ) ) {
Led * rude_solo = dynamic_cast < Led * > ( x - > second ) ;
if ( rude_solo ) {
surface - > write ( rude_solo - > set_state ( active ? flashing : off ) ) ;
}
2012-04-10 10:27:44 -04:00
}
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : notify_remote_id_changed ( )
2008-06-02 17:41:35 -04:00
{
2015-10-10 17:13:04 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
if ( surfaces . empty ( ) ) {
return ;
}
}
2008-06-02 17:41:35 -04:00
Sorted sorted = get_sorted_routes ( ) ;
2012-04-10 10:27:44 -04:00
uint32_t sz = n_strips ( ) ;
2009-10-20 20:15:42 -04:00
2008-06-02 17:41:35 -04:00
// if a remote id has been moved off the end, we need to shift
// the current bank backwards.
2012-04-08 20:32:13 -04:00
if ( sorted . size ( ) - _current_initial_bank < sz ) {
2008-06-02 17:41:35 -04:00
// but don't shift backwards past the zeroth channel
2016-01-16 14:17:52 -05:00
if ( sorted . size ( ) < sz ) { // avoid unsigned math mistake below
switch_banks ( 0 , true ) ;
} else {
switch_banks ( max ( ( Sorted : : size_type ) 0 , sorted . size ( ) - sz ) , true ) ;
}
2011-09-26 18:32:24 -04:00
} else {
// Otherwise just refresh the current bank
2008-06-02 17:41:35 -04:00
refresh_current_bank ( ) ;
}
}
///////////////////////////////////////////
// Transport signals
///////////////////////////////////////////
2015-10-03 14:03:29 -04:00
void
2012-04-10 22:30:35 -04:00
MackieControlProtocol : : notify_loop_state_changed ( )
2008-06-02 17:41:35 -04:00
{
2012-04-14 15:02:54 -04:00
update_global_button ( Button : : Loop , session - > get_play_loop ( ) ) ;
2008-06-02 17:41:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2009-12-20 11:49:55 -05:00
MackieControlProtocol : : notify_transport_state_changed ( )
2008-06-02 17:41:35 -04:00
{
2012-06-09 15:06:52 -04:00
if ( ! _device_info . has_global_controls ( ) ) {
return ;
}
2008-06-02 17:41:35 -04:00
// switch various play and stop buttons on / off
2012-04-25 23:46:18 -04:00
update_global_button ( Button : : Loop , session - > get_play_loop ( ) ) ;
2012-04-14 15:02:54 -04:00
update_global_button ( Button : : Play , session - > transport_speed ( ) = = 1.0 ) ;
2012-06-06 08:20:57 -04:00
update_global_button ( Button : : Stop , session - > transport_stopped ( ) ) ;
2012-04-14 15:02:54 -04:00
update_global_button ( Button : : Rewind , session - > transport_speed ( ) < 0.0 ) ;
update_global_button ( Button : : Ffwd , session - > transport_speed ( ) > 1.0 ) ;
2012-06-01 08:56:20 -04:00
2015-12-16 15:24:10 -05:00
// sometimes a return to start leaves time code at old time
_timecode_last = string ( 10 , ' ' ) ;
2012-06-01 08:56:20 -04:00
notify_metering_state_changed ( ) ;
2012-04-10 22:30:35 -04:00
}
2015-10-03 14:03:29 -04:00
void
2012-06-01 08:56:20 -04:00
MackieControlProtocol : : notify_metering_state_changed ( )
{
2012-12-31 11:04:46 -05:00
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2012-06-01 08:56:20 -04:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > notify_metering_state_changed ( ) ;
2015-10-03 14:03:29 -04:00
}
2012-06-01 08:56:20 -04:00
}
2012-04-10 22:30:35 -04:00
void
MackieControlProtocol : : notify_record_state_changed ( )
{
2012-06-09 15:06:52 -04:00
if ( ! _device_info . has_global_controls ( ) ) {
return ;
}
2012-04-10 22:54:25 -04:00
2012-12-31 11:04:46 -05:00
boost : : shared_ptr < Surface > surface ;
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-10 17:13:04 -04:00
if ( surfaces . empty ( ) ) {
return ;
}
2015-08-13 16:00:04 -04:00
surface = _master_surface ;
2012-12-31 11:04:46 -05:00
}
2015-10-03 14:03:29 -04:00
2012-04-14 15:02:54 -04:00
/* rec is a tristate */
2012-04-10 22:30:35 -04:00
2012-04-14 15:02:54 -04:00
map < int , Control * > : : iterator x = surface - > controls_by_device_independent_id . find ( Button : : Record ) ;
if ( x ! = surface - > controls_by_device_independent_id . end ( ) ) {
Button * rec = dynamic_cast < Button * > ( x - > second ) ;
if ( rec ) {
LedState ls ;
2015-10-03 14:03:29 -04:00
2012-04-14 15:02:54 -04:00
switch ( session - > record_status ( ) ) {
case Session : : Disabled :
DEBUG_TRACE ( DEBUG : : MackieControl , " record state changed to disabled, LED off \n " ) ;
ls = off ;
break ;
case Session : : Recording :
DEBUG_TRACE ( DEBUG : : MackieControl , " record state changed to recording, LED on \n " ) ;
ls = on ;
break ;
case Session : : Enabled :
DEBUG_TRACE ( DEBUG : : MackieControl , " record state changed to enabled, LED flashing \n " ) ;
ls = flashing ;
break ;
}
2012-06-06 08:20:57 -04:00
2012-04-14 15:02:54 -04:00
surface - > write ( rec - > set_state ( ls ) ) ;
2012-04-10 22:30:35 -04:00
}
2008-12-12 17:55:03 -05:00
}
}
2010-07-29 22:09:39 -04:00
list < boost : : shared_ptr < ARDOUR : : Bundle > >
MackieControlProtocol : : bundles ( )
{
list < boost : : shared_ptr < ARDOUR : : Bundle > > b ;
2013-12-21 15:30:07 -05:00
if ( _input_bundle ) {
b . push_back ( _input_bundle ) ;
b . push_back ( _output_bundle ) ;
}
2010-07-29 22:09:39 -04:00
return b ;
}
2011-09-26 18:22:21 -04:00
2011-09-26 20:43:04 -04:00
void
MackieControlProtocol : : do_request ( MackieControlUIRequest * req )
{
2016-01-12 23:30:14 -05:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " doing request type %1 \n " , req - > type ) ) ;
2011-09-26 20:43:04 -04:00
if ( req - > type = = CallSlot ) {
2012-04-10 20:10:31 -04:00
call_slot ( MISSING_INVALIDATOR , req - > the_slot ) ;
2011-09-26 20:43:04 -04:00
} else if ( req - > type = = Quit ) {
stop ( ) ;
}
}
int
MackieControlProtocol : : stop ( )
{
BaseUI : : quit ( ) ;
return 0 ;
}
2012-04-08 11:10:46 -04:00
2015-10-03 14:03:29 -04:00
void
2012-04-10 10:27:44 -04:00
MackieControlProtocol : : update_led ( Surface & surface , Button & button , Mackie : : LedState ls )
2012-04-09 11:32:25 -04:00
{
if ( ls ! = none ) {
2012-04-11 15:47:41 -04:00
surface . port ( ) . write ( button . set_state ( ls ) ) ;
2012-04-09 11:32:25 -04:00
}
}
2012-04-10 22:54:25 -04:00
void
MackieControlProtocol : : build_button_map ( )
{
2012-04-15 09:28:45 -04:00
/* this maps our device-independent button codes to the methods that handle them.
*/
2012-04-14 15:02:54 -04:00
# define DEFINE_BUTTON_HANDLER(b,p,r) button_map.insert (pair<Button::ID,ButtonHandlers> ((b), ButtonHandlers ((p),(r))));
2012-04-10 23:18:35 -04:00
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Track , & MackieControlProtocol : : track_press , & MackieControlProtocol : : track_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Send , & MackieControlProtocol : : send_press , & MackieControlProtocol : : send_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Pan , & MackieControlProtocol : : pan_press , & MackieControlProtocol : : pan_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Plugin , & MackieControlProtocol : : plugin_press , & MackieControlProtocol : : plugin_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Eq , & MackieControlProtocol : : eq_press , & MackieControlProtocol : : eq_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Dyn , & MackieControlProtocol : : dyn_press , & MackieControlProtocol : : dyn_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Left , & MackieControlProtocol : : left_press , & MackieControlProtocol : : left_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Right , & MackieControlProtocol : : right_press , & MackieControlProtocol : : right_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : ChannelLeft , & MackieControlProtocol : : channel_left_press , & MackieControlProtocol : : channel_left_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : ChannelRight , & MackieControlProtocol : : channel_right_press , & MackieControlProtocol : : channel_right_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Flip , & MackieControlProtocol : : flip_press , & MackieControlProtocol : : flip_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : View , & MackieControlProtocol : : view_press , & MackieControlProtocol : : view_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : NameValue , & MackieControlProtocol : : name_value_press , & MackieControlProtocol : : name_value_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : TimecodeBeats , & MackieControlProtocol : : timecode_beats_press , & MackieControlProtocol : : timecode_beats_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F1 , & MackieControlProtocol : : F1_press , & MackieControlProtocol : : F1_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F2 , & MackieControlProtocol : : F2_press , & MackieControlProtocol : : F2_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F3 , & MackieControlProtocol : : F3_press , & MackieControlProtocol : : F3_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F4 , & MackieControlProtocol : : F4_press , & MackieControlProtocol : : F4_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F5 , & MackieControlProtocol : : F5_press , & MackieControlProtocol : : F5_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F6 , & MackieControlProtocol : : F6_press , & MackieControlProtocol : : F6_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F7 , & MackieControlProtocol : : F7_press , & MackieControlProtocol : : F7_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : F8 , & MackieControlProtocol : : F8_press , & MackieControlProtocol : : F8_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : MidiTracks , & MackieControlProtocol : : miditracks_press , & MackieControlProtocol : : miditracks_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Inputs , & MackieControlProtocol : : inputs_press , & MackieControlProtocol : : inputs_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : AudioTracks , & MackieControlProtocol : : audiotracks_press , & MackieControlProtocol : : audiotracks_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : AudioInstruments , & MackieControlProtocol : : audioinstruments_press , & MackieControlProtocol : : audioinstruments_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Aux , & MackieControlProtocol : : aux_press , & MackieControlProtocol : : aux_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Busses , & MackieControlProtocol : : busses_press , & MackieControlProtocol : : busses_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Outputs , & MackieControlProtocol : : outputs_press , & MackieControlProtocol : : outputs_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : User , & MackieControlProtocol : : user_press , & MackieControlProtocol : : user_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Shift , & MackieControlProtocol : : shift_press , & MackieControlProtocol : : shift_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Option , & MackieControlProtocol : : option_press , & MackieControlProtocol : : option_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Ctrl , & MackieControlProtocol : : control_press , & MackieControlProtocol : : control_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : CmdAlt , & MackieControlProtocol : : cmd_alt_press , & MackieControlProtocol : : cmd_alt_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Read , & MackieControlProtocol : : read_press , & MackieControlProtocol : : read_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Write , & MackieControlProtocol : : write_press , & MackieControlProtocol : : write_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Trim , & MackieControlProtocol : : trim_press , & MackieControlProtocol : : trim_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Touch , & MackieControlProtocol : : touch_press , & MackieControlProtocol : : touch_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Latch , & MackieControlProtocol : : latch_press , & MackieControlProtocol : : latch_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Grp , & MackieControlProtocol : : grp_press , & MackieControlProtocol : : grp_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Save , & MackieControlProtocol : : save_press , & MackieControlProtocol : : save_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Undo , & MackieControlProtocol : : undo_press , & MackieControlProtocol : : undo_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Cancel , & MackieControlProtocol : : cancel_press , & MackieControlProtocol : : cancel_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Enter , & MackieControlProtocol : : enter_press , & MackieControlProtocol : : enter_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Marker , & MackieControlProtocol : : marker_press , & MackieControlProtocol : : marker_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Nudge , & MackieControlProtocol : : nudge_press , & MackieControlProtocol : : nudge_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Loop , & MackieControlProtocol : : loop_press , & MackieControlProtocol : : loop_release ) ;
2015-06-04 18:02:51 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Drop , & MackieControlProtocol : : drop_press , & MackieControlProtocol : : drop_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Replace , & MackieControlProtocol : : replace_press , & MackieControlProtocol : : replace_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Click , & MackieControlProtocol : : click_press , & MackieControlProtocol : : click_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : ClearSolo , & MackieControlProtocol : : clearsolo_press , & MackieControlProtocol : : clearsolo_release ) ;
2012-04-10 23:18:35 -04:00
DEFINE_BUTTON_HANDLER ( Button : : Rewind , & MackieControlProtocol : : rewind_press , & MackieControlProtocol : : rewind_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Ffwd , & MackieControlProtocol : : ffwd_press , & MackieControlProtocol : : ffwd_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Stop , & MackieControlProtocol : : stop_press , & MackieControlProtocol : : stop_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Play , & MackieControlProtocol : : play_press , & MackieControlProtocol : : play_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Record , & MackieControlProtocol : : record_press , & MackieControlProtocol : : record_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : CursorUp , & MackieControlProtocol : : cursor_up_press , & MackieControlProtocol : : cursor_up_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : CursorDown , & MackieControlProtocol : : cursor_down_press , & MackieControlProtocol : : cursor_down_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : CursorLeft , & MackieControlProtocol : : cursor_left_press , & MackieControlProtocol : : cursor_left_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : CursorRight , & MackieControlProtocol : : cursor_right_press , & MackieControlProtocol : : cursor_right_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Zoom , & MackieControlProtocol : : zoom_press , & MackieControlProtocol : : zoom_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : Scrub , & MackieControlProtocol : : scrub_press , & MackieControlProtocol : : scrub_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : UserA , & MackieControlProtocol : : user_a_press , & MackieControlProtocol : : user_a_release ) ;
DEFINE_BUTTON_HANDLER ( Button : : UserB , & MackieControlProtocol : : user_b_press , & MackieControlProtocol : : user_b_release ) ;
2012-06-09 15:06:52 -04:00
DEFINE_BUTTON_HANDLER ( Button : : MasterFaderTouch , & MackieControlProtocol : : master_fader_touch_press , & MackieControlProtocol : : master_fader_touch_release ) ;
2012-04-10 22:54:25 -04:00
}
2015-10-03 14:03:29 -04:00
void
2012-04-10 10:27:44 -04:00
MackieControlProtocol : : handle_button_event ( Surface & surface , Button & button , ButtonState bs )
2012-04-09 11:32:25 -04:00
{
2015-10-02 10:21:20 -04:00
Button : : ID button_id = button . bid ( ) ;
2015-10-02 22:03:17 -04:00
2012-04-09 11:32:25 -04:00
if ( bs ! = press & & bs ! = release ) {
2012-04-10 10:27:44 -04:00
update_led ( surface , button , none ) ;
2012-04-09 11:32:25 -04:00
return ;
}
2015-10-03 14:03:29 -04:00
2012-04-22 13:37:52 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Handling %1 for button %2 (%3) \n " , ( bs = = press ? " press " : " release " ) , button . id ( ) ,
Button : : id_to_name ( button . bid ( ) ) ) ) ;
2012-04-09 11:32:25 -04:00
2012-04-17 16:41:31 -04:00
/* check profile first */
2015-10-03 14:03:29 -04:00
2012-04-17 16:41:31 -04:00
string action = _device_profile . get_button_action ( button . bid ( ) , _modifier_state ) ;
2012-04-18 08:20:28 -04:00
2012-04-17 16:41:31 -04:00
if ( ! action . empty ( ) ) {
2015-10-02 22:03:17 -04:00
2015-10-02 10:21:20 -04:00
if ( action . find ( ' / ' ) ! = string : : npos ) { /* good chance that this is really an action */
2015-10-02 22:03:17 -04:00
2015-10-02 10:21:20 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " Looked up action for button %1 with modifier %2, got [%3] \n " ,
2015-10-07 13:17:42 -04:00
button . bid ( ) , _modifier_state , action ) ) ;
2015-10-03 14:03:29 -04:00
2015-10-02 10:21:20 -04:00
/* if there is a bound action for this button, and this is a press event,
2015-10-03 14:03:29 -04:00
carry out the action . If its a release event , do nothing since we
don ' t bind to them at all but don ' t want any other handling to
2015-10-02 10:21:20 -04:00
occur either .
*/
if ( bs = = press ) {
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " executing action %1 \n " , action ) ) ;
access_action ( action ) ;
}
2015-10-02 22:03:17 -04:00
2015-10-02 10:21:20 -04:00
return ;
2015-10-02 22:03:17 -04:00
2015-10-02 10:21:20 -04:00
} else {
2015-10-03 14:03:29 -04:00
2015-10-02 10:21:20 -04:00
/* "action" is more likely to be a button name. We use this to
* allow remapping buttons to different ( builtin ) functionality
* associated with an existing button . This is similar to the
* way that ( for example ) Nuendo moves the " Shift " function to
* the " Enter " key of the MCU Pro .
*/
2015-10-03 14:03:29 -04:00
2015-10-02 10:21:20 -04:00
int bid = Button : : name_to_id ( action ) ;
2015-10-03 14:03:29 -04:00
2015-10-02 10:21:20 -04:00
if ( bid < 0 ) {
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " apparent button name %1 not found \n " , action ) ) ;
return ;
}
2015-10-03 14:03:29 -04:00
2015-10-02 10:21:20 -04:00
button_id = ( Button : : ID ) bid ;
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " handling button %1 as if it was %2 (%3) \n " , Button : : id_to_name ( button . bid ( ) ) , button_id , Button : : id_to_name ( button_id ) ) ) ;
2012-04-17 16:41:31 -04:00
}
}
2012-04-14 15:02:54 -04:00
/* lookup using the device-INDEPENDENT button ID */
2015-10-02 10:21:20 -04:00
ButtonMap : : iterator b = button_map . find ( button_id ) ;
2012-04-10 22:54:25 -04:00
2012-04-10 23:11:56 -04:00
if ( b ! = button_map . end ( ) ) {
2012-04-10 22:54:25 -04:00
2012-04-10 23:11:56 -04:00
ButtonHandlers & bh ( b - > second ) ;
2012-04-10 22:54:25 -04:00
switch ( bs ) {
2015-10-03 14:03:29 -04:00
case press :
2012-04-11 15:47:41 -04:00
surface . write ( button . set_state ( ( this - > * ( bh . press ) ) ( button ) ) ) ;
2012-04-18 17:34:15 -04:00
break ;
2015-10-03 14:03:29 -04:00
case release :
2012-04-11 15:47:41 -04:00
surface . write ( button . set_state ( ( this - > * ( bh . release ) ) ( button ) ) ) ;
2012-04-11 00:02:46 -04:00
break ;
default :
break ;
2012-04-10 22:54:25 -04:00
}
2012-04-11 16:48:51 -04:00
} else {
2015-10-03 14:03:29 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " no button handlers for button ID %1 (device ID %2) \n " ,
2012-04-15 09:28:45 -04:00
button . bid ( ) , button . id ( ) ) ) ;
2015-10-03 14:03:29 -04:00
error < < string_compose ( " no button handlers for button ID %1 (device ID %2) \n " ,
2012-04-15 09:28:45 -04:00
button . bid ( ) , button . id ( ) ) < < endmsg ;
2012-04-09 11:32:25 -04:00
}
2012-04-10 10:27:44 -04:00
}
2012-04-10 13:13:55 -04:00
bool
MackieControlProtocol : : midi_input_handler ( IOCondition ioc , MIDI : : Port * port )
{
if ( ioc & ~ IO_IN ) {
2015-10-08 21:23:48 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , " MIDI port closed \n " ) ;
2012-04-10 13:13:55 -04:00
return false ;
}
if ( ioc & IO_IN ) {
2015-10-08 21:23:48 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " something happend on %1 \n " , port - > name ( ) ) ) ;
2012-05-29 19:30:13 -04:00
/* Devices using regular JACK MIDI ports will need to have
the x - thread FIFO drained to avoid burning endless CPU .
Devices using ipMIDI have port - > selectable ( ) as the same
file descriptor that data arrives on , so doing this
for them will simply throw all incoming data away .
*/
if ( ! _device_info . uses_ipmidi ( ) ) {
2014-11-23 10:37:13 -05:00
AsyncMIDIPort * asp = dynamic_cast < AsyncMIDIPort * > ( port ) ;
if ( asp ) {
asp - > clear ( ) ;
}
2012-05-29 19:30:13 -04:00
}
2012-05-27 06:57:36 -04:00
2012-04-24 12:45:38 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " data available on %1 \n " , port - > name ( ) ) ) ;
2013-07-24 19:29:45 -04:00
framepos_t now = session - > engine ( ) . sample_time ( ) ;
2012-04-10 13:13:55 -04:00
port - > parse ( now ) ;
}
return true ;
}
void
MackieControlProtocol : : clear_ports ( )
{
2013-12-21 15:30:07 -05:00
if ( _input_bundle ) {
_input_bundle - > remove_channels ( ) ;
_output_bundle - > remove_channels ( ) ;
}
2012-04-10 13:13:55 -04:00
}
2015-12-15 11:10:35 -05:00
void
MackieControlProtocol : : notify_subview_route_deleted ( )
{
/* return to global/mixer view */
_subview_route . reset ( ) ;
set_view_mode ( Mixer ) ;
}
2015-12-11 11:05:57 -05:00
void
2015-12-11 11:46:39 -05:00
MackieControlProtocol : : set_subview_mode ( SubViewMode sm , boost : : shared_ptr < Route > r )
2015-12-11 11:05:57 -05:00
{
2015-12-15 11:10:35 -05:00
SubViewMode old_mode = _subview_mode ;
boost : : shared_ptr < Route > old_route = _subview_route ;
2015-12-14 22:22:34 -05:00
2015-12-11 11:05:57 -05:00
_subview_mode = sm ;
2015-12-11 11:46:39 -05:00
2015-12-14 22:22:34 -05:00
if ( r ) {
2015-12-15 11:10:35 -05:00
/* retain _subview_route even if it is reset to null implicitly */
_subview_route = r ;
2015-12-11 11:46:39 -05:00
}
2015-12-15 11:10:35 -05:00
if ( ( _subview_mode ! = old_mode ) | | ( _subview_route ! = old_route ) ) {
if ( r ! = old_route ) {
subview_route_connections . drop_connections ( ) ;
if ( _subview_route ) {
_subview_route - > DropReferences . connect ( subview_route_connections , MISSING_INVALIDATOR , boost : : bind ( & MackieControlProtocol : : notify_subview_route_deleted , this ) , this ) ;
}
}
2015-12-11 11:46:39 -05:00
2015-12-14 22:22:34 -05:00
/* subview mode did actually change */
{
Surfaces copy ; /* can't hold surfaces lock while calling Strip::subview_mode_changed */
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
copy = surfaces ;
}
for ( Surfaces : : iterator s = copy . begin ( ) ; s ! = copy . end ( ) ; + + s ) {
2015-12-15 11:10:35 -05:00
( * s ) - > subview_mode_changed ( ) ;
2015-12-14 22:22:34 -05:00
}
2015-12-11 11:46:39 -05:00
}
2015-12-15 11:10:35 -05:00
if ( _subview_mode ! = old_mode ) {
2015-12-11 11:46:39 -05:00
2015-12-15 11:10:35 -05:00
/* turn buttons related to vpot mode on or off as required */
switch ( _subview_mode ) {
case MackieControlProtocol : : None :
pot_mode_globals ( ) ;
break ;
case MackieControlProtocol : : EQ :
update_global_button ( Button : : Eq , on ) ;
update_global_button ( Button : : Dyn , off ) ;
update_global_button ( Button : : AudioInstruments , off ) ; /* faking up Dyn */
update_global_button ( Button : : Trim , off ) ;
update_global_button ( Button : : Send , off ) ;
update_global_button ( Button : : Pan , off ) ;
break ;
case MackieControlProtocol : : Dynamics :
update_global_button ( Button : : Eq , off ) ;
update_global_button ( Button : : Dyn , on ) ;
update_global_button ( Button : : AudioInstruments , on ) ; /* faking up Dyn */
update_global_button ( Button : : Trim , off ) ;
update_global_button ( Button : : Send , off ) ;
update_global_button ( Button : : Pan , off ) ;
break ;
}
2015-12-14 22:22:34 -05:00
}
2015-12-11 11:46:39 -05:00
}
2015-12-11 11:05:57 -05:00
}
2012-04-11 14:51:01 -04:00
void
MackieControlProtocol : : set_view_mode ( ViewMode m )
{
2015-10-22 18:30:34 -04:00
_last_bank [ _view_mode ] = _current_initial_bank ;
2012-12-31 11:04:46 -05:00
2012-04-11 14:51:01 -04:00
_view_mode = m ;
2015-12-14 22:22:34 -05:00
set_subview_mode ( None , boost : : shared_ptr < Route > ( ) ) ;
2012-04-11 14:51:01 -04:00
2015-10-22 18:30:34 -04:00
switch_banks ( _last_bank [ _view_mode ] , true ) ;
2015-12-16 17:38:21 -05:00
display_view_mode ( ) ;
2015-10-22 18:30:34 -04:00
}
void
MackieControlProtocol : : display_view_mode ( )
{
2015-12-11 11:05:57 -05:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-22 18:30:34 -04:00
2015-12-11 11:05:57 -05:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > update_view_mode_display ( ) ;
}
2012-04-11 14:51:01 -04:00
}
}
2012-04-11 16:10:10 -04:00
2012-04-11 20:50:18 -04:00
void
2013-08-24 11:45:31 -04:00
MackieControlProtocol : : set_flip_mode ( FlipMode fm )
2012-04-11 20:50:18 -04:00
{
2015-10-12 16:52:10 -04:00
if ( _flip_mode ! = fm ) {
if ( fm = = Normal ) {
update_global_button ( Button : : Flip , off ) ;
} else {
update_global_button ( Button : : Flip , on ) ;
}
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2012-12-31 11:04:46 -05:00
2015-10-12 16:52:10 -04:00
_flip_mode = fm ;
2015-10-03 14:03:29 -04:00
2015-10-12 16:52:10 -04:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > update_flip_mode_display ( ) ;
}
2012-04-11 20:50:18 -04:00
}
}
2015-10-03 14:03:29 -04:00
2015-10-08 00:36:16 -04:00
void
MackieControlProtocol : : set_pot_mode ( PotMode m )
{
2015-10-18 10:38:40 -04:00
// maybe not in flip mode.
if ( flip_mode ( ) ) {
return ;
}
2015-12-11 11:05:57 -05:00
2015-10-08 00:36:16 -04:00
_pot_mode = m ;
2015-10-13 15:34:53 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-08 00:36:16 -04:00
2015-10-13 15:34:53 -04:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > update_potmode ( ) ;
}
2015-10-08 00:36:16 -04:00
}
2015-12-11 11:05:57 -05:00
pot_mode_globals ( ) ;
}
void
MackieControlProtocol : : pot_mode_globals ( )
{
update_global_button ( Button : : Eq , off ) ;
update_global_button ( Button : : Dyn , off ) ;
2015-12-15 08:35:30 -05:00
update_global_button ( Button : : AudioInstruments , off ) ;
2015-12-11 11:05:57 -05:00
2015-10-13 15:34:53 -04:00
switch ( _pot_mode ) {
case Trim :
update_global_button ( Button : : Track , on ) ;
update_global_button ( Button : : Send , off ) ;
update_global_button ( Button : : Pan , off ) ;
break ;
case Send :
update_global_button ( Button : : Track , off ) ;
update_global_button ( Button : : Send , on ) ;
update_global_button ( Button : : Pan , off ) ;
break ;
case Pan :
update_global_button ( Button : : Track , off ) ;
update_global_button ( Button : : Send , off ) ;
update_global_button ( Button : : Pan , on ) ;
} ;
2015-10-08 00:36:16 -04:00
}
2012-04-11 16:10:10 -04:00
void
MackieControlProtocol : : set_master_on_surface_strip ( uint32_t surface , uint32_t strip_number )
{
force_special_route_to_strip ( session - > master_out ( ) , surface , strip_number ) ;
}
void
MackieControlProtocol : : set_monitor_on_surface_strip ( uint32_t surface , uint32_t strip_number )
{
force_special_route_to_strip ( session - > monitor_out ( ) , surface , strip_number ) ;
}
void
MackieControlProtocol : : force_special_route_to_strip ( boost : : shared_ptr < Route > r , uint32_t surface , uint32_t strip_number )
{
if ( ! r ) {
return ;
}
2012-12-31 11:04:46 -05:00
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2012-04-11 16:10:10 -04:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
if ( ( * s ) - > number ( ) = = surface ) {
Strip * strip = ( * s ) - > nth_strip ( strip_number ) ;
if ( strip ) {
strip - > set_route ( session - > master_out ( ) ) ;
2012-04-12 17:02:43 -04:00
strip - > lock_controls ( ) ;
2012-04-11 16:10:10 -04:00
}
}
}
}
2012-04-11 20:50:18 -04:00
2012-04-12 10:34:03 -04:00
void
2012-04-27 21:43:38 -04:00
MackieControlProtocol : : gui_track_selection_changed ( ARDOUR : : RouteNotificationListPtr rl , bool save_list )
2012-04-12 10:34:03 -04:00
{
2015-12-14 22:22:34 -05:00
_gui_track_selection_changed ( rl . get ( ) , save_list , true ) ;
2012-04-27 21:43:38 -04:00
}
void
2015-12-14 22:22:34 -05:00
MackieControlProtocol : : _gui_track_selection_changed ( ARDOUR : : RouteNotificationList * rl , bool save_list , bool gui_selection_did_change )
2012-04-27 21:43:38 -04:00
{
/* We need to keep a list of the most recently selected routes around,
but we are not allowed to keep shared_ptr < Route > unless we want to
handle the complexities of route deletion . So instead , the GUI sends
us a notification using weak_ptr < Route > , which we keep a copy
of . For efficiency ' s sake , however , we convert the weak_ptr ' s into
shared_ptr < Route > before passing them to however many surfaces ( and
thus strips ) that we have .
*/
StrongRouteNotificationList srl ;
for ( ARDOUR : : RouteNotificationList : : const_iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < ARDOUR : : Route > r = ( * i ) . lock ( ) ;
if ( r ) {
srl . push_back ( r ) ;
}
}
2012-12-31 11:04:46 -05:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2015-10-03 14:03:29 -04:00
2012-12-31 11:04:46 -05:00
for ( Surfaces : : iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > gui_selection_changed ( srl ) ;
}
2012-04-12 10:34:03 -04:00
}
2015-10-03 14:03:29 -04:00
2012-04-27 21:43:38 -04:00
if ( save_list ) {
_last_selected_routes = * rl ;
}
2015-12-14 22:22:34 -05:00
if ( gui_selection_did_change ) {
/* actual GUI selection changed */
set_subview_mode ( _subview_mode , first_selected_route ( ) ) ;
}
2012-04-12 10:34:03 -04:00
}
2012-04-12 17:02:43 -04:00
framepos_t
MackieControlProtocol : : transport_frame ( ) const
{
return session - > transport_frame ( ) ;
}
2012-04-12 23:46:38 -04:00
void
MackieControlProtocol : : add_down_select_button ( int surface , int strip )
{
2012-04-13 17:46:26 -04:00
_down_select_buttons . insert ( ( surface < < 8 ) | ( strip & 0xf ) ) ;
2012-04-12 23:46:38 -04:00
}
void
MackieControlProtocol : : remove_down_select_button ( int surface , int strip )
{
2013-10-15 10:58:46 -04:00
DownButtonList : : iterator x = find ( _down_select_buttons . begin ( ) , _down_select_buttons . end ( ) , ( uint32_t ) ( surface < < 8 ) | ( strip & 0xf ) ) ;
2012-04-13 17:46:26 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " removing surface %1 strip %2 from down select buttons \n " , surface , strip ) ) ;
2012-04-12 23:46:38 -04:00
if ( x ! = _down_select_buttons . end ( ) ) {
_down_select_buttons . erase ( x ) ;
2012-04-13 17:46:26 -04:00
} else {
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " surface %1 strip %2 not found in down select buttons \n " ,
surface , strip ) ) ;
2012-04-12 23:46:38 -04:00
}
}
2012-04-13 12:11:55 -04:00
void
2012-04-12 23:46:38 -04:00
MackieControlProtocol : : select_range ( )
{
2012-04-13 12:11:55 -04:00
RouteList routes ;
2012-04-12 23:46:38 -04:00
pull_route_range ( _down_select_buttons , routes ) ;
2012-04-13 13:58:36 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " select range: found %1 routes \n " , routes . size ( ) ) ) ;
2012-04-13 12:11:55 -04:00
if ( ! routes . empty ( ) ) {
for ( RouteList : : iterator r = routes . begin ( ) ; r ! = routes . end ( ) ; + + r ) {
2012-04-26 18:10:32 -04:00
2015-10-02 07:31:31 -04:00
if ( main_modifier_state ( ) = = MODIFIER_CONTROL ) {
2012-04-26 18:10:32 -04:00
ToggleRouteSelection ( ( * r ) - > remote_control_id ( ) ) ;
2012-04-13 12:11:55 -04:00
} else {
2012-04-26 18:10:32 -04:00
if ( r = = routes . begin ( ) ) {
SetRouteSelection ( ( * r ) - > remote_control_id ( ) ) ;
} else {
AddRouteToSelection ( ( * r ) - > remote_control_id ( ) ) ;
}
2012-04-13 12:11:55 -04:00
}
}
2012-04-12 23:46:38 -04:00
}
}
void
2012-04-13 12:11:55 -04:00
MackieControlProtocol : : add_down_button ( AutomationType a , int surface , int strip )
2012-04-12 23:46:38 -04:00
{
2012-04-13 12:11:55 -04:00
DownButtonMap : : iterator m = _down_buttons . find ( a ) ;
2012-04-12 23:46:38 -04:00
2012-04-13 12:11:55 -04:00
if ( m = = _down_buttons . end ( ) ) {
_down_buttons [ a ] = DownButtonList ( ) ;
2012-04-12 23:46:38 -04:00
}
2012-04-13 17:46:26 -04:00
_down_buttons [ a ] . insert ( ( surface < < 8 ) | ( strip & 0xf ) ) ;
2012-04-12 23:46:38 -04:00
}
void
2012-04-13 12:11:55 -04:00
MackieControlProtocol : : remove_down_button ( AutomationType a , int surface , int strip )
2012-04-12 23:46:38 -04:00
{
2012-04-13 12:11:55 -04:00
DownButtonMap : : iterator m = _down_buttons . find ( a ) ;
2012-04-12 23:46:38 -04:00
2012-04-13 17:46:26 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " removing surface %1 strip %2 from down buttons for %3 \n " , surface , strip , ( int ) a ) ) ;
2012-04-13 12:11:55 -04:00
if ( m = = _down_buttons . end ( ) ) {
return ;
2012-04-12 23:46:38 -04:00
}
2012-04-13 12:11:55 -04:00
DownButtonList & l ( m - > second ) ;
2012-04-13 17:46:26 -04:00
DownButtonList : : iterator x = find ( l . begin ( ) , l . end ( ) , ( surface < < 8 ) | ( strip & 0xf ) ) ;
2012-04-12 23:46:38 -04:00
2012-04-13 12:11:55 -04:00
if ( x ! = l . end ( ) ) {
l . erase ( x ) ;
2012-04-13 17:46:26 -04:00
} else {
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " surface %1 strip %2 not found in down buttons for %3 \n " ,
surface , strip , ( int ) a ) ) ;
2012-04-12 23:46:38 -04:00
}
}
2012-04-13 12:11:55 -04:00
MackieControlProtocol : : ControlList
MackieControlProtocol : : down_controls ( AutomationType p )
2012-04-12 23:46:38 -04:00
{
2012-04-13 12:11:55 -04:00
ControlList controls ;
RouteList routes ;
2012-04-12 23:46:38 -04:00
2012-04-13 12:11:55 -04:00
DownButtonMap : : iterator m = _down_buttons . find ( p ) ;
2012-04-12 23:46:38 -04:00
2012-04-13 12:11:55 -04:00
if ( m = = _down_buttons . end ( ) ) {
return controls ;
}
2015-10-03 14:03:29 -04:00
2012-04-13 15:17:28 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " looking for down buttons for %1, got %2 \n " ,
p , m - > second . size ( ) ) ) ;
2012-04-13 12:11:55 -04:00
pull_route_range ( m - > second , routes ) ;
2015-10-03 14:03:29 -04:00
2012-04-13 12:11:55 -04:00
switch ( p ) {
case GainAutomation :
for ( RouteList : : iterator r = routes . begin ( ) ; r ! = routes . end ( ) ; + + r ) {
controls . push_back ( ( * r ) - > gain_control ( ) ) ;
}
break ;
case SoloAutomation :
for ( RouteList : : iterator r = routes . begin ( ) ; r ! = routes . end ( ) ; + + r ) {
controls . push_back ( ( * r ) - > solo_control ( ) ) ;
}
break ;
case MuteAutomation :
for ( RouteList : : iterator r = routes . begin ( ) ; r ! = routes . end ( ) ; + + r ) {
controls . push_back ( ( * r ) - > mute_control ( ) ) ;
}
break ;
2012-04-13 17:46:26 -04:00
case RecEnableAutomation :
for ( RouteList : : iterator r = routes . begin ( ) ; r ! = routes . end ( ) ; + + r ) {
boost : : shared_ptr < Track > trk = boost : : dynamic_pointer_cast < Track > ( * r ) ;
if ( trk ) {
controls . push_back ( trk - > rec_enable_control ( ) ) ;
}
}
break ;
2012-04-13 12:11:55 -04:00
default :
break ;
2012-04-12 23:46:38 -04:00
}
2012-04-13 12:11:55 -04:00
return controls ;
2012-04-12 23:46:38 -04:00
}
2015-10-03 14:03:29 -04:00
2012-04-12 23:46:38 -04:00
struct ButtonRangeSorter {
bool operator ( ) ( const uint32_t & a , const uint32_t & b ) {
return ( a > > 8 ) < ( b > > 8 ) // a.surface < b.surface
| |
( ( a > > 8 ) = = ( b > > 8 ) & & ( a & 0xf ) < ( b & 0xf ) ) ; // a.surface == b.surface && a.strip < b.strip
}
} ;
void
2012-04-13 17:46:26 -04:00
MackieControlProtocol : : pull_route_range ( DownButtonList & down , RouteList & selected )
2012-04-12 23:46:38 -04:00
{
ButtonRangeSorter cmp ;
if ( down . empty ( ) ) {
return ;
}
2012-04-13 17:46:26 -04:00
list < uint32_t > ldown ;
ldown . insert ( ldown . end ( ) , down . begin ( ) , down . end ( ) ) ;
ldown . sort ( cmp ) ;
2012-04-12 23:46:38 -04:00
2012-04-13 17:46:26 -04:00
uint32_t first = ldown . front ( ) ;
uint32_t last = ldown . back ( ) ;
2015-10-03 14:03:29 -04:00
2012-04-12 23:46:38 -04:00
uint32_t first_surface = first > > 8 ;
2012-04-13 15:17:28 -04:00
uint32_t first_strip = first & 0xf ;
2012-04-12 23:46:38 -04:00
uint32_t last_surface = last > > 8 ;
2012-04-13 15:17:28 -04:00
uint32_t last_strip = last & 0xf ;
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " PRR %5 in list %1.%2 - %3.%4 \n " , first_surface , first_strip , last_surface , last_strip ,
down . size ( ) ) ) ;
2015-10-03 14:03:29 -04:00
2012-12-31 11:04:46 -05:00
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
2012-04-12 23:46:38 -04:00
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
2015-10-03 14:03:29 -04:00
2012-04-12 23:46:38 -04:00
if ( ( * s ) - > number ( ) > = first_surface & & ( * s ) - > number ( ) < = last_surface ) {
uint32_t fs ;
uint32_t ls ;
if ( ( * s ) - > number ( ) = = first_surface ) {
fs = first_strip ;
} else {
fs = 0 ;
}
if ( ( * s ) - > number ( ) = = last_surface ) {
ls = last_strip ;
2012-04-13 18:10:41 -04:00
ls + = 1 ;
2012-04-12 23:46:38 -04:00
} else {
ls = ( * s ) - > n_strips ( ) ;
}
2012-04-13 15:17:28 -04:00
DEBUG_TRACE ( DEBUG : : MackieControl , string_compose ( " adding strips for surface %1 (%2 .. %3) \n " ,
( * s ) - > number ( ) , fs , ls ) ) ;
2012-04-12 23:46:38 -04:00
for ( uint32_t n = fs ; n < ls ; + + n ) {
boost : : shared_ptr < Route > r = ( * s ) - > nth_strip ( n ) - > route ( ) ;
if ( r ) {
selected . push_back ( r ) ;
}
}
}
}
}
2012-04-25 17:21:36 -04:00
void
MackieControlProtocol : : set_ipmidi_base ( int16_t portnum )
{
/* this will not be saved without a session save, so .. */
session - > set_dirty ( ) ;
_ipmidi_base = portnum ;
/* if the current device uses ipMIDI we need
to restart .
*/
2013-12-21 15:30:07 -05:00
if ( active ( ) & & _device_info . uses_ipmidi ( ) ) {
2012-04-25 17:21:36 -04:00
needs_ipmidi_restart = true ;
}
}
2013-09-06 10:39:14 -04:00
int
2012-04-25 17:21:36 -04:00
MackieControlProtocol : : ipmidi_restart ( )
{
2012-12-31 11:04:46 -05:00
clear_surfaces ( ) ;
2013-09-06 10:39:14 -04:00
if ( create_surfaces ( ) ) {
return - 1 ;
}
2012-04-25 17:21:36 -04:00
switch_banks ( _current_initial_bank , true ) ;
needs_ipmidi_restart = false ;
2013-09-06 10:39:14 -04:00
return 0 ;
2012-04-25 17:21:36 -04:00
}
2012-12-31 11:04:46 -05:00
void
MackieControlProtocol : : clear_surfaces ( )
{
2013-12-21 15:30:07 -05:00
clear_ports ( ) ;
2015-10-09 14:01:22 -04:00
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
_master_surface . reset ( ) ;
surfaces . clear ( ) ;
}
2012-12-31 11:04:46 -05:00
}
2015-10-02 21:54:40 -04:00
void
MackieControlProtocol : : set_touch_sensitivity ( int sensitivity )
{
sensitivity = min ( 9 , sensitivity ) ;
sensitivity = max ( 0 , sensitivity ) ;
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > set_touch_sensitivity ( sensitivity ) ;
}
}
void
MackieControlProtocol : : recalibrate_faders ( )
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > recalibrate_faders ( ) ;
}
}
void
MackieControlProtocol : : toggle_backlight ( )
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
( * s ) - > toggle_backlight ( ) ;
}
}
2015-10-08 21:23:48 -04:00
2015-10-10 17:13:04 -04:00
boost : : shared_ptr < Surface >
MackieControlProtocol : : get_surface_by_raw_pointer ( void * ptr ) const
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
if ( ( * s ) . get ( ) = = ( Surface * ) ptr ) {
return * s ;
}
}
return boost : : shared_ptr < Surface > ( ) ;
}
2015-10-08 21:23:48 -04:00
boost : : shared_ptr < Surface >
MackieControlProtocol : : nth_surface ( uint32_t n ) const
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s , - - n ) {
if ( n = = 0 ) {
return * s ;
}
}
return boost : : shared_ptr < Surface > ( ) ;
}
2015-10-09 14:01:22 -04:00
void
MackieControlProtocol : : connection_handler ( boost : : weak_ptr < ARDOUR : : Port > wp1 , std : : string name1 , boost : : weak_ptr < ARDOUR : : Port > wp2 , std : : string name2 , bool yn )
{
2015-10-10 17:13:04 -04:00
Surfaces scopy ;
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
scopy = surfaces ;
}
2015-10-09 14:01:22 -04:00
2015-10-10 17:13:04 -04:00
for ( Surfaces : : const_iterator s = scopy . begin ( ) ; s ! = scopy . end ( ) ; + + s ) {
2015-10-09 14:01:22 -04:00
if ( ( * s ) - > connection_handler ( wp1 , name1 , wp2 , name2 , yn ) ) {
ConnectionChange ( * s ) ;
break ;
}
}
}
2015-10-18 21:13:16 -04:00
2015-10-18 22:55:56 -04:00
bool
MackieControlProtocol : : is_track ( boost : : shared_ptr < Route > r ) const
{
return boost : : dynamic_pointer_cast < Track > ( r ) ! = 0 ;
}
bool
MackieControlProtocol : : is_audio_track ( boost : : shared_ptr < Route > r ) const
{
return boost : : dynamic_pointer_cast < AudioTrack > ( r ) ! = 0 ;
}
2015-10-18 21:13:16 -04:00
bool
MackieControlProtocol : : is_midi_track ( boost : : shared_ptr < Route > r ) const
{
return boost : : dynamic_pointer_cast < MidiTrack > ( r ) ! = 0 ;
}
2015-10-20 21:54:56 -04:00
bool
MackieControlProtocol : : selected ( boost : : shared_ptr < Route > r ) const
{
const RouteNotificationList * rl = & _last_selected_routes ;
for ( ARDOUR : : RouteNotificationList : : const_iterator i = rl - > begin ( ) ; i ! = rl - > end ( ) ; + + i ) {
boost : : shared_ptr < ARDOUR : : Route > rt = ( * i ) . lock ( ) ;
if ( rt = = r ) {
return true ;
}
}
return false ;
}
2015-12-11 11:46:39 -05:00
2016-01-15 16:16:24 -05:00
bool
MackieControlProtocol : : is_hidden ( boost : : shared_ptr < Route > r ) const
{
2016-01-15 16:58:08 -05:00
if ( ! r ) {
return false ;
}
2016-01-17 17:17:02 -05:00
return ( ( ( r - > remote_control_id ( ) ) > > 31 ) ! = 0 ) ;
2016-01-15 16:16:24 -05:00
}
2015-12-11 11:46:39 -05:00
boost : : shared_ptr < Route >
MackieControlProtocol : : first_selected_route ( ) const
{
if ( _last_selected_routes . empty ( ) ) {
return boost : : shared_ptr < Route > ( ) ;
}
boost : : shared_ptr < Route > r = _last_selected_routes . front ( ) . lock ( ) ;
return r ; /* may be null */
}
boost : : shared_ptr < Route >
MackieControlProtocol : : subview_route ( ) const
{
return _subview_route ;
}
2015-12-14 22:22:34 -05:00
uint32_t
MackieControlProtocol : : global_index ( Strip & strip )
{
Glib : : Threads : : Mutex : : Lock lm ( surfaces_lock ) ;
uint32_t global = 0 ;
for ( Surfaces : : const_iterator s = surfaces . begin ( ) ; s ! = surfaces . end ( ) ; + + s ) {
if ( ( * s ) . get ( ) = = strip . surface ( ) ) {
return global + strip . index ( ) ;
}
global + = ( * s ) - > n_strips ( ) ;
}
return global ;
}
2015-12-28 10:14:17 -05:00
void *
MackieControlProtocol : : request_factory ( uint32_t num_requests )
{
/* AbstractUI<T>::request_buffer_factory() is a template method only
instantiated in this source module . To provide something visible for
use in the interface / descriptor , we have this static method that is
template - free .
*/
return request_buffer_factory ( num_requests ) ;
}