diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h index c4ab78e19b..f42d1da9b7 100644 --- a/gtk2_ardour/option_editor.h +++ b/gtk2_ardour/option_editor.h @@ -181,6 +181,23 @@ private: Gtk::Label* _label; ///< label for button, so we can use markup }; +/** Component which allows to add any GTK Widget - intended for single buttons and custom stateless objects */ +class FooOption : public OptionEditorComponent +{ +public: + FooOption (Gtk::Widget *w) : _w (w) {} + + void add_to_page (OptionEditorPage* p) { + add_widget_to_page (p, _w); + } + + Gtk::Widget& tip_widget() { return *_w; } + void set_state_from_config () {} + void parameter_changed (std::string const &) {} +private: + Gtk::Widget *_w; +}; + /** Component which provides the UI to handle a string option using a GTK Entry */ class EntryOption : public Option { diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc index 58ad5b03ff..2e0622fda0 100644 --- a/gtk2_ardour/session_option_editor.cc +++ b/gtk2_ardour/session_option_editor.cc @@ -282,50 +282,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s) sigc::mem_fun (*this, &SessionOptionEditor::get_use_monitor_section), sigc::mem_fun (*this, &SessionOptionEditor::set_use_monitor_section) )); - - /* Misc */ - - add_option (_("Misc"), new OptionEditorHeading (_("MIDI Options"))); - - add_option (_("Misc"), new BoolOption ( - "midi-copy-is-fork", - _("MIDI region copies are independent"), - sigc::mem_fun (*_session_config, &SessionConfiguration::get_midi_copy_is_fork), - sigc::mem_fun (*_session_config, &SessionConfiguration::set_midi_copy_is_fork) - )); - - ComboOption* li = new ComboOption ( - "insert-merge-policy", - _("Policy for handling overlapping notes\n on the same MIDI channel"), - sigc::mem_fun (*_session_config, &SessionConfiguration::get_insert_merge_policy), - sigc::mem_fun (*_session_config, &SessionConfiguration::set_insert_merge_policy) - ); - - li->add (InsertMergeReject, _("never allow them")); - li->add (InsertMergeRelax, _("don't do anything in particular")); - li->add (InsertMergeReplace, _("replace any overlapped existing note")); - li->add (InsertMergeTruncateExisting, _("shorten the overlapped existing note")); - li->add (InsertMergeTruncateAddition, _("shorten the overlapping new note")); - li->add (InsertMergeExtend, _("replace both overlapping notes with a single note")); - - add_option (_("Misc"), li); - - add_option (_("Misc"), new OptionEditorHeading (_("Glue to bars and beats"))); - - add_option (_("Misc"), new BoolOption ( - "glue-new-markers-to-bars-and-beats", - _("Glue new markers to bars and beats"), - sigc::mem_fun (*_session_config, &SessionConfiguration::get_glue_new_markers_to_bars_and_beats), - sigc::mem_fun (*_session_config, &SessionConfiguration::set_glue_new_markers_to_bars_and_beats) - )); - - add_option (_("Misc"), new BoolOption ( - "glue-new-regions-to-bars-and-beats", - _("Glue new regions to bars and beats"), - sigc::mem_fun (*_session_config, &SessionConfiguration::get_glue_new_regions_to_bars_and_beats), - sigc::mem_fun (*_session_config, &SessionConfiguration::set_glue_new_regions_to_bars_and_beats) - )); - + /* Meterbridge */ add_option (_("Meterbridge"), new OptionEditorHeading (_("Route Display"))); add_option (_("Meterbridge"), new BoolOption ( @@ -388,6 +345,55 @@ SessionOptionEditor::SessionOptionEditor (Session* s) sigc::mem_fun (*_session_config, &SessionConfiguration::set_show_name_on_meterbridge) )); + /* Misc */ + + add_option (_("Misc"), new OptionEditorHeading (_("MIDI Options"))); + + add_option (_("Misc"), new BoolOption ( + "midi-copy-is-fork", + _("MIDI region copies are independent"), + sigc::mem_fun (*_session_config, &SessionConfiguration::get_midi_copy_is_fork), + sigc::mem_fun (*_session_config, &SessionConfiguration::set_midi_copy_is_fork) + )); + + ComboOption* li = new ComboOption ( + "insert-merge-policy", + _("Policy for handling overlapping notes\n on the same MIDI channel"), + sigc::mem_fun (*_session_config, &SessionConfiguration::get_insert_merge_policy), + sigc::mem_fun (*_session_config, &SessionConfiguration::set_insert_merge_policy) + ); + + li->add (InsertMergeReject, _("never allow them")); + li->add (InsertMergeRelax, _("don't do anything in particular")); + li->add (InsertMergeReplace, _("replace any overlapped existing note")); + li->add (InsertMergeTruncateExisting, _("shorten the overlapped existing note")); + li->add (InsertMergeTruncateAddition, _("shorten the overlapping new note")); + li->add (InsertMergeExtend, _("replace both overlapping notes with a single note")); + + add_option (_("Misc"), li); + + add_option (_("Misc"), new OptionEditorHeading (_("Glue to bars and beats"))); + + add_option (_("Misc"), new BoolOption ( + "glue-new-markers-to-bars-and-beats", + _("Glue new markers to bars and beats"), + sigc::mem_fun (*_session_config, &SessionConfiguration::get_glue_new_markers_to_bars_and_beats), + sigc::mem_fun (*_session_config, &SessionConfiguration::set_glue_new_markers_to_bars_and_beats) + )); + + add_option (_("Misc"), new BoolOption ( + "glue-new-regions-to-bars-and-beats", + _("Glue new regions to bars and beats"), + sigc::mem_fun (*_session_config, &SessionConfiguration::get_glue_new_regions_to_bars_and_beats), + sigc::mem_fun (*_session_config, &SessionConfiguration::set_glue_new_regions_to_bars_and_beats) + )); + + add_option (_("Misc"), new OptionEditorHeading (_("Defaults"))); + + Gtk::Button* btn = Gtk::manage (new Gtk::Button (_("Use these settings as defaults"))); + btn->signal_clicked().connect (sigc::mem_fun (*this, &SessionOptionEditor::save_defaults)); + add_option (_("Misc"), new FooOption (btn)); + } void @@ -470,3 +476,9 @@ std::string SessionOptionEditor::get_midi_source_dir () } return s; } + +void +SessionOptionEditor::save_defaults () +{ + _session->save_default_options(); +} diff --git a/gtk2_ardour/session_option_editor.h b/gtk2_ardour/session_option_editor.h index a80bbedbfd..d9eacf0da2 100644 --- a/gtk2_ardour/session_option_editor.h +++ b/gtk2_ardour/session_option_editor.h @@ -47,6 +47,8 @@ private: bool set_audio_source_dir(std::string); std::string get_midi_source_dir(); bool set_midi_source_dir(std::string); + + void save_defaults (); }; #endif /* __gtk_ardour_session_option_editor_h__ */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 1ed9566712..7f9e3a6a9b 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -407,6 +407,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop int rename (const std::string&); bool get_nsm_state () const { return _under_nsm_control; } void set_nsm_state (bool state) { _under_nsm_control = state; } + bool save_default_options (); PBD::Signal1 StateSaved; PBD::Signal0 StateReady; diff --git a/libs/ardour/ardour/session_configuration.h b/libs/ardour/ardour/session_configuration.h index e72d19f322..c0af223943 100644 --- a/libs/ardour/ardour/session_configuration.h +++ b/libs/ardour/ardour/session_configuration.h @@ -35,6 +35,9 @@ public: XMLNode& get_variables (); void set_variables (XMLNode const &); + bool load_state (); + bool save_state (); + /* define accessor methods */ #undef CONFIG_VARIABLE diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 16197d869a..474f194f5f 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -300,6 +300,9 @@ Session::Session (AudioEngine &eng, throw failed_constructor (); } + /* load default session properties - if any */ + config.load_state(); + } else { if (load_state (_current_snapshot_name)) { diff --git a/libs/ardour/session_configuration.cc b/libs/ardour/session_configuration.cc index 0cfdb52872..f9f43ba4b2 100644 --- a/libs/ardour/session_configuration.cc +++ b/libs/ardour/session_configuration.cc @@ -17,9 +17,15 @@ */ +#include +#include /* for g_stat() */ +#include /* for build_filename() */ + +#include "pbd/file_utils.h" #include "pbd/pathexpand.h" #include "ardour/types.h" +#include "ardour/filesystem_paths.h" #include "ardour/session_configuration.h" #include "i18n.h" @@ -122,3 +128,67 @@ SessionConfiguration::map_parameters (boost::function& funct #undef CONFIG_VARIABLE #undef CONFIG_VARIABLE_SPECIAL } + + +bool +SessionConfiguration::load_state () +{ + std::string rcfile; + GStatBuf statbuf; + if (find_file (ardour_config_search_path(), "session.rc", rcfile)) { + if (g_stat (rcfile.c_str(), &statbuf)) { + return false; + } + if (statbuf.st_size == 0) { + return false; + } + XMLTree tree; + if (!tree.read (rcfile.c_str())) { + error << string_compose(_("%1: cannot part default session options \"%2\""), PROGRAM_NAME, rcfile) << endmsg; + return false; + } + + XMLNode& root (*tree.root()); + if (root.name() != X_("SessionDefaults")) { + warning << _("Invalid session default XML Root.") << endmsg; + return false; + } + + XMLNode* node; + if (((node = find_named_node (root, X_("Config"))) != 0)) { + LocaleGuard lg (X_("POSIX")); + set_variables(*node); + info << _("Loaded custom session defaults.") << endmsg; + } else { + warning << _("Found no session defaults in XML file.") << endmsg; + return false; + } + + /* CUSTOM OVERRIDES */ + set_audio_search_path(""); + set_midi_search_path(""); + set_raid_path(""); + } + return true; +} + +bool +SessionConfiguration::save_state () +{ + const std::string rcfile = Glib::build_filename (user_config_directory(), "session.rc"); + if (rcfile.empty()) { + return false; + } + + XMLTree tree; + XMLNode* root = new XMLNode(X_("SessionDefaults")); + root->add_child_nocopy (get_variables ()); + tree.set_root (root); + + if (!tree.write (rcfile.c_str())) { + error << _("Could not save session options") << endmsg; + return false; + } + + return true; +} diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index da6b12270b..1df3f31030 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -879,6 +879,12 @@ Session::load_options (const XMLNode& node) return 0; } +bool +Session::save_default_options () +{ + return config.save_state(); +} + XMLNode& Session::get_state() { diff --git a/libs/ardouralsautil/request_device.c b/libs/ardouralsautil/request_device.c index 6bb68ac05a..4ba80ec624 100644 --- a/libs/ardouralsautil/request_device.c +++ b/libs/ardouralsautil/request_device.c @@ -31,6 +31,16 @@ #include "ardouralsautil/reserve.h" +#ifndef ARD_PROG_NAME +#define ARD_PROG_NAME "alsa_request_device" +#endif +#ifndef ARD_APPL_NAME +#define ARD_APPL_NAME "ALSA User" +#endif +#ifndef VERSION +#define VERSION "v0.3" +#endif + static int run = 1; static int release_wait_for_signal = 0; static pid_t parent_pid = 0; @@ -48,7 +58,7 @@ static int stdin_available(void) { } static void print_version(int status) { - printf ("ardour-request-device 0.2\n\n"); + printf (ARD_PROG_NAME " " VERSION "\n\n"); printf ( "Copyright (C) 2014 Robin Gareus \n" "This is free software; see the source for copying conditions. There is NO\n" @@ -58,8 +68,8 @@ static void print_version(int status) { } static void usage(int status) { - printf ("ardour-request-device - DBus Audio Reservation Utility.\n"); - printf ("Usage: ardour-request-device [ OPTIONS ] \n"); + printf (ARD_PROG_NAME " - DBus Audio Reservation Utility.\n"); + printf ("Usage: " ARD_PROG_NAME " [ OPTIONS ] \n"); printf ("Options:\n\ -h, --help display this help and exit\n\ -p, --priority reservation priority (default: int32_max)\n\ @@ -74,23 +84,23 @@ This tool issues a dbus request to reserve an ALSA Audio-device.\n\ If successful other users of the device (e.g. pulseaudio) will\n\ release the device.\n\ \n\ -ardour-request-device by default announces itself as \"Ardour ALSA Backend\"\n\ +" ARD_PROG_NAME " by default announces itself as \"" ARD_APPL_NAME "\"\n\ and uses the maximum possible priority for requesting the device.\n\ These settings can be overriden using the -n and -p options respectively.\n\ \n\ If a PID is given the tool will watch the process and if that is not running\n\ -release the device and exit. Otherwise ardour-request-device runs until\n\ +release the device and exit. Otherwise " ARD_PROG_NAME " runs until\n\ either stdin is closed, a SIGINT or SIGTERM is received or some other\n\ application requests the device with a higher priority.\n\ \n\ -Without the -w option, ardour-request-device yields the device after 500ms to\n\ +Without the -w option, " ARD_PROG_NAME " yields the device after 500ms to\n\ any higher-priority request. With the -w option this tool waits until it\n\ for SIGINT or SIGTERM - but at most 4 sec to acknowledge before releasing.\n\ \n\ The audio-device-id is a string e.g. 'Audio1'\n\ \n\ Examples:\n\ -ardour-request-device Audio0\n\ +" ARD_PROG_NAME " Audio0\n\ \n"); printf ("Report bugs to Robin Gareus \n"); @@ -140,7 +150,7 @@ int main(int argc, char **argv) { int ret, c; int32_t priority = INT32_MAX; - char *name = strdup("Ardour ALSA Backend"); + char *name = strdup(ARD_APPL_NAME); while ((c = getopt_long (argc, argv, "h" /* help */ diff --git a/libs/ardouralsautil/wscript b/libs/ardouralsautil/wscript index 6aeadcd767..d32b2ab4c4 100644 --- a/libs/ardouralsautil/wscript +++ b/libs/ardouralsautil/wscript @@ -50,4 +50,6 @@ def build(bld): obj.defines = [ '_POSIX_SOURCE', '_XOPEN_SOURCE=500', + 'ARD_PROG_NAME="ardour-request-device"', + 'ARD_APPL_NAME="Ardour ALSA Backend"', ] diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h index e084d18566..b14f20b69c 100644 --- a/libs/canvas/canvas/canvas.h +++ b/libs/canvas/canvas/canvas.h @@ -40,8 +40,8 @@ namespace ArdourCanvas { +struct Rect; -class Rect; class Item; class ScrollGroup; diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h index 85beedc6b3..9b058ab83a 100644 --- a/libs/canvas/canvas/item.h +++ b/libs/canvas/canvas/item.h @@ -36,9 +36,9 @@ namespace ArdourCanvas { +struct Rect; class Canvas; -class Rect; class ScrollGroup; /** The parent class for anything that goes on the canvas. diff --git a/libs/canvas/canvas/types.h b/libs/canvas/canvas/types.h index 2800ccc91b..6d952794c9 100644 --- a/libs/canvas/canvas/types.h +++ b/libs/canvas/canvas/types.h @@ -30,7 +30,7 @@ #include "canvas/visibility.h" namespace Cairo { - struct Context; + class Context; } namespace ArdourCanvas