2 * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
3 * Copyright (C) 2005-2017 Tim Mayberry <mojofunk@gmail.com>
4 * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
5 * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
6 * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
7 * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
8 * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
9 * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
10 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
11 * Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
12 * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
13 * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
14 * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
15 * Copyright (C) 2015 André Nusser <andre.nusser@googlemail.com>
16 * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
17 * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
39 #include <gtkmm/progressbar.h>
40 #include <gtkmm/stock.h>
42 #include "pbd/basename.h"
43 #include "pbd/localtime_r.h"
44 #include "pbd/unwind.h"
46 #include "gtkmm2ext/application.h"
47 #include "gtkmm2ext/doi.h"
49 #include "widgets/prompter.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/filename_extensions.h"
53 #include "ardour/profile.h"
54 #include "ardour/session.h"
55 #include "ardour/session_utils.h"
56 #include "ardour/session_state_utils.h"
57 #include "ardour/session_directory.h"
59 #include "ardour_message.h"
60 #include "ardour_ui.h"
61 #include "engine_dialog.h"
62 #include "missing_plugin_dialog.h"
64 #include "public_editor.h"
65 #include "save_as_dialog.h"
66 #include "session_dialog.h"
67 #include "session_archive_dialog.h"
71 #ifdef WINDOWS_VST_SUPPORT
77 using namespace ARDOUR;
78 using namespace ARDOUR_UI_UTILS;
82 using namespace ArdourWidgets;
85 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
87 std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
89 ArdourMessageDialog msg (str,
95 msg.set_name (X_("OpenExistingDialog"));
96 msg.set_title (_("Open Existing Session"));
97 msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
98 msg.set_position (Gtk::WIN_POS_CENTER);
109 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name, std::string const& session_template)
111 BusProfile bus_profile;
114 bus_profile.master_out_channels = 2;
115 } else if ( Profile->get_mixbus()) {
116 bus_profile.master_out_channels = 2;
118 /* get settings from advanced section of NSD */
119 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
122 build_session (session_path, session_name, session_template, bus_profile);
125 /** This is only ever used once Ardour is already running with a session
126 * loaded. The startup case is handled by StartupFSM
129 ARDOUR_UI::start_session_load (bool create_new)
131 /* deal with any existing DIRTY session now, rather than later. don't
132 * treat a non-dirty session this way, so that it stays visible
133 * as we bring up the new session dialog.
136 if (_session && ARDOUR_UI::instance()->video_timeline) {
137 ARDOUR_UI::instance()->video_timeline->sync_session_state();
140 if (_session && _session->dirty()) {
141 if (unload_session (false)) {
142 /* unload cancelled by user */
147 SessionDialog* session_dialog = new SessionDialog (create_new, string(), Config->get_default_session_parent_dir(), string(), true);
148 session_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::session_dialog_response_handler), session_dialog));
149 session_dialog->present ();
153 ARDOUR_UI::session_dialog_response_handler (int response, SessionDialog* session_dialog)
157 string template_name;
158 bool likely_new = false;
164 case RESPONSE_ACCEPT:
167 return; /* back to main event loop */
170 session_name = session_dialog->session_name (likely_new);
171 session_path = session_dialog->session_folder ();
177 /* could be an archived session, so test for that and use the
182 int rv = ARDOUR::inflate_session (session_name, Config->get_default_session_parent_dir(), session_path, session_name);
185 ArdourMessageDialog msg (*session_dialog, string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
187 return; /* back to main event loop */
188 } else if (rv == 0) {
189 session_dialog->set_provided_session (session_name, session_path);
193 string::size_type suffix = session_name.find (statefile_suffix);
195 if (suffix != string::npos) {
196 session_name = session_name.substr (0, suffix);
199 /* this shouldn't happen, but we catch it just in case it does */
201 if (session_name.empty()) {
202 return; /* back to main event loop */
205 if (session_dialog->use_session_template()) {
206 template_name = session_dialog->session_template_name();
207 _session_is_new = true;
210 if (session_name[0] == G_DIR_SEPARATOR ||
211 #ifdef PLATFORM_WINDOWS
212 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
214 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
215 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
220 /* absolute path or cwd-relative path specified for session name: infer session folder
224 session_path = Glib::path_get_dirname (session_name);
225 session_name = Glib::path_get_basename (session_name);
229 session_path = session_dialog->session_folder();
231 char illegal = Session::session_name_is_legal (session_name);
234 ArdourMessageDialog msg (*session_dialog,
235 string_compose (_("To ensure compatibility with various systems\n"
236 "session names may not contain a '%1' character"),
239 return; /* back to main event loop */
243 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
246 if (likely_new && !nsm) {
248 std::string existing = Glib::build_filename (session_path, session_name);
250 if (!ask_about_loading_existing_session (existing)) {
251 return; /* back to main event loop */
255 _session_is_new = false;
260 ArdourMessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
262 return; /* back to main event loop */
265 char illegal = Session::session_name_is_legal(session_name);
268 ArdourMessageDialog msg (*session_dialog, string_compose(_("To ensure compatibility with various systems\n"
269 "session names may not contain a '%1' character"), illegal));
271 return; /* back to main event loop */
275 _session_is_new = true;
279 /* OK, parameters provided ... good to go. */
281 session_dialog->hide ();
282 delete_when_idle (session_dialog);
284 if (!template_name.empty() || likely_new) {
286 build_session_from_dialog (*session_dialog, session_path, session_name, template_name);
290 load_session (session_path, session_name, template_name);
295 ARDOUR_UI::close_session()
297 if (!check_audioengine (_main_window)) {
301 if (unload_session (true)) {
305 start_session_load (false);
309 /** @param snap_name Snapshot name (without .ardour suffix).
310 * @return -2 if the load failed because we are not connected to the AudioEngine.
313 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
315 /* load_session calls flush_pending() which allows
316 * GUI interaction and potentially loading another session
317 * (that was easy via snapshot sidebar).
318 * Recursing into load_session() from load_session() and recusive
319 * event loops causes all kind of crashes.
321 assert (!session_load_in_progress);
322 if (session_load_in_progress) {
325 PBD::Unwinder<bool> lsu (session_load_in_progress, true);
328 bool had_session = false;
333 unload_status = unload_session ();
335 if (unload_status != 0) {
346 Session::get_info_from_path (Glib::build_filename (path, snap_name + statefile_suffix), sr, sf, pv);
348 /* this will stop the engine if the SR is different */
350 audio_midi_setup->set_desired_sample_rate (sr);
352 if (!AudioEngine::instance()->running()) {
353 audio_midi_setup->set_position (WIN_POS_CENTER);
354 audio_midi_setup->present ();
355 _engine_dialog_connection.disconnect ();
356 _engine_dialog_connection = audio_midi_setup->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::audio_midi_setup_reconfigure_done), path, snap_name, mix_template));
357 /* not done yet, but we're avoiding modal dialogs */
362 return load_session_stage_two (path, snap_name, mix_template);
366 ARDOUR_UI::audio_midi_setup_reconfigure_done (int response, std::string path, std::string snap_name, std::string mix_template)
369 case Gtk::RESPONSE_DELETE_EVENT:
372 if (!AudioEngine::instance()->running()) {
373 return; // keep dialog visible, maybe try again
377 audio_midi_setup->hide();
379 (void) load_session_stage_two (path, snap_name, mix_template);
383 ARDOUR_UI::load_session_stage_two (const std::string& path, const std::string& snap_name, std::string mix_template)
385 Session *new_session;
388 BootMessage (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
391 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
394 /* this one is special */
396 catch (AudioEngine::PortRegistrationFailure const& err) {
398 ArdourMessageDialog msg (err.what(),
403 msg.set_title (_("Port Registration Error"));
404 msg.set_secondary_text (_("Click the Close button to try again."));
405 msg.set_position (Gtk::WIN_POS_CENTER);
407 int response = msg.run ();
411 case RESPONSE_CANCEL:
418 catch (SessionException const& e) {
419 ArdourMessageDialog msg (string_compose(
420 _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
421 path, snap_name, e.what()),
426 msg.set_title (_("Loading Error"));
427 msg.set_position (Gtk::WIN_POS_CENTER);
438 ArdourMessageDialog msg (string_compose(
439 _("Session \"%1 (snapshot %2)\" did not load successfully."),
445 msg.set_title (_("Loading Error"));
446 msg.set_position (Gtk::WIN_POS_CENTER);
457 list<string> const u = new_session->unknown_processors ();
459 MissingPluginDialog d (_session, u);
464 if (!new_session->writable()) {
465 ArdourMessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
470 msg.set_title (_("Read-only Session"));
471 msg.set_position (Gtk::WIN_POS_CENTER);
477 /* Now the session been created, add the transport controls */
478 new_session->add_controllable(roll_controllable);
479 new_session->add_controllable(stop_controllable);
480 new_session->add_controllable(goto_start_controllable);
481 new_session->add_controllable(goto_end_controllable);
482 new_session->add_controllable(auto_loop_controllable);
483 new_session->add_controllable(play_selection_controllable);
484 new_session->add_controllable(rec_controllable);
486 set_session (new_session);
489 _session->set_clean ();
492 #ifdef WINDOWS_VST_SUPPORT
493 fst_stop_threading();
497 Timers::TimerSuspender t;
501 #ifdef WINDOWS_VST_SUPPORT
502 fst_start_threading();
506 if (!mix_template.empty ()) {
507 /* if mix_template is given, assume this is a new session */
508 string metascript = Glib::build_filename (mix_template, "template.lua");
509 meta_session_setup (metascript);
514 /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
515 * which is queued by set_session().
516 * If session-loading fails we hide it explicitly.
517 * This covers both cases in a central place.
526 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, const std::string& session_template, BusProfile const& bus_profile, bool from_startup_fsm)
530 x = unload_session ();
538 _session_is_new = true;
540 /* when running from startup FSM all is fine,
541 * engine should be running and the FSM will also have
542 * asked for the SR (even if try-autostart-engine is set)
544 if (from_startup_fsm && AudioEngine::instance()->running ()) {
545 return build_session_stage_two (path, snap_name, session_template, bus_profile);
547 /* Sample-rate cannot be changed when JACK is running */
548 if (!ARDOUR::AudioEngine::instance()->setup_required () && AudioEngine::instance()->running ()) {
549 return build_session_stage_two (path, snap_name, session_template, bus_profile);
552 /* Ask for the Sample-rate to use with the new session */
553 audio_midi_setup->set_position (WIN_POS_CENTER);
554 audio_midi_setup->set_modal ();
555 audio_midi_setup->present ();
556 _engine_dialog_connection.disconnect ();
557 _engine_dialog_connection = audio_midi_setup->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::audio_midi_setup_for_new_session_done), path, snap_name, session_template, bus_profile));
559 /* not done yet, but we're avoiding modal dialogs */
565 ARDOUR_UI::audio_midi_setup_for_new_session_done (int response, std::string path, std::string snap_name, std::string template_name, BusProfile const& bus_profile)
568 case Gtk::RESPONSE_DELETE_EVENT:
569 audio_midi_setup->set_modal (false);
575 if (!AudioEngine::instance()->running()) {
576 return; // keep dialog visible, maybe try again
578 audio_midi_setup->set_modal (false);
579 audio_midi_setup->hide();
581 build_session_stage_two (path, snap_name, template_name, bus_profile);
585 ARDOUR_UI::build_session_stage_two (std::string const& path, std::string const& snap_name, std::string const& session_template, BusProfile const& bus_profile)
587 Session* new_session;
590 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL);
592 catch (SessionException const& e) {
593 cerr << "Here are the errors associated with this failed session:\n";
595 cerr << "---------\n";
596 ArdourMessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
597 msg.set_title (_("Loading Error"));
598 msg.set_position (Gtk::WIN_POS_CENTER);
603 cerr << "Here are the errors associated with this failed session:\n";
605 cerr << "---------\n";
606 ArdourMessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
607 msg.set_title (_("Loading Error"));
608 msg.set_position (Gtk::WIN_POS_CENTER);
613 /* Give the new session the default GUI state, if such things exist */
616 n = Config->instant_xml (X_("Editor"));
618 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
619 new_session->add_instant_xml (*n, false);
621 n = Config->instant_xml (X_("Mixer"));
623 new_session->add_instant_xml (*n, false);
626 n = Config->instant_xml (X_("Preferences"));
628 new_session->add_instant_xml (*n, false);
631 /* Put the playhead at 0 and scroll fully left */
632 n = new_session->instant_xml (X_("Editor"));
634 n->set_property (X_("playhead"), X_("0"));
635 n->set_property (X_("left-frame"), X_("0"));
638 set_session (new_session);
640 new_session->save_state(new_session->name());
642 if (!session_template.empty() && session_template.substr (0, 11) == "urn:ardour:") {
643 meta_session_setup (session_template.substr (11));
649 /** Ask the user for the name of a new snapshot and then take it.
653 ARDOUR_UI::snapshot_session (bool switch_to_it)
655 if (switch_to_it && _session->dirty()) {
656 vector<string> actions;
657 actions.push_back (_("Abort saving snapshot"));
658 actions.push_back (_("Don't save now, just snapshot"));
659 actions.push_back (_("Save it first"));
660 switch (ask_about_saving_session(actions)) {
665 if (save_state_canfail ("")) {
666 ArdourMessageDialog msg (_main_window,
668 %1 was unable to save your session.\n\n\
669 If you still wish to proceed, please use the\n\n\
670 \"Don't save now\" option."), PROGRAM_NAME));
676 _session->remove_pending_capture_state ();
681 Prompter prompter (true);
682 prompter.set_name ("Prompter");
683 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
685 prompter.set_title (_("Snapshot and switch"));
686 prompter.set_prompt (_("New session name"));
688 prompter.set_title (_("Take Snapshot"));
689 prompter.set_prompt (_("Name of new snapshot"));
693 prompter.set_initial_text (_session->snap_name());
695 Glib::DateTime tm (g_date_time_new_now_local ());
696 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
699 bool finished = false;
701 switch (prompter.run()) {
702 case RESPONSE_ACCEPT:
704 finished = process_snapshot_session_prompter (prompter, switch_to_it);
715 /** Ask the user for a new session name and then rename the session to it.
719 ARDOUR_UI::rename_session ()
725 Prompter prompter (true);
728 prompter.set_name ("Prompter");
729 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
730 prompter.set_title (_("Rename Session"));
731 prompter.set_prompt (_("New session name"));
734 switch (prompter.run()) {
735 case RESPONSE_ACCEPT:
737 prompter.get_result (name);
739 bool do_rename = (name.length() != 0);
742 char illegal = Session::session_name_is_legal (name);
745 ArdourMessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
746 "session names may not contain a '%1' character"), illegal));
751 switch (_session->rename (name)) {
753 ArdourMessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
761 ArdourMessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
777 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
781 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
783 label->set_text (buf);
784 bar->set_fraction (fraction);
786 /* process events, redraws, etc. */
788 while (gtk_events_pending()) {
789 gtk_main_iteration ();
792 return true; /* continue with save-as */
796 ARDOUR_UI::save_session_as ()
802 if (_session->dirty()) {
803 vector<string> actions;
804 actions.push_back (_("Abort save-as"));
805 actions.push_back (_("Don't save now, just save-as"));
806 actions.push_back (_("Save it first"));
807 switch (ask_about_saving_session(actions)) {
812 if (save_state_canfail ("")) {
813 ArdourMessageDialog msg (_main_window,
815 %1 was unable to save your session.\n\n\
816 If you still wish to proceed, please use the\n\n\
817 \"Don't save now\" option."), PROGRAM_NAME));
823 _session->remove_pending_capture_state ();
828 if (!save_as_dialog) {
829 save_as_dialog = new SaveAsDialog;
832 save_as_dialog->set_name (_session->name());
834 int response = save_as_dialog->run ();
836 save_as_dialog->hide ();
839 case Gtk::RESPONSE_OK:
848 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
849 sa.new_name = save_as_dialog->new_name ();
850 sa.switch_to = save_as_dialog->switch_to();
851 sa.copy_media = save_as_dialog->copy_media();
852 sa.copy_external = save_as_dialog->copy_external();
853 sa.include_media = save_as_dialog->include_media ();
855 /* Only bother with a progress dialog if we're going to copy
856 media into the save-as target. Without that choice, this
857 will be very fast because we're only talking about a few kB's to
858 perhaps a couple of MB's of data.
861 ArdourDialog progress_dialog (_("Save As"), true);
864 if (sa.include_media && sa.copy_media) {
866 Gtk::Label* label = manage (new Gtk::Label());
867 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
869 progress_dialog.get_vbox()->pack_start (*label);
870 progress_dialog.get_vbox()->pack_start (*progress_bar);
872 progress_bar->show ();
874 /* this signal will be emitted from within this, the calling thread,
875 * after every file is copied. It provides information on percentage
876 * complete (in terms of total data to copy), the number of files
877 * copied so far, and the total number to copy.
880 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
882 progress_dialog.show_all ();
883 progress_dialog.present ();
886 if (_session->save_as (sa)) {
888 ArdourMessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
892 /* the logic here may seem odd: why isn't the condition sa.switch_to ?
893 * the trick is this: if the new session was copy with media included,
894 * then Session::save_as() will have already done a neat trick to avoid
895 * us having to unload and load the new state. But if the media was not
896 * included, then this is required (it avoids us having to otherwise
897 * drop all references to media (sources).
900 if (!sa.include_media && sa.switch_to) {
901 unload_session (false);
902 load_session (sa.final_session_folder_name, sa.new_name);
907 ARDOUR_UI::archive_session ()
915 Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
917 SessionArchiveDialog sad;
918 sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
919 int response = sad.run ();
921 if (response != Gtk::RESPONSE_OK) {
926 if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
927 ArdourMessageDialog msg (_("Session Archiving failed."));
933 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
937 struct tm local_time;
940 localtime_r (&n, &local_time);
941 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
942 if (switch_to_it && _session->dirty ()) {
943 save_state_canfail ("");
946 save_state (timebuf, switch_to_it);
951 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
955 prompter.get_result (snapname);
957 bool do_save = (snapname.length() != 0);
960 char illegal = Session::session_name_is_legal(snapname);
962 ArdourMessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
963 "snapshot names may not contain a '%1' character"), illegal));
969 vector<std::string> p;
970 get_state_files_in_directory (_session->session_directory().root_path(), p);
971 vector<string> n = get_file_names_no_extension (p);
973 if (find (n.begin(), n.end(), snapname) != n.end()) {
975 do_save = overwrite_file_dialog (prompter,
976 _("Confirm Snapshot Overwrite"),
977 _("A snapshot already exists with that name. Do you want to overwrite it?"));
981 save_state (snapname, switch_to_it);
992 ARDOUR_UI::open_session ()
994 if (!check_audioengine (_main_window)) {
998 /* ardour sessions are folders */
999 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1000 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1001 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1002 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1005 string session_parent_dir = Glib::path_get_dirname(_session->path());
1006 open_session_selector.set_current_folder(session_parent_dir);
1008 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1011 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1013 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1014 string default_session_folder = Config->get_default_session_parent_dir();
1015 open_session_selector.add_shortcut_folder (default_session_folder);
1017 catch (Glib::Error const& e) {
1018 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1021 FileFilter session_filter;
1022 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1023 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1024 open_session_selector.add_filter (session_filter);
1026 FileFilter archive_filter;
1027 archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
1028 archive_filter.set_name (_("Session Archives"));
1030 open_session_selector.add_filter (archive_filter);
1032 open_session_selector.set_filter (session_filter);
1034 int response = open_session_selector.run();
1035 open_session_selector.hide ();
1037 if (response == Gtk::RESPONSE_CANCEL) {
1041 string session_path = open_session_selector.get_filename();
1045 if (session_path.length() > 0) {
1046 int rv = ARDOUR::inflate_session (session_path,
1047 Config->get_default_session_parent_dir(), path, name);
1049 _session_is_new = false;
1050 load_session (path, name);
1053 ArdourMessageDialog msg (_main_window,
1054 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1057 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1058 _session_is_new = isnew;
1059 load_session (path, name);
1065 ARDOUR_UI::open_recent_session ()
1067 bool can_return = (_session != 0);
1069 SessionDialog recent_session_dialog;
1073 ResponseType r = (ResponseType) recent_session_dialog.run ();
1076 case RESPONSE_ACCEPT:
1080 recent_session_dialog.hide();
1083 exit (EXIT_FAILURE);
1087 recent_session_dialog.hide();
1091 std::string path = recent_session_dialog.session_folder();
1092 std::string state = recent_session_dialog.session_name (should_be_new);
1094 if (should_be_new == true) {
1098 _session_is_new = false;
1100 if (load_session (path, state) == 0) {
1109 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1111 ArdourDialog window (_("Unsaved Session"));
1112 Gtk::HBox dhbox; // the hbox for the image and text
1113 Gtk::Label prompt_label;
1114 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1118 assert (actions.size() >= 3);
1120 window.add_button (actions[0], RESPONSE_REJECT);
1121 window.add_button (actions[1], RESPONSE_APPLY);
1122 window.add_button (actions[2], RESPONSE_ACCEPT);
1124 window.set_default_response (RESPONSE_ACCEPT);
1126 Gtk::Button noquit_button (msg);
1127 noquit_button.set_name ("EditorGTKButton");
1131 if (_session->snap_name() == _session->name()) {
1132 prompt = string_compose(_("The session \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1133 _session->snap_name());
1135 prompt = string_compose(_("The snapshot \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1136 _session->snap_name());
1139 prompt_label.set_text (prompt);
1140 prompt_label.set_name (X_("PrompterLabel"));
1141 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1143 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1144 dhbox.set_homogeneous (false);
1145 dhbox.pack_start (*dimage, false, false, 5);
1146 dhbox.pack_start (prompt_label, true, false, 5);
1147 window.get_vbox()->pack_start (dhbox);
1149 window.set_name (_("Prompter"));
1150 window.set_modal (true);
1151 window.set_resizable (false);
1154 prompt_label.show();
1159 ResponseType r = (ResponseType) window.run();
1164 case RESPONSE_ACCEPT: // save and get out of here
1166 case RESPONSE_APPLY: // get out of here
1177 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
1180 _session->save_state (snapshot_name);
1185 ARDOUR_UI::autosave_session ()
1187 if (g_main_depth() > 1) {
1188 /* inside a recursive main loop,
1189 give up because we may not be able to
1195 if (!Config->get_periodic_safety_backups()) {
1200 _session->maybe_write_autosave();