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)
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 // NULL profile: no master, no monitor
123 if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
130 /** This is only ever used once Ardour is already running with a session
131 * loaded. The startup case is handled by StartupFSM
134 ARDOUR_UI::start_session_load (bool create_new)
136 /* deal with any existing DIRTY session now, rather than later. don't
137 * treat a non-dirty session this way, so that it stays visible
138 * as we bring up the new session dialog.
141 if (_session && ARDOUR_UI::instance()->video_timeline) {
142 ARDOUR_UI::instance()->video_timeline->sync_session_state();
145 if (_session && _session->dirty()) {
146 if (unload_session (false)) {
147 /* unload cancelled by user */
152 SessionDialog* session_dialog = new SessionDialog (create_new, string(), Config->get_default_session_parent_dir(), string(), true);
153 session_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::session_dialog_response_handler), session_dialog));
154 session_dialog->present ();
158 ARDOUR_UI::session_dialog_response_handler (int response, SessionDialog* session_dialog)
162 string template_name;
163 bool likely_new = false;
169 case RESPONSE_ACCEPT:
172 return; /* back to main event loop */
175 session_name = session_dialog->session_name (likely_new);
176 session_path = session_dialog->session_folder ();
182 /* could be an archived session, so test for that and use the
187 int rv = ARDOUR::inflate_session (session_name, Config->get_default_session_parent_dir(), session_path, session_name);
190 ArdourMessageDialog msg (*session_dialog, string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
192 return; /* back to main event loop */
193 } else if (rv == 0) {
194 session_dialog->set_provided_session (session_name, session_path);
198 string::size_type suffix = session_name.find (statefile_suffix);
200 if (suffix != string::npos) {
201 session_name = session_name.substr (0, suffix);
204 /* this shouldn't happen, but we catch it just in case it does */
206 if (session_name.empty()) {
207 return; /* back to main event loop */
210 if (session_dialog->use_session_template()) {
211 template_name = session_dialog->session_template_name();
212 _session_is_new = true;
215 if (session_name[0] == G_DIR_SEPARATOR ||
216 #ifdef PLATFORM_WINDOWS
217 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
219 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
220 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
225 /* absolute path or cwd-relative path specified for session name: infer session folder
229 session_path = Glib::path_get_dirname (session_name);
230 session_name = Glib::path_get_basename (session_name);
234 session_path = session_dialog->session_folder();
236 char illegal = Session::session_name_is_legal (session_name);
239 ArdourMessageDialog msg (*session_dialog,
240 string_compose (_("To ensure compatibility with various systems\n"
241 "session names may not contain a '%1' character"),
244 return; /* back to main event loop */
248 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
251 if (likely_new && !nsm) {
253 std::string existing = Glib::build_filename (session_path, session_name);
255 if (!ask_about_loading_existing_session (existing)) {
256 return; /* back to main event loop */
260 _session_is_new = false;
265 ArdourMessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
267 return; /* back to main event loop */
270 char illegal = Session::session_name_is_legal(session_name);
273 ArdourMessageDialog msg (*session_dialog, string_compose(_("To ensure compatibility with various systems\n"
274 "session names may not contain a '%1' character"), illegal));
276 return; /* back to main event loop */
280 _session_is_new = true;
284 /* OK, parameters provided ... good to go. */
286 session_dialog->hide ();
287 delete_when_idle (session_dialog);
289 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
291 build_session_from_dialog (*session_dialog, session_path, session_name);
292 meta_session_setup (template_name.substr (11));
294 } else if (likely_new) {
296 build_session_from_dialog (*session_dialog, session_path, session_name);
300 load_session (session_path, session_name, template_name);
305 ARDOUR_UI::close_session()
307 if (!check_audioengine (_main_window)) {
311 if (unload_session (true)) {
315 start_session_load (false);
319 /** @param snap_name Snapshot name (without .ardour suffix).
320 * @return -2 if the load failed because we are not connected to the AudioEngine.
323 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
325 /* load_session calls flush_pending() which allows
326 * GUI interaction and potentially loading another session
327 * (that was easy via snapshot sidebar).
328 * Recursing into load_session() from load_session() and recusive
329 * event loops causes all kind of crashes.
331 assert (!session_load_in_progress);
332 if (session_load_in_progress) {
335 PBD::Unwinder<bool> lsu (session_load_in_progress, true);
338 bool had_session = false;
343 unload_status = unload_session ();
345 if (unload_status != 0) {
356 Session::get_info_from_path (Glib::build_filename (path, snap_name + statefile_suffix), sr, sf, pv);
358 /* this will stop the engine if the SR is different */
360 audio_midi_setup->set_desired_sample_rate (sr);
362 if (!AudioEngine::instance()->running()) {
363 audio_midi_setup->set_position (WIN_POS_CENTER);
364 audio_midi_setup->present ();
365 audio_midi_setup->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::audio_midi_setup_reconfigure_done), path, snap_name, mix_template));
366 /* not done yet, but we're avoiding modal dialogs */
371 return load_session_stage_two (path, snap_name, mix_template);
375 ARDOUR_UI::audio_midi_setup_reconfigure_done (int response, std::string path, std::string snap_name, std::string mix_template)
378 case Gtk::RESPONSE_DELETE_EVENT:
381 if (!AudioEngine::instance()->running()) {
382 return; // keep dialog visible, maybe try again
386 audio_midi_setup->hide();
388 (void) load_session_stage_two (path, snap_name, mix_template);
392 ARDOUR_UI::load_session_stage_two (const std::string& path, const std::string& snap_name, std::string mix_template)
394 Session *new_session;
397 BootMessage (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
400 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
403 /* this one is special */
405 catch (AudioEngine::PortRegistrationFailure const& err) {
407 ArdourMessageDialog msg (err.what(),
412 msg.set_title (_("Port Registration Error"));
413 msg.set_secondary_text (_("Click the Close button to try again."));
414 msg.set_position (Gtk::WIN_POS_CENTER);
416 int response = msg.run ();
420 case RESPONSE_CANCEL:
427 catch (SessionException const& e) {
428 ArdourMessageDialog msg (string_compose(
429 _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
430 path, snap_name, e.what()),
435 msg.set_title (_("Loading Error"));
436 msg.set_position (Gtk::WIN_POS_CENTER);
447 ArdourMessageDialog msg (string_compose(
448 _("Session \"%1 (snapshot %2)\" did not load successfully."),
454 msg.set_title (_("Loading Error"));
455 msg.set_position (Gtk::WIN_POS_CENTER);
466 list<string> const u = new_session->unknown_processors ();
468 MissingPluginDialog d (_session, u);
473 if (!new_session->writable()) {
474 ArdourMessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
479 msg.set_title (_("Read-only Session"));
480 msg.set_position (Gtk::WIN_POS_CENTER);
486 /* Now the session been created, add the transport controls */
487 new_session->add_controllable(roll_controllable);
488 new_session->add_controllable(stop_controllable);
489 new_session->add_controllable(goto_start_controllable);
490 new_session->add_controllable(goto_end_controllable);
491 new_session->add_controllable(auto_loop_controllable);
492 new_session->add_controllable(play_selection_controllable);
493 new_session->add_controllable(rec_controllable);
495 set_session (new_session);
498 _session->set_clean ();
501 #ifdef WINDOWS_VST_SUPPORT
502 fst_stop_threading();
506 Timers::TimerSuspender t;
510 #ifdef WINDOWS_VST_SUPPORT
511 fst_start_threading();
515 if (!mix_template.empty ()) {
516 /* if mix_template is given, assume this is a new session */
517 string metascript = Glib::build_filename (mix_template, "template.lua");
518 meta_session_setup (metascript);
523 /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
524 * which is queued by set_session().
525 * If session-loading fails we hide it explicitly.
526 * This covers both cases in a central place.
535 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile const * bus_profile)
537 Session *new_session;
540 x = unload_session ();
548 _session_is_new = true;
551 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
554 catch (SessionException const& e) {
555 cerr << "Here are the errors associated with this failed session:\n";
557 cerr << "---------\n";
558 ArdourMessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
559 msg.set_title (_("Loading Error"));
560 msg.set_position (Gtk::WIN_POS_CENTER);
565 cerr << "Here are the errors associated with this failed session:\n";
567 cerr << "---------\n";
568 ArdourMessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
569 msg.set_title (_("Loading Error"));
570 msg.set_position (Gtk::WIN_POS_CENTER);
575 /* Give the new session the default GUI state, if such things exist */
578 n = Config->instant_xml (X_("Editor"));
580 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
581 new_session->add_instant_xml (*n, false);
583 n = Config->instant_xml (X_("Mixer"));
585 new_session->add_instant_xml (*n, false);
588 n = Config->instant_xml (X_("Preferences"));
590 new_session->add_instant_xml (*n, false);
593 /* Put the playhead at 0 and scroll fully left */
594 n = new_session->instant_xml (X_("Editor"));
596 n->set_property (X_("playhead"), X_("0"));
597 n->set_property (X_("left-frame"), X_("0"));
600 set_session (new_session);
602 new_session->save_state(new_session->name());
607 /** Ask the user for the name of a new snapshot and then take it.
611 ARDOUR_UI::snapshot_session (bool switch_to_it)
613 if (switch_to_it && _session->dirty()) {
614 vector<string> actions;
615 actions.push_back (_("Abort saving snapshot"));
616 actions.push_back (_("Don't save now, just snapshot"));
617 actions.push_back (_("Save it first"));
618 switch (ask_about_saving_session(actions)) {
623 if (save_state_canfail ("")) {
624 ArdourMessageDialog msg (_main_window,
626 %1 was unable to save your session.\n\n\
627 If you still wish to proceed, please use the\n\n\
628 \"Don't save now\" option."), PROGRAM_NAME));
634 _session->remove_pending_capture_state ();
639 Prompter prompter (true);
640 prompter.set_name ("Prompter");
641 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
643 prompter.set_title (_("Snapshot and switch"));
644 prompter.set_prompt (_("New session name"));
646 prompter.set_title (_("Take Snapshot"));
647 prompter.set_prompt (_("Name of new snapshot"));
651 prompter.set_initial_text (_session->snap_name());
653 Glib::DateTime tm (g_date_time_new_now_local ());
654 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
657 bool finished = false;
659 switch (prompter.run()) {
660 case RESPONSE_ACCEPT:
662 finished = process_snapshot_session_prompter (prompter, switch_to_it);
673 /** Ask the user for a new session name and then rename the session to it.
677 ARDOUR_UI::rename_session ()
683 Prompter prompter (true);
686 prompter.set_name ("Prompter");
687 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
688 prompter.set_title (_("Rename Session"));
689 prompter.set_prompt (_("New session name"));
692 switch (prompter.run()) {
693 case RESPONSE_ACCEPT:
695 prompter.get_result (name);
697 bool do_rename = (name.length() != 0);
700 char illegal = Session::session_name_is_legal (name);
703 ArdourMessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
704 "session names may not contain a '%1' character"), illegal));
709 switch (_session->rename (name)) {
711 ArdourMessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
719 ArdourMessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
735 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
739 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
741 label->set_text (buf);
742 bar->set_fraction (fraction);
744 /* process events, redraws, etc. */
746 while (gtk_events_pending()) {
747 gtk_main_iteration ();
750 return true; /* continue with save-as */
754 ARDOUR_UI::save_session_as ()
760 if (_session->dirty()) {
761 vector<string> actions;
762 actions.push_back (_("Abort save-as"));
763 actions.push_back (_("Don't save now, just save-as"));
764 actions.push_back (_("Save it first"));
765 switch (ask_about_saving_session(actions)) {
770 if (save_state_canfail ("")) {
771 ArdourMessageDialog msg (_main_window,
773 %1 was unable to save your session.\n\n\
774 If you still wish to proceed, please use the\n\n\
775 \"Don't save now\" option."), PROGRAM_NAME));
781 _session->remove_pending_capture_state ();
786 if (!save_as_dialog) {
787 save_as_dialog = new SaveAsDialog;
790 save_as_dialog->set_name (_session->name());
792 int response = save_as_dialog->run ();
794 save_as_dialog->hide ();
797 case Gtk::RESPONSE_OK:
806 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
807 sa.new_name = save_as_dialog->new_name ();
808 sa.switch_to = save_as_dialog->switch_to();
809 sa.copy_media = save_as_dialog->copy_media();
810 sa.copy_external = save_as_dialog->copy_external();
811 sa.include_media = save_as_dialog->include_media ();
813 /* Only bother with a progress dialog if we're going to copy
814 media into the save-as target. Without that choice, this
815 will be very fast because we're only talking about a few kB's to
816 perhaps a couple of MB's of data.
819 ArdourDialog progress_dialog (_("Save As"), true);
822 if (sa.include_media && sa.copy_media) {
824 Gtk::Label* label = manage (new Gtk::Label());
825 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
827 progress_dialog.get_vbox()->pack_start (*label);
828 progress_dialog.get_vbox()->pack_start (*progress_bar);
830 progress_bar->show ();
832 /* this signal will be emitted from within this, the calling thread,
833 * after every file is copied. It provides information on percentage
834 * complete (in terms of total data to copy), the number of files
835 * copied so far, and the total number to copy.
838 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
840 progress_dialog.show_all ();
841 progress_dialog.present ();
844 if (_session->save_as (sa)) {
846 ArdourMessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
850 /* the logic here may seem odd: why isn't the condition sa.switch_to ?
851 * the trick is this: if the new session was copy with media included,
852 * then Session::save_as() will have already done a neat trick to avoid
853 * us having to unload and load the new state. But if the media was not
854 * included, then this is required (it avoids us having to otherwise
855 * drop all references to media (sources).
858 if (!sa.include_media && sa.switch_to) {
859 unload_session (false);
860 load_session (sa.final_session_folder_name, sa.new_name);
865 ARDOUR_UI::archive_session ()
873 Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
875 SessionArchiveDialog sad;
876 sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
877 int response = sad.run ();
879 if (response != Gtk::RESPONSE_OK) {
884 if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
885 ArdourMessageDialog msg (_("Session Archiving failed."));
891 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
895 struct tm local_time;
898 localtime_r (&n, &local_time);
899 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
900 if (switch_to_it && _session->dirty ()) {
901 save_state_canfail ("");
904 save_state (timebuf, switch_to_it);
909 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
913 prompter.get_result (snapname);
915 bool do_save = (snapname.length() != 0);
918 char illegal = Session::session_name_is_legal(snapname);
920 ArdourMessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
921 "snapshot names may not contain a '%1' character"), illegal));
927 vector<std::string> p;
928 get_state_files_in_directory (_session->session_directory().root_path(), p);
929 vector<string> n = get_file_names_no_extension (p);
931 if (find (n.begin(), n.end(), snapname) != n.end()) {
933 do_save = overwrite_file_dialog (prompter,
934 _("Confirm Snapshot Overwrite"),
935 _("A snapshot already exists with that name. Do you want to overwrite it?"));
939 save_state (snapname, switch_to_it);
950 ARDOUR_UI::open_session ()
952 if (!check_audioengine (_main_window)) {
956 /* ardour sessions are folders */
957 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
958 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
959 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
960 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
963 string session_parent_dir = Glib::path_get_dirname(_session->path());
964 open_session_selector.set_current_folder(session_parent_dir);
966 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
969 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
971 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
972 string default_session_folder = Config->get_default_session_parent_dir();
973 open_session_selector.add_shortcut_folder (default_session_folder);
975 catch (Glib::Error const& e) {
976 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
979 FileFilter session_filter;
980 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
981 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
982 open_session_selector.add_filter (session_filter);
984 FileFilter archive_filter;
985 archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
986 archive_filter.set_name (_("Session Archives"));
988 open_session_selector.add_filter (archive_filter);
990 open_session_selector.set_filter (session_filter);
992 int response = open_session_selector.run();
993 open_session_selector.hide ();
995 if (response == Gtk::RESPONSE_CANCEL) {
999 string session_path = open_session_selector.get_filename();
1003 if (session_path.length() > 0) {
1004 int rv = ARDOUR::inflate_session (session_path,
1005 Config->get_default_session_parent_dir(), path, name);
1007 _session_is_new = false;
1008 load_session (path, name);
1011 ArdourMessageDialog msg (_main_window,
1012 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1015 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1016 _session_is_new = isnew;
1017 load_session (path, name);
1023 ARDOUR_UI::open_recent_session ()
1025 bool can_return = (_session != 0);
1027 SessionDialog recent_session_dialog;
1031 ResponseType r = (ResponseType) recent_session_dialog.run ();
1034 case RESPONSE_ACCEPT:
1038 recent_session_dialog.hide();
1041 exit (EXIT_FAILURE);
1045 recent_session_dialog.hide();
1049 std::string path = recent_session_dialog.session_folder();
1050 std::string state = recent_session_dialog.session_name (should_be_new);
1052 if (should_be_new == true) {
1056 _session_is_new = false;
1058 if (load_session (path, state) == 0) {
1067 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1069 ArdourDialog window (_("Unsaved Session"));
1070 Gtk::HBox dhbox; // the hbox for the image and text
1071 Gtk::Label prompt_label;
1072 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1076 assert (actions.size() >= 3);
1078 window.add_button (actions[0], RESPONSE_REJECT);
1079 window.add_button (actions[1], RESPONSE_APPLY);
1080 window.add_button (actions[2], RESPONSE_ACCEPT);
1082 window.set_default_response (RESPONSE_ACCEPT);
1084 Gtk::Button noquit_button (msg);
1085 noquit_button.set_name ("EditorGTKButton");
1089 if (_session->snap_name() == _session->name()) {
1090 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?"),
1091 _session->snap_name());
1093 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?"),
1094 _session->snap_name());
1097 prompt_label.set_text (prompt);
1098 prompt_label.set_name (X_("PrompterLabel"));
1099 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1101 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1102 dhbox.set_homogeneous (false);
1103 dhbox.pack_start (*dimage, false, false, 5);
1104 dhbox.pack_start (prompt_label, true, false, 5);
1105 window.get_vbox()->pack_start (dhbox);
1107 window.set_name (_("Prompter"));
1108 window.set_modal (true);
1109 window.set_resizable (false);
1112 prompt_label.show();
1117 ResponseType r = (ResponseType) window.run();
1122 case RESPONSE_ACCEPT: // save and get out of here
1124 case RESPONSE_APPLY: // get out of here
1135 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
1138 _session->save_state (snapshot_name);
1143 ARDOUR_UI::autosave_session ()
1145 if (g_main_depth() > 1) {
1146 /* inside a recursive main loop,
1147 give up because we may not be able to
1153 if (!Config->get_periodic_safety_backups()) {
1158 _session->maybe_write_autosave();