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"
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/session.h"
53 #include "ardour/session_utils.h"
54 #include "ardour/session_state_utils.h"
55 #include "ardour/session_directory.h"
57 #include "ardour_ui.h"
58 #include "engine_dialog.h"
59 #include "missing_plugin_dialog.h"
61 #include "public_editor.h"
62 #include "save_as_dialog.h"
63 #include "session_dialog.h"
64 #include "session_archive_dialog.h"
68 #ifdef WINDOWS_VST_SUPPORT
72 using namespace ARDOUR;
73 using namespace ARDOUR_UI_UTILS;
77 using namespace ArdourWidgets;
80 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
82 std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
84 MessageDialog msg (str,
91 msg.set_name (X_("OpenExistingDialog"));
92 msg.set_title (_("Open Existing Session"));
93 msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
94 msg.set_position (Gtk::WIN_POS_CENTER);
95 pop_back_splash (msg);
106 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
108 BusProfile bus_profile;
111 bus_profile.master_out_channels = 2;
113 /* get settings from advanced section of NSD */
114 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
117 // NULL profile: no master, no monitor
118 if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
126 ARDOUR_UI::load_from_application_api (const std::string& path)
128 /* OS X El Capitan (and probably later) now somehow passes the command
129 line arguments to an app via the openFile delegate protocol. Ardour
130 already does its own command line processing, and having both
131 pathways active causes crashes. So, if the command line was already
132 set, do nothing here.
135 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
139 ARDOUR_COMMAND_LINE::session_name = path;
141 /* Cancel SessionDialog if it's visible to make OSX delegates work.
143 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
145 * - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
146 * -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
147 * - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
148 * -> SessionDialog is not displayed
151 if (_session_dialog) {
152 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
153 std::string session_path = path;
154 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
155 session_path = Glib::path_get_dirname (session_path);
157 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
158 _session_dialog->set_provided_session (session_name, session_path);
159 _session_dialog->response (RESPONSE_NONE);
160 _session_dialog->hide();
165 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
166 /* /path/to/foo => /path/to/foo, foo */
167 rv = load_session (path, basename_nosuffix (path));
169 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
170 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
173 // if load_session fails -> pop up SessionDialog.
175 ARDOUR_COMMAND_LINE::session_name = "";
177 if (get_session_parameters (true, false)) {
183 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
185 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
189 string template_name;
191 bool likely_new = false;
192 bool cancel_not_quit;
194 /* deal with any existing DIRTY session now, rather than later. don't
195 * treat a non-dirty session this way, so that it stays visible
196 * as we bring up the new session dialog.
199 if (_session && ARDOUR_UI::instance()->video_timeline) {
200 ARDOUR_UI::instance()->video_timeline->sync_session_state();
203 /* if there is already a session, relabel the button
204 on the SessionDialog so that we don't Quit directly
206 cancel_not_quit = (_session != 0) && !quit_on_cancel;
208 if (_session && _session->dirty()) {
209 if (unload_session (false)) {
210 /* unload cancelled by user */
213 ARDOUR_COMMAND_LINE::session_name = "";
216 if (!load_template.empty()) {
217 should_be_new = true;
218 template_name = load_template;
221 session_path = ARDOUR_COMMAND_LINE::session_name;
223 if (!session_path.empty()) {
225 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
227 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
229 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
230 /* session/snapshot file, change path to be dir */
231 session_path = Glib::path_get_dirname (session_path);
235 /* session (file or folder) does not exist ... did the
236 * user give us a path or just a name?
239 if (session_path.find (G_DIR_SEPARATOR) == string::npos) {
240 /* user gave session name with no path info, use
241 default session folder.
243 session_name = ARDOUR_COMMAND_LINE::session_name;
244 session_path = Glib::build_filename (Config->get_default_session_parent_dir (), session_name);
246 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
251 SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
253 _session_dialog = &session_dialog;
256 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
258 /* if they named a specific statefile, use it, otherwise they are
259 just giving a session folder, and we want to use it as is
263 string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
265 if (suffix != string::npos) {
266 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
267 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
268 session_name = Glib::path_get_basename (session_name);
270 session_path = ARDOUR_COMMAND_LINE::session_name;
271 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
276 session_dialog.clear_given ();
279 if (session_name.empty()) {
280 /* need the dialog to get the name (at least) from the user */
281 switch (session_dialog.run()) {
282 case RESPONSE_ACCEPT:
285 /* this is used for async * app->ShouldLoad(). */
286 continue; // while loop
289 if (quit_on_cancel) {
290 ARDOUR_UI::finish ();
291 Gtkmm2ext::Application::instance()->cleanup();
293 pthread_cancel_all ();
294 return -1; // caller is responsible to call exit()
300 session_dialog.hide ();
303 /* if we run the startup dialog again, offer more than just "new session" */
305 should_be_new = false;
307 session_name = session_dialog.session_name (likely_new);
308 session_path = session_dialog.session_folder ();
315 int rv = ARDOUR::inflate_session (session_name,
316 Config->get_default_session_parent_dir(), session_path, session_name);
318 MessageDialog msg (session_dialog,
319 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
324 session_dialog.set_provided_session (session_name, session_path);
328 // XXX check archive, inflate
329 string::size_type suffix = session_name.find (statefile_suffix);
331 if (suffix != string::npos) {
332 session_name = session_name.substr (0, suffix);
335 /* this shouldn't happen, but we catch it just in case it does */
337 if (session_name.empty()) {
341 if (session_dialog.use_session_template()) {
342 template_name = session_dialog.session_template_name();
343 _session_is_new = true;
346 if (session_name[0] == G_DIR_SEPARATOR ||
347 #ifdef PLATFORM_WINDOWS
348 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
350 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
351 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
356 /* absolute path or cwd-relative path specified for session name: infer session folder
360 session_path = Glib::path_get_dirname (session_name);
361 session_name = Glib::path_get_basename (session_name);
365 session_path = session_dialog.session_folder();
367 char illegal = Session::session_name_is_legal (session_name);
370 MessageDialog msg (session_dialog,
371 string_compose (_("To ensure compatibility with various systems\n"
372 "session names may not contain a '%1' character"),
375 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
380 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
383 if (likely_new && !nsm) {
385 std::string existing = Glib::build_filename (session_path, session_name);
387 if (!ask_about_loading_existing_session (existing)) {
388 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
393 _session_is_new = false;
398 pop_back_splash (session_dialog);
399 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
401 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
405 char illegal = Session::session_name_is_legal(session_name);
408 pop_back_splash (session_dialog);
409 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
410 "session names may not contain a '%1' character"), illegal));
412 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
416 _session_is_new = true;
419 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
421 ret = build_session_from_dialog (session_dialog, session_path, session_name);
422 meta_session_setup (template_name.substr (11));
424 } else if (likely_new && template_name.empty()) {
426 ret = build_session_from_dialog (session_dialog, session_path, session_name);
430 ret = load_session (session_path, session_name, template_name);
433 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
437 /* clear this to avoid endless attempts to load the
441 ARDOUR_COMMAND_LINE::session_name = "";
445 _session_dialog = NULL;
451 ARDOUR_UI::close_session()
453 if (!check_audioengine (_main_window)) {
457 if (unload_session (true)) {
461 ARDOUR_COMMAND_LINE::session_name = "";
463 if (get_session_parameters (true, false)) {
469 /** @param snap_name Snapshot name (without .ardour suffix).
470 * @return -2 if the load failed because we are not connected to the AudioEngine.
473 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
475 /* load_session calls flush_pending() which allows
476 * GUI interaction and potentially loading another session
477 * (that was easy via snapshot sidebar).
478 * Recursing into load_session() from load_session() and recusive
479 * event loops causes all kind of crashes.
481 assert (!session_load_in_progress);
482 if (session_load_in_progress) {
485 PBD::Unwinder<bool> lsu (session_load_in_progress, true);
487 Session *new_session;
492 unload_status = unload_session ();
494 if (unload_status < 0) {
496 } else if (unload_status > 0) {
502 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
505 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
508 /* this one is special */
510 catch (AudioEngine::PortRegistrationFailure const& err) {
512 MessageDialog msg (err.what(),
517 msg.set_title (_("Port Registration Error"));
518 msg.set_secondary_text (_("Click the Close button to try again."));
519 msg.set_position (Gtk::WIN_POS_CENTER);
520 pop_back_splash (msg);
523 int response = msg.run ();
528 case RESPONSE_CANCEL:
535 catch (SessionException const& e) {
536 MessageDialog msg (string_compose(
537 _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
538 path, snap_name, e.what()),
543 msg.set_title (_("Loading Error"));
544 msg.set_position (Gtk::WIN_POS_CENTER);
545 pop_back_splash (msg);
557 MessageDialog msg (string_compose(
558 _("Session \"%1 (snapshot %2)\" did not load successfully."),
564 msg.set_title (_("Loading Error"));
565 msg.set_position (Gtk::WIN_POS_CENTER);
566 pop_back_splash (msg);
578 list<string> const u = new_session->unknown_processors ();
580 MissingPluginDialog d (_session, u);
585 if (!new_session->writable()) {
586 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
591 msg.set_title (_("Read-only Session"));
592 msg.set_position (Gtk::WIN_POS_CENTER);
593 pop_back_splash (msg);
600 /* Now the session been created, add the transport controls */
601 new_session->add_controllable(roll_controllable);
602 new_session->add_controllable(stop_controllable);
603 new_session->add_controllable(goto_start_controllable);
604 new_session->add_controllable(goto_end_controllable);
605 new_session->add_controllable(auto_loop_controllable);
606 new_session->add_controllable(play_selection_controllable);
607 new_session->add_controllable(rec_controllable);
609 set_session (new_session);
612 _session->set_clean ();
615 #ifdef WINDOWS_VST_SUPPORT
616 fst_stop_threading();
620 Timers::TimerSuspender t;
624 #ifdef WINDOWS_VST_SUPPORT
625 fst_start_threading();
629 if (!mix_template.empty ()) {
630 /* if mix_template is given, assume this is a new session */
631 string metascript = Glib::build_filename (mix_template, "template.lua");
632 meta_session_setup (metascript);
637 /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
638 * which is queued by set_session().
639 * If session-loading fails we hide it explicitly.
640 * This covers both cases in a central place.
649 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
651 Session *new_session;
654 x = unload_session ();
662 _session_is_new = true;
665 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
668 catch (SessionException const& e) {
669 cerr << "Here are the errors associated with this failed session:\n";
671 cerr << "---------\n";
672 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
673 msg.set_title (_("Loading Error"));
674 msg.set_position (Gtk::WIN_POS_CENTER);
675 pop_back_splash (msg);
680 cerr << "Here are the errors associated with this failed session:\n";
682 cerr << "---------\n";
683 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
684 msg.set_title (_("Loading Error"));
685 msg.set_position (Gtk::WIN_POS_CENTER);
686 pop_back_splash (msg);
691 /* Give the new session the default GUI state, if such things exist */
694 n = Config->instant_xml (X_("Editor"));
696 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
697 new_session->add_instant_xml (*n, false);
699 n = Config->instant_xml (X_("Mixer"));
701 new_session->add_instant_xml (*n, false);
704 n = Config->instant_xml (X_("Preferences"));
706 new_session->add_instant_xml (*n, false);
709 /* Put the playhead at 0 and scroll fully left */
710 n = new_session->instant_xml (X_("Editor"));
712 n->set_property (X_("playhead"), X_("0"));
713 n->set_property (X_("left-frame"), X_("0"));
716 set_session (new_session);
718 new_session->save_state(new_session->name());
723 /** Ask the user for the name of a new snapshot and then take it.
727 ARDOUR_UI::snapshot_session (bool switch_to_it)
729 if (switch_to_it && _session->dirty()) {
730 vector<string> actions;
731 actions.push_back (_("Abort saving snapshot"));
732 actions.push_back (_("Don't save now, just snapshot"));
733 actions.push_back (_("Save it first"));
734 switch (ask_about_saving_session(actions)) {
739 if (save_state_canfail ("")) {
740 MessageDialog msg (_main_window,
742 %1 was unable to save your session.\n\n\
743 If you still wish to proceed, please use the\n\n\
744 \"Don't save now\" option."), PROGRAM_NAME));
745 pop_back_splash(msg);
751 _session->remove_pending_capture_state ();
756 Prompter prompter (true);
757 prompter.set_name ("Prompter");
758 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
760 prompter.set_title (_("Snapshot and switch"));
761 prompter.set_prompt (_("New session name"));
763 prompter.set_title (_("Take Snapshot"));
764 prompter.set_prompt (_("Name of new snapshot"));
768 prompter.set_initial_text (_session->snap_name());
770 Glib::DateTime tm (g_date_time_new_now_local ());
771 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
774 bool finished = false;
776 switch (prompter.run()) {
777 case RESPONSE_ACCEPT:
779 finished = process_snapshot_session_prompter (prompter, switch_to_it);
790 /** Ask the user for a new session name and then rename the session to it.
794 ARDOUR_UI::rename_session ()
800 Prompter prompter (true);
803 prompter.set_name ("Prompter");
804 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
805 prompter.set_title (_("Rename Session"));
806 prompter.set_prompt (_("New session name"));
809 switch (prompter.run()) {
810 case RESPONSE_ACCEPT:
812 prompter.get_result (name);
814 bool do_rename = (name.length() != 0);
817 char illegal = Session::session_name_is_legal (name);
820 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
821 "session names may not contain a '%1' character"), illegal));
826 switch (_session->rename (name)) {
828 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
829 msg.set_position (WIN_POS_MOUSE);
837 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
838 msg.set_position (WIN_POS_MOUSE);
854 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
858 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
860 label->set_text (buf);
861 bar->set_fraction (fraction);
863 /* process events, redraws, etc. */
865 while (gtk_events_pending()) {
866 gtk_main_iteration ();
869 return true; /* continue with save-as */
873 ARDOUR_UI::save_session_as ()
879 if (_session->dirty()) {
880 vector<string> actions;
881 actions.push_back (_("Abort save-as"));
882 actions.push_back (_("Don't save now, just save-as"));
883 actions.push_back (_("Save it first"));
884 switch (ask_about_saving_session(actions)) {
889 if (save_state_canfail ("")) {
890 MessageDialog msg (_main_window,
892 %1 was unable to save your session.\n\n\
893 If you still wish to proceed, please use the\n\n\
894 \"Don't save now\" option."), PROGRAM_NAME));
895 pop_back_splash(msg);
901 _session->remove_pending_capture_state ();
906 if (!save_as_dialog) {
907 save_as_dialog = new SaveAsDialog;
910 save_as_dialog->set_name (_session->name());
912 int response = save_as_dialog->run ();
914 save_as_dialog->hide ();
917 case Gtk::RESPONSE_OK:
926 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
927 sa.new_name = save_as_dialog->new_name ();
928 sa.switch_to = save_as_dialog->switch_to();
929 sa.copy_media = save_as_dialog->copy_media();
930 sa.copy_external = save_as_dialog->copy_external();
931 sa.include_media = save_as_dialog->include_media ();
933 /* Only bother with a progress dialog if we're going to copy
934 media into the save-as target. Without that choice, this
935 will be very fast because we're only talking about a few kB's to
936 perhaps a couple of MB's of data.
939 ArdourDialog progress_dialog (_("Save As"), true);
942 if (sa.include_media && sa.copy_media) {
944 Gtk::Label* label = manage (new Gtk::Label());
945 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
947 progress_dialog.get_vbox()->pack_start (*label);
948 progress_dialog.get_vbox()->pack_start (*progress_bar);
950 progress_bar->show ();
952 /* this signal will be emitted from within this, the calling thread,
953 * after every file is copied. It provides information on percentage
954 * complete (in terms of total data to copy), the number of files
955 * copied so far, and the total number to copy.
958 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
960 progress_dialog.show_all ();
961 progress_dialog.present ();
964 if (_session->save_as (sa)) {
966 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
970 /* the logic here may seem odd: why isn't the condition sa.switch_to ?
971 * the trick is this: if the new session was copy with media included,
972 * then Session::save_as() will have already done a neat trick to avoid
973 * us having to unload and load the new state. But if the media was not
974 * included, then this is required (it avoids us having to otherwise
975 * drop all references to media (sources).
978 if (!sa.include_media && sa.switch_to) {
979 unload_session (false);
980 load_session (sa.final_session_folder_name, sa.new_name);
985 ARDOUR_UI::archive_session ()
993 Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
995 SessionArchiveDialog sad;
996 sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
997 int response = sad.run ();
999 if (response != Gtk::RESPONSE_OK) {
1004 if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
1005 MessageDialog msg (_("Session Archiving failed."));
1011 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
1015 struct tm local_time;
1018 localtime_r (&n, &local_time);
1019 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
1020 if (switch_to_it && _session->dirty ()) {
1021 save_state_canfail ("");
1024 save_state (timebuf, switch_to_it);
1029 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
1033 prompter.get_result (snapname);
1035 bool do_save = (snapname.length() != 0);
1038 char illegal = Session::session_name_is_legal(snapname);
1040 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
1041 "snapshot names may not contain a '%1' character"), illegal));
1047 vector<std::string> p;
1048 get_state_files_in_directory (_session->session_directory().root_path(), p);
1049 vector<string> n = get_file_names_no_extension (p);
1051 if (find (n.begin(), n.end(), snapname) != n.end()) {
1053 do_save = overwrite_file_dialog (prompter,
1054 _("Confirm Snapshot Overwrite"),
1055 _("A snapshot already exists with that name. Do you want to overwrite it?"));
1059 save_state (snapname, switch_to_it);
1070 ARDOUR_UI::open_session ()
1072 if (!check_audioengine (_main_window)) {
1076 /* ardour sessions are folders */
1077 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1078 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1079 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1080 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1083 string session_parent_dir = Glib::path_get_dirname(_session->path());
1084 open_session_selector.set_current_folder(session_parent_dir);
1086 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1089 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1091 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1092 string default_session_folder = Config->get_default_session_parent_dir();
1093 open_session_selector.add_shortcut_folder (default_session_folder);
1095 catch (Glib::Error const& e) {
1096 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1099 FileFilter session_filter;
1100 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1101 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1102 open_session_selector.add_filter (session_filter);
1104 FileFilter archive_filter;
1105 archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
1106 archive_filter.set_name (_("Session Archives"));
1108 open_session_selector.add_filter (archive_filter);
1110 open_session_selector.set_filter (session_filter);
1112 int response = open_session_selector.run();
1113 open_session_selector.hide ();
1115 if (response == Gtk::RESPONSE_CANCEL) {
1119 string session_path = open_session_selector.get_filename();
1123 if (session_path.length() > 0) {
1124 int rv = ARDOUR::inflate_session (session_path,
1125 Config->get_default_session_parent_dir(), path, name);
1127 _session_is_new = false;
1128 load_session (path, name);
1131 MessageDialog msg (_main_window,
1132 string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1135 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1136 _session_is_new = isnew;
1137 load_session (path, name);
1143 ARDOUR_UI::open_recent_session ()
1145 bool can_return = (_session != 0);
1147 SessionDialog recent_session_dialog;
1151 ResponseType r = (ResponseType) recent_session_dialog.run ();
1154 case RESPONSE_ACCEPT:
1158 recent_session_dialog.hide();
1161 exit (EXIT_FAILURE);
1165 recent_session_dialog.hide();
1169 std::string path = recent_session_dialog.session_folder();
1170 std::string state = recent_session_dialog.session_name (should_be_new);
1172 if (should_be_new == true) {
1176 _session_is_new = false;
1178 if (load_session (path, state) == 0) {
1187 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1189 ArdourDialog window (_("Unsaved Session"));
1190 Gtk::HBox dhbox; // the hbox for the image and text
1191 Gtk::Label prompt_label;
1192 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1196 assert (actions.size() >= 3);
1198 window.add_button (actions[0], RESPONSE_REJECT);
1199 window.add_button (actions[1], RESPONSE_APPLY);
1200 window.add_button (actions[2], RESPONSE_ACCEPT);
1202 window.set_default_response (RESPONSE_ACCEPT);
1204 Gtk::Button noquit_button (msg);
1205 noquit_button.set_name ("EditorGTKButton");
1209 if (_session->snap_name() == _session->name()) {
1210 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?"),
1211 _session->snap_name());
1213 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?"),
1214 _session->snap_name());
1217 prompt_label.set_text (prompt);
1218 prompt_label.set_name (X_("PrompterLabel"));
1219 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1221 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1222 dhbox.set_homogeneous (false);
1223 dhbox.pack_start (*dimage, false, false, 5);
1224 dhbox.pack_start (prompt_label, true, false, 5);
1225 window.get_vbox()->pack_start (dhbox);
1227 window.set_name (_("Prompter"));
1228 window.set_modal (true);
1229 window.set_resizable (false);
1232 prompt_label.show();
1237 ResponseType r = (ResponseType) window.run();
1242 case RESPONSE_ACCEPT: // save and get out of here
1244 case RESPONSE_APPLY: // get out of here
1255 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
1258 _session->save_state (snapshot_name);
1263 ARDOUR_UI::autosave_session ()
1265 if (g_main_depth() > 1) {
1266 /* inside a recursive main loop,
1267 give up because we may not be able to
1273 if (!Config->get_periodic_safety_backups()) {
1278 _session->maybe_write_autosave();