2011-05-04 05:22:11 -04:00
/*
2019-08-03 08:34:29 -04:00
* Copyright ( C ) 2006 - 2007 John Anderson
* Copyright ( C ) 2011 Carl Hetherington < carl @ carlh . net >
* Copyright ( C ) 2012 - 2019 Paul Davis < paul @ linuxaudiosystems . com >
* Copyright ( C ) 2014 - 2015 Robin Gareus < robin @ gareus . org >
* Copyright ( C ) 2015 - 2017 Len Ovens < len @ ovenwerks . net >
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* 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 . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2011-05-04 05:22:11 -04:00
# include <gtkmm/comboboxtext.h>
# include <gtkmm/box.h>
2011-05-05 18:44:50 -04:00
# include <gtkmm/spinbutton.h>
# include <gtkmm/table.h>
2012-04-13 13:06:35 -04:00
# include <gtkmm/treeview.h>
# include <gtkmm/liststore.h>
# include <gtkmm/treestore.h>
# include <gtkmm/notebook.h>
# include <gtkmm/cellrenderercombo.h>
2012-04-18 12:21:16 -04:00
# include <gtkmm/scale.h>
# include <gtkmm/alignment.h>
2012-04-13 13:06:35 -04:00
2015-10-08 21:55:31 -04:00
# include "pbd/error.h"
2015-10-12 13:36:22 -04:00
# include "pbd/unwind.h"
2012-04-13 16:27:08 -04:00
# include "pbd/strsplit.h"
2015-10-12 13:36:22 -04:00
# include "pbd/stacktrace.h"
2012-04-13 16:27:08 -04:00
2012-04-13 13:06:35 -04:00
# include "gtkmm2ext/actions.h"
2019-04-20 08:08:36 -04:00
# include "gtkmm2ext/action_model.h"
2015-09-01 15:46:59 -04:00
# include "gtkmm2ext/bindings.h"
2015-10-08 21:55:31 -04:00
# include "gtkmm2ext/gui_thread.h"
# include "gtkmm2ext/utils.h"
2012-04-12 08:58:42 -04:00
2015-10-03 13:13:52 -04:00
# include "ardour/audioengine.h"
2015-10-08 21:55:31 -04:00
# include "ardour/port.h"
2012-04-21 22:15:24 -04:00
# include "ardour/rc_configuration.h"
2011-05-04 05:22:11 -04:00
# include "mackie_control_protocol.h"
2012-04-12 08:58:42 -04:00
# include "device_info.h"
2012-04-13 13:06:35 -04:00
# include "gui.h"
2015-10-08 21:55:31 -04:00
# include "surface.h"
# include "surface_port.h"
2012-04-12 08:58:42 -04:00
2016-07-14 14:44:52 -04:00
# include "pbd/i18n.h"
2011-05-04 05:22:11 -04:00
using namespace std ;
2012-04-13 13:06:35 -04:00
using namespace Gtk ;
2015-04-15 20:37:20 -04:00
using namespace ArdourSurface ;
using namespace Mackie ;
2011-05-04 05:22:11 -04:00
void *
MackieControlProtocol : : get_gui ( ) const
{
if ( ! _gui ) {
const_cast < MackieControlProtocol * > ( this ) - > build_gui ( ) ;
}
2014-09-13 10:59:02 -04:00
static_cast < Gtk : : Notebook * > ( _gui ) - > show_all ( ) ;
2011-05-04 05:22:11 -04:00
return _gui ;
}
void
MackieControlProtocol : : tear_down_gui ( )
{
2014-09-13 10:59:02 -04:00
if ( _gui ) {
Gtk : : Widget * w = static_cast < Gtk : : Widget * > ( _gui ) - > get_parent ( ) ;
if ( w ) {
w - > hide ( ) ;
delete w ;
}
}
2011-05-04 05:22:11 -04:00
delete ( MackieControlProtocolGUI * ) _gui ;
2014-09-13 10:59:02 -04:00
_gui = 0 ;
2011-05-04 05:22:11 -04:00
}
void
MackieControlProtocol : : build_gui ( )
{
_gui = ( void * ) new MackieControlProtocolGUI ( * this ) ;
}
MackieControlProtocolGUI : : MackieControlProtocolGUI ( MackieControlProtocol & p )
: _cp ( p )
2015-10-08 21:55:31 -04:00
, table ( 2 , 9 )
2019-04-20 08:08:36 -04:00
, action_model ( ActionManager : : ActionModel : : instance ( ) )
2012-04-18 12:21:16 -04:00
, touch_sensitivity_adjustment ( 0 , 0 , 9 , 1 , 4 )
, touch_sensitivity_scale ( touch_sensitivity_adjustment )
, recalibrate_fader_button ( _ ( " Recalibrate Faders " ) )
2012-04-25 17:21:36 -04:00
, ipmidi_base_port_adjustment ( _cp . ipmidi_base ( ) , 0 , 32767 , 1 , 1000 )
2012-05-09 12:44:06 -04:00
, discover_button ( _ ( " Discover Mackie Devices " ) )
2015-10-08 21:55:31 -04:00
, _device_dependent_widget ( 0 )
2017-05-05 17:38:19 -04:00
, _ignore_profile_changed ( false )
2015-10-12 13:36:22 -04:00
, ignore_active_change ( false )
2011-05-04 05:22:11 -04:00
{
2012-04-18 12:21:16 -04:00
Gtk : : Label * l ;
Gtk : : Alignment * align ;
2015-10-03 12:11:04 -04:00
int row = 0 ;
2015-10-05 10:17:49 -04:00
2012-04-13 13:06:35 -04:00
set_border_width ( 12 ) ;
2015-10-08 21:55:31 -04:00
table . set_row_spacings ( 4 ) ;
table . set_col_spacings ( 6 ) ;
table . set_border_width ( 12 ) ;
table . set_homogeneous ( false ) ;
2015-10-03 13:13:52 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Device Type: " ) ) ) ;
2012-04-26 12:18:03 -04:00
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
table . attach ( _surface_combo , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) , 0 , 0 ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-12 08:58:42 -04:00
vector < string > surfaces ;
2015-10-05 10:17:49 -04:00
2012-04-12 08:58:42 -04:00
for ( std : : map < std : : string , DeviceInfo > : : iterator i = DeviceInfo : : device_info . begin ( ) ; i ! = DeviceInfo : : device_info . end ( ) ; + + i ) {
surfaces . push_back ( i - > first ) ;
}
2011-05-04 05:22:11 -04:00
Gtkmm2ext : : set_popdown_strings ( _surface_combo , surfaces ) ;
2012-04-13 13:06:35 -04:00
_surface_combo . signal_changed ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : surface_combo_changed ) ) ;
2011-05-04 05:22:11 -04:00
2015-10-08 21:55:31 -04:00
_cp . DeviceChanged . connect ( device_change_connection , invalidator ( * this ) , boost : : bind ( & MackieControlProtocolGUI : : device_changed , this ) , gui_context ( ) ) ;
2015-10-10 17:13:04 -04:00
_cp . ConnectionChange . connect ( connection_change_connection , invalidator ( * this ) , boost : : bind ( & MackieControlProtocolGUI : : connection_handler , this ) , gui_context ( ) ) ;
2015-10-03 13:13:52 -04:00
2015-10-08 21:55:31 -04:00
ipmidi_base_port_adjustment . signal_value_changed ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : ipmidi_spinner_changed ) ) ;
2015-10-05 10:17:49 -04:00
2015-10-08 21:55:31 -04:00
/* device-dependent part */
2015-10-03 13:13:52 -04:00
2015-10-08 21:55:31 -04:00
device_dependent_row = row ;
2015-10-03 13:13:52 -04:00
2015-10-08 21:55:31 -04:00
if ( _device_dependent_widget ) {
table . remove ( * _device_dependent_widget ) ;
_device_dependent_widget = 0 ;
}
2015-10-03 13:13:52 -04:00
2015-10-08 21:55:31 -04:00
_device_dependent_widget = device_dependent_widget ( ) ;
table . attach ( * _device_dependent_widget , 0 , 12 , row , row + 1 , AttachOptions ( 0 ) , AttachOptions ( 0 ) , 0 , 0 ) ;
2015-10-03 13:13:52 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2015-10-08 21:55:31 -04:00
/* back to the boilerplate */
2015-10-03 13:13:52 -04:00
2012-04-18 12:21:16 -04:00
RadioButtonGroup rb_group = absolute_touch_mode_button . get_group ( ) ;
touch_move_mode_button . set_group ( rb_group ) ;
2015-10-02 21:54:40 -04:00
recalibrate_fader_button . signal_clicked ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : recalibrate_faders ) ) ;
backlight_button . signal_clicked ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : toggle_backlight ) ) ;
touch_sensitivity_adjustment . signal_value_changed ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : touch_sensitive_change ) ) ;
touch_sensitivity_scale . set_update_policy ( Gtk : : UPDATE_DISCONTINUOUS ) ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Button click " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-04-18 12:21:16 -04:00
align = manage ( new Alignment ) ;
align - > set ( 0.0 , 0.5 ) ;
align - > add ( relay_click_button ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * align , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Backlight " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-04-18 12:21:16 -04:00
align = manage ( new Alignment ) ;
align - > set ( 0.0 , 0.5 ) ;
align - > add ( backlight_button ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * align , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Send Fader Position Only When Touched " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-04-18 12:21:16 -04:00
align = manage ( new Alignment ) ;
align - > set ( 0.0 , 0.5 ) ;
align - > add ( absolute_touch_mode_button ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * align , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Send Fader Position When Moved " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-04-18 12:21:16 -04:00
align = manage ( new Alignment ) ;
align - > set ( 0.0 , 0.5 ) ;
align - > add ( touch_move_mode_button ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * align , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Fader Touch Sense Sensitivity " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
2015-10-08 21:55:31 -04:00
table . attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-04-18 12:21:16 -04:00
touch_sensitivity_scale . property_digits ( ) = 0 ;
touch_sensitivity_scale . property_draw_value ( ) = false ;
2015-10-13 07:32:56 -04:00
table . attach ( touch_sensitivity_scale , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-08 21:55:31 -04:00
row + + ;
2015-10-13 07:32:56 -04:00
table . attach ( recalibrate_fader_button , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
2015-10-08 21:55:31 -04:00
table . attach ( discover_button , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
2012-05-09 12:44:06 -04:00
discover_button . signal_clicked ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : discover_clicked ) ) ;
2015-10-03 12:11:04 -04:00
row + + ;
2015-10-05 10:17:49 -04:00
2012-04-17 16:41:31 -04:00
vector < string > profiles ;
2015-10-05 10:17:49 -04:00
2012-04-17 16:41:31 -04:00
for ( std : : map < std : : string , DeviceProfile > : : iterator i = DeviceProfile : : device_profiles . begin ( ) ; i ! = DeviceProfile : : device_profiles . end ( ) ; + + i ) {
2016-02-04 11:23:28 -05:00
cerr < < " add discovered profile " < < i - > first < < endl ;
2012-04-17 16:41:31 -04:00
profiles . push_back ( i - > first ) ;
}
Gtkmm2ext : : set_popdown_strings ( _profile_combo , profiles ) ;
2016-02-04 11:23:28 -05:00
cerr < < " set active profile from " < < p . device_profile ( ) . name ( ) < < endl ;
2012-04-17 16:41:31 -04:00
_profile_combo . set_active_text ( p . device_profile ( ) . name ( ) ) ;
_profile_combo . signal_changed ( ) . connect ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : profile_combo_changed ) ) ;
2015-10-08 21:55:31 -04:00
append_page ( table , _ ( " Device Setup " ) ) ;
table . show_all ( ) ;
2011-05-05 18:44:50 -04:00
2012-04-13 13:06:35 -04:00
/* function key editor */
2011-05-04 05:22:11 -04:00
2012-04-18 08:20:28 -04:00
VBox * fkey_packer = manage ( new VBox ) ;
HBox * profile_packer = manage ( new HBox ) ;
2012-06-06 08:20:57 -04:00
HBox * observation_packer = manage ( new HBox ) ;
2015-10-05 10:17:49 -04:00
2012-04-18 12:21:16 -04:00
l = manage ( new Gtk : : Label ( _ ( " Profile/Settings: " ) ) ) ;
2012-04-18 08:20:28 -04:00
profile_packer - > pack_start ( * l , false , false ) ;
profile_packer - > pack_start ( _profile_combo , true , true ) ;
profile_packer - > set_spacing ( 12 ) ;
profile_packer - > set_border_width ( 12 ) ;
2015-10-05 10:17:49 -04:00
2012-06-06 08:20:57 -04:00
l = manage ( new Gtk : : Label ( _ ( " * Button available at the original Mackie MCU PRO or current device if enabled (NOT implemented yet). Device specific name presented. " ) ) ) ;
observation_packer - > pack_start ( * l , false , false ) ;
2012-04-18 08:20:28 -04:00
fkey_packer - > pack_start ( * profile_packer , false , false ) ;
fkey_packer - > pack_start ( function_key_scroller , true , true ) ;
2012-06-06 08:20:57 -04:00
fkey_packer - > pack_start ( * observation_packer , false , false ) ;
2012-04-18 08:20:28 -04:00
fkey_packer - > set_spacing ( 12 ) ;
function_key_scroller . property_shadow_type ( ) = Gtk : : SHADOW_NONE ;
2012-04-13 13:06:35 -04:00
function_key_scroller . add ( function_key_editor ) ;
2012-04-18 08:20:28 -04:00
append_page ( * fkey_packer , _ ( " Function Keys " ) ) ;
2013-10-15 13:28:01 -04:00
2012-04-17 16:41:31 -04:00
build_function_key_editor ( ) ;
refresh_function_key_editor ( ) ;
2012-04-18 08:20:28 -04:00
fkey_packer - > show_all ( ) ;
2012-04-13 13:06:35 -04:00
}
2015-10-10 17:13:04 -04:00
void
MackieControlProtocolGUI : : connection_handler ( )
{
2015-10-12 13:36:22 -04:00
/* ignore all changes to combobox active strings here, because we're
updating them to match a new ( " external " ) reality - we were called
because port connections have changed .
*/
PBD : : Unwinder < bool > ici ( ignore_active_change , true ) ;
vector < Gtk : : ComboBox * > : : iterator ic ;
vector < Gtk : : ComboBox * > : : iterator oc ;
2015-10-10 17:13:04 -04:00
vector < string > midi_inputs ;
vector < string > midi_outputs ;
2015-10-12 14:42:49 -04:00
ARDOUR : : AudioEngine : : instance ( ) - > get_ports ( " " , ARDOUR : : DataType : : MIDI , ARDOUR : : PortFlags ( ARDOUR : : IsOutput | ARDOUR : : IsTerminal ) , midi_inputs ) ;
ARDOUR : : AudioEngine : : instance ( ) - > get_ports ( " " , ARDOUR : : DataType : : MIDI , ARDOUR : : PortFlags ( ARDOUR : : IsInput | ARDOUR : : IsTerminal ) , midi_outputs ) ;
2015-10-10 17:13:04 -04:00
for ( ic = input_combos . begin ( ) , oc = output_combos . begin ( ) ; ic ! = input_combos . end ( ) & & oc ! = output_combos . end ( ) ; + + ic , + + oc ) {
boost : : shared_ptr < Surface > surface = _cp . get_surface_by_raw_pointer ( ( * ic ) - > get_data ( " surface " ) ) ;
if ( surface ) {
update_port_combos ( midi_inputs , midi_outputs , * ic , * oc , surface ) ;
}
}
}
2015-10-09 14:01:22 -04:00
void
MackieControlProtocolGUI : : update_port_combos ( vector < string > const & midi_inputs , vector < string > const & midi_outputs ,
2015-10-12 13:36:22 -04:00
Gtk : : ComboBox * input_combo ,
Gtk : : ComboBox * output_combo ,
2015-10-09 14:01:22 -04:00
boost : : shared_ptr < Surface > surface )
{
2015-10-12 13:36:22 -04:00
Glib : : RefPtr < Gtk : : ListStore > input = build_midi_port_list ( midi_inputs , true ) ;
Glib : : RefPtr < Gtk : : ListStore > output = build_midi_port_list ( midi_outputs , false ) ;
2015-10-09 14:01:22 -04:00
bool input_found = false ;
2015-10-12 13:36:22 -04:00
bool output_found = false ;
int n ;
input_combo - > set_model ( input ) ;
output_combo - > set_model ( output ) ;
2015-10-09 14:01:22 -04:00
2015-10-12 13:36:22 -04:00
Gtk : : TreeModel : : Children children = input - > children ( ) ;
Gtk : : TreeModel : : Children : : iterator i ;
i = children . begin ( ) ;
+ + i ; /* skip "Disconnected" */
2015-10-09 14:01:22 -04:00
2015-10-12 13:36:22 -04:00
for ( n = 1 ; i ! = children . end ( ) ; + + i , + + n ) {
string port_name = ( * i ) [ midi_port_columns . full_name ] ;
if ( surface - > port ( ) . input ( ) . connected_to ( port_name ) ) {
input_combo - > set_active ( n ) ;
2015-10-09 14:01:22 -04:00
input_found = true ;
break ;
}
}
if ( ! input_found ) {
2015-10-12 13:36:22 -04:00
input_combo - > set_active ( 0 ) ; /* disconnected */
2015-10-09 14:01:22 -04:00
}
2015-10-12 13:36:22 -04:00
children = output - > children ( ) ;
i = children . begin ( ) ;
+ + i ; /* skip "Disconnected" */
2015-10-09 14:01:22 -04:00
2015-10-12 13:36:22 -04:00
for ( n = 1 ; i ! = children . end ( ) ; + + i , + + n ) {
string port_name = ( * i ) [ midi_port_columns . full_name ] ;
if ( surface - > port ( ) . output ( ) . connected_to ( port_name ) ) {
output_combo - > set_active ( n ) ;
2015-10-09 14:01:22 -04:00
output_found = true ;
break ;
}
}
if ( ! output_found ) {
2015-10-12 13:36:22 -04:00
output_combo - > set_active ( 0 ) ; /* disconnected */
2015-10-09 14:01:22 -04:00
}
}
2015-10-08 21:55:31 -04:00
Gtk : : Widget *
MackieControlProtocolGUI : : device_dependent_widget ( )
{
Gtk : : Table * dd_table ;
Gtk : : Label * l ;
int row = 0 ;
uint32_t n_surfaces = 1 + _cp . device_info ( ) . extenders ( ) ;
2017-01-28 00:44:40 -05:00
uint32_t main_pos = _cp . device_info ( ) . master_position ( ) ;
2015-10-08 21:55:31 -04:00
if ( ! _cp . device_info ( ) . uses_ipmidi ( ) ) {
dd_table = Gtk : : manage ( new Gtk : : Table ( n_surfaces , 2 ) ) ;
} else {
dd_table = Gtk : : manage ( new Gtk : : Table ( 1 , 2 ) ) ;
}
dd_table = Gtk : : manage ( new Gtk : : Table ( 2 , n_surfaces ) ) ;
dd_table - > set_row_spacings ( 4 ) ;
dd_table - > set_col_spacings ( 6 ) ;
dd_table - > set_border_width ( 12 ) ;
_surface_combo . set_active_text ( _cp . device_info ( ) . name ( ) ) ;
vector < string > midi_inputs ;
vector < string > midi_outputs ;
ARDOUR : : AudioEngine : : instance ( ) - > get_ports ( " " , ARDOUR : : DataType : : MIDI , ARDOUR : : PortFlags ( ARDOUR : : IsOutput | ARDOUR : : IsPhysical ) , midi_inputs ) ;
ARDOUR : : AudioEngine : : instance ( ) - > get_ports ( " " , ARDOUR : : DataType : : MIDI , ARDOUR : : PortFlags ( ARDOUR : : IsInput | ARDOUR : : IsPhysical ) , midi_outputs ) ;
2015-10-09 14:01:22 -04:00
input_combos . clear ( ) ;
output_combos . clear ( ) ;
2015-10-08 21:55:31 -04:00
if ( ! _cp . device_info ( ) . uses_ipmidi ( ) ) {
2015-10-09 14:01:22 -04:00
for ( uint32_t n = 0 ; n < n_surfaces ; + + n ) {
2015-10-08 21:55:31 -04:00
boost : : shared_ptr < Surface > surface = _cp . nth_surface ( n ) ;
if ( ! surface ) {
PBD : : fatal < < string_compose ( _ ( " programming error: %1 \n " ) , string_compose ( " n=%1 surface not found! " , n ) ) < < endmsg ;
2019-09-17 23:57:26 -04:00
abort ( ) ; /*NOTREACHED*/
2015-10-08 21:55:31 -04:00
}
2015-10-12 13:36:22 -04:00
Gtk : : ComboBox * input_combo = manage ( new Gtk : : ComboBox ) ;
Gtk : : ComboBox * output_combo = manage ( new Gtk : : ComboBox ) ;
2015-10-08 21:55:31 -04:00
2015-10-12 13:36:22 -04:00
update_port_combos ( midi_inputs , midi_outputs , input_combo , output_combo , surface ) ;
2015-10-08 21:55:31 -04:00
2015-10-12 13:36:22 -04:00
input_combo - > pack_start ( midi_port_columns . short_name ) ;
input_combo - > set_data ( " surface " , surface . get ( ) ) ;
2015-10-09 14:01:22 -04:00
input_combos . push_back ( input_combo ) ;
2015-10-12 13:36:22 -04:00
output_combo - > pack_start ( midi_port_columns . short_name ) ;
output_combo - > set_data ( " surface " , surface . get ( ) ) ;
2015-10-09 14:01:22 -04:00
output_combos . push_back ( output_combo ) ;
2015-10-12 13:36:22 -04:00
boost : : weak_ptr < Surface > ws ( surface ) ;
input_combo - > signal_changed ( ) . connect ( sigc : : bind ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : active_port_changed ) , input_combo , ws , true ) ) ;
output_combo - > signal_changed ( ) . connect ( sigc : : bind ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : active_port_changed ) , output_combo , ws , false ) ) ;
2015-10-08 21:55:31 -04:00
string send_string ;
string receive_string ;
if ( n_surfaces > 1 ) {
2017-01-28 00:44:40 -05:00
if ( n = = main_pos ) {
2017-01-28 12:35:42 -05:00
send_string = string_compose ( _ ( " Main surface at position %1 sends via: " ) , n + 1 ) ;
receive_string = string_compose ( _ ( " Main surface at position %1 receives via: " ) , n + 1 ) ;
2015-10-08 21:55:31 -04:00
} else {
2017-01-28 12:35:42 -05:00
send_string = string_compose ( _ ( " Extender at position %1 sends via: " ) , n + 1 ) ;
receive_string = string_compose ( _ ( " Extender at position %1 receives via: " ) , n + 1 ) ;
2015-10-08 21:55:31 -04:00
}
} else {
send_string = _ ( " Surface sends via: " ) ;
receive_string = _ ( " Surface receives via: " ) ;
}
l = manage ( new Gtk : : Label ( send_string ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
dd_table - > attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
dd_table - > attach ( * input_combo , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) , 0 , 0 ) ;
row + + ;
l = manage ( new Gtk : : Label ( receive_string ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
dd_table - > attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
dd_table - > attach ( * output_combo , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) , 0 , 0 ) ;
row + + ;
}
} else {
l = manage ( new Gtk : : Label ( _ ( " ipMIDI Port (lowest) " ) ) ) ;
l - > set_alignment ( 1.0 , 0.5 ) ;
Gtk : : SpinButton * ipmidi_base_port_spinner = manage ( new Gtk : : SpinButton ( ipmidi_base_port_adjustment ) ) ;
dd_table - > attach ( * l , 0 , 1 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
dd_table - > attach ( * ipmidi_base_port_spinner , 1 , 2 , row , row + 1 , AttachOptions ( FILL | EXPAND ) , AttachOptions ( 0 ) ) ;
row + + ;
}
return dd_table ;
}
2012-04-13 17:46:26 -04:00
CellRendererCombo *
MackieControlProtocolGUI : : make_action_renderer ( Glib : : RefPtr < TreeStore > model , Gtk : : TreeModelColumnBase column )
{
CellRendererCombo * renderer = manage ( new CellRendererCombo ) ;
renderer - > property_model ( ) = model ;
renderer - > property_editable ( ) = true ;
renderer - > property_text_column ( ) = 0 ;
renderer - > property_has_entry ( ) = false ;
renderer - > signal_edited ( ) . connect ( sigc : : bind ( sigc : : mem_fun ( * this , & MackieControlProtocolGUI : : action_changed ) , column ) ) ;
return renderer ;
}
2012-04-17 16:41:31 -04:00
void
MackieControlProtocolGUI : : build_function_key_editor ( )
{
2012-04-13 13:06:35 -04:00
function_key_editor . append_column ( _ ( " Key " ) , function_key_columns . name ) ;
2012-04-13 15:17:28 -04:00
TreeViewColumn * col ;
2012-04-13 17:46:26 -04:00
CellRendererCombo * renderer ;
2012-04-13 15:17:28 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . plain ) ;
2016-02-04 11:23:28 -05:00
col = manage ( new TreeViewColumn ( _ ( " Plain " ) , * renderer ) ) ;
2012-04-13 17:46:26 -04:00
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . plain ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2015-10-05 10:17:49 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . shift ) ;
2016-02-04 11:23:28 -05:00
col = manage ( new TreeViewColumn ( _ ( " Shift " ) , * renderer ) ) ;
2012-04-13 17:46:26 -04:00
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . shift ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2012-04-13 13:58:36 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . control ) ;
2012-04-13 17:46:26 -04:00
col = manage ( new TreeViewColumn ( _ ( " Control " ) , * renderer ) ) ;
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . control ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2012-04-13 13:58:36 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . option ) ;
2012-04-13 17:46:26 -04:00
col = manage ( new TreeViewColumn ( _ ( " Option " ) , * renderer ) ) ;
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . option ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2012-04-13 13:58:36 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . cmdalt ) ;
2012-04-13 17:46:26 -04:00
col = manage ( new TreeViewColumn ( _ ( " Cmd/Alt " ) , * renderer ) ) ;
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . cmdalt ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2012-04-13 13:58:36 -04:00
2019-04-20 08:08:36 -04:00
renderer = make_action_renderer ( action_model . model ( ) , function_key_columns . shiftcontrol ) ;
2012-04-13 17:46:26 -04:00
col = manage ( new TreeViewColumn ( _ ( " Shift+Control " ) , * renderer ) ) ;
col - > add_attribute ( renderer - > property_text ( ) , function_key_columns . shiftcontrol ) ;
2012-04-13 15:17:28 -04:00
function_key_editor . append_column ( * col ) ;
2012-04-13 13:58:36 -04:00
function_key_model = ListStore : : create ( function_key_columns ) ;
2012-04-17 16:41:31 -04:00
function_key_editor . set_model ( function_key_model ) ;
}
void
MackieControlProtocolGUI : : refresh_function_key_editor ( )
{
function_key_editor . set_model ( Glib : : RefPtr < TreeModel > ( ) ) ;
function_key_model - > clear ( ) ;
/* now fill with data */
2012-04-13 13:58:36 -04:00
2012-04-13 16:27:08 -04:00
TreeModel : : Row row ;
2012-04-17 16:41:31 -04:00
DeviceProfile dp ( _cp . device_profile ( ) ) ;
2012-06-06 08:20:57 -04:00
DeviceInfo di ;
2012-04-17 16:41:31 -04:00
2016-02-04 11:23:28 -05:00
for ( int n = 0 ; n < Mackie : : Button : : FinalGlobalButton ; + + n ) {
2012-04-17 16:41:31 -04:00
2016-02-04 11:23:28 -05:00
Mackie : : Button : : ID bid = ( Mackie : : Button : : ID ) n ;
2012-04-13 17:46:26 -04:00
row = * ( function_key_model - > append ( ) ) ;
2012-06-06 08:20:57 -04:00
if ( di . global_buttons ( ) . find ( bid ) = = di . global_buttons ( ) . end ( ) ) {
row [ function_key_columns . name ] = Mackie : : Button : : id_to_name ( bid ) ;
} else {
row [ function_key_columns . name ] = di . get_global_button_name ( bid ) + " * " ;
}
2012-04-17 16:41:31 -04:00
row [ function_key_columns . id ] = bid ;
Glib : : RefPtr < Gtk : : Action > act ;
string action ;
2012-04-25 17:21:36 -04:00
const string defstring = " \u2022 " ;
2012-04-17 16:41:31 -04:00
2016-02-04 11:23:28 -05:00
/* We only allow plain bindings for Fn keys. All others are
* reserved for hard - coded actions .
*/
2015-10-05 10:17:49 -04:00
2016-02-04 11:23:28 -05:00
if ( bid > = Mackie : : Button : : F1 & & bid < = Mackie : : Button : : F8 ) {
action = dp . get_button_action ( bid , 0 ) ;
if ( action . empty ( ) ) {
row [ function_key_columns . plain ] = defstring ;
} else {
if ( action . find ( ' / ' ) = = string : : npos ) {
/* Probably a key alias */
row [ function_key_columns . plain ] = action ;
2015-10-03 11:08:47 -04:00
} else {
2016-02-04 11:23:28 -05:00
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2016-02-04 11:23:28 -05:00
if ( act ) {
row [ function_key_columns . plain ] = act - > get_label ( ) ;
} else {
row [ function_key_columns . plain ] = defstring ;
}
2015-10-03 11:08:47 -04:00
}
2012-04-17 16:41:31 -04:00
}
}
2016-02-04 11:23:28 -05:00
/* We only allow plain bindings for Fn keys. All others are
* reserved for hard - coded actions .
*/
if ( bid > = Mackie : : Button : : F1 & & bid < = Mackie : : Button : : F8 ) {
action = dp . get_button_action ( bid , MackieControlProtocol : : MODIFIER_SHIFT ) ;
if ( action . empty ( ) ) {
row [ function_key_columns . shift ] = defstring ;
2012-04-17 16:41:31 -04:00
} else {
2016-02-04 11:23:28 -05:00
if ( action . find ( ' / ' ) = = string : : npos ) {
/* Probably a key alias */
row [ function_key_columns . shift ] = action ;
2015-10-03 11:08:47 -04:00
} else {
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2016-02-04 11:23:28 -05:00
if ( act ) {
row [ function_key_columns . shift ] = act - > get_label ( ) ;
} else {
row [ function_key_columns . shift ] = defstring ;
}
2015-10-03 11:08:47 -04:00
}
2012-04-17 16:41:31 -04:00
}
}
2016-02-04 09:48:16 -05:00
action = dp . get_button_action ( bid , MackieControlProtocol : : MODIFIER_CONTROL ) ;
2012-04-17 16:41:31 -04:00
if ( action . empty ( ) ) {
2016-02-04 09:48:16 -05:00
row [ function_key_columns . control ] = defstring ;
2012-04-17 16:41:31 -04:00
} else {
2015-10-03 11:08:47 -04:00
if ( action . find ( ' / ' ) = = string : : npos ) {
/* Probably a key alias */
2016-02-04 09:48:16 -05:00
row [ function_key_columns . control ] = action ;
2012-04-17 16:41:31 -04:00
} else {
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2015-10-03 11:08:47 -04:00
if ( act ) {
2016-02-04 09:48:16 -05:00
row [ function_key_columns . control ] = act - > get_label ( ) ;
2015-10-03 11:08:47 -04:00
} else {
2016-02-04 09:48:16 -05:00
row [ function_key_columns . control ] = defstring ;
2015-10-03 11:08:47 -04:00
}
2012-04-17 16:41:31 -04:00
}
}
action = dp . get_button_action ( bid , MackieControlProtocol : : MODIFIER_OPTION ) ;
if ( action . empty ( ) ) {
row [ function_key_columns . option ] = defstring ;
} else {
2015-10-03 11:08:47 -04:00
if ( action . find ( ' / ' ) = = string : : npos ) {
/* Probably a key alias */
row [ function_key_columns . option ] = action ;
2012-04-17 16:41:31 -04:00
} else {
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2015-10-03 11:08:47 -04:00
if ( act ) {
row [ function_key_columns . option ] = act - > get_label ( ) ;
} else {
row [ function_key_columns . option ] = defstring ;
}
2012-04-17 16:41:31 -04:00
}
}
action = dp . get_button_action ( bid , MackieControlProtocol : : MODIFIER_CMDALT ) ;
if ( action . empty ( ) ) {
row [ function_key_columns . cmdalt ] = defstring ;
} else {
2015-10-03 11:08:47 -04:00
if ( action . find ( ' / ' ) = = string : : npos ) {
/* Probably a key alias */
row [ function_key_columns . cmdalt ] = action ;
2012-04-17 16:41:31 -04:00
} else {
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2015-10-03 11:08:47 -04:00
if ( act ) {
row [ function_key_columns . cmdalt ] = act - > get_label ( ) ;
} else {
row [ function_key_columns . cmdalt ] = defstring ;
}
2012-04-17 16:41:31 -04:00
}
}
action = dp . get_button_action ( bid , ( MackieControlProtocol : : MODIFIER_SHIFT | MackieControlProtocol : : MODIFIER_CONTROL ) ) ;
if ( action . empty ( ) ) {
row [ function_key_columns . shiftcontrol ] = defstring ;
} else {
2019-01-14 09:14:23 -05:00
act = ActionManager : : get_action ( action , false ) ;
2012-04-17 16:41:31 -04:00
if ( act ) {
row [ function_key_columns . shiftcontrol ] = act - > get_label ( ) ;
} else {
row [ function_key_columns . shiftcontrol ] = defstring ;
}
}
2012-04-13 17:46:26 -04:00
}
2012-04-13 13:58:36 -04:00
function_key_editor . set_model ( function_key_model ) ;
2011-05-04 05:22:11 -04:00
}
2015-10-04 14:51:05 -04:00
void
2012-04-13 17:46:26 -04:00
MackieControlProtocolGUI : : action_changed ( const Glib : : ustring & sPath , const Glib : : ustring & text , TreeModelColumnBase col )
2012-04-13 16:39:59 -04:00
{
2015-06-20 12:32:46 -04:00
// Remove Binding is not in the action map but still valid
bool remove ( false ) ;
if ( text = = " Remove Binding " ) {
remove = true ;
}
2012-04-13 16:39:59 -04:00
Gtk : : TreePath path ( sPath ) ;
Gtk : : TreeModel : : iterator row = function_key_model - > get_iter ( path ) ;
2012-04-13 17:46:26 -04:00
if ( row ) {
2012-04-17 16:41:31 -04:00
std : : map < std : : string , std : : string > : : iterator i = action_map . find ( text ) ;
2015-10-05 10:17:49 -04:00
2012-04-17 16:41:31 -04:00
if ( i = = action_map . end ( ) ) {
2015-06-20 12:32:46 -04:00
if ( ! remove ) {
return ;
}
2012-04-17 16:41:31 -04:00
}
2019-01-14 09:14:23 -05:00
Glib : : RefPtr < Gtk : : Action > act = ActionManager : : get_action ( i - > second , false ) ;
2012-04-17 16:41:31 -04:00
2015-06-20 12:32:46 -04:00
if ( act | | remove ) {
2012-04-17 23:24:59 -04:00
/* update visible text, using string supplied by
available action model so that it matches and is found
within the model .
*/
2015-06-20 12:32:46 -04:00
if ( remove ) {
Glib : : ustring dot = " \u2022 " ;
( * row ) . set_value ( col . index ( ) , dot ) ;
} else {
( * row ) . set_value ( col . index ( ) , text ) ;
}
2012-04-17 23:24:59 -04:00
/* update the current DeviceProfile, using the full
* path
*/
int modifier ;
switch ( col . index ( ) ) {
case 3 :
modifier = MackieControlProtocol : : MODIFIER_SHIFT ;
break ;
case 4 :
modifier = MackieControlProtocol : : MODIFIER_CONTROL ;
break ;
case 5 :
modifier = MackieControlProtocol : : MODIFIER_OPTION ;
break ;
case 6 :
modifier = MackieControlProtocol : : MODIFIER_CMDALT ;
break ;
case 7 :
modifier = ( MackieControlProtocol : : MODIFIER_SHIFT | MackieControlProtocol : : MODIFIER_CONTROL ) ;
break ;
default :
modifier = 0 ;
}
2015-06-20 12:32:46 -04:00
if ( remove ) {
_cp . device_profile ( ) . set_button_action ( ( * row ) [ function_key_columns . id ] , modifier , " " ) ;
} else {
_cp . device_profile ( ) . set_button_action ( ( * row ) [ function_key_columns . id ] , modifier , i - > second ) ;
}
2017-05-05 17:38:19 -04:00
_ignore_profile_changed = true ;
_profile_combo . set_active_text ( _cp . device_profile ( ) . name ( ) ) ;
_ignore_profile_changed = false ;
2012-04-25 17:21:36 -04:00
} else {
std : : cerr < < " no such action \n " ;
2012-04-17 16:41:31 -04:00
}
2012-04-13 17:46:26 -04:00
}
2012-04-13 16:39:59 -04:00
}
2011-05-04 05:22:11 -04:00
void
MackieControlProtocolGUI : : surface_combo_changed ( )
{
2015-10-09 14:01:22 -04:00
_cp . set_device ( _surface_combo . get_active_text ( ) , false ) ;
2015-10-08 21:55:31 -04:00
}
2012-04-25 00:42:01 -04:00
2015-10-08 21:55:31 -04:00
void
MackieControlProtocolGUI : : device_changed ( )
{
if ( _device_dependent_widget ) {
table . remove ( * _device_dependent_widget ) ;
_device_dependent_widget = 0 ;
2015-10-03 13:13:52 -04:00
}
2015-10-08 21:55:31 -04:00
_device_dependent_widget = device_dependent_widget ( ) ;
_device_dependent_widget - > show_all ( ) ;
table . attach ( * _device_dependent_widget , 0 , 12 , device_dependent_row , device_dependent_row + 1 , AttachOptions ( 0 ) , AttachOptions ( 0 ) , 0 , 0 ) ;
2011-05-04 05:22:11 -04:00
}
2011-05-05 18:44:50 -04:00
2012-04-17 16:41:31 -04:00
void
MackieControlProtocolGUI : : profile_combo_changed ( )
{
2017-05-05 17:38:19 -04:00
if ( ! _ignore_profile_changed ) {
string profile = _profile_combo . get_active_text ( ) ;
2012-04-17 16:41:31 -04:00
2017-05-05 17:38:19 -04:00
_cp . set_profile ( profile ) ;
2012-04-12 12:41:07 -04:00
2017-05-05 17:38:19 -04:00
refresh_function_key_editor ( ) ;
}
2012-04-21 22:15:24 -04:00
}
2012-04-25 17:21:36 -04:00
void
MackieControlProtocolGUI : : ipmidi_spinner_changed ( )
{
2015-10-08 21:55:31 -04:00
_cp . set_ipmidi_base ( ( int16_t ) lrintf ( ipmidi_base_port_adjustment . get_value ( ) ) ) ;
2012-04-25 17:21:36 -04:00
}
2012-05-09 12:44:06 -04:00
void
MackieControlProtocolGUI : : discover_clicked ( )
{
/* this should help to get things started */
2015-10-07 13:17:42 -04:00
_cp . ping_devices ( ) ;
2012-05-09 12:44:06 -04:00
}
2015-10-02 21:54:40 -04:00
void
MackieControlProtocolGUI : : recalibrate_faders ( )
{
_cp . recalibrate_faders ( ) ;
}
void
MackieControlProtocolGUI : : toggle_backlight ( )
{
_cp . toggle_backlight ( ) ;
}
void
MackieControlProtocolGUI : : touch_sensitive_change ( )
{
int sensitivity = ( int ) touch_sensitivity_adjustment . get_value ( ) ;
_cp . set_touch_sensitivity ( sensitivity ) ;
}
2015-10-12 13:36:22 -04:00
Glib : : RefPtr < Gtk : : ListStore >
MackieControlProtocolGUI : : build_midi_port_list ( vector < string > const & ports , bool for_input )
{
Glib : : RefPtr < Gtk : : ListStore > store = ListStore : : create ( midi_port_columns ) ;
TreeModel : : Row row ;
row = * store - > append ( ) ;
row [ midi_port_columns . full_name ] = string ( ) ;
row [ midi_port_columns . short_name ] = _ ( " Disconnected " ) ;
for ( vector < string > : : const_iterator p = ports . begin ( ) ; p ! = ports . end ( ) ; + + p ) {
row = * store - > append ( ) ;
row [ midi_port_columns . full_name ] = * p ;
2015-11-25 18:30:35 -05:00
std : : string pn = ARDOUR : : AudioEngine : : instance ( ) - > get_pretty_name_by_name ( * p ) ;
if ( pn . empty ( ) ) {
pn = ( * p ) . substr ( ( * p ) . find ( ' : ' ) + 1 ) ;
}
row [ midi_port_columns . short_name ] = pn ;
2015-10-12 13:36:22 -04:00
}
return store ;
}
void
MackieControlProtocolGUI : : active_port_changed ( Gtk : : ComboBox * combo , boost : : weak_ptr < Surface > ws , bool for_input )
{
if ( ignore_active_change ) {
return ;
}
boost : : shared_ptr < Surface > surface = ws . lock ( ) ;
if ( ! surface ) {
return ;
}
TreeModel : : iterator active = combo - > get_active ( ) ;
string new_port = ( * active ) [ midi_port_columns . full_name ] ;
if ( new_port . empty ( ) ) {
if ( for_input ) {
surface - > port ( ) . input ( ) . disconnect_all ( ) ;
} else {
surface - > port ( ) . output ( ) . disconnect_all ( ) ;
}
return ;
}
if ( for_input ) {
if ( ! surface - > port ( ) . input ( ) . connected_to ( new_port ) ) {
surface - > port ( ) . input ( ) . disconnect_all ( ) ;
surface - > port ( ) . input ( ) . connect ( new_port ) ;
}
} else {
if ( ! surface - > port ( ) . output ( ) . connected_to ( new_port ) ) {
surface - > port ( ) . output ( ) . disconnect_all ( ) ;
surface - > port ( ) . output ( ) . connect ( new_port ) ;
}
}
}