X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=8c2ec7605387bee27aef65cdcac10367b4176711;hb=cef341631b55526e4b2bad940064491922c07701;hp=4778b6c47db0b94885da56cd8424e2123d4aa976;hpb=11f8e3adc4640c4fa167fd0aaec5799a28111790;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 4778b6c47d..8c2ec76053 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -56,6 +56,7 @@ #include "pbd/compose.h" #include "pbd/convert.h" #include "pbd/failed_constructor.h" +#include "pbd/file_archive.h" #include "pbd/enumwriter.h" #include "pbd/memento_command.h" #include "pbd/openuri.h" @@ -162,6 +163,7 @@ typedef uint64_t microseconds_t; #include "route_params_ui.h" #include "save_as_dialog.h" #include "script_selector.h" +#include "session_archive_dialog.h" #include "session_dialog.h" #include "session_metadata_dialog.h" #include "session_option_editor.h" @@ -177,7 +179,7 @@ typedef uint64_t microseconds_t; #include "add_video_dialog.h" #include "transcode_video_dialog.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; using namespace ARDOUR_UI_UTILS; @@ -1069,6 +1071,45 @@ ARDOUR_UI::starting () } } + // TODO: maybe IFF brand_new_user + if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) { + std::string dspd (Config->get_default_session_parent_dir()); + Searchpath ds (ARDOUR::ardour_data_search_path()); + ds.add_subdirectory_to_paths ("sessions"); + vector demos; + find_files_matching_pattern (demos, ds, "*.tar.xz"); + + ARDOUR::RecentSessions rs; + ARDOUR::read_recent_sessions (rs); + + for (vector::iterator i = demos.begin(); i != demos.end (); ++i) { + /* "demo-session" must be inside "demo-session.tar.xz" + * strip ".tar.xz" + */ + std::string name = basename_nosuffix (basename_nosuffix (*i)); + std::string path = Glib::build_filename (dspd, name); + /* skip if session-dir already exists */ + if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) { + continue; + } + /* skip sessions that are already in 'recent'. + * eg. a new user changed shorly after installation + */ + for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) { + if ((*r).first == name) { + continue; + } + } + try { + PBD::FileArchive ar (*i); + if (0 == ar.inflate (dspd)) { + store_recent_sessions (name, path); + info << string_compose (_("Copied Demo Session %1."), name) << endmsg; + } + } catch (...) {} + } + } + #ifdef NO_PLUGIN_STATE ARDOUR::RecentSessions rs; @@ -1284,6 +1325,10 @@ If you still wish to quit, please use the\n\n\ */ save_ardour_state (); + if (key_editor.get (false)) { + key_editor->disconnect (); + } + close_all_dialogs (); if (_session) { @@ -2654,6 +2699,32 @@ ARDOUR_UI::save_session_as () } } +void +ARDOUR_UI::archive_session () +{ + if (!_session) { + return; + } + + time_t n; + time (&n); + Glib::DateTime gdt (Glib::DateTime::create_now_local (n)); + + SessionArchiveDialog sad; + sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S")); + int response = sad.run (); + + if (response != Gtk::RESPONSE_OK) { + sad.hide (); + return; + } + + if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.only_used_sources (), &sad)) { + MessageDialog msg (_("Session Archiving failed.")); + msg.run (); + } +} + void ARDOUR_UI::quick_snapshot_session (bool switch_to_it) { @@ -2731,14 +2802,8 @@ ARDOUR_UI::snapshot_session (bool switch_to_it) if (switch_to_it) { prompter.set_initial_text (_session->snap_name()); } else { - char timebuf[128]; - time_t n; - struct tm local_time; - - time (&n); - localtime_r (&n, &local_time); - strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time); - prompter.set_initial_text (timebuf); + Glib::DateTime tm (g_date_time_new_now_local ()); + prompter.set_initial_text (tm.format ("%FT%H.%M.%S")); } bool finished = false; @@ -3060,7 +3125,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 @@ -3509,7 +3586,7 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, { Timers::TimerSuspender t; - flush_pending (); + flush_pending (10); } #ifdef WINDOWS_VST_SUPPORT @@ -3543,7 +3620,9 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, } catch (SessionException e) { + cerr << "Here are the errors associated with this failed session:\n"; dump_errors (cerr); + cerr << "---------\n"; MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what())); msg.set_title (_("Loading Error")); msg.set_position (Gtk::WIN_POS_CENTER); @@ -3552,7 +3631,9 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, return -1; } catch (...) { + cerr << "Here are the errors associated with this failed session:\n"; dump_errors (cerr); + cerr << "---------\n"; MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path)); msg.set_title (_("Loading Error")); msg.set_position (Gtk::WIN_POS_CENTER); @@ -3574,6 +3655,11 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, new_session->add_instant_xml (*n, false); } + n = Config->instant_xml (X_("Preferences")); + if (n) { + new_session->add_instant_xml (*n, false); + } + /* Put the playhead at 0 and scroll fully left */ n = new_session->instant_xml (X_("Editor")); if (n) { @@ -3964,7 +4050,7 @@ ARDOUR_UI::cleanup_peakfiles () } PresentationInfo::order_t -ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place) +ARDOUR_UI::translate_order (RouteDialogs::InsertAt place) { if (editor->get_selection().tracks.empty()) { return PresentationInfo::max_order; @@ -3977,18 +4063,18 @@ ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place) the highest order key in the selection + 1 (if available). */ - if (place == AddRouteDialog::AfterSelection) { + if (place == RouteDialogs::AfterSelection) { RouteTimeAxisView *rtav = dynamic_cast (editor->get_selection().tracks.back()); if (rtav) { order_hint = rtav->route()->presentation_info().order(); order_hint++; } - } else if (place == AddRouteDialog::BeforeSelection) { + } else if (place == RouteDialogs::BeforeSelection) { RouteTimeAxisView *rtav = dynamic_cast (editor->get_selection().tracks.front()); if (rtav) { order_hint = rtav->route()->presentation_info().order(); } - } else if (place == AddRouteDialog::First) { + } else if (place == RouteDialogs::First) { order_hint = 0; } else { /* leave order_hint at max_order */ @@ -4056,9 +4142,9 @@ ARDOUR_UI::add_route_dialog_finished (int r) if (!template_path.empty()) { if (add_route_dialog->name_template_is_default()) { - _session->new_route_from_template (count, template_path, string()); + _session->new_route_from_template (count, order, template_path, string()); } else { - _session->new_route_from_template (count, template_path, add_route_dialog->name_template()); + _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template()); } return; } @@ -4544,6 +4630,24 @@ ARDOUR_UI::export_video (bool range) export_video_dialog->hide (); } +XMLNode* +ARDOUR_UI::preferences_settings () const +{ + XMLNode* node = 0; + + if (_session) { + node = _session->instant_xml(X_("Preferences")); + } else { + node = Config->instant_xml(X_("Preferences")); + } + + if (!node) { + node = new XMLNode (X_("Preferences")); + } + + return node; +} + XMLNode* ARDOUR_UI::mixer_settings () const { @@ -4963,16 +5067,21 @@ ARDOUR_UI::record_state_changed () { ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed); - if (!_session || !big_clock_window) { + if (!_session) { /* why bother - the clock isn't visible */ return; } - if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) { - big_clock->set_active (true); - } else { - big_clock->set_active (false); + ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording()); + + if (big_clock_window) { + if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) { + big_clock->set_active (true); + } else { + big_clock->set_active (false); + } } + } bool @@ -5374,16 +5483,16 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* if (window_icons.empty()) { Glib::RefPtr icon; - if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) { window_icons.push_back (icon); } - if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) { window_icons.push_back (icon); } - if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) { window_icons.push_back (icon); } - if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) { + if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) { window_icons.push_back (icon); } } @@ -5465,15 +5574,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); @@ -5484,6 +5593,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)); @@ -5502,7 +5612,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())); @@ -5513,7 +5623,7 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey 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), + Gtkmm2ext::show_gdk_event_state (ev->state), special_handling_of_unmodified_accelerators, Keyboard::some_magic_widget_has_focus(), focus, @@ -5564,7 +5674,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)); @@ -5572,6 +5682,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"); @@ -5602,7 +5723,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"); @@ -5612,6 +5733,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"); @@ -5638,9 +5769,58 @@ void ARDOUR_UI::cancel_solo () { if (_session) { - if (_session) { - _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_control), 0.0, Controllable::NoGroup); + _session->cancel_all_solo (); + } +} + +void +ARDOUR_UI::reset_focus (Gtk::Widget* w) +{ + /* this resets focus to the first focusable parent of the given widget, + * or, if there is no focusable parent, cancels focus in the toplevel + * window that the given widget is packed into (if there is one). + */ + + if (!w) { + return; + } + + Gtk::Widget* top = w->get_toplevel(); + + if (!top || !top->is_toplevel()) { + return; + } + + w = w->get_parent (); + + while (w) { + + if (w->is_toplevel()) { + /* Setting the focus widget to a Gtk::Window causes all + * subsequent calls to ::has_focus() on the nominal + * focus widget in that window to return + * false. Workaround: never set focus to the toplevel + * itself. + */ + break; } - _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window + + if (w->get_can_focus ()) { + Gtk::Window* win = dynamic_cast (top); + win->set_focus (*w); + return; + } + w = w->get_parent (); } + + if (top == &_main_window) { + + } + + /* no focusable parent found, cancel focus in top level window. + C++ API cannot be used for this. Thanks, references. + */ + + gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0); + }