X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=d01a92ebf659c43a74f8eb22e2d9e9b964134004;hb=0b189a576670a49693331e00ad8e8626f5826af7;hp=d5498a2fc69c728755a650e9883cd4a0478a5a27;hpb=1f88b6d35fcbe9674c82fea26cb2260789f0ed14;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index d5498a2fc6..d01a92ebf6 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -61,10 +61,12 @@ #include "pbd/memento_command.h" #include "pbd/openuri.h" #include "pbd/stl_delete.h" +#include "pbd/types_convert.h" #include "pbd/file_utils.h" #include "pbd/localtime_r.h" #include "pbd/pthread_utils.h" #include "pbd/replace_all.h" +#include "pbd/scoped_file_descriptor.h" #include "pbd/xml++.h" #include "gtkmm2ext/application.h" @@ -93,6 +95,7 @@ #include "ardour/profile.h" #include "ardour/recent_sessions.h" #include "ardour/record_enable_control.h" +#include "ardour/revision.h" #include "ardour/session_directory.h" #include "ardour/session_route.h" #include "ardour/session_state_utils.h" @@ -124,6 +127,7 @@ typedef uint64_t microseconds_t; #include "about.h" #include "editing.h" +#include "enums_convert.h" #include "actions.h" #include "add_route_dialog.h" #include "ambiguous_file_dialog.h" @@ -141,6 +145,7 @@ typedef uint64_t microseconds_t; #include "global_port_matrix.h" #include "gui_object.h" #include "gui_thread.h" +#include "idleometer.h" #include "keyboard.h" #include "keyeditor.h" #include "location_ui.h" @@ -151,6 +156,7 @@ typedef uint64_t microseconds_t; #include "missing_plugin_dialog.h" #include "mixer_ui.h" #include "meterbridge.h" +#include "meter_patterns.h" #include "mouse_cursors.h" #include "nsm.h" #include "opts.h" @@ -167,14 +173,14 @@ typedef uint64_t microseconds_t; #include "session_dialog.h" #include "session_metadata_dialog.h" #include "session_option_editor.h" -#include "shuttle_control.h" #include "speaker_dialog.h" #include "splash.h" #include "startup.h" -#include "theme_manager.h" #include "time_axis_view_item.h" +#include "time_info_box.h" #include "timers.h" #include "utils.h" +#include "utils_videotl.h" #include "video_server_dialog.h" #include "add_video_dialog.h" #include "transcode_video_dialog.h" @@ -272,6 +278,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , _mixer_on_top (false) , _initial_verbose_plugin_scan (false) , first_time_engine_run (true) + , secondary_clock_spacer (0) , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)) , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)) , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)) @@ -279,15 +286,17 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)) , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)) , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)) + , auto_input_button (ArdourButton::led_default_elements) + , time_info_box (0) , auto_return_button (ArdourButton::led_default_elements) , follow_edits_button (ArdourButton::led_default_elements) - , auto_input_button (ArdourButton::led_default_elements) , auditioning_alert_button (_("Audition")) , solo_alert_button (_("Solo")) , feedback_alert_button (_("Feedback")) , error_alert_button ( ArdourButton::just_led_default_elements ) , editor_meter(0) , editor_meter_peak_display() + , _suspend_editor_meter_callbacks (false) , _numpad_locate_happening (false) , _session_is_new (false) , last_key_press_time (0) @@ -303,13 +312,14 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , 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")) + , idleometer (X_("idle-o-meter"), _("Idle'o'Meter")) , 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)) , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this)) , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO)) , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI)) - , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this)) + , key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this)) , video_server_process (0) , splash (0) , have_configure_timeout (false) @@ -329,6 +339,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) UIConfiguration::instance().post_gui_init (); if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) { + { + /* "touch" the been-here-before path now that config has been migrated */ + PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666)); + } MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true); msg.run (); /* configuration was modified, exit immediately */ @@ -470,6 +484,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) midi_port_matrix.set_state (*ui_xml, 0); export_video_dialog.set_state (*ui_xml, 0); lua_script_window.set_state (*ui_xml, 0); + idleometer.set_state (*ui_xml, 0); } /* Separate windows */ @@ -489,6 +504,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) WM::Manager::instance().register_window (&big_clock_window); WM::Manager::instance().register_window (&audio_port_matrix); WM::Manager::instance().register_window (&midi_port_matrix); + WM::Manager::instance().register_window (&idleometer); /* do not retain position for add route dialog */ add_route_dialog.set_state_mask (WindowProxy::Size); @@ -672,6 +688,55 @@ ARDOUR_UI::post_engine () */ if (ARDOUR_COMMAND_LINE::show_key_actions) { + stringstream sstr; + Bindings::save_all_bindings_as_html (sstr); + + if (sstr.str().empty()) { + return; + } + gchar* file_name; + GError *err = NULL; + gint fd; + + if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) { + if (err) { + error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg; + g_error_free (err); + } + return; + } + +#ifdef PLATFORM_WINDOWS + ::close (fd); +#endif + + err = NULL; + + if (!g_file_set_contents (file_name, sstr.str().c_str(), sstr.str().size(), &err)) { +#ifndef PLATFORM_WINDOWS + ::close (fd); +#endif + g_unlink (file_name); + if (err) { + error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg; + g_error_free (err); + } + return; + } + +#ifndef PLATFORM_WINDOWS + ::close (fd); +#endif + + PBD::open_uri (string_compose ("file:///%1", file_name)); + + halt_connection.disconnect (); + AudioEngine::instance()->stop (); + exit (0); + + } + + if (ARDOUR_COMMAND_LINE::show_actions) { vector paths; @@ -679,21 +744,70 @@ ARDOUR_UI::post_engine () vector tooltips; vector keys; vector > actions; + string ver_in = revision; + string ver = ver_in.substr(0, ver_in.find("-")); + + stringstream output; + output << "\n

Menu actions

" << endl; + output << "

\n Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl; + output << " surfaces or scripts.\n

\n" << endl; + output << "

\n The list below shows all available values of action-name as of" << endl; + output << " " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl; + output << " time by running " << PROGRAM_NAME << " with the -A flag.\n

\n" << endl; + output << "\n " << endl; + output << " " << endl; + output << " \n " << endl; Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions); - vector::iterator k; vector::iterator p; + vector::iterator l; - for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) { + for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) { + output << " " << endl; + } + output << " \n
Action NameMenu Name
" << (*p).substr (9, string::npos); + output << "" << *l << "
" << endl; + + // output this mess to a browser for easiest X-platform use + // it is not pretty HTML, but it works and it's main purpose + // is to create raw html to fit in Ardour's manual with no editing + gchar* file_name; + GError *err = NULL; + gint fd; + + if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) { + if (err) { + error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg; + g_error_free (err); + } + return; + } - if ((*k).empty()) { - cout << *p << endl; - } else { - cout << *p << " => " << *k << endl; +#ifdef PLATFORM_WINDOWS + ::close (fd); +#endif + + err = NULL; + + if (!g_file_set_contents (file_name, output.str().c_str(), output.str().size(), &err)) { +#ifndef PLATFORM_WINDOWS + ::close (fd); +#endif + g_unlink (file_name); + if (err) { + error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg; + g_error_free (err); } + return; } +#ifndef PLATFORM_WINDOWS + ::close (fd); +#endif + + PBD::open_uri (string_compose ("file:///%1", file_name)); + halt_connection.disconnect (); AudioEngine::instance()->stop (); exit (0); @@ -739,10 +853,12 @@ ARDOUR_UI::~ARDOUR_UI () delete primary_clock; primary_clock = 0; delete secondary_clock; secondary_clock = 0; delete _process_thread; _process_thread = 0; + delete time_info_box; time_info_box = 0; delete meterbridge; meterbridge = 0; delete luawindow; luawindow = 0; delete editor; editor = 0; delete mixer; mixer = 0; + delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning delete nsm; nsm = 0; delete gui_object_state; gui_object_state = 0; delete main_window_visibility; @@ -804,31 +920,31 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/) void ARDOUR_UI::set_transport_controllable_state (const XMLNode& node) { - XMLProperty const * prop; + std::string str; - if ((prop = node.property ("roll")) != 0) { - roll_controllable->set_id (prop->value()); + if (node.get_property ("roll", str)){ + roll_controllable->set_id (str); } - if ((prop = node.property ("stop")) != 0) { - stop_controllable->set_id (prop->value()); + if (node.get_property ("stop", str)) { + stop_controllable->set_id (str); } - if ((prop = node.property ("goto-start")) != 0) { - goto_start_controllable->set_id (prop->value()); + if (node.get_property ("goto-start", str)) { + goto_start_controllable->set_id (str); } - if ((prop = node.property ("goto-end")) != 0) { - goto_end_controllable->set_id (prop->value()); + if (node.get_property ("goto-end", str)) { + goto_end_controllable->set_id (str); } - if ((prop = node.property ("auto-loop")) != 0) { - auto_loop_controllable->set_id (prop->value()); + if (node.get_property ("auto-loop", str)) { + auto_loop_controllable->set_id (str); } - if ((prop = node.property ("play-selection")) != 0) { - play_selection_controllable->set_id (prop->value()); + if (node.get_property ("play-selection", str)) { + play_selection_controllable->set_id (str); } - if ((prop = node.property ("rec")) != 0) { - rec_controllable->set_id (prop->value()); + if (node.get_property ("rec", str)) { + rec_controllable->set_id (str); } - if ((prop = node.property ("shuttle")) != 0) { - shuttle_box->controllable()->set_id (prop->value()); + if (node.get_property ("shuttle", str)) { + shuttle_box.controllable()->set_id (str); } } @@ -836,24 +952,15 @@ XMLNode& ARDOUR_UI::get_transport_controllable_state () { XMLNode* node = new XMLNode(X_("TransportControllables")); - char buf[64]; - roll_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("roll"), buf); - stop_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("stop"), buf); - goto_start_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("goto_start"), buf); - goto_end_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("goto_end"), buf); - auto_loop_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("auto_loop"), buf); - play_selection_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("play_selection"), buf); - rec_controllable->id().print (buf, sizeof (buf)); - node->add_property (X_("rec"), buf); - shuttle_box->controllable()->id().print (buf, sizeof (buf)); - node->add_property (X_("shuttle"), buf); + node->set_property (X_("roll"), roll_controllable->id()); + node->set_property (X_("stop"), stop_controllable->id()); + node->set_property (X_("goto_start"), goto_start_controllable->id()); + node->set_property (X_("goto_end"), goto_end_controllable->id()); + node->set_property (X_("auto_loop"), auto_loop_controllable->id()); + node->set_property (X_("play_selection"), play_selection_controllable->id()); + node->set_property (X_("rec"), rec_controllable->id()); + node->set_property (X_("shuttle"), shuttle_box.controllable()->id()); return *node; } @@ -1450,7 +1557,7 @@ ARDOUR_UI::every_point_zero_something_seconds () { // august 2007: actual update frequency: 25Hz (40ms), not 100Hz - if (editor_meter && UIConfiguration::instance().get_show_editor_meter()) { + if (editor_meter && UIConfiguration::instance().get_show_editor_meter() && editor_meter_peak_display.is_mapped ()) { float mpeak = editor_meter->update_meters(); if (mpeak > editor_meter_max_peak) { if (mpeak >= UIConfiguration::instance().get_meter_peak()) { @@ -1875,6 +1982,13 @@ ARDOUR_UI::open_session () session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix)); session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME)); open_session_selector.add_filter (session_filter); + + FileFilter archive_filter; + archive_filter.add_pattern (X_("*.tar.xz")); + archive_filter.set_name (_("Session Archives")); + + open_session_selector.add_filter (archive_filter); + open_session_selector.set_filter (session_filter); int response = open_session_selector.run(); @@ -1889,7 +2003,18 @@ ARDOUR_UI::open_session () bool isnew; if (session_path.length() > 0) { - if (ARDOUR::find_session (session_path, path, name, isnew) == 0) { + int rv = ARDOUR::inflate_session (session_path, + Config->get_default_session_parent_dir(), path, name); + if (rv == 0) { + _session_is_new = false; + load_session (path, name); + } + else if (rv < 0) { + MessageDialog msg (_main_window, + string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv))); + msg.run (); + } + else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) { _session_is_new = isnew; load_session (path, name); } @@ -1918,15 +2043,18 @@ ARDOUR_UI::session_add_mixed_track ( Plugin::PresetRecord* pset, ARDOUR::PresentationInfo::order_t order) { - list > tracks; - if (_session == 0) { warning << _("You cannot add a track without a session already loaded.") << endmsg; return; } + if (Profile->get_mixbus ()) { + strict_io = true; + } + try { - tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal); + list > tracks; + tracks = _session->new_midi_track (input, output, strict_io, 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; @@ -1937,12 +2065,6 @@ ARDOUR_UI::session_add_mixed_track ( display_insufficient_ports_message (); return; } - - if (strict_io) { - for (list >::iterator i = tracks.begin(); i != tracks.end(); ++i) { - (*i)->set_strict_io (true); - } - } } void @@ -1955,16 +2077,18 @@ ARDOUR_UI::session_add_midi_bus ( 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 { + if (Profile->get_mixbus ()) { + strict_io = true; + } - routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order); + try { + RouteList routes; + routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, 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; } @@ -1974,12 +2098,6 @@ ARDOUR_UI::session_add_midi_bus ( display_insufficient_ports_message (); return; } - - if (strict_io) { - for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) { - (*i)->set_strict_io (true); - } - } } void @@ -2428,6 +2546,24 @@ ARDOUR_UI::transport_play_preroll () editor->play_with_preroll (); } +void +ARDOUR_UI::transport_rec_preroll () +{ + if (!_session) { + return; + } + editor->rec_with_preroll (); +} + +void +ARDOUR_UI::transport_rec_count_in () +{ + if (!_session) { + return; + } + editor->rec_with_count_in (); +} + void ARDOUR_UI::transport_rewind (int option) { @@ -2509,10 +2645,11 @@ ARDOUR_UI::map_transport_state () play_selection_button.unset_active_state (); roll_button.unset_active_state (); stop_button.set_active_state (Gtkmm2ext::ExplicitActive); + layered_button.set_sensitive (false); return; } - shuttle_box->map_transport_state (); + shuttle_box.map_transport_state (); float sp = _session->transport_speed(); @@ -2548,11 +2685,13 @@ ARDOUR_UI::map_transport_state () roll_button.set_active (true); play_selection_button.set_active (true); } + layered_button.set_sensitive (!_session->actively_recording ()); stop_button.set_active (false); } else { + layered_button.set_sensitive (true); stop_button.set_active (true); roll_button.set_active (false); play_selection_button.set_active (false); @@ -2569,11 +2708,15 @@ void ARDOUR_UI::blink_handler (bool blink_on) { transport_rec_enable_blink (blink_on); - solo_blink (blink_on); sync_blink (blink_on); + + if (!UIConfiguration::instance().get_blink_alert_indicators()) { + blink_on = true; + } + error_blink (blink_on); + solo_blink (blink_on); audition_blink (blink_on); feedback_blink (blink_on); - error_blink (blink_on); } void @@ -2662,16 +2805,17 @@ ARDOUR_UI::save_session_as () */ ArdourDialog progress_dialog (_("Save As"), true); + ScopedConnection c; if (sa.include_media && sa.copy_media) { - Gtk::Label label; - Gtk::ProgressBar progress_bar; + Gtk::Label* label = manage (new Gtk::Label()); + Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ()); - progress_dialog.get_vbox()->pack_start (label); - progress_dialog.get_vbox()->pack_start (progress_bar); - label.show (); - progress_bar.show (); + progress_dialog.get_vbox()->pack_start (*label); + progress_dialog.get_vbox()->pack_start (*progress_bar); + label->show (); + progress_bar->show (); /* this signal will be emitted from within this, the calling thread, * after every file is copied. It provides information on percentage @@ -2679,9 +2823,7 @@ ARDOUR_UI::save_session_as () * copied so far, and the total number to copy. */ - ScopedConnection c; - - sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar)); + sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar)); progress_dialog.show_all (); progress_dialog.present (); @@ -2693,9 +2835,18 @@ ARDOUR_UI::save_session_as () msg.run (); } - if (!sa.include_media) { + /* the logic here may seem odd: why isn't the condition sa.switch_to ? + * the trick is this: if the new session was copy with media included, + * then Session::save_as() will have already done a neat trick to avoid + * us having to unload and load the new state. But if the media was not + * included, then this is required (it avoids us having to otherwise + * drop all references to media (sources). + */ + + if (!sa.include_media && sa.switch_to) { unload_session (false); load_session (sa.final_session_folder_name, sa.new_name); + hide_splash (); } } @@ -3125,7 +3276,19 @@ ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& sess void ARDOUR_UI::load_from_application_api (const std::string& path) { + /* OS X El Capitan (and probably later) now somehow passes the command + line arguments to an app via the openFile delegate protocol. Ardour + already does its own command line processing, and having both + pathways active causes crashes. So, if the command line was already + set, do nothing here. + */ + + if (!ARDOUR_COMMAND_LINE::session_name.empty()) { + return; + } + ARDOUR_COMMAND_LINE::session_name = path; + /* Cancel SessionDialog if it's visible to make OSX delegates work. * * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog @@ -3287,6 +3450,21 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri likely_new = true; } + if (!likely_new) { + int rv = ARDOUR::inflate_session (session_name, + Config->get_default_session_parent_dir(), session_path, session_name); + if (rv < 0) { + MessageDialog msg (session_dialog, + string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv))); + msg.run (); + continue; + } + else if (rv == 0) { + session_dialog.set_provided_session (session_name, session_path); + } + } + + // XXX check archive, inflate string::size_type suffix = session_name.find (statefile_suffix); if (suffix != string::npos) { @@ -3651,8 +3829,8 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, /* Put the playhead at 0 and scroll fully left */ n = new_session->instant_xml (X_("Editor")); if (n) { - n->add_property (X_("playhead"), X_("0")); - n->add_property (X_("left-frame"), X_("0")); + n->set_property (X_("playhead"), X_("0")); + n->set_property (X_("left-frame"), X_("0")); } set_session (new_session); @@ -4154,6 +4332,8 @@ ARDOUR_UI::add_route_dialog_finished (int r) /* XXX do something with name template */ + Session::ProcessorChangeBlocker pcb (_session); + 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, strict_io, order); @@ -4176,89 +4356,6 @@ ARDOUR_UI::add_route_dialog_finished (int r) } } -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 (); - } -} - void ARDOUR_UI::stop_video_server (bool ask_confirm) { @@ -4327,15 +4424,18 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg) std::string icsd_exec = video_server_dialog->get_exec_path(); std::string icsd_docroot = video_server_dialog->get_docroot(); - if (icsd_docroot.empty()) { #ifndef PLATFORM_WINDOWS - icsd_docroot = X_("/"); -#else - icsd_docroot = X_("C:\\"); -#endif + if (icsd_docroot.empty()) { + icsd_docroot = VideoUtils::video_get_docroot (Config); } +#endif GStatBuf sb; +#ifdef PLATFORM_WINDOWS + if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) { + /* OK, allow all drive letters */ + } else +#endif if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) { warning << _("Specified docroot is not an existing directory.") << endmsg; continue; @@ -4367,12 +4467,16 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg) argp[8] = 0; stop_video_server(); +#ifdef PLATFORM_WINDOWS + if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) { + /* OK, allow all drive letters */ + } else +#endif if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) { Config->set_video_advanced_setup(false); } else { - std::ostringstream osstream; - osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/"; - Config->set_video_server_url(osstream.str()); + std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/"; + Config->set_video_server_url(url_str); Config->set_video_server_docroot(icsd_docroot); Config->set_video_advanced_setup(true); } @@ -4504,11 +4608,11 @@ ARDOUR_UI::add_video (Gtk::Window* float_window) if (video_timeline->video_file_info(path, local_file)) { XMLNode* node = new XMLNode(X_("Videotimeline")); - node->add_property (X_("Filename"), path); - node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0")); - node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0")); + node->set_property (X_("Filename"), path); + node->set_property (X_("AutoFPS"), auto_set_session_fps); + node->set_property (X_("LocalFile"), local_file); if (orig_local_file) { - node->add_property (X_("OriginalVideoFile"), orig_path); + node->set_property (X_("OriginalVideoFile"), orig_path); } else { node->remove_property (X_("OriginalVideoFile")); } @@ -4720,7 +4824,7 @@ void ARDOUR_UI::create_xrun_marker (framepos_t where) { if (_session) { - Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark); + Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0); _session->locations()->add (location); } } @@ -5095,9 +5199,9 @@ ARDOUR_UI::store_clock_modes () for (vector::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) { XMLNode* child = new XMLNode (X_("Clock")); - child->add_property (X_("name"), (*x)->name()); - child->add_property (X_("mode"), enum_2_string ((*x)->mode())); - child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes"))); + child->set_property (X_("name"), (*x)->name()); + child->set_property (X_("mode"), (*x)->mode()); + child->set_property (X_("on"), (*x)->on()); node->add_child_nocopy (*child); } @@ -5290,6 +5394,52 @@ ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_pat msg.run (); } +void +ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type) +{ + using namespace Menu_Helpers; + + items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type))); + RadioMenuItem* i = dynamic_cast (&items.back ()); + i->set_active (editor_meter->meter_type () == type); +} + +void +ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev) +{ + using namespace Gtk::Menu_Helpers; + + Gtk::Menu* m = manage (new Menu); + MenuList& items = m->items (); + + RadioMenuItem::Group group; + + _suspend_editor_meter_callbacks = true; + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms), MeterKrms); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12); + add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU), MeterVU); + + m->popup (ev->button, ev->time); + _suspend_editor_meter_callbacks = false; +} + +bool +ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev) +{ + if (ev->button == 3 && editor_meter) { + popup_editor_meter_menu (ev); + return true; + } + return false; +} void ARDOUR_UI::reset_peak_display () @@ -5324,25 +5474,33 @@ 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); - if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) { - audio_midi_setup->try_autostart (); - if (ARDOUR::AudioEngine::instance()->running()) { - return 0; + if (desired_sample_rate != 0) { + if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) { + audio_midi_setup->try_autostart (); + if (ARDOUR::AudioEngine::instance()->running()) { + return 0; + } } } while (true) { int response = audio_midi_setup->run(); switch (response) { - case Gtk::RESPONSE_OK: + case Gtk::RESPONSE_DELETE_EVENT: + // after latency callibration engine may run, + // Running() signal was emitted, but dialog will not + // have emitted a response. The user needs to close + // the dialog -> Gtk::RESPONSE_DELETE_EVENT + if (!AudioEngine::instance()->running()) { + return -1; + } + // fall through + default: if (!AudioEngine::instance()->running()) { continue; - } else { - return 0; } + audio_midi_setup->hide (); return 0; - default: - return -1; } } } @@ -5496,7 +5654,7 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* } window.set_title (title.get_string()); - window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME); + window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME); window.set_flags (CAN_FOCUS); window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); @@ -5562,15 +5720,15 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) } static Gtkmm2ext::Bindings* -get_bindings_from_widget_heirarchy (GtkWidget* w) +get_bindings_from_widget_heirarchy (GtkWidget** w) { void* p = NULL; - while (w) { - if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) { + while (*w) { + if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) { break; } - w = gtk_widget_get_parent (w); + *w = gtk_widget_get_parent (*w); } return reinterpret_cast (p); @@ -5581,6 +5739,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey { GtkWindow* win = window.gobj(); GtkWidget* focus = gtk_window_get_focus (win); + GtkWidget* binding_widget = focus; bool special_handling_of_unmodified_accelerators = false; const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); @@ -5599,7 +5758,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey } else { - Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus); + Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget); if (focus_bindings) { bindings = focus_bindings; DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name())); @@ -5661,7 +5820,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n"); KeyboardKey k (ev->state, ev->keyval); - if (bindings) { + while (bindings) { DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings)); @@ -5669,6 +5828,17 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); return true; } + + if (binding_widget) { + binding_widget = gtk_widget_get_parent (binding_widget); + if (binding_widget) { + bindings = get_bindings_from_widget_heirarchy (&binding_widget); + } else { + bindings = 0; + } + } else { + bindings = 0; + } } DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n"); @@ -5699,7 +5869,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n"); KeyboardKey k (ev->state, ev->keyval); - if (bindings) { + while (bindings) { DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n"); @@ -5709,6 +5879,16 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey return true; } + if (binding_widget) { + binding_widget = gtk_widget_get_parent (binding_widget); + if (binding_widget) { + bindings = get_bindings_from_widget_heirarchy (&binding_widget); + } else { + bindings = 0; + } + } else { + bindings = 0; + } } DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");