2009-05-13 20:15:38 -04:00
/*
2019-08-02 22:01:25 -04:00
* Copyright ( C ) 1999 - 2018 Paul Davis < paul @ linuxaudiosystems . com >
* Copyright ( C ) 2009 - 2011 Carl Hetherington < carl @ carlh . net >
* Copyright ( C ) 2009 - 2012 David Robillard < d @ drobilla . net >
* Copyright ( C ) 2012 - 2016 Tim Mayberry < mojofunk @ gmail . com >
* Copyright ( C ) 2015 - 2019 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 .
*/
2009-05-13 20:15:38 -04:00
# include <unistd.h>
# include <cstdio> /* for snprintf, grrr */
2009-10-14 12:10:01 -04:00
# include <glib.h>
2015-10-05 16:10:58 -04:00
# include "pbd/gstdio_compat.h"
2009-05-13 20:15:38 -04:00
# include <glibmm/miscutils.h>
2023-01-27 14:06:47 -05:00
# include "pbd/convert.h"
2009-05-13 20:15:38 -04:00
# include "pbd/xml++.h"
# include "pbd/file_utils.h"
2015-05-08 17:49:51 -04:00
# include "pbd/replace_all.h"
2009-05-13 20:15:38 -04:00
2021-01-13 11:02:47 -05:00
# include "temporal/types_convert.h"
2013-08-13 21:59:05 -04:00
# include "ardour/audioengine.h"
2017-04-10 06:44:48 -04:00
# include "ardour/disk_reader.h"
# include "ardour/disk_writer.h"
2009-05-13 20:15:38 -04:00
# include "ardour/control_protocol_manager.h"
2020-05-19 13:47:34 -04:00
# include "ardour/filename_extensions.h"
2009-05-13 20:15:38 -04:00
# include "ardour/filesystem_paths.h"
2013-08-13 21:59:05 -04:00
# include "ardour/port.h"
2012-05-24 02:09:29 -04:00
# include "ardour/rc_configuration.h"
2012-04-18 13:46:29 -04:00
# include "ardour/session_metadata.h"
2018-09-18 18:51:59 -04:00
# include "ardour/transport_master_manager.h"
2016-08-24 08:32:51 -04:00
# include "ardour/types_convert.h"
2009-05-13 20:15:38 -04:00
2016-07-14 14:44:52 -04:00
# include "pbd/i18n.h"
2009-05-13 20:15:38 -04:00
using namespace ARDOUR ;
using namespace std ;
using namespace PBD ;
/* this is global so that we do not have to indirect through an object pointer
to reference it .
*/
namespace ARDOUR {
float speed_quietning = 0.251189 ; // -12dB reduction for ffwd or rewind
}
2014-09-04 12:31:30 -04:00
static const char * user_config_file_name = " config " ;
static const char * system_config_file_name = " system_config " ;
2009-05-13 20:15:38 -04:00
RCConfiguration : : RCConfiguration ( )
:
/* construct variables */
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-05-13 20:15:38 -04:00
# define CONFIG_VARIABLE(Type,var,name,value) var (name,value),
# define CONFIG_VARIABLE_SPECIAL(Type,var,name,value,mutator) var (name,value,mutator),
# include "ardour/rc_configuration_vars.h"
# undef CONFIG_VARIABLE
# undef CONFIG_VARIABLE_SPECIAL
_control_protocol_state ( 0 )
2018-09-18 18:51:59 -04:00
, _transport_master_state ( 0 )
2009-05-13 20:15:38 -04:00
{
2023-01-24 19:16:06 -05:00
2023-01-27 17:11:54 -05:00
/* Uncomment the following to get a list of all config variables */
#if 0
2023-01-24 19:16:06 -05:00
# undef CONFIG_VARIABLE
# undef CONFIG_VARIABLE_SPECIAL
# define CONFIG_VARIABLE(Type,var,name,value) _my_variables.insert (std::make_pair ((name), &(var)));
# define CONFIG_VARIABLE_SPECIAL(Type,var,name,value,mutator) _my_variables.insert (std::make_pair ((name), &(var)));
# include "ardour/rc_configuration_vars.h"
# undef CONFIG_VARIABLE
# undef CONFIG_VARIABLE_SPECIAL
2023-01-27 17:11:54 -05:00
for ( auto const & s : _my_variables ) {
std : : cerr < < s . first < < std : : endl ;
}
# endif
2009-05-13 20:15:38 -04:00
}
2010-02-23 15:25:53 -05:00
RCConfiguration : : ~ RCConfiguration ( )
{
delete _control_protocol_state ;
2018-09-18 18:51:59 -04:00
delete _transport_master_state ;
2010-02-23 15:25:53 -05:00
}
2009-05-13 20:15:38 -04:00
int
RCConfiguration : : load_state ( )
{
2012-06-23 01:06:54 -04:00
std : : string rcfile ;
2013-08-04 10:36:07 -04:00
GStatBuf statbuf ;
2009-05-13 20:15:38 -04:00
/* load system configuration first */
2009-10-14 12:10:01 -04:00
2014-09-04 12:31:30 -04:00
if ( find_file ( ardour_config_search_path ( ) , system_config_file_name , rcfile ) ) {
2009-05-13 20:15:38 -04:00
/* stupid XML Parser hates empty files */
2009-10-14 12:10:01 -04:00
2009-05-13 20:15:38 -04:00
if ( g_stat ( rcfile . c_str ( ) , & statbuf ) ) {
return - 1 ;
}
if ( statbuf . st_size ! = 0 ) {
2016-07-20 16:34:00 -04:00
info < < string_compose ( _ ( " Loading system configuration file %1 " ) , rcfile ) < < endmsg ;
2009-10-14 12:10:01 -04:00
2010-02-23 15:25:53 -05:00
XMLTree tree ;
2009-05-13 20:15:38 -04:00
if ( ! tree . read ( rcfile . c_str ( ) ) ) {
2010-03-13 14:22:34 -05:00
error < < string_compose ( _ ( " %1: cannot read system configuration file \" %2 \" " ) , PROGRAM_NAME , rcfile ) < < endmsg ;
2009-05-13 20:15:38 -04:00
return - 1 ;
}
2009-10-14 12:10:01 -04:00
2009-10-15 14:56:11 -04:00
if ( set_state ( * tree . root ( ) , Stateful : : current_state_version ) ) {
2010-03-13 14:22:34 -05:00
error < < string_compose ( _ ( " %1: system configuration file \" %2 \" not loaded successfully. " ) , PROGRAM_NAME , rcfile ) < < endmsg ;
2009-05-13 20:15:38 -04:00
return - 1 ;
}
} else {
2013-01-09 10:05:04 -05:00
error < < string_compose ( _ ( " Your system %1 configuration file is empty. This probably means that there was an error installing %1 " ) , PROGRAM_NAME ) < < endmsg ;
2009-05-13 20:15:38 -04:00
}
}
/* now load configuration file for user */
2014-09-04 12:31:30 -04:00
if ( find_file ( ardour_config_search_path ( ) , user_config_file_name , rcfile ) ) {
2009-05-13 20:15:38 -04:00
/* stupid XML parser hates empty files */
if ( g_stat ( rcfile . c_str ( ) , & statbuf ) ) {
return - 1 ;
}
if ( statbuf . st_size ! = 0 ) {
2016-07-20 16:34:00 -04:00
info < < string_compose ( _ ( " Loading user configuration file %1 " ) , rcfile ) < < endmsg ;
2009-10-14 12:10:01 -04:00
2010-02-23 15:25:53 -05:00
XMLTree tree ;
2009-05-13 20:15:38 -04:00
if ( ! tree . read ( rcfile ) ) {
2010-03-13 14:22:34 -05:00
error < < string_compose ( _ ( " %1: cannot read configuration file \" %2 \" " ) , PROGRAM_NAME , rcfile ) < < endmsg ;
2009-05-13 20:15:38 -04:00
return - 1 ;
}
2009-10-14 12:10:01 -04:00
2009-10-15 14:56:11 -04:00
if ( set_state ( * tree . root ( ) , Stateful : : current_state_version ) ) {
2010-03-13 14:22:34 -05:00
error < < string_compose ( _ ( " %1: user configuration file \" %2 \" not loaded successfully. " ) , PROGRAM_NAME , rcfile ) < < endmsg ;
2009-05-13 20:15:38 -04:00
return - 1 ;
}
} else {
2010-03-13 14:22:34 -05:00
warning < < string_compose ( _ ( " your %1 configuration file is empty. This is not normal. " ) , PROGRAM_NAME ) < < endmsg ;
2009-10-14 12:10:01 -04:00
}
2009-05-13 20:15:38 -04:00
}
return 0 ;
}
int
RCConfiguration : : save_state ( )
{
2014-09-04 12:31:30 -04:00
const std : : string rcfile = Glib : : build_filename ( user_config_directory ( ) , user_config_file_name ) ;
2021-07-06 15:09:19 -04:00
const std : : string tmp = rcfile + temp_suffix ;
2020-05-19 13:47:34 -04:00
XMLTree tree ;
tree . set_root ( & get_state ( ) ) ;
2021-07-06 15:09:19 -04:00
if ( ! tree . write ( tmp . c_str ( ) ) ) {
2020-05-19 13:47:34 -04:00
error < < string_compose ( _ ( " Config file %1 not saved " ) , rcfile ) < < endmsg ;
2021-07-06 15:09:19 -04:00
if ( g_remove ( tmp . c_str ( ) ) ! = 0 ) {
error < < string_compose ( _ ( " Could not remove temporary config file at path \" %1 \" (%2) " ) , tmp , g_strerror ( errno ) ) < < endmsg ;
2020-05-19 13:47:34 -04:00
}
return - 1 ;
}
2009-05-13 20:15:38 -04:00
2021-07-06 15:09:19 -04:00
if ( : : g_rename ( tmp . c_str ( ) , rcfile . c_str ( ) ) ! = 0 ) {
error < < string_compose ( _ ( " Could not rename temporary config file %1 to %2 (%3) " ) , tmp , rcfile , g_strerror ( errno ) ) < < endmsg ;
if ( g_remove ( tmp . c_str ( ) ) ! = 0 ) {
error < < string_compose ( _ ( " Could not remove temporary config file at path \" %1 \" (%2) " ) , tmp , g_strerror ( errno ) ) < < endmsg ;
2009-05-13 20:15:38 -04:00
}
2020-05-19 13:47:34 -04:00
return - 1 ;
2009-05-13 20:15:38 -04:00
}
return 0 ;
}
void
RCConfiguration : : add_instant_xml ( XMLNode & node )
{
Stateful : : add_instant_xml ( node , user_config_directory ( ) ) ;
}
XMLNode *
RCConfiguration : : instant_xml ( const string & node_name )
{
return Stateful : : instant_xml ( node_name , user_config_directory ( ) ) ;
}
XMLNode &
2022-04-06 23:56:32 -04:00
RCConfiguration : : get_state ( ) const
2009-05-13 20:15:38 -04:00
{
XMLNode * root ;
root = new XMLNode ( " Ardour " ) ;
2023-01-27 14:06:47 -05:00
root - > add_child_nocopy ( get_variables ( X_ ( " Config " ) ) ) ;
2009-10-14 12:10:01 -04:00
2012-04-18 13:46:29 -04:00
root - > add_child_nocopy ( SessionMetadata : : Metadata ( ) - > get_user_state ( ) ) ;
2009-05-13 20:15:38 -04:00
if ( _extra_xml ) {
root - > add_child_copy ( * _extra_xml ) ;
}
2009-10-14 12:10:01 -04:00
2009-05-13 20:15:38 -04:00
root - > add_child_nocopy ( ControlProtocolManager : : instance ( ) . get_state ( ) ) ;
2018-11-02 21:36:53 -04:00
if ( TransportMasterManager : : exists ( ) ) {
root - > add_child_nocopy ( TransportMasterManager : : instance ( ) . get_state ( ) ) ;
}
2009-10-14 12:10:01 -04:00
2009-05-13 20:15:38 -04:00
return * root ;
}
XMLNode &
2023-01-27 14:06:47 -05:00
RCConfiguration : : get_variables ( std : : string const & node_name ) const
2009-05-13 20:15:38 -04:00
{
XMLNode * node ;
2023-01-27 14:06:47 -05:00
node = new XMLNode ( node_name ) ;
2009-05-13 20:15:38 -04:00
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-05-13 20:15:38 -04:00
# define CONFIG_VARIABLE(type,var,Name,value) \
var . add_to_node ( * node ) ;
# define CONFIG_VARIABLE_SPECIAL(type,var,Name,value,mutator) \
var . add_to_node ( * node ) ;
# include "ardour/rc_configuration_vars.h"
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-05-13 20:15:38 -04:00
return * node ;
}
int
2012-04-18 13:46:29 -04:00
RCConfiguration : : set_state ( const XMLNode & root , int version )
2009-05-13 20:15:38 -04:00
{
if ( root . name ( ) ! = " Ardour " ) {
return - 1 ;
}
XMLNodeList nlist = root . children ( ) ;
XMLNodeConstIterator niter ;
XMLNode * node ;
2011-06-11 11:35:34 -04:00
Stateful : : save_extra_xml ( root ) ;
2009-05-13 20:15:38 -04:00
for ( niter = nlist . begin ( ) ; niter ! = nlist . end ( ) ; + + niter ) {
node = * niter ;
2010-07-06 20:40:58 -04:00
if ( node - > name ( ) = = " Config " ) {
2009-05-13 20:15:38 -04:00
set_variables ( * node ) ;
2012-04-18 13:46:29 -04:00
} else if ( node - > name ( ) = = " Metadata " ) {
SessionMetadata : : Metadata ( ) - > set_state ( * node , version ) ;
2009-05-13 20:15:38 -04:00
} else if ( node - > name ( ) = = ControlProtocolManager : : state_node_name ) {
_control_protocol_state = new XMLNode ( * node ) ;
2018-09-18 18:51:59 -04:00
} else if ( node - > name ( ) = = TransportMasterManager : : state_node_name ) {
_transport_master_state = new XMLNode ( * node ) ;
2009-05-13 20:15:38 -04:00
}
}
2017-09-18 12:39:17 -04:00
DiskReader : : set_chunk_samples ( minimum_disk_read_bytes . get ( ) / sizeof ( Sample ) ) ;
DiskWriter : : set_chunk_samples ( minimum_disk_write_bytes . get ( ) / sizeof ( Sample ) ) ;
2009-05-13 20:15:38 -04:00
return 0 ;
}
void
RCConfiguration : : set_variables ( const XMLNode & node )
{
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-05-13 20:15:38 -04:00
# define CONFIG_VARIABLE(type,var,name,value) \
2019-04-13 13:19:29 -04:00
if ( var . set_from_node ( node ) ) { \
ParameterChanged ( name ) ; \
}
2009-05-13 20:15:38 -04:00
# define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
2019-04-13 13:19:29 -04:00
if ( var . set_from_node ( node ) ) { \
ParameterChanged ( name ) ; \
}
2009-05-13 20:15:38 -04:00
# include "ardour/rc_configuration_vars.h"
# undef CONFIG_VARIABLE
# undef CONFIG_VARIABLE_SPECIAL
2009-10-14 12:10:01 -04:00
2009-05-13 20:15:38 -04:00
}
void
2009-12-12 10:02:15 -05:00
RCConfiguration : : map_parameters ( boost : : function < void ( std : : string ) > & functor )
2009-05-13 20:15:38 -04:00
{
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-12-12 10:02:15 -05:00
# define CONFIG_VARIABLE(type,var,name,value) functor (name);
# define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) functor (name);
2009-05-13 20:15:38 -04:00
# include "ardour/rc_configuration_vars.h"
# undef CONFIG_VARIABLE
2009-10-14 12:10:01 -04:00
# undef CONFIG_VARIABLE_SPECIAL
2009-05-13 20:15:38 -04:00
}
2015-01-22 12:52:06 -05:00