2010-08-31 10:16:29 -04:00
/*
2019-08-02 17:26:43 -04:00
* Copyright ( C ) 2010 - 2011 Carl Hetherington < carl @ carlh . net >
* Copyright ( C ) 2010 - 2017 Paul Davis < paul @ linuxaudiosystems . com >
* Copyright ( C ) 2011 - 2012 David Robillard < d @ drobilla . net >
* Copyright ( C ) 2013 - 2017 Robin Gareus < robin @ gareus . org >
*
* 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 .
*/
2010-08-31 10:16:29 -04:00
# include <glibmm/objectbase.h>
2017-07-16 21:48:18 -04:00
# include <gtkmm/messagedialog.h>
# include <gtkmm/stock.h>
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
# include "gtkmm2ext/keyboard.h"
2010-08-31 10:16:29 -04:00
# include "ardour/audioengine.h"
# include "ardour/mtdm.h"
2012-05-24 02:09:29 -04:00
# include "ardour/port_insert.h"
# include "ardour/session.h"
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
# include "widgets/binding_proxy.h"
2017-07-16 21:48:18 -04:00
2022-10-11 00:16:10 -04:00
# include "context_menu_helper.h"
2010-08-31 10:16:29 -04:00
# include "gui_thread.h"
2022-10-11 00:16:10 -04:00
# include "latency_gui.h"
# include "port_insert_ui.h"
# include "timers.h"
# include "utils.h"
2016-07-14 14:44:52 -04:00
# include "pbd/i18n.h"
2010-08-31 10:16:29 -04:00
using namespace ARDOUR ;
2023-02-16 18:33:28 -05:00
PortInsertUI : : PortInsertUI ( Gtk : : Window * parent , ARDOUR : : Session * sess , std : : shared_ptr < ARDOUR : : PortInsert > pi )
2017-07-01 12:42:24 -04:00
: _pi ( pi )
2022-10-11 00:16:10 -04:00
, _measure_latency_button ( _ ( " Measure Latency " ) )
, _invert_button ( X_ ( " Ø " ) )
, _input_selector ( parent , sess , pi - > input ( ) )
, _output_selector ( parent , sess , pi - > output ( ) )
, _input_gpm ( sess , 250 )
, _output_gpm ( sess , 250 )
, _parent ( parent )
, _latency_gui ( 0 )
, _latency_dialog ( 0 )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
_latency_hbox . pack_start ( _measure_latency_button , false , false ) ;
_latency_hbox . pack_start ( _edit_latency_button , false , false ) ;
_latency_hbox . pack_start ( _latency_display , false , false ) ;
_latency_hbox . set_spacing ( 4 ) ;
_output_selector . set_min_height_divisor ( 2 ) ;
_input_selector . set_min_height_divisor ( 2 ) ;
_input_vbox . pack_start ( _input_gpm , false , false ) ;
_input_vbox . set_spacing ( 4 ) ;
_input_vbox . set_border_width ( 4 ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
_input_hbox . pack_start ( _input_vbox , false , false ) ;
_input_hbox . pack_start ( _input_selector , true , true ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
_output_vbox . pack_start ( _output_gpm , false , false ) ;
_output_vbox . pack_start ( _invert_button , false , false ) ;
_output_vbox . set_spacing ( 4 ) ;
_output_vbox . set_border_width ( 4 ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
_output_hbox . pack_start ( _output_vbox , false , false ) ;
_output_hbox . pack_start ( _output_selector , true , true ) ;
_notebook . append_page ( _output_hbox , _ ( " Send/Output " ) ) ;
_notebook . append_page ( _input_hbox , _ ( " Return/Input " ) ) ;
_notebook . set_current_page ( 0 ) ;
2011-06-01 13:00:29 -04:00
2017-07-01 12:42:24 -04:00
set_spacing ( 12 ) ;
2022-10-11 00:16:10 -04:00
pack_start ( _notebook , true , true ) ;
pack_start ( _latency_hbox , false , false ) ;
_invert_button . set_controllable ( _pi - > send_polarity_control ( ) ) ;
_invert_button . watch ( ) ;
_invert_button . set_name ( X_ ( " invert button " ) ) ;
_invert_button . signal_button_press_event ( ) . connect ( sigc : : mem_fun ( * this , & PortInsertUI : : invert_press ) , false ) ;
_invert_button . signal_button_release_event ( ) . connect ( sigc : : mem_fun ( * this , & PortInsertUI : : invert_release ) , false ) ;
_edit_latency_button . set_icon ( ArdourWidgets : : ArdourIcon : : LatencyClock ) ;
_edit_latency_button . add_elements ( ArdourWidgets : : ArdourButton : : Text ) ;
_edit_latency_button . signal_clicked . connect ( sigc : : mem_fun ( * this , & PortInsertUI : : edit_latency_button_clicked ) ) ;
_measure_latency_button . set_name ( X_ ( " MeasureLatencyButton " ) ) ;
_measure_latency_button . signal_toggled ( ) . connect ( mem_fun ( * this , & PortInsertUI : : latency_button_toggled ) ) ;
_measure_latency_button . signal_button_press_event ( ) . connect ( sigc : : mem_fun ( * this , & PortInsertUI : : measure_latency_press ) , false ) ;
_input_gpm . setup_meters ( ) ;
_input_gpm . set_fader_name ( X_ ( " SendUIFader " ) ) ;
2023-02-16 18:33:28 -05:00
_input_gpm . set_controls ( std : : shared_ptr < Route > ( ) , _pi - > return_meter ( ) , _pi - > return_amp ( ) , _pi - > return_gain_control ( ) ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
_output_gpm . setup_meters ( ) ;
_output_gpm . set_fader_name ( X_ ( " SendUIFader " ) ) ;
2023-02-16 18:33:28 -05:00
_output_gpm . set_controls ( std : : shared_ptr < Route > ( ) , _pi - > send_meter ( ) , _pi - > send_amp ( ) , _pi - > send_gain_control ( ) ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
Gtkmm2ext : : UI : : instance ( ) - > set_tip ( _invert_button , _ ( " Click to invert polarity of all send channels " ) ) ;
Gtkmm2ext : : UI : : instance ( ) - > set_tip ( _edit_latency_button , _ ( " Edit Latency, manually override measured or I/O reported latency " ) ) ;
2022-10-15 14:40:50 -04:00
Gtkmm2ext : : UI : : instance ( ) - > set_tip ( _measure_latency_button , _ ( " Measure Latency using the first port of each direction \n (note that gain is not applied during measurement). \n Right-click to forget previous measurements, \n and revert to use default port latency. " ) ) ;
2022-10-11 00:16:10 -04:00
_pi - > set_metering ( true ) ;
_pi - > input ( ) - > changed . connect ( _connections , invalidator ( * this ) , boost : : bind ( & PortInsertUI : : return_changed , this , _1 , _2 ) , gui_context ( ) ) ;
_pi - > output ( ) - > changed . connect ( _connections , invalidator ( * this ) , boost : : bind ( & PortInsertUI : : send_changed , this , _1 , _2 ) , gui_context ( ) ) ;
_pi - > LatencyChanged . connect ( _connections , invalidator ( * this ) , boost : : bind ( & PortInsertUI : : set_latency_label , this ) , gui_context ( ) ) ;
_fast_screen_update_connection = Timers : : super_rapid_connect ( sigc : : mem_fun ( * this , & PortInsertUI : : fast_update ) ) ;
set_latency_label ( ) ;
set_measured_status ( NULL ) ;
show_all ( ) ;
}
PortInsertUI : : ~ PortInsertUI ( )
{
_pi - > set_metering ( false ) ;
_fast_screen_update_connection . disconnect ( ) ;
delete _latency_gui ;
delete _latency_dialog ;
2010-08-31 10:16:29 -04:00
}
void
2022-10-11 00:16:10 -04:00
PortInsertUI : : send_changed ( IOChange change , void * /*ignored*/ )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
ENSURE_GUI_THREAD ( * this , & PortInsertUI : : outs_changed , change , ignored ) ;
if ( change . type & IOChange : : ConfigurationChanged ) {
_output_gpm . setup_meters ( ) ;
}
}
void
PortInsertUI : : return_changed ( IOChange change , void * /*ignored*/ )
{
ENSURE_GUI_THREAD ( * this , & PortInsertUI : : outs_changed , change , ignored ) ;
if ( change . type & IOChange : : ConfigurationChanged ) {
_input_gpm . setup_meters ( ) ;
}
}
void
PortInsertUI : : fast_update ( )
{
if ( ! get_mapped ( ) ) {
return ;
}
if ( Config - > get_meter_falloff ( ) > 0.0f ) {
_input_gpm . update_meters ( ) ;
_output_gpm . update_meters ( ) ;
2017-07-01 12:42:24 -04:00
}
2010-08-31 10:16:29 -04:00
}
2022-10-11 00:16:10 -04:00
bool
PortInsertUI : : invert_press ( GdkEventButton * ev )
{
if ( ArdourWidgets : : BindingProxy : : is_bind_action ( ev ) ) {
return false ;
}
if ( ev - > button ! = 1 | | ev - > type = = GDK_2BUTTON_PRESS | | ev - > type = = GDK_3BUTTON_PRESS ) {
return true ;
}
2023-02-16 18:33:28 -05:00
std : : shared_ptr < AutomationControl > ac = _pi - > send_polarity_control ( ) ;
2022-10-11 00:16:10 -04:00
ac - > start_touch ( timepos_t ( ac - > session ( ) . audible_sample ( ) ) ) ;
return true ;
}
bool
PortInsertUI : : invert_release ( GdkEventButton * ev )
{
if ( ev - > button ! = 1 | | ev - > type = = GDK_2BUTTON_PRESS | | ev - > type = = GDK_3BUTTON_PRESS ) {
return true ;
}
2023-02-16 18:33:28 -05:00
std : : shared_ptr < AutomationControl > ac = _pi - > send_polarity_control ( ) ;
2022-10-11 00:16:10 -04:00
ac - > set_value ( _invert_button . get_active ( ) ? 0 : 1 , PBD : : Controllable : : NoGroup ) ;
ac - > stop_touch ( timepos_t ( ac - > session ( ) . audible_sample ( ) ) ) ;
return true ;
}
2010-08-31 10:16:29 -04:00
bool
PortInsertUI : : check_latency_measurement ( )
{
2017-07-01 12:42:24 -04:00
MTDM * mtdm = _pi - > mtdm ( ) ;
2010-08-31 10:16:29 -04:00
2017-07-01 12:42:24 -04:00
if ( mtdm - > resolve ( ) < 0 ) {
2022-10-11 00:16:10 -04:00
_latency_display . set_text ( _ ( " No signal detected " ) ) ;
2017-07-01 12:42:24 -04:00
return true ;
}
2010-08-31 10:16:29 -04:00
2017-07-01 12:42:24 -04:00
if ( mtdm - > err ( ) > 0.3 ) {
mtdm - > invert ( ) ;
mtdm - > resolve ( ) ;
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
samplecnt_t const sample_rate = AudioEngine : : instance ( ) - > sample_rate ( ) ;
2010-08-31 10:16:29 -04:00
2017-07-01 12:42:24 -04:00
if ( sample_rate = = 0 ) {
2022-10-11 00:16:10 -04:00
_latency_display . set_text ( _ ( " Disconnected from audio engine " ) ) ;
2017-07-01 12:42:24 -04:00
_pi - > stop_latency_detection ( ) ;
return false ;
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
if ( ! ( mtdm - > err ( ) > 0.2 | | mtdm - > inv ( ) ) ) {
_pi - > unset_user_latency ( ) ;
_pi - > set_measured_latency ( rint ( mtdm - > del ( ) ) ) ;
_measure_latency_button . set_active ( false ) ;
2017-07-01 12:42:24 -04:00
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
set_measured_status ( mtdm ) ;
2017-07-01 12:42:24 -04:00
return true ;
2010-08-31 10:16:29 -04:00
}
void
2022-10-11 00:16:10 -04:00
PortInsertUI : : forget_measuremed_latency ( )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
_measure_latency_button . set_active ( false ) ;
_pi - > stop_latency_detection ( ) ;
_pi - > set_measured_latency ( 0 ) ;
set_measured_status ( NULL ) ;
2010-08-31 10:16:29 -04:00
}
void
2022-10-11 00:16:10 -04:00
PortInsertUI : : set_latency_label ( )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
samplecnt_t const l = _pi - > effective_latency ( ) ;
float const sr = _pi - > session ( ) . sample_rate ( ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
_edit_latency_button . set_text ( ARDOUR_UI_UTILS : : samples_as_time_string ( l , sr , true ) ) ;
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
if ( _latency_gui ) {
_latency_gui - > refresh ( ) ;
}
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
void
PortInsertUI : : set_measured_status ( MTDM * mtdm )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
samplecnt_t const ml = _pi - > measured_latency ( ) ;
float const sr = _pi - > session ( ) . sample_rate ( ) ;
if ( sr < = 0 | | ml < = 0 ) {
_latency_display . set_text ( " " ) ;
return ;
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
bool set = false ;
if ( mtdm & & ! ( mtdm - > err ( ) > 0.2 | | mtdm - > inv ( ) ) ) {
set = true ;
}
2010-08-31 10:16:29 -04:00
2022-10-11 00:16:10 -04:00
char buf [ 256 ] ;
snprintf ( buf , sizeof ( buf ) , " %s %ld spl = %.2f ms%s%s%s " ,
mtdm ? _ ( " Measured: " ) : _ ( " Previously measured: " ) ,
ml ,
ml * 1000.0f / sr ,
mtdm & & mtdm - > err ( ) > 0.2 ? _ ( " (err) " ) : " " ,
mtdm & & mtdm - > inv ( ) ? _ ( " (inv) " ) : " " ,
set ? _ ( " (set) " ) : " "
) ;
_latency_display . set_text ( buf ) ;
}
2011-11-18 19:56:35 -05:00
2022-10-11 00:16:10 -04:00
void
PortInsertUI : : edit_latency_button_clicked ( )
{
assert ( _pi ) ;
if ( ! _latency_gui ) {
_latency_gui = new LatencyGUI ( * ( _pi . get ( ) ) , _pi - > session ( ) . sample_rate ( ) , _pi - > session ( ) . get_block_size ( ) ) ;
_latency_dialog = new ArdourWindow ( _ ( " Edit Latency " ) ) ;
/* use both keep-above and transient for to try cover as many
different WM ' s as possible .
*/
_latency_dialog - > set_keep_above ( true ) ;
_latency_dialog - > add ( * _latency_gui ) ;
2023-04-03 19:38:33 -04:00
if ( _parent ) {
_latency_dialog - > set_transient_for ( * _parent ) ;
}
2022-10-11 00:16:10 -04:00
}
2011-11-18 19:56:35 -05:00
2022-10-11 00:16:10 -04:00
_latency_gui - > refresh ( ) ;
_latency_dialog - > show_all ( ) ;
2010-08-31 10:16:29 -04:00
}
bool
2022-10-11 00:16:10 -04:00
PortInsertUI : : measure_latency_press ( GdkEventButton * ev )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
if ( Gtkmm2ext : : Keyboard : : is_context_menu_event ( ev ) ) {
using namespace Gtk : : Menu_Helpers ;
Gtk : : Menu * menu = ARDOUR_UI_UTILS : : shared_popup_menu ( ) ;
MenuList & items = menu - > items ( ) ;
items . push_back ( MenuElem ( _ ( " Forget previous measurement " ) , sigc : : mem_fun ( * this , & PortInsertUI : : forget_measuremed_latency ) ) ) ;
menu - > popup ( ev - > button , ev - > time ) ;
return true ;
}
2013-07-07 16:24:15 -04:00
return false ;
2010-08-31 10:16:29 -04:00
}
void
2022-10-11 00:16:10 -04:00
PortInsertUI : : latency_button_toggled ( )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
if ( _measure_latency_button . get_active ( ) ) {
_pi - > start_latency_detection ( ) ;
_latency_display . set_text ( _ ( " Detecting ... " ) ) ;
_latency_timeout = Glib : : signal_timeout ( ) . connect ( mem_fun ( * this , & PortInsertUI : : check_latency_measurement ) , 250 ) ;
} else {
_pi - > stop_latency_detection ( ) ;
_latency_timeout . disconnect ( ) ;
set_measured_status ( NULL ) ;
}
2010-08-31 10:16:29 -04:00
}
void
2022-10-11 00:16:10 -04:00
PortInsertUI : : finished ( IOSelector : : Result r )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
_input_selector . Finished ( r ) ;
_output_selector . Finished ( r ) ;
2010-08-31 10:16:29 -04:00
}
2023-02-16 18:33:28 -05:00
PortInsertWindow : : PortInsertWindow ( Gtk : : Window & parent , ARDOUR : : Session * s , std : : shared_ptr < ARDOUR : : PortInsert > pi )
2022-10-11 00:16:10 -04:00
: ArdourWindow ( parent , string_compose ( _ ( " Port Insert: %1 " ) , pi - > name ( ) ) )
, _portinsertui ( this , s , pi )
2010-08-31 10:16:29 -04:00
{
2022-10-11 00:16:10 -04:00
set_name ( " IOSelectorWindow " ) ;
add ( _portinsertui ) ;
2023-05-15 16:47:12 -04:00
_portinsertui . show ( ) ;
}
PortInsertWindow : : PortInsertWindow ( ARDOUR : : Session * s , std : : shared_ptr < ARDOUR : : PortInsert > pi )
: ArdourWindow ( string_compose ( _ ( " Port Insert: %1 " ) , pi - > name ( ) ) )
, _portinsertui ( this , s , pi )
{
set_name ( " IOSelectorWindow " ) ;
add ( _portinsertui ) ;
_portinsertui . show ( ) ;
2010-08-31 10:16:29 -04:00
}