X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=2ef51d80ecce420f3c6ee322d73ea0c78c1bae60;hb=eab3c57b834c3f4dbaeb5d412cdef3a672276c56;hp=30113ece44eba9d9a5eb10754712ad801774c77f;hpb=09f90208976f64f2ecac7977beb9d8c4b6896d21;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 30113ece44..2ef51d80ec 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -33,6 +33,11 @@ #include #endif +#ifdef __FreeBSD__ +#include +#include +#endif + #include #include #include @@ -44,6 +49,7 @@ #include #include +#include #include "pbd/error.h" #include "pbd/basename.h" @@ -71,6 +77,7 @@ #include "ardour/ardour.h" #include "ardour/audio_backend.h" +#include "ardour/audio_track.h" #include "ardour/audioengine.h" #include "ardour/audiofilesource.h" #include "ardour/automation_watch.h" @@ -78,11 +85,13 @@ #include "ardour/filename_extensions.h" #include "ardour/filesystem_paths.h" #include "ardour/ltc_file_reader.h" +#include "ardour/midi_track.h" #include "ardour/port.h" #include "ardour/plugin_manager.h" #include "ardour/process_thread.h" #include "ardour/profile.h" #include "ardour/recent_sessions.h" +#include "ardour/record_enable_control.h" #include "ardour/session_directory.h" #include "ardour/session_route.h" #include "ardour/session_state_utils.h" @@ -90,6 +99,11 @@ #include "ardour/source_factory.h" #include "ardour/slave.h" #include "ardour/system_exec.h" +#include "ardour/track.h" +#include "ardour/vca_manager.h" +#include "ardour/utils.h" + +#include "LuaBridge/LuaBridge.h" #ifdef WINDOWS_VST_SUPPORT #include @@ -98,6 +112,11 @@ #include "ardour/audio_unit.h" #endif +// fix for OSX (nsm.h has a check function, AU/Apple defines check) +#ifdef check +#undef check +#endif + #include "timecode/time.h" typedef uint64_t microseconds_t; @@ -124,6 +143,8 @@ typedef uint64_t microseconds_t; #include "keyboard.h" #include "keyeditor.h" #include "location_ui.h" +#include "lua_script_manager.h" +#include "luawindow.h" #include "main_clock.h" #include "missing_file_dialog.h" #include "missing_plugin_dialog.h" @@ -140,6 +161,7 @@ typedef uint64_t microseconds_t; #include "route_time_axis.h" #include "route_params_ui.h" #include "save_as_dialog.h" +#include "script_selector.h" #include "session_dialog.h" #include "session_metadata_dialog.h" #include "session_option_editor.h" @@ -214,24 +236,24 @@ libxml_structured_error_func (void* /* parsing_context*/, replace_all (msg, "\n", ""); - if (err->file && err->line) { - error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line; + if (!msg.empty()) { + if (err->file && err->line) { + error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line; + + if (err->int2) { + error << ':' << err->int2; + } - if (err->int2) { - error << ':' << err->int2; + error << endmsg; + } else { + error << X_("XML error: ") << msg << endmsg; } } - error << endmsg; } ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) -<<<<<<< HEAD - : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) -======= - : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp) ->>>>>>> first compilable version of tabbable design. , session_loaded (false) , gui_object_state (new GUIObjectState) , primary_clock (new MainClock (X_("primary"), X_("transport"), true )) @@ -240,6 +262,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , video_timeline(0) , global_actions (X_("global")) , ignore_dual_punch (false) + , main_window_visibility (0) , editor (0) , mixer (0) , nsm (0) @@ -268,14 +291,16 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , last_key_press_time (0) , save_as_dialog (0) , meterbridge (0) + , luawindow (0) , rc_option_editor (0) , speaker_config_window (X_("speaker-config"), _("Speaker Configuration")) , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses")) , about (X_("about"), _("About")) - , location_ui (X_("locations"), _("Locations")) + , location_ui (X_("locations"), S_("Ranges|Locations")) , route_params (X_("inspector"), _("Tracks and Busses")) , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup")) , export_video_dialog (X_("video-export"), _("Video Export Dialog")) + , lua_script_window (X_("script-manager"), _("Script Manager")) , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this)) , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this)) , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this)) @@ -293,6 +318,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , _feedback_exists (false) , _log_not_acknowledged (LogLevelNone) , duplicate_routes_dialog (0) + , editor_visibility_button (S_("Window|Editor")) + , mixer_visibility_button (S_("Window|Mixer")) + , prefs_visibility_button (S_("Window|Preferences")) { Gtkmm2ext::init (localedir); @@ -305,10 +333,22 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) _exit (0); } + + if (string (VERSIONSTRING).find (".pre") != string::npos) { + /* check this is not being run from ./ardev etc. */ + if (!running_from_source_tree ()) { + pre_release_dialog (); + } + } + if (theArdourUI == 0) { theArdourUI = this; } + /* track main window visibility */ + + main_window_visibility = new VisibilityTracker (_main_window); + /* stop libxml from spewing to stdout/stderr */ xmlSetGenericErrorFunc (this, libxml_generic_error_func); @@ -356,6 +396,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2)); + /* handle sr mismatch with a dialog - cross-thread from engine */ + ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ()); + /* handle requests to quit (coming from JACK session) */ ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ()); @@ -398,9 +441,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) keyboard->set_state (*node, Stateful::loading_state_version); } - /* we don't like certain modifiers */ - Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK); - UIConfiguration::instance().reset_dpi (); TimeAxisViewItem::set_constant_heights (); @@ -427,10 +467,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) audio_port_matrix.set_state (*ui_xml, 0); midi_port_matrix.set_state (*ui_xml, 0); export_video_dialog.set_state (*ui_xml, 0); + lua_script_window.set_state (*ui_xml, 0); } /* Separate windows */ - + WM::Manager::instance().register_window (&key_editor); WM::Manager::instance().register_window (&session_option_editor); WM::Manager::instance().register_window (&speaker_config_window); @@ -440,12 +481,16 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) WM::Manager::instance().register_window (&route_params); WM::Manager::instance().register_window (&audio_midi_setup); WM::Manager::instance().register_window (&export_video_dialog); + WM::Manager::instance().register_window (&lua_script_window); WM::Manager::instance().register_window (&bundle_manager); WM::Manager::instance().register_window (&location_ui); WM::Manager::instance().register_window (&big_clock_window); WM::Manager::instance().register_window (&audio_port_matrix); WM::Manager::instance().register_window (&midi_port_matrix); + /* do not retain position for add route dialog */ + add_route_dialog.set_state_mask (WindowProxy::Size); + /* Trigger setting up the color scheme and loading the GTK RC file */ UIConfiguration::instance().load_rc_file (false); @@ -458,6 +503,40 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) attach_to_engine (); } +void +ARDOUR_UI::pre_release_dialog () +{ + ArdourDialog d (_("Pre-Release Warning"), true, false); + d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + + Label* label = manage (new Label); + label->set_markup (string_compose (_("Welcome to this pre-release build of %1 %2\n\n\ +There are still several issues and bugs to be worked on,\n\ +as well as general workflow improvements, before this can be considered\n\ +release software. So, a few guidelines:\n\ +\n\ +1) Please do NOT use this software with the expectation that it is stable or reliable\n\ + though it may be so, depending on your workflow.\n\ +2) Please wait for a helpful writeup of new features.\n\ +3) Please do NOT use the forums at ardour.org to report issues.\n\ +4) Please DO use the bugtracker at http://tracker.ardour.org/ to report issues\n\ + making sure to note the product version number as 5.0-pre.\n\ +5) Please DO use the ardour-users mailing list to discuss ideas and pass on comments.\n\ +6) Please DO join us on IRC for real time discussions about %1 %2. You\n\ + can get there directly from within the program via the Help->Chat menu option.\n\ +\n\ +Full information on all the above can be found on the support page at\n\ +\n\ + http://ardour.org/support\n\ +"), PROGRAM_NAME, VERSIONSTRING)); + + d.get_vbox()->set_border_width (12); + d.get_vbox()->pack_start (*label, false, false, 12); + d.get_vbox()->show_all (); + + d.run (); +} + GlobalPortMatrixWindow* ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type) { @@ -592,20 +671,24 @@ ARDOUR_UI::post_engine () if (ARDOUR_COMMAND_LINE::show_key_actions) { - for (list::const_iterator mb = Bindings::bindings.begin(); mb != Bindings::bindings.end(); ++mb) { - vector names; - vector paths; - vector keys; + vector paths; + vector labels; + vector tooltips; + vector keys; + vector > actions; + + Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions); + + vector::iterator k; + vector::iterator p; -#warning Paul fix this before tabbed is merged - // mb->second->get_all_actions (names, paths, keys); - - vector::iterator n; - vector::iterator k; - vector::iterator p; - for (n = names.begin(), k = keys.begin(), p = paths.begin(); n != names.end(); ++n, ++k, ++p) { - cout << "Action: '" << (*n) << "' bound to '" << (*k) << "' Path: '" << (*p) << "'" << endl; + for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) { + + if ((*k).empty()) { + cout << *p << endl; + } else { + cout << *p << " => " << *k << endl; } } @@ -613,7 +696,7 @@ ARDOUR_UI::post_engine () AudioEngine::instance()->stop (); exit (0); } - + /* this being a GUI and all, we want peakfiles */ AudioFileSource::set_build_peakfiles (true); @@ -621,17 +704,12 @@ ARDOUR_UI::post_engine () /* set default clock modes */ - if (Profile->get_sae()) { - primary_clock->set_mode (AudioClock::BBT); - secondary_clock->set_mode (AudioClock::MinSec); - } else { - primary_clock->set_mode (AudioClock::Timecode); - secondary_clock->set_mode (AudioClock::BBT); - } + primary_clock->set_mode (AudioClock::Timecode); + secondary_clock->set_mode (AudioClock::BBT); /* start the time-of-day-clock */ -#ifndef GTKOSX +#ifndef __APPLE__ /* OS X provides a nearly-always visible wallclock, so don't be stupid */ update_wall_clock (); Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1); @@ -655,15 +733,17 @@ ARDOUR_UI::~ARDOUR_UI () if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) { // don't bother at 'real' exit. the OS cleans up for us. - delete big_clock; - delete primary_clock; - delete secondary_clock; - delete _process_thread; - delete meterbridge; - delete editor; - delete mixer; - delete nsm; - delete gui_object_state; + delete big_clock; big_clock = 0; + delete primary_clock; primary_clock = 0; + delete secondary_clock; secondary_clock = 0; + delete _process_thread; _process_thread = 0; + delete meterbridge; meterbridge = 0; + delete luawindow; luawindow = 0; + delete editor; editor = 0; + delete mixer; mixer = 0; + delete nsm; nsm = 0; + delete gui_object_state; gui_object_state = 0; + delete main_window_visibility; FastMeter::flush_pattern_cache (); PixFader::flush_pattern_cache (); } @@ -722,7 +802,7 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/) void ARDOUR_UI::set_transport_controllable_state (const XMLNode& node) { - const XMLProperty* prop; + XMLProperty const * prop; if ((prop = node.property ("roll")) != 0) { roll_controllable->set_id (prop->value()); @@ -1544,7 +1624,7 @@ void ARDOUR_UI::count_recenabled_streams (Route& route) { Track* track = dynamic_cast(&route); - if (track && track->record_enabled()) { + if (track && track->rec_enable_control()->get_value()) { rec_enabled_streams += track->n_inputs().n_total(); } } @@ -1695,6 +1775,10 @@ ARDOUR_UI::open_recent_session () can_return = false; } + if (splash && splash->is_visible()) { + // in 1 second, hide the splash screen + Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000); + } } bool @@ -1702,8 +1786,8 @@ ARDOUR_UI::check_audioengine (Gtk::Window& parent) { if (!AudioEngine::instance()->connected()) { MessageDialog msg (parent, string_compose ( - _("%1 is not connected to any audio backend.\n" - "You cannot open or close sessions in this condition"), + _("%1 is not connected to any audio backend.\n" + "You cannot open or close sessions in this condition"), PROGRAM_NAME)); pop_back_splash (msg); msg.run (); @@ -1715,7 +1799,7 @@ ARDOUR_UI::check_audioengine (Gtk::Window& parent) void ARDOUR_UI::open_session () { - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -1767,10 +1851,27 @@ ARDOUR_UI::open_session () } } +void +ARDOUR_UI::session_add_vca (const string& name_template, uint32_t n) +{ + if (!_session) { + return; + } + + _session->vca_manager().create_vca (n, name_template); +} void -ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& output, RouteGroup* route_group, - uint32_t how_many, const string& name_template, PluginInfoPtr instrument) +ARDOUR_UI::session_add_mixed_track ( + const ChanCount& input, + const ChanCount& output, + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument, + Plugin::PresetRecord* pset, + ARDOUR::PresentationInfo::order_t order) { list > tracks; @@ -1780,7 +1881,7 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out } try { - tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template); + tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal); if (tracks.size() != how_many) { error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg; @@ -1788,24 +1889,72 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out } catch (...) { - MessageDialog msg (_main_window, - string_compose (_("There are insufficient ports available\n\ -to create a new track or bus.\n\ -You should save %1, exit and\n\ -restart with more ports."), PROGRAM_NAME)); - msg.run (); + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (list >::iterator i = tracks.begin(); i != tracks.end(); ++i) { + (*i)->set_strict_io (true); + } } } +void +ARDOUR_UI::session_add_midi_bus ( + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument, + Plugin::PresetRecord* pset, + ARDOUR::PresentationInfo::order_t order) +{ + RouteList routes; + + if (_session == 0) { + warning << _("You cannot add a track without a session already loaded.") << endmsg; + return; + } + + try { + + routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order); + if (routes.size() != how_many) { + error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg; + } + + } + catch (...) { + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { + (*i)->set_strict_io (true); + } + } +} void -ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument) +ARDOUR_UI::session_add_midi_route ( + bool disk, + RouteGroup* route_group, + uint32_t how_many, + const string& name_template, + bool strict_io, + PluginInfoPtr instrument, + Plugin::PresetRecord* pset, + ARDOUR::PresentationInfo::order_t order) { ChanCount one_midi_channel; one_midi_channel.set (DataType::MIDI, 1); if (disk) { - session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument); + session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset, order); + } else { + session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order); } } @@ -1817,8 +1966,9 @@ ARDOUR_UI::session_add_audio_route ( ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many, - string const & name_template - ) + string const & name_template, + bool strict_io, + ARDOUR::PresentationInfo::order_t order) { list > tracks; RouteList routes; @@ -1830,7 +1980,7 @@ ARDOUR_UI::session_add_audio_route ( try { if (track) { - tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template); + tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode); if (tracks.size() != how_many) { error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many) @@ -1839,7 +1989,7 @@ ARDOUR_UI::session_add_audio_route ( } else { - routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template); + routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order); if (routes.size() != how_many) { error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many) @@ -1849,14 +1999,30 @@ ARDOUR_UI::session_add_audio_route ( } catch (...) { - MessageDialog msg (_main_window, - string_compose (_("There are insufficient ports available\n\ + display_insufficient_ports_message (); + return; + } + + if (strict_io) { + for (list >::iterator i = tracks.begin(); i != tracks.end(); ++i) { + (*i)->set_strict_io (true); + } + for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { + (*i)->set_strict_io (true); + } + } +} + +void +ARDOUR_UI::display_insufficient_ports_message () +{ + MessageDialog msg (_main_window, + string_compose (_("There are insufficient ports available\n\ to create a new track or bus.\n\ You should save %1, exit and\n\ restart with more ports."), PROGRAM_NAME)); - pop_back_splash (msg); - msg.run (); - } + pop_back_splash (msg); + msg.run (); } void @@ -1975,14 +2141,14 @@ ARDOUR_UI::trx_record_enable_all_tracks () boost::shared_ptr t = boost::dynamic_pointer_cast (*r); assert (t); - if (t->record_enabled()) { + if (t->rec_enable_control()->get_value()) { none_record_enabled = false; break; } } if (none_record_enabled) { - _session->set_record_enabled (rl, true, Session::rt_cleanup); + _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup); } return none_record_enabled; @@ -2140,7 +2306,12 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode) if (affect_transport) { if (rolling) { _session->request_stop (with_abort, true); - } else { + + } else if (!with_abort) { /* with_abort == true means the + * command was intended to stop + * transport, not start. + */ + /* the only external sync condition we can be in here * would be Engine (JACK) sync, in which case we still * want to do this. @@ -2267,7 +2438,7 @@ ARDOUR_UI::transport_forward (int option) } void -ARDOUR_UI::toggle_record_enable (uint32_t rid) +ARDOUR_UI::toggle_record_enable (uint16_t rid) { if (!_session) { return; @@ -2275,12 +2446,12 @@ ARDOUR_UI::toggle_record_enable (uint32_t rid) boost::shared_ptr r; - if ((r = _session->route_by_remote_id (rid)) != 0) { + if ((r = _session->get_remote_nth_route (rid)) != 0) { boost::shared_ptr t; if ((t = boost::dynamic_pointer_cast(r)) != 0) { - t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup); + t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup); } } } @@ -2550,7 +2721,7 @@ ARDOUR_UI::snapshot_session (bool switch_to_it) prompter.set_name ("Prompter"); prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); if (switch_to_it) { - prompter.set_title (_("Save as...")); + prompter.set_title (_("Snapshot and switch")); prompter.set_prompt (_("New session name")); } else { prompter.set_title (_("Take Snapshot")); @@ -2769,7 +2940,7 @@ ARDOUR_UI::save_template () { ArdourPrompter prompter (true); - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -2841,7 +3012,7 @@ ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& sess { BusProfile bus_profile; - if (nsm || Profile->get_sae()) { + if (nsm) { bus_profile.master_out_channels = 2; bus_profile.input_ac = AutoConnectPhysical; @@ -2929,8 +3100,6 @@ ARDOUR_UI::load_from_application_api (const std::string& path) if (get_session_parameters (true, false)) { exit (1); } - - goto_editor_window (); } } @@ -3177,7 +3346,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri void ARDOUR_UI::close_session() { - if (!check_audioengine(*editor)) { + if (!check_audioengine (_main_window)) { return; } @@ -3190,6 +3359,10 @@ ARDOUR_UI::close_session() if (get_session_parameters (true, false)) { exit (1); } + if (splash && splash->is_visible()) { + // in 1 second, hide the splash screen + Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000); + } } /** @param snap_name Snapshot name (without .ardour suffix). @@ -3790,15 +3963,15 @@ ARDOUR_UI::cleanup_peakfiles () } } -void -ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place) +PresentationInfo::order_t +ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place) { - uint32_t order_hint = UINT32_MAX; - if (editor->get_selection().tracks.empty()) { - return; + return PresentationInfo::max_order; } + PresentationInfo::order_t order_hint = PresentationInfo::max_order; + /* we want the new routes to have their order keys set starting from the highest order key in the selection + 1 (if available). @@ -3807,42 +3980,21 @@ ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place) if (place == AddRouteDialog::AfterSelection) { RouteTimeAxisView *rtav = dynamic_cast (editor->get_selection().tracks.back()); if (rtav) { - order_hint = rtav->route()->order_key(); + order_hint = rtav->route()->presentation_info().order(); order_hint++; } } else if (place == AddRouteDialog::BeforeSelection) { RouteTimeAxisView *rtav = dynamic_cast (editor->get_selection().tracks.front()); if (rtav) { - order_hint = rtav->route()->order_key(); + order_hint = rtav->route()->presentation_info().order(); } } else if (place == AddRouteDialog::First) { order_hint = 0; } else { - /* leave order_hint at UINT32_MAX */ - } - - if (order_hint == UINT32_MAX) { - /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView - * not setting an order hint will place new routes last. - */ - return; + /* leave order_hint at max_order */ } - _session->set_order_hint (order_hint); - - /* create a gap in the existing route order keys to accomodate new routes.*/ - boost::shared_ptr rd = _session->get_routes(); - for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) { - boost::shared_ptr rt (*ri); - - if (rt->is_monitor()) { - continue; - } - - if (rt->order_key () >= order_hint) { - rt->set_order_key (rt->order_key () + add_route_dialog->count()); - } - } + return order_hint; } void @@ -3860,9 +4012,11 @@ ARDOUR_UI::start_duplicate_routes () } void -ARDOUR_UI::add_route (Gtk::Window* /* ignored */) +ARDOUR_UI::add_route () { - int count; + if (!add_route_dialog.get (false)) { + add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished)); + } if (!_session) { return; @@ -3873,7 +4027,14 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) return; } - ResponseType r = (ResponseType) add_route_dialog->run (); + add_route_dialog->set_position (WIN_POS_MOUSE); + add_route_dialog->present(); +} + +void +ARDOUR_UI::add_route_dialog_finished (int r) +{ + int count; add_route_dialog->hide(); @@ -3889,8 +4050,7 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) return; } - setup_order_hint(add_route_dialog->insert_at()); - + PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at()); string template_path = add_route_dialog->track_template(); DisplaySuspender ds; @@ -3909,6 +4069,7 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) PluginInfoPtr instrument = add_route_dialog->requested_instrument (); RouteGroup* route_group = add_route_dialog->route_group (); AutoConnectOption oac = Config->get_output_auto_connect(); + bool strict_io = add_route_dialog->use_strict_io (); if (oac & AutoConnectMaster) { output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio())); @@ -3921,17 +4082,106 @@ ARDOUR_UI::add_route (Gtk::Window* /* ignored */) switch (add_route_dialog->type_wanted()) { case AddRouteDialog::AudioTrack: - session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template); + session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order); break; case AddRouteDialog::MidiTrack: - session_add_midi_track (route_group, count, name_template, instrument); + session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order); break; case AddRouteDialog::MixedTrack: - session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument); + session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order); break; case AddRouteDialog::AudioBus: - session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template); + session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order); break; + case AddRouteDialog::MidiBus: + session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order); + break; + case AddRouteDialog::VCAMaster: + session_add_vca (name_template, count); + break; + } +} + +void +ARDOUR_UI::add_lua_script () +{ + if (!_session) { + return; + } + + LuaScriptInfoPtr spi; + ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session); + switch (ss.run ()) { + case Gtk::RESPONSE_ACCEPT: + spi = ss.script(); + break; + default: + return; + } + ss.hide(); + + std::string script = ""; + + try { + script = Glib::file_get_contents (spi->path); + } catch (Glib::FileError e) { + string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what()); + MessageDialog am (msg); + am.run (); + return; + } + + LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params"); + std::vector reg = _session->registered_lua_functions (); + + ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp); + switch (spd.run ()) { + case Gtk::RESPONSE_ACCEPT: + break; + default: + return; + } + + try { + _session->register_lua_function (spd.name(), script, lsp); + } catch (luabridge::LuaException const& e) { + string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ()); + MessageDialog am (msg); + am.run (); + } catch (SessionException e) { + string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ()); + MessageDialog am (msg); + am.run (); + } +} + +void +ARDOUR_UI::remove_lua_script () +{ + if (!_session) { + return; + } + if (_session->registered_lua_function_count () == 0) { + string msg = _("There are no active Lua session scripts present in this session."); + MessageDialog am (msg); + am.run (); + return; + } + + std::vector reg = _session->registered_lua_functions (); + SessionScriptManager sm ("Remove Lua Session Script", reg); + switch (sm.run ()) { + case Gtk::RESPONSE_ACCEPT: + break; + default: + return; + } + try { + _session->unregister_lua_function (sm.name()); + } catch (luabridge::LuaException const& e) { + string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ()); + MessageDialog am (msg); + am.run (); } } @@ -4648,6 +4898,21 @@ audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual return 1; } +void +ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual) +{ + MessageDialog msg (string_compose (_("\ +This session was created with a sample rate of %1 Hz, but\n\ +%2 is currently running at %3 Hz.\n\ +Audio will be recorded and played at the wrong sample rate.\n\ +Re-Configure the Audio Engine in\n\ +Menu > Window > Audio/Midi Setup"), + desired, PROGRAM_NAME, actual), + true, + Gtk::MESSAGE_WARNING); + msg.run (); +} + void ARDOUR_UI::use_config () { @@ -4831,11 +5096,6 @@ ARDOUR_UI::setup_profile () Profile->set_small_screen (); } - if (g_getenv ("ARDOUR_SAE")) { - Profile->set_sae (); - Profile->set_single_package (); - } - if (g_getenv ("TRX")) { Profile->set_trx (); } @@ -4925,7 +5185,7 @@ ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_pat MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n" "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n" - "From now on, use the -2000 version with older versions of %3"), + "From now on, use the backup copy with older versions of %3"), xml_path, backup_path, PROGRAM_NAME, start_big, end_big, start_mono, end_mono), true); @@ -4967,10 +5227,15 @@ ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate) audio_midi_setup->set_desired_sample_rate (desired_sample_rate); audio_midi_setup->set_position (WIN_POS_CENTER); - int response; + if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) { + audio_midi_setup->try_autostart (); + if (ARDOUR::AudioEngine::instance()->running()) { + return 0; + } + } while (true) { - response = audio_midi_setup->run(); + int response = audio_midi_setup->run(); switch (response) { case Gtk::RESPONSE_OK: if (!AudioEngine::instance()->running()) { @@ -5109,16 +5374,16 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* if (window_icons.empty()) { Glib::RefPtr icon; - if ((icon = ::get_icon ("ardour_icon_16px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) { window_icons.push_back (icon); } - if ((icon = ::get_icon ("ardour_icon_22px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) { window_icons.push_back (icon); } - if ((icon = ::get_icon ("ardour_icon_32px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) { window_icons.push_back (icon); } - if ((icon = ::get_icon ("ardour_icon_48px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) { window_icons.push_back (icon); } } @@ -5126,7 +5391,7 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* if (!window_icons.empty()) { window.set_default_icon_list (window_icons); } - + Gtkmm2ext::WindowTitle title (Glib::get_application_name()); if (!name.empty()) { @@ -5160,15 +5425,15 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) /* until we get ardour bindings working, we are not handling key * releases yet. */ - + if (ev->type != GDK_KEY_PRESS) { return false; } - + if (event_window == &_main_window) { window = event_window; - + /* find current tab contents */ Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); @@ -5180,61 +5445,81 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) } DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings)); - - } else if (event_window != 0) { + + } else { window = event_window; - + /* see if window uses ardour binding system */ bindings = reinterpret_cast(window->get_data ("ardour-bindings")); - } + } /* An empty binding set is treated as if it doesn't exist */ - + if (bindings && bindings->empty()) { bindings = 0; } - + return key_press_focus_accelerator_handler (*window, ev, bindings); } - + +static Gtkmm2ext::Bindings* +get_bindings_from_widget_heirarchy (GtkWidget* w) +{ + void* p = NULL; + + while (w) { + if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) { + break; + } + w = gtk_widget_get_parent (w); + } + + return reinterpret_cast (p); +} + bool ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings) { GtkWindow* win = window.gobj(); GtkWidget* focus = gtk_window_get_focus (win); bool special_handling_of_unmodified_accelerators = false; - /* consider all relevant modifiers but not LOCK or SHIFT */ const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); - GdkModifierType modifier = GdkModifierType (ev->state); - modifier = GdkModifierType (modifier & gtk_accelerator_get_default_mod_mask()); - Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator(modifier); - if (focus) { - + /* some widget has keyboard focus */ if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) { /* A particular kind of focusable widget currently has keyboard * focus. All unmodified key events should go to that widget - * first and not be used as an accelerator by default + * first and not be used as an accelerator by default */ special_handling_of_unmodified_accelerators = true; + + } else { + + Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus); + if (focus_bindings) { + bindings = focus_bindings; + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name())); + } } } - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7\n", + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n", win, ev->keyval, show_gdk_event_state (ev->state), special_handling_of_unmodified_accelerators, Keyboard::some_magic_widget_has_focus(), focus, - (focus ? gtk_widget_get_name (focus) : "no focus widget"))); + (focus ? gtk_widget_get_name (focus) : "no focus widget"), + ((ev->state & mask) ? "yes" : "no"), + window.get_title())); /* This exists to allow us to override the way GTK handles key events. The normal sequence is: @@ -5267,9 +5552,9 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey all "normal text" accelerators. */ - + if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) { - + /* no special handling or there are modifiers in effect: accelerate first */ DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n"); @@ -5281,8 +5566,8 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey if (bindings) { - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 for this event\n", bindings)); - + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings)); + if (bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; @@ -5290,48 +5575,48 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey } DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n"); - - if (global_bindings->activate (k, Bindings::Press)) { + + if (global_bindings && global_bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n"); - + if (gtk_window_propagate_key_event (win, ev)) { DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n"); return true; } } else { - + /* no modifiers, propagate first */ - + DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n"); - + if (gtk_window_propagate_key_event (win, ev)) { DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n"); return true; } DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n"); - KeyboardKey k (ev->state, ev->keyval); + KeyboardKey k (ev->state, ev->keyval); if (bindings) { - + DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n"); - + if (bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } - - } - + + } + DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n"); - - if (global_bindings->activate (k, Bindings::Press)) { + + if (global_bindings && global_bindings->activate (k, Bindings::Press)) { DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } @@ -5344,8 +5629,16 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey void ARDOUR_UI::load_bindings () { - if ((global_bindings = Bindings::get_bindings ("global", global_actions)) == 0) { + if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) { error << _("Global keybindings are missing") << endmsg; } } +void +ARDOUR_UI::cancel_solo () +{ + if (_session) { + _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_control), 0.0, Controllable::NoGroup); + _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window + } +}