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"
48 #include "widgets/prompter.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/filename_extensions.h"
52 #include "ardour/profile.h"
53 #include "ardour/session.h"
54 #include "ardour/session_utils.h"
55 #include "ardour/session_state_utils.h"
56 #include "ardour/session_directory.h"
58 #include "ardour_ui.h"
59 #include "engine_dialog.h"
60 #include "missing_plugin_dialog.h"
62 #include "public_editor.h"
63 #include "save_as_dialog.h"
64 #include "session_dialog.h"
65 #include "session_archive_dialog.h"
69 #ifdef WINDOWS_VST_SUPPORT
75 using namespace ARDOUR;
76 using namespace ARDOUR_UI_UTILS;
80 using namespace ArdourWidgets;
83 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
85 std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
87 MessageDialog msg (str,
94 msg.set_name (X_("OpenExistingDialog"));
95 msg.set_title (_("Open Existing Session"));
96 msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
97 msg.set_position (Gtk::WIN_POS_CENTER);
98 pop_back_splash (msg);
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)) {
131 ARDOUR_UI::load_from_application_api (const std::string& path)
133 /* OS X El Capitan (and probably later) now somehow passes the command
134 line arguments to an app via the openFile delegate protocol. Ardour
135 already does its own command line processing, and having both
136 pathways active causes crashes. So, if the command line was already
137 set, do nothing here.
140 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
144 ARDOUR_COMMAND_LINE::session_name = path;
146 /* Cancel SessionDialog if it's visible to make OSX delegates work.
148 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
150 * - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
151 * -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
152 * - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
153 * -> SessionDialog is not displayed
156 if (_session_dialog) {
157 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
158 std::string session_path = path;
159 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
160 session_path = Glib::path_get_dirname (session_path);
162 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
163 _session_dialog->set_provided_session (session_name, session_path);
164 _session_dialog->response (RESPONSE_NONE);
165 _session_dialog->hide();
170 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
171 /* /path/to/foo => /path/to/foo, foo */
172 rv = load_session (path, basename_nosuffix (path));
174 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
175 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
178 // if load_session fails -> pop up SessionDialog.
180 ARDOUR_COMMAND_LINE::session_name = "";
182 if (get_session_parameters (true, false)) {
188 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
190 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
194 string template_name;
196 bool likely_new = false;
197 bool cancel_not_quit;
199 /* deal with any existing DIRTY session now, rather than later. don't
200 * treat a non-dirty session this way, so that it stays visible
201 * as we bring up the new session dialog.
204 if (_session && ARDOUR_UI::instance()->video_timeline) {
205 ARDOUR_UI::instance()->video_timeline->sync_session_state();
208 /* if there is already a session, relabel the button
209 on the SessionDialog so that we don't Quit directly
211 cancel_not_quit = (_session != 0) && !quit_on_cancel;
213 if (_session && _session->dirty()) {
214 if (unload_session (false)) {
215 /* unload cancelled by user */
218 ARDOUR_COMMAND_LINE::session_name = "";
221 if (!load_template.empty()) {
222 should_be_new = true;
223 template_name = load_template;
226 session_path = ARDOUR_COMMAND_LINE::session_name;
228 if (!session_path.empty()) {
230 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
232 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
234 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
235 /* session/snapshot file, change path to be dir */
236 session_path = Glib::path_get_dirname (session_path);
240 /* session (file or folder) does not exist ... did the
241 * user give us a path or just a name?
244 if (session_path.find (G_DIR_SEPARATOR) == string::npos) {
245 /* user gave session name with no path info, use
246 default session folder.
248 session_name = ARDOUR_COMMAND_LINE::session_name;
249 session_path = Glib::build_filename (Config->get_default_session_parent_dir (), session_name);
251 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
256 SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
258 _session_dialog = &session_dialog;
261 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
263 /* if they named a specific statefile, use it, otherwise they are
264 just giving a session folder, and we want to use it as is
268 string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
270 if (suffix != string::npos) {
271 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
272 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
273 session_name = Glib::path_get_basename (session_name);
275 session_path = ARDOUR_COMMAND_LINE::session_name;
276 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
281 session_dialog.clear_given ();
284 if (session_name.empty()) {
285 /* need the dialog to get the name (at least) from the user */
286 switch (session_dialog.run()) {
287 case RESPONSE_ACCEPT:
290 /* this is used for async * app->ShouldLoad(). */
291 continue; // while loop
294 if (quit_on_cancel) {
295 ARDOUR_UI::finish ();
296 Gtkmm2ext::Application::instance()->cleanup();
298 pthread_cancel_all ();
299 return -1; // caller is responsible to call exit()
305 session_dialog.hide ();
308 /* if we run the startup dialog again, offer more than just "new session" */
310 should_be_new = false;
312 session_name = session_dialog.session_name (likely_new);
313 session_path = session_dialog.session_folder ();
320 int rv = ARDOUR::inflate_session (session_name,
321 Config->get_default_session_parent_dir(), session_path, session_name);
323 MessageDialog msg (session_dialog,
324 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
329 session_dialog.set_provided_session (session_name, session_path);
333 // XXX check archive, inflate
334 string::size_type suffix = session_name.find (statefile_suffix);
336 if (suffix != string::npos) {
337 session_name = session_name.substr (0, suffix);
340 /* this shouldn't happen, but we catch it just in case it does */
342 if (session_name.empty()) {
346 if (session_dialog.use_session_template()) {
347 template_name = session_dialog.session_template_name();
348 _session_is_new = true;
351 if (session_name[0] == G_DIR_SEPARATOR ||
352 #ifdef PLATFORM_WINDOWS
353 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
355 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
356 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
361 /* absolute path or cwd-relative path specified for session name: infer session folder
365 session_path = Glib::path_get_dirname (session_name);
366 session_name = Glib::path_get_basename (session_name);
370 session_path = session_dialog.session_folder();
372 char illegal = Session::session_name_is_legal (session_name);
375 MessageDialog msg (session_dialog,
376 string_compose (_("To ensure compatibility with various systems\n"
377 "session names may not contain a '%1' character"),
380 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
385 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
388 if (likely_new && !nsm) {
390 std::string existing = Glib::build_filename (session_path, session_name);
392 if (!ask_about_loading_existing_session (existing)) {
393 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
398 _session_is_new = false;
403 pop_back_splash (session_dialog);
404 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
406 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
410 char illegal = Session::session_name_is_legal(session_name);
413 pop_back_splash (session_dialog);
414 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
415 "session names may not contain a '%1' character"), illegal));
417 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
421 _session_is_new = true;
424 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
426 ret = build_session_from_dialog (session_dialog, session_path, session_name);
427 meta_session_setup (template_name.substr (11));
429 } else if (likely_new && template_name.empty()) {
431 ret = build_session_from_dialog (session_dialog, session_path, session_name);
435 ret = load_session (session_path, session_name, template_name);
438 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
442 /* clear this to avoid endless attempts to load the
446 ARDOUR_COMMAND_LINE::session_name = "";
450 _session_dialog = NULL;
456 ARDOUR_UI::close_session()
458 if (!check_audioengine (_main_window)) {
462 if (unload_session (true)) {
466 ARDOUR_COMMAND_LINE::session_name = "";
468 if (get_session_parameters (true, false)) {
474 /** @param snap_name Snapshot name (without .ardour suffix).
475 * @return -2 if the load failed because we are not connected to the AudioEngine.
478 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
480 /* load_session calls flush_pending() which allows
481 * GUI interaction and potentially loading another session
482 * (that was easy via snapshot sidebar).
483 * Recursing into load_session() from load_session() and recusive
484 * event loops causes all kind of crashes.
486 assert (!session_load_in_progress);
487 if (session_load_in_progress) {
490 PBD::Unwinder<bool> lsu (session_load_in_progress, true);
492 Session *new_session;
497 unload_status = unload_session ();
499 if (unload_status < 0) {
501 } else if (unload_status > 0) {
507 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
510 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
513 /* this one is special */
515 catch (AudioEngine::PortRegistrationFailure const& err) {
517 MessageDialog msg (err.what(),
522 msg.set_title (_("Port Registration Error"));
523 msg.set_secondary_text (_("Click the Close button to try again."));
524 msg.set_position (Gtk::WIN_POS_CENTER);
525 pop_back_splash (msg);
528 int response = msg.run ();
533 case RESPONSE_CANCEL:
540 catch (SessionException const& e) {
541 MessageDialog msg (string_compose(
542 _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
543 path, snap_name, e.what()),
548 msg.set_title (_("Loading Error"));
549 msg.set_position (Gtk::WIN_POS_CENTER);
550 pop_back_splash (msg);
562 MessageDialog msg (string_compose(
563 _("Session \"%1 (snapshot %2)\" did not load successfully."),
569 msg.set_title (_("Loading Error"));
570 msg.set_position (Gtk::WIN_POS_CENTER);
571 pop_back_splash (msg);
583 list<string> const u = new_session->unknown_processors ();
585 MissingPluginDialog d (_session, u);
590 if (!new_session->writable()) {
591 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
596 msg.set_title (_("Read-only Session"));
597 msg.set_position (Gtk::WIN_POS_CENTER);
598 pop_back_splash (msg);
605 /* Now the session been created, add the transport controls */
606 new_session->add_controllable(roll_controllable);
607 new_session->add_controllable(stop_controllable);
608 new_session->add_controllable(goto_start_controllable);
609 new_session->add_controllable(goto_end_controllable);
610 new_session->add_controllable(auto_loop_controllable);
611 new_session->add_controllable(play_selection_controllable);
612 new_session->add_controllable(rec_controllable);
614 set_session (new_session);
617 _session->set_clean ();
620 #ifdef WINDOWS_VST_SUPPORT
621 fst_stop_threading();
625 Timers::TimerSuspender t;
629 #ifdef WINDOWS_VST_SUPPORT
630 fst_start_threading();
634 if (!mix_template.empty ()) {
635 /* if mix_template is given, assume this is a new session */
636 string metascript = Glib::build_filename (mix_template, "template.lua");
637 meta_session_setup (metascript);
642 /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
643 * which is queued by set_session().
644 * If session-loading fails we hide it explicitly.
645 * This covers both cases in a central place.
654 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
656 Session *new_session;
659 x = unload_session ();
667 _session_is_new = true;
670 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
673 catch (SessionException const& e) {
674 cerr << "Here are the errors associated with this failed session:\n";
676 cerr << "---------\n";
677 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
678 msg.set_title (_("Loading Error"));
679 msg.set_position (Gtk::WIN_POS_CENTER);
680 pop_back_splash (msg);
685 cerr << "Here are the errors associated with this failed session:\n";
687 cerr << "---------\n";
688 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
689 msg.set_title (_("Loading Error"));
690 msg.set_position (Gtk::WIN_POS_CENTER);
691 pop_back_splash (msg);
696 /* Give the new session the default GUI state, if such things exist */
699 n = Config->instant_xml (X_("Editor"));
701 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
702 new_session->add_instant_xml (*n, false);
704 n = Config->instant_xml (X_("Mixer"));
706 new_session->add_instant_xml (*n, false);
709 n = Config->instant_xml (X_("Preferences"));
711 new_session->add_instant_xml (*n, false);
714 /* Put the playhead at 0 and scroll fully left */
715 n = new_session->instant_xml (X_("Editor"));
717 n->set_property (X_("playhead"), X_("0"));
718 n->set_property (X_("left-frame"), X_("0"));
721 set_session (new_session);
723 new_session->save_state(new_session->name());
728 /** Ask the user for the name of a new snapshot and then take it.
732 ARDOUR_UI::snapshot_session (bool switch_to_it)
734 if (switch_to_it && _session->dirty()) {
735 vector<string> actions;
736 actions.push_back (_("Abort saving snapshot"));
737 actions.push_back (_("Don't save now, just snapshot"));
738 actions.push_back (_("Save it first"));
739 switch (ask_about_saving_session(actions)) {
744 if (save_state_canfail ("")) {
745 MessageDialog msg (_main_window,
747 %1 was unable to save your session.\n\n\
748 If you still wish to proceed, please use the\n\n\
749 \"Don't save now\" option."), PROGRAM_NAME));
750 pop_back_splash(msg);
756 _session->remove_pending_capture_state ();
761 Prompter prompter (true);
762 prompter.set_name ("Prompter");
763 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
765 prompter.set_title (_("Snapshot and switch"));
766 prompter.set_prompt (_("New session name"));
768 prompter.set_title (_("Take Snapshot"));
769 prompter.set_prompt (_("Name of new snapshot"));
773 prompter.set_initial_text (_session->snap_name());
775 Glib::DateTime tm (g_date_time_new_now_local ());
776 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
779 bool finished = false;
781 switch (prompter.run()) {
782 case RESPONSE_ACCEPT:
784 finished = process_snapshot_session_prompter (prompter, switch_to_it);
795 /** Ask the user for a new session name and then rename the session to it.
799 ARDOUR_UI::rename_session ()
805 Prompter prompter (true);
808 prompter.set_name ("Prompter");
809 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
810 prompter.set_title (_("Rename Session"));
811 prompter.set_prompt (_("New session name"));
814 switch (prompter.run()) {
815 case RESPONSE_ACCEPT:
817 prompter.get_result (name);
819 bool do_rename = (name.length() != 0);
822 char illegal = Session::session_name_is_legal (name);
825 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
826 "session names may not contain a '%1' character"), illegal));
831 switch (_session->rename (name)) {
833 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
834 msg.set_position (WIN_POS_MOUSE);
842 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
843 msg.set_position (WIN_POS_MOUSE);
859 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
863 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
865 label->set_text (buf);
866 bar->set_fraction (fraction);
868 /* process events, redraws, etc. */
870 while (gtk_events_pending()) {
871 gtk_main_iteration ();
874 return true; /* continue with save-as */
878 ARDOUR_UI::save_session_as ()
884 if (_session->dirty()) {
885 vector<string> actions;
886 actions.push_back (_("Abort save-as"));
887 actions.push_back (_("Don't save now, just save-as"));
888 actions.push_back (_("Save it first"));
889 switch (ask_about_saving_session(actions)) {
894 if (save_state_canfail ("")) {
895 MessageDialog msg (_main_window,
897 %1 was unable to save your session.\n\n\
898 If you still wish to proceed, please use the\n\n\
899 \"Don't save now\" option."), PROGRAM_NAME));
900 pop_back_splash(msg);
906 _session->remove_pending_capture_state ();
911 if (!save_as_dialog) {
912 save_as_dialog = new SaveAsDialog;
915 save_as_dialog->set_name (_session->name());
917 int response = save_as_dialog->run ();
919 save_as_dialog->hide ();
922 case Gtk::RESPONSE_OK:
931 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
932 sa.new_name = save_as_dialog->new_name ();
933 sa.switch_to = save_as_dialog->switch_to();
934 sa.copy_media = save_as_dialog->copy_media();
935 sa.copy_external = save_as_dialog->copy_external();
936 sa.include_media = save_as_dialog->include_media ();
938 /* Only bother with a progress dialog if we're going to copy
939 media into the save-as target. Without that choice, this
940 will be very fast because we're only talking about a few kB's to
941 perhaps a couple of MB's of data.
944 ArdourDialog progress_dialog (_("Save As"), true);
947 if (sa.include_media && sa.copy_media) {
949 Gtk::Label* label = manage (new Gtk::Label());
950 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
952 progress_dialog.get_vbox()->pack_start (*label);
953 progress_dialog.get_vbox()->pack_start (*progress_bar);
955 progress_bar->show ();
957 /* this signal will be emitted from within this, the calling thread,
958 * after every file is copied. It provides information on percentage
959 * complete (in terms of total data to copy), the number of files
960 * copied so far, and the total number to copy.
963 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
965 progress_dialog.show_all ();
966 progress_dialog.present ();
969 if (_session->save_as (sa)) {
971 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
975 /* the logic here may seem odd: why isn't the condition sa.switch_to ?
976 * the trick is this: if the new session was copy with media included,
977 * then Session::save_as() will have already done a neat trick to avoid
978 * us having to unload and load the new state. But if the media was not
979 * included, then this is required (it avoids us having to otherwise
980 * drop all references to media (sources).
983 if (!sa.include_media && sa.switch_to) {
984 unload_session (false);
985 load_session (sa.final_session_folder_name, sa.new_name);
990 ARDOUR_UI::archive_session ()
998 Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
1000 SessionArchiveDialog sad;
1001 sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
1002 int response = sad.run ();
1004 if (response != Gtk::RESPONSE_OK) {
1009 if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
1010 MessageDialog msg (_("Session Archiving failed."));
1016 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
1020 struct tm local_time;
1023 localtime_r (&n, &local_time);
1024 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
1025 if (switch_to_it && _session->dirty ()) {
1026 save_state_canfail ("");
1029 save_state (timebuf, switch_to_it);
1034 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
1038 prompter.get_result (snapname);
1040 bool do_save = (snapname.length() != 0);
1043 char illegal = Session::session_name_is_legal(snapname);
1045 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
1046 "snapshot names may not contain a '%1' character"), illegal));
1052 vector<std::string> p;
1053 get_state_files_in_directory (_session->session_directory().root_path(), p);
1054 vector<string> n = get_file_names_no_extension (p);
1056 if (find (n.begin(), n.end(), snapname) != n.end()) {
1058 do_save = overwrite_file_dialog (prompter,
1059 _("Confirm Snapshot Overwrite"),
1060 _("A snapshot already exists with that name. Do you want to overwrite it?"));
1064 save_state (snapname, switch_to_it);
1075 ARDOUR_UI::open_session ()
1077 if (!check_audioengine (_main_window)) {
1081 /* ardour sessions are folders */
1082 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1083 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1084 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1085 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1088 string session_parent_dir = Glib::path_get_dirname(_session->path());
1089 open_session_selector.set_current_folder(session_parent_dir);
1091 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1094 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1096 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1097 string default_session_folder = Config->get_default_session_parent_dir();
1098 open_session_selector.add_shortcut_folder (default_session_folder);
1100 catch (Glib::Error const& e) {
1101 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1104 FileFilter session_filter;
1105 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1106 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1107 open_session_selector.add_filter (session_filter);
1109 FileFilter archive_filter;
1110 archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
1111 archive_filter.set_name (_("Session Archives"));
1113 open_session_selector.add_filter (archive_filter);
1115 open_session_selector.set_filter (session_filter);
1117 int response = open_session_selector.run();
1118 open_session_selector.hide ();
1120 if (response == Gtk::RESPONSE_CANCEL) {
1124 string session_path = open_session_selector.get_filename();
1128 if (session_path.length() > 0) {
1129 int rv = ARDOUR::inflate_session (session_path,
1130 Config->get_default_session_parent_dir(), path, name);
1132 _session_is_new = false;
1133 load_session (path, name);
1136 MessageDialog msg (_main_window,
1137 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1140 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1141 _session_is_new = isnew;
1142 load_session (path, name);
1148 ARDOUR_UI::open_recent_session ()
1150 bool can_return = (_session != 0);
1152 SessionDialog recent_session_dialog;
1156 ResponseType r = (ResponseType) recent_session_dialog.run ();
1159 case RESPONSE_ACCEPT:
1163 recent_session_dialog.hide();
1166 exit (EXIT_FAILURE);
1170 recent_session_dialog.hide();
1174 std::string path = recent_session_dialog.session_folder();
1175 std::string state = recent_session_dialog.session_name (should_be_new);
1177 if (should_be_new == true) {
1181 _session_is_new = false;
1183 if (load_session (path, state) == 0) {
1192 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1194 ArdourDialog window (_("Unsaved Session"));
1195 Gtk::HBox dhbox; // the hbox for the image and text
1196 Gtk::Label prompt_label;
1197 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1201 assert (actions.size() >= 3);
1203 window.add_button (actions[0], RESPONSE_REJECT);
1204 window.add_button (actions[1], RESPONSE_APPLY);
1205 window.add_button (actions[2], RESPONSE_ACCEPT);
1207 window.set_default_response (RESPONSE_ACCEPT);
1209 Gtk::Button noquit_button (msg);
1210 noquit_button.set_name ("EditorGTKButton");
1214 if (_session->snap_name() == _session->name()) {
1215 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?"),
1216 _session->snap_name());
1218 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?"),
1219 _session->snap_name());
1222 prompt_label.set_text (prompt);
1223 prompt_label.set_name (X_("PrompterLabel"));
1224 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1226 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1227 dhbox.set_homogeneous (false);
1228 dhbox.pack_start (*dimage, false, false, 5);
1229 dhbox.pack_start (prompt_label, true, false, 5);
1230 window.get_vbox()->pack_start (dhbox);
1232 window.set_name (_("Prompter"));
1233 window.set_modal (true);
1234 window.set_resizable (false);
1237 prompt_label.show();
1242 ResponseType r = (ResponseType) window.run();
1247 case RESPONSE_ACCEPT: // save and get out of here
1249 case RESPONSE_APPLY: // get out of here
1260 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
1263 _session->save_state (snapshot_name);
1268 ARDOUR_UI::autosave_session ()
1270 if (g_main_depth() > 1) {
1271 /* inside a recursive main loop,
1272 give up because we may not be able to
1278 if (!Config->get_periodic_safety_backups()) {
1283 _session->maybe_write_autosave();