2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/basename.h>
37 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/audiofilesource.h>
63 #include <ardour/recent_sessions.h>
64 #include <ardour/port.h>
65 #include <ardour/audio_track.h>
68 #include "ardour_ui.h"
69 #include "public_editor.h"
70 #include "audio_clock.h"
75 #include "add_route_dialog.h"
76 #include "new_session_dialog.h"
80 #include "gui_thread.h"
81 #include "theme_manager.h"
82 #include "engine_dialog.h"
86 using namespace ARDOUR;
88 using namespace Gtkmm2ext;
92 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
93 UIConfiguration *ARDOUR_UI::ui_config = 0;
95 sigc::signal<void,bool> ARDOUR_UI::Blink;
96 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
97 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
98 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
100 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
102 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
104 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
105 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
106 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
107 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
111 adjuster_table (3, 3),
115 preroll_button (_("pre\nroll")),
116 postroll_button (_("post\nroll")),
120 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
124 roll_controllable ("transport roll", *this, TransportControllable::Roll),
125 stop_controllable ("transport stop", *this, TransportControllable::Stop),
126 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
127 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
128 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
129 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
130 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
131 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
132 shuttle_controller_binding_proxy (shuttle_controllable),
134 roll_button (roll_controllable),
135 stop_button (stop_controllable),
136 goto_start_button (goto_start_controllable),
137 goto_end_button (goto_end_controllable),
138 auto_loop_button (auto_loop_controllable),
139 play_selection_button (play_selection_controllable),
140 rec_button (rec_controllable),
142 shuttle_units_button (_("% ")),
144 punch_in_button (_("Punch In")),
145 punch_out_button (_("Punch Out")),
146 auto_return_button (_("Auto Return")),
147 auto_play_button (_("Auto Play")),
148 auto_input_button (_("Auto Input")),
149 click_button (_("Click")),
150 time_master_button (_("time\nmaster")),
152 auditioning_alert_button (_("AUDITION")),
153 solo_alert_button (_("SOLO")),
155 error_log_button (_("Errors"))
157 using namespace Gtk::Menu_Helpers;
162 _auto_display_errors = false;
165 if (getenv ("ARDOUR_DEBUG_UPDATES")) {
166 gdk_window_set_debug_updates (true);
172 if (ARDOUR_COMMAND_LINE::session_name.length()) {
173 /* only show this if we're not going to post the new session dialog */
177 if (theArdourUI == 0) {
181 ui_config = new UIConfiguration();
182 theme_manager = new ThemeManager();
188 _session_is_new = false;
189 big_clock_window = 0;
190 session_selector_window = 0;
191 new_session_dialog = 0;
192 last_key_press_time = 0;
193 connection_editor = 0;
194 add_route_dialog = 0;
199 open_session_selector = 0;
200 have_configure_timeout = false;
201 have_disk_speed_dialog_displayed = false;
202 _will_create_new_session_automatically = false;
203 session_loaded = false;
204 last_speed_displayed = -1.0f;
206 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
207 /* all changes go to the user directory */
208 user_keybindings_path = get_user_ardour_path ();
209 user_keybindings_path += '/';
210 user_keybindings_path += "ardour.bindings";
212 can_save_keybindings = false;
214 last_configure_time.tv_sec = 0;
215 last_configure_time.tv_usec = 0;
217 shuttle_grabbed = false;
219 shuttle_max_speed = 8.0f;
221 shuttle_style_menu = 0;
222 shuttle_unit_menu = 0;
224 gettimeofday (&last_peak_grab, 0);
225 gettimeofday (&last_shuttle_request, 0);
227 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
228 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
230 /* handle pending state with a dialog */
232 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
234 /* handle sr mismatch with a dialog */
236 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
238 /* lets get this party started */
241 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
242 throw failed_constructor ();
245 setup_gtk_ardour_enums ();
246 Config->set_current_owner (ConfigVariableBase::Interface);
249 } catch (failed_constructor& err) {
250 error << _("could not initialize Ardour.") << endmsg;
255 /* we like keyboards */
257 keyboard = new Keyboard;
259 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
260 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
266 ARDOUR_UI::create_engine ()
268 // this gets called every time by new_session()
274 loading_message (_("Starting audio engine"));
277 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
284 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
285 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
286 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
287 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
295 ARDOUR_UI::post_engine ()
297 /* Things to be done once we create the AudioEngine
300 check_memory_locking();
302 ActionManager::init ();
305 if (setup_windows ()) {
306 throw failed_constructor ();
309 /* this is the first point at which all the keybindings are available */
311 if (ARDOUR_COMMAND_LINE::show_key_actions) {
312 vector<string> names;
313 vector<string> paths;
315 vector<AccelKey> bindings;
317 ActionManager::get_all_actions (names, paths, keys, bindings);
319 vector<string>::iterator n;
320 vector<string>::iterator k;
321 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
322 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
328 blink_timeout_tag = -1;
330 /* the global configuration object is now valid */
334 /* this being a GUI and all, we want peakfiles */
336 AudioFileSource::set_build_peakfiles (true);
337 AudioFileSource::set_build_missing_peakfiles (true);
339 /* set default clock modes */
341 primary_clock.set_mode (AudioClock::SMPTE);
342 secondary_clock.set_mode (AudioClock::BBT);
344 /* start the time-of-day-clock */
347 /* OS X provides an always visible wallclock, so don't be stupid */
348 update_wall_clock ();
349 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
352 update_disk_space ();
354 update_sample_rate (engine->frame_rate());
356 platform_specific ();
358 /* now start and maybe save state */
360 if (do_engine_start () == 0) {
361 if (session && _session_is_new) {
362 /* we need to retain initial visual
363 settings for a new session
365 session->save_state ("");
370 ARDOUR_UI::~ARDOUR_UI ()
372 save_ardour_state ();
386 if (add_route_dialog) {
387 delete add_route_dialog;
390 if (new_session_dialog) {
391 delete new_session_dialog;
396 ARDOUR_UI::pop_back_splash ()
398 if (Splash::instance()) {
399 // Splash::instance()->pop_back();
400 Splash::instance()->hide ();
405 ARDOUR_UI::configure_timeout ()
410 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
411 /* no configure events yet */
415 gettimeofday (&now, 0);
416 timersub (&now, &last_configure_time, &diff);
418 /* force a gap of 0.5 seconds since the last configure event
421 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
424 have_configure_timeout = false;
425 save_ardour_state ();
431 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
433 if (have_configure_timeout) {
434 gettimeofday (&last_configure_time, 0);
436 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
437 have_configure_timeout = true;
444 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
446 const XMLProperty* prop;
448 if ((prop = node.property ("roll")) != 0) {
449 roll_controllable.set_id (prop->value());
451 if ((prop = node.property ("stop")) != 0) {
452 stop_controllable.set_id (prop->value());
454 if ((prop = node.property ("goto_start")) != 0) {
455 goto_start_controllable.set_id (prop->value());
457 if ((prop = node.property ("goto_end")) != 0) {
458 goto_end_controllable.set_id (prop->value());
460 if ((prop = node.property ("auto_loop")) != 0) {
461 auto_loop_controllable.set_id (prop->value());
463 if ((prop = node.property ("play_selection")) != 0) {
464 play_selection_controllable.set_id (prop->value());
466 if ((prop = node.property ("rec")) != 0) {
467 rec_controllable.set_id (prop->value());
469 if ((prop = node.property ("shuttle")) != 0) {
470 shuttle_controllable.set_id (prop->value());
475 ARDOUR_UI::get_transport_controllable_state ()
477 XMLNode* node = new XMLNode(X_("TransportControllables"));
480 roll_controllable.id().print (buf, sizeof (buf));
481 node->add_property (X_("roll"), buf);
482 stop_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("stop"), buf);
484 goto_start_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("goto_start"), buf);
486 goto_end_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("goto_end"), buf);
488 auto_loop_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("auto_loop"), buf);
490 play_selection_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("play_selection"), buf);
492 rec_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("rec"), buf);
494 shuttle_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("shuttle"), buf);
501 ARDOUR_UI::save_ardour_state ()
503 if (!keyboard || !mixer || !editor) {
507 /* XXX this is all a bit dubious. add_extra_xml() uses
508 a different lifetime model from add_instant_xml().
511 XMLNode* node = new XMLNode (keyboard->get_state());
512 Config->add_extra_xml (*node);
513 Config->add_extra_xml (get_transport_controllable_state());
514 if (new_session_dialog) {
515 if (new_session_dialog->engine_control.was_used()) {
516 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
519 Config->save_state();
520 ui_config->save_state ();
522 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
523 XMLNode mnode(mixer->get_state());
526 session->add_instant_xml (enode, session->path());
527 session->add_instant_xml (mnode, session->path());
529 Config->add_instant_xml (enode, get_user_ardour_path());
530 Config->add_instant_xml (mnode, get_user_ardour_path());
537 ARDOUR_UI::autosave_session ()
539 if (!Config->get_periodic_safety_backups())
543 session->maybe_write_autosave();
550 ARDOUR_UI::update_autosave ()
552 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
554 if (session->dirty()) {
555 if (_autosave_connection.connected()) {
556 _autosave_connection.disconnect();
559 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
560 Config->get_periodic_safety_backup_interval() * 1000);
563 if (_autosave_connection.connected()) {
564 _autosave_connection.disconnect();
570 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
574 title = _("Ardour could not start JACK");
576 title = _("Ardour could not connect to JACK.");
579 MessageDialog win (title,
585 win.set_secondary_text(_("There are several possible reasons:\n\
587 1) You requested audio parameters that are not supported..\n\
588 2) JACK is running as another user.\n\
590 Please consider the possibilities, and perhaps try different parameters."));
592 win.set_secondary_text(_("There are several possible reasons:\n\
594 1) JACK is not running.\n\
595 2) JACK is running as another user, perhaps root.\n\
596 3) There is already another client called \"ardour\".\n\
598 Please consider the possibilities, and perhaps (re)start JACK."));
602 win.set_transient_for (*toplevel);
606 win.add_button (Stock::OK, RESPONSE_CLOSE);
608 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
611 win.set_default_response (RESPONSE_CLOSE);
614 win.set_position (Gtk::WIN_POS_CENTER);
617 /* we just don't care about the result, but we want to block */
623 ARDOUR_UI::startup ()
627 new_session_dialog = new NewSessionDialog();
629 bool backend_audio_is_running = EngineControl::engine_running();
630 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
633 new_session_dialog->engine_control.set_state (*audio_setup);
636 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
644 ARDOUR_UI::no_memory_warning ()
646 XMLNode node (X_("no-memory-warning"));
647 Config->add_instant_xml (node, get_user_ardour_path());
651 ARDOUR_UI::check_memory_locking ()
654 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
658 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
660 if (engine->is_realtime() && memory_warning_node == 0) {
662 struct rlimit limits;
664 long pages, page_size;
666 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
669 ram = (int64_t) pages * (int64_t) page_size;
672 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
676 if (limits.rlim_cur != RLIM_INFINITY) {
678 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
681 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
682 "This might cause Ardour to run out of memory before your system "
683 "runs out of memory. \n\n"
684 "You can view the memory limit with 'ulimit -l', "
685 "and it is normally controlled by /etc/security/limits.conf"));
687 VBox* vbox = msg.get_vbox();
689 CheckButton cb (_("Do not show this window again"));
691 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
693 hbox.pack_start (cb, true, false);
694 vbox->pack_start (hbox);
712 if (session->transport_rolling()) {
713 session->request_stop ();
717 if (session->dirty()) {
718 switch (ask_about_saving_session(_("quit"))) {
723 /* use the default name */
724 if (save_state_canfail ("")) {
725 /* failed - don't quit */
726 MessageDialog msg (*editor,
728 Ardour was unable to save your session.\n\n\
729 If you still wish to quit, please use the\n\n\
730 \"Just quit\" option."));
741 session->set_deletion_in_progress ();
745 save_ardour_state ();
750 ARDOUR_UI::ask_about_saving_session (const string & what)
752 ArdourDialog window (_("ardour: save session?"));
753 Gtk::HBox dhbox; // the hbox for the image and text
754 Gtk::Label prompt_label;
755 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
759 msg = string_compose(_("Don't %1"), what);
760 window.add_button (msg, RESPONSE_REJECT);
761 msg = string_compose(_("Just %1"), what);
762 window.add_button (msg, RESPONSE_APPLY);
763 msg = string_compose(_("Save and %1"), what);
764 window.add_button (msg, RESPONSE_ACCEPT);
766 window.set_default_response (RESPONSE_ACCEPT);
768 Gtk::Button noquit_button (msg);
769 noquit_button.set_name ("EditorGTKButton");
774 if (session->snap_name() == session->name()) {
777 type = _("snapshot");
779 prompt = string_compose(_("The %1\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
780 type, session->snap_name());
782 prompt_label.set_text (prompt);
783 prompt_label.set_name (X_("PrompterLabel"));
784 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
786 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
788 dhbox.set_homogeneous (false);
789 dhbox.pack_start (*dimage, false, false, 5);
790 dhbox.pack_start (prompt_label, true, false, 5);
791 window.get_vbox()->pack_start (dhbox);
793 window.set_name (_("Prompter"));
794 window.set_position (Gtk::WIN_POS_MOUSE);
795 window.set_modal (true);
796 window.set_resizable (false);
799 save_the_session = 0;
801 window.set_keep_above (true);
804 ResponseType r = (ResponseType) window.run();
809 case RESPONSE_ACCEPT: // save and get out of here
811 case RESPONSE_APPLY: // get out of here
821 ARDOUR_UI::every_second ()
824 update_buffer_load ();
825 update_disk_space ();
830 ARDOUR_UI::every_point_one_seconds ()
832 update_speed_display ();
833 RapidScreenUpdate(); /* EMIT_SIGNAL */
838 ARDOUR_UI::every_point_zero_one_seconds ()
840 // august 2007: actual update frequency: 40Hz, not 100Hz
842 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
847 ARDOUR_UI::update_sample_rate (nframes_t ignored)
851 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
853 if (!engine->connected()) {
855 snprintf (buf, sizeof (buf), _("disconnected"));
859 nframes_t rate = engine->frame_rate();
861 if (fmod (rate, 1000.0) != 0.0) {
862 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
863 (float) rate/1000.0f,
864 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
866 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
868 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
872 sample_rate_label.set_text (buf);
876 ARDOUR_UI::update_cpu_load ()
879 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
880 cpu_load_label.set_text (buf);
884 ARDOUR_UI::update_buffer_load ()
889 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
890 session->playback_load(), session->capture_load());
891 buffer_load_label.set_text (buf);
893 buffer_load_label.set_text ("");
898 ARDOUR_UI::count_recenabled_streams (Route& route)
900 Track* track = dynamic_cast<Track*>(&route);
901 if (track && track->diskstream()->record_enabled()) {
902 rec_enabled_streams += track->n_inputs();
907 ARDOUR_UI::update_disk_space()
913 nframes_t frames = session->available_capture_duration();
916 if (frames == max_frames) {
917 strcpy (buf, _("Disk: 24hrs+"));
922 nframes_t fr = session->frame_rate();
924 rec_enabled_streams = 0;
925 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
927 if (rec_enabled_streams) {
928 frames /= rec_enabled_streams;
931 hrs = frames / (fr * 3600);
932 frames -= hrs * fr * 3600;
933 mins = frames / (fr * 60);
934 frames -= mins * fr * 60;
937 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
940 disk_space_label.set_text (buf);
944 ARDOUR_UI::update_wall_clock ()
951 tm_now = localtime (&now);
953 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
954 wall_clock_label.set_text (buf);
960 ARDOUR_UI::session_menu (GdkEventButton *ev)
962 session_popup_menu->popup (0, 0);
967 ARDOUR_UI::redisplay_recent_sessions ()
969 vector<string *> *sessions;
970 vector<string *>::iterator i;
971 RecentSessionsSorter cmp;
973 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
974 recent_session_model->clear ();
977 ARDOUR::read_recent_sessions (rs);
980 recent_session_display.set_model (recent_session_model);
984 /* sort them alphabetically */
985 sort (rs.begin(), rs.end(), cmp);
986 sessions = new vector<string*>;
988 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
989 sessions->push_back (new string ((*i).second));
992 for (i = sessions->begin(); i != sessions->end(); ++i) {
994 vector<string*>* states;
995 vector<const gchar*> item;
996 string fullpath = *(*i);
998 /* remove any trailing / */
1000 if (fullpath[fullpath.length()-1] == '/') {
1001 fullpath = fullpath.substr (0, fullpath.length()-1);
1004 /* check whether session still exists */
1005 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1006 /* session doesn't exist */
1007 cerr << "skipping non-existent session " << fullpath << endl;
1011 /* now get available states for this session */
1013 if ((states = Session::possible_states (fullpath)) == 0) {
1014 /* no state file? */
1018 TreeModel::Row row = *(recent_session_model->append());
1020 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1021 row[recent_session_columns.fullpath] = fullpath;
1023 if (states->size() > 1) {
1025 /* add the children */
1027 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1029 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1031 child_row[recent_session_columns.visible_name] = **i2;
1032 child_row[recent_session_columns.fullpath] = fullpath;
1041 recent_session_display.set_model (recent_session_model);
1046 ARDOUR_UI::build_session_selector ()
1048 session_selector_window = new ArdourDialog ("session selector");
1050 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1052 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1053 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1054 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1055 recent_session_model = TreeStore::create (recent_session_columns);
1056 recent_session_display.set_model (recent_session_model);
1057 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1058 recent_session_display.set_headers_visible (false);
1059 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1060 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1062 scroller->add (recent_session_display);
1063 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1065 session_selector_window->set_name ("SessionSelectorWindow");
1066 session_selector_window->set_size_request (200, 400);
1067 session_selector_window->get_vbox()->pack_start (*scroller);
1068 session_selector_window->show_all_children();
1072 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1074 session_selector_window->response (RESPONSE_ACCEPT);
1078 ARDOUR_UI::open_recent_session ()
1080 bool can_return = (session != 0);
1082 if (session_selector_window == 0) {
1083 build_session_selector ();
1086 redisplay_recent_sessions ();
1090 session_selector_window->set_position (WIN_POS_MOUSE);
1092 ResponseType r = (ResponseType) session_selector_window->run ();
1095 case RESPONSE_ACCEPT:
1099 session_selector_window->hide();
1106 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1110 session_selector_window->hide();
1112 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1114 if (i == recent_session_model->children().end()) {
1118 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1119 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1121 _session_is_new = false;
1123 if (load_session (path, state) == 0) {
1132 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1134 struct stat statbuf;
1136 if (stat (info.filename.c_str(), &statbuf) != 0) {
1140 if (!S_ISDIR(statbuf.st_mode)) {
1146 string session_file = info.filename;
1147 session_file += '/';
1148 session_file += Glib::path_get_basename (info.filename);
1149 session_file += ".ardour";
1151 if (stat (session_file.c_str(), &statbuf) != 0) {
1155 return S_ISREG (statbuf.st_mode);
1159 ARDOUR_UI::check_audioengine ()
1162 if (!engine->connected()) {
1163 MessageDialog msg (_("Ardour is not connected to JACK\n"
1164 "You cannot open or close sessions in this condition"));
1176 ARDOUR_UI::open_session ()
1178 if (!check_audioengine()) {
1182 /* popup selector window */
1184 if (open_session_selector == 0) {
1186 /* ardour sessions are folders */
1188 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1189 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1190 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1191 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1193 FileFilter session_filter;
1194 session_filter.add_pattern ("*.ardour");
1195 session_filter.set_name (_("Ardour sessions"));
1196 open_session_selector->add_filter (session_filter);
1197 open_session_selector->set_filter (session_filter);
1200 int response = open_session_selector->run();
1201 open_session_selector->hide ();
1204 case RESPONSE_ACCEPT:
1207 open_session_selector->hide();
1211 open_session_selector->hide();
1212 string session_path = open_session_selector->get_filename();
1216 if (session_path.length() > 0) {
1217 if (Session::find_session (session_path, path, name, isnew) == 0) {
1218 _session_is_new = isnew;
1219 load_session (path, name);
1226 ARDOUR_UI::session_add_midi_track ()
1228 cerr << _("Patience is a virtue.\n");
1232 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1234 list<boost::shared_ptr<AudioTrack> > tracks;
1235 Session::RouteList routes;
1238 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1244 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1246 if (tracks.size() != how_many) {
1247 if (how_many == 1) {
1248 error << _("could not create a new audio track") << endmsg;
1250 error << string_compose (_("could only create %1 of %2 new audio %3"),
1251 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1257 routes = session->new_audio_route (input_channels, output_channels, how_many);
1259 if (routes.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new audio track") << endmsg;
1263 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1269 if (need_control_room_outs) {
1275 route->set_stereo_control_outs (control_lr_channels);
1276 route->control_outs()->set_stereo_pan (pans, this);
1278 #endif /* CONTROLOUTS */
1282 MessageDialog msg (*editor,
1283 _("There are insufficient JACK ports available\n\
1284 to create a new track or bus.\n\
1285 You should save Ardour, exit and\n\
1286 restart JACK with more ports."));
1293 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1295 nframes_t _preroll = 0;
1298 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1299 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1301 if (new_position > _preroll) {
1302 new_position -= _preroll;
1307 session->request_locate (new_position);
1312 ARDOUR_UI::transport_goto_start ()
1315 session->goto_start();
1318 /* force displayed area in editor to start no matter
1319 what "follow playhead" setting is.
1323 editor->reset_x_origin (session->current_start_frame());
1329 ARDOUR_UI::transport_goto_zero ()
1332 session->request_locate (0);
1335 /* force displayed area in editor to start no matter
1336 what "follow playhead" setting is.
1340 editor->reset_x_origin (0);
1346 ARDOUR_UI::transport_goto_end ()
1349 nframes_t frame = session->current_end_frame();
1350 session->request_locate (frame);
1352 /* force displayed area in editor to start no matter
1353 what "follow playhead" setting is.
1357 editor->reset_x_origin (frame);
1363 ARDOUR_UI::transport_stop ()
1369 if (session->is_auditioning()) {
1370 session->cancel_audition ();
1374 if (session->get_play_loop ()) {
1375 session->request_play_loop (false);
1378 session->request_stop ();
1382 ARDOUR_UI::transport_stop_and_forget_capture ()
1385 session->request_stop (true);
1390 ARDOUR_UI::remove_last_capture()
1393 editor->remove_last_capture();
1398 ARDOUR_UI::transport_record (bool roll)
1401 switch (session->record_status()) {
1402 case Session::Disabled:
1403 if (session->ntracks() == 0) {
1404 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1408 session->maybe_enable_record ();
1413 case Session::Recording:
1415 session->request_stop();
1417 session->disable_record (false, true);
1421 case Session::Enabled:
1422 session->disable_record (false, true);
1428 ARDOUR_UI::transport_roll ()
1436 rolling = session->transport_rolling ();
1438 if (session->get_play_loop()) {
1439 session->request_play_loop (false);
1440 auto_loop_button.set_visual_state (1);
1441 roll_button.set_visual_state (1);
1442 } else if (session->get_play_range ()) {
1443 session->request_play_range (false);
1444 play_selection_button.set_visual_state (0);
1445 } else if (rolling) {
1446 session->request_locate (session->last_transport_start(), true);
1449 session->request_transport_speed (1.0f);
1453 ARDOUR_UI::transport_loop()
1456 if (session->get_play_loop()) {
1457 if (session->transport_rolling()) {
1458 Location * looploc = session->locations()->auto_loop_location();
1460 session->request_locate (looploc->start(), true);
1465 session->request_play_loop (true);
1471 ARDOUR_UI::transport_play_selection ()
1477 if (!session->get_play_range()) {
1478 session->request_stop ();
1481 editor->play_selection ();
1485 ARDOUR_UI::transport_rewind (int option)
1487 float current_transport_speed;
1490 current_transport_speed = session->transport_speed();
1492 if (current_transport_speed >= 0.0f) {
1495 session->request_transport_speed (-1.0f);
1498 session->request_transport_speed (-4.0f);
1501 session->request_transport_speed (-0.5f);
1506 session->request_transport_speed (current_transport_speed * 1.5f);
1512 ARDOUR_UI::transport_forward (int option)
1514 float current_transport_speed;
1517 current_transport_speed = session->transport_speed();
1519 if (current_transport_speed <= 0.0f) {
1522 session->request_transport_speed (1.0f);
1525 session->request_transport_speed (4.0f);
1528 session->request_transport_speed (0.5f);
1533 session->request_transport_speed (current_transport_speed * 1.5f);
1539 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1545 boost::shared_ptr<Route> r;
1547 if ((r = session->route_by_remote_id (dstream)) != 0) {
1551 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1552 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1561 ARDOUR_UI::queue_transport_change ()
1563 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1567 ARDOUR_UI::map_transport_state ()
1569 float sp = session->transport_speed();
1572 transport_rolling ();
1573 } else if (sp < 0.0f) {
1574 transport_rewinding ();
1575 } else if (sp > 0.0f) {
1576 transport_forwarding ();
1578 transport_stopped ();
1583 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1585 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1586 (int) adj.get_value()].c_str());
1590 ARDOUR_UI::engine_stopped ()
1592 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1593 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1594 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1598 ARDOUR_UI::engine_running ()
1600 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1601 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1602 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1604 Glib::RefPtr<Action> action;
1605 char* action_name = 0;
1607 switch (engine->frames_per_cycle()) {
1609 action_name = X_("JACKLatency32");
1612 action_name = X_("JACKLatency64");
1615 action_name = X_("JACKLatency128");
1618 action_name = X_("JACKLatency512");
1621 action_name = X_("JACKLatency1024");
1624 action_name = X_("JACKLatency2048");
1627 action_name = X_("JACKLatency4096");
1630 action_name = X_("JACKLatency8192");
1633 /* XXX can we do anything useful ? */
1639 action = ActionManager::get_action (X_("JACK"), action_name);
1642 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1643 ract->set_active ();
1649 ARDOUR_UI::engine_halted ()
1651 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1653 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1654 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1656 update_sample_rate (0);
1658 MessageDialog msg (*editor,
1660 JACK has either been shutdown or it\n\
1661 disconnected Ardour because Ardour\n\
1662 was not fast enough. You can save the\n\
1663 session and/or try to reconnect to JACK ."));
1669 ARDOUR_UI::do_engine_start ()
1677 error << _("Unable to start the session running")
1687 ARDOUR_UI::setup_theme ()
1689 theme_manager->setup_theme();
1693 ARDOUR_UI::update_clocks ()
1695 if (!editor || !editor->dragging_playhead()) {
1696 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1701 ARDOUR_UI::start_clocking ()
1703 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1707 ARDOUR_UI::stop_clocking ()
1709 clock_signal_connection.disconnect ();
1713 ARDOUR_UI::toggle_clocking ()
1716 if (clock_button.get_active()) {
1725 ARDOUR_UI::_blink (void *arg)
1728 ((ARDOUR_UI *) arg)->blink ();
1735 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1739 ARDOUR_UI::start_blinking ()
1741 /* Start the blink signal. Everybody with a blinking widget
1742 uses Blink to drive the widget's state.
1745 if (blink_timeout_tag < 0) {
1747 blink_timeout_tag = g_timeout_add (240, _blink, this);
1752 ARDOUR_UI::stop_blinking ()
1754 if (blink_timeout_tag >= 0) {
1755 g_source_remove (blink_timeout_tag);
1756 blink_timeout_tag = -1;
1761 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1767 if (io.n_inputs() == 0) {
1772 /* XXX we're not handling multiple ports yet. */
1774 const char **connections = io.input(0)->get_connections();
1776 if (connections == 0 || connections[0] == '\0') {
1779 buf = connections[0];
1786 if (io.n_outputs() == 0) {
1791 /* XXX we're not handling multiple ports yet. */
1793 const char **connections = io.output(0)->get_connections();
1795 if (connections == 0 || connections[0] == '\0') {
1798 buf = connections[0];
1805 /** Ask the user for the name of a new shapshot and then take it.
1808 ARDOUR_UI::snapshot_session ()
1810 ArdourPrompter prompter (true);
1814 struct tm local_time;
1817 localtime_r (&n, &local_time);
1818 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1820 prompter.set_name ("Prompter");
1821 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1822 prompter.set_prompt (_("Name of New Snapshot"));
1823 prompter.set_initial_text (timebuf);
1825 switch (prompter.run()) {
1826 case RESPONSE_ACCEPT:
1827 prompter.get_result (snapname);
1828 if (snapname.length()){
1829 save_state (snapname);
1839 ARDOUR_UI::save_state (const string & name)
1841 (void) save_state_canfail (name);
1845 ARDOUR_UI::save_state_canfail (string name)
1850 if (name.length() == 0) {
1851 name = session->snap_name();
1854 if ((ret = session->save_state (name)) != 0) {
1858 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1863 ARDOUR_UI::restore_state (string name)
1866 if (name.length() == 0) {
1867 name = session->name();
1869 session->restore_state (name);
1874 ARDOUR_UI::primary_clock_value_changed ()
1877 session->request_locate (primary_clock.current_time ());
1882 ARDOUR_UI::big_clock_value_changed ()
1885 session->request_locate (big_clock.current_time ());
1890 ARDOUR_UI::secondary_clock_value_changed ()
1893 session->request_locate (secondary_clock.current_time ());
1898 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1900 if (session && dstream && dstream->record_enabled()) {
1902 Session::RecordState rs;
1904 rs = session->record_status ();
1907 case Session::Disabled:
1908 case Session::Enabled:
1909 if (w->get_state() != STATE_SELECTED) {
1910 w->set_state (STATE_SELECTED);
1914 case Session::Recording:
1915 if (w->get_state() != STATE_ACTIVE) {
1916 w->set_state (STATE_ACTIVE);
1922 if (w->get_state() != STATE_NORMAL) {
1923 w->set_state (STATE_NORMAL);
1929 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1935 switch (session->record_status()) {
1936 case Session::Enabled:
1938 rec_button.set_visual_state (2);
1940 rec_button.set_visual_state (0);
1944 case Session::Recording:
1945 rec_button.set_visual_state (1);
1949 rec_button.set_visual_state (0);
1955 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1963 ARDOUR_UI::save_template ()
1966 ArdourPrompter prompter (true);
1969 if (!check_audioengine()) {
1973 prompter.set_name (X_("Prompter"));
1974 prompter.set_prompt (_("Name for mix template:"));
1975 prompter.set_initial_text(session->name() + _("-template"));
1976 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1978 switch (prompter.run()) {
1979 case RESPONSE_ACCEPT:
1980 prompter.get_result (name);
1982 if (name.length()) {
1983 session->save_template (name);
1993 ARDOUR_UI::fontconfig_dialog ()
1996 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1997 may not and it can take a while to build it. Warn them.
2000 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2002 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2003 MessageDialog msg (*new_session_dialog,
2004 _("Welcome to Ardour.\n\n"
2005 "The program will take a bit longer to start up\n"
2006 "while the system fonts are checked.\n\n"
2007 "This will only be done once, and you will\n"
2008 "not see this message again\n"),
2021 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2023 existing_session = false;
2025 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2026 session_path = cmdline_path;
2027 existing_session = true;
2028 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2029 session_path = Glib::path_get_dirname (string (cmdline_path));
2030 existing_session = true;
2032 /* it doesn't exist, assume the best */
2033 session_path = Glib::path_get_dirname (string (cmdline_path));
2036 session_name = basename_nosuffix (string (cmdline_path));
2040 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2042 /* when this is called, the backend audio system must be running */
2044 /* the main idea here is to deal with the fact that a cmdline argument for the session
2045 can be interpreted in different ways - it could be a directory or a file, and before
2046 we load, we need to know both the session directory and the snapshot (statefile) within it
2047 that we are supposed to use.
2050 if (session_name.length() == 0 || session_path.length() == 0) {
2054 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2056 Glib::ustring predicted_session_file;
2058 predicted_session_file = session_path;
2059 predicted_session_file += '/';
2060 predicted_session_file += session_name;
2061 predicted_session_file += Session::statefile_suffix();
2063 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2064 existing_session = true;
2067 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2069 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2070 /* existing .ardour file */
2071 existing_session = true;
2075 existing_session = false;
2078 /* lets just try to load it */
2080 if (create_engine ()) {
2081 backend_audio_error (false, new_session_dialog);
2085 return load_session (session_path, session_name);
2089 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2091 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2093 MessageDialog msg (str,
2095 Gtk::MESSAGE_WARNING,
2096 Gtk::BUTTONS_YES_NO,
2100 msg.set_name (X_("CleanupDialog"));
2101 msg.set_wmclass (X_("existing_session"), "Ardour");
2102 msg.set_position (Gtk::WIN_POS_MOUSE);
2105 switch (msg.run()) {
2114 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2119 AutoConnectOption iconnect;
2120 AutoConnectOption oconnect;
2124 if (Profile->get_sae()) {
2128 iconnect = AutoConnectPhysical;
2129 oconnect = AutoConnectMaster;
2130 nphysin = 0; // use all available
2131 nphysout = 0; // use all available
2135 /* get settings from advanced section of NSD */
2137 if (new_session_dialog->create_control_bus()) {
2138 cchns = (uint32_t) new_session_dialog->control_channel_count();
2143 if (new_session_dialog->create_master_bus()) {
2144 mchns = (uint32_t) new_session_dialog->master_channel_count();
2149 if (new_session_dialog->connect_inputs()) {
2150 iconnect = AutoConnectPhysical;
2152 iconnect = AutoConnectOption (0);
2155 /// @todo some minor tweaks.
2157 if (new_session_dialog->connect_outs_to_master()) {
2158 oconnect = AutoConnectMaster;
2159 } else if (new_session_dialog->connect_outs_to_physical()) {
2160 oconnect = AutoConnectPhysical;
2162 oconnect = AutoConnectOption (0);
2165 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2166 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2169 if (build_session (session_path,
2177 engine->frame_rate() * 60 * 5)) {
2186 ARDOUR_UI::end_loading_messages ()
2192 ARDOUR_UI::loading_message (const std::string& msg)
2194 cerr << "say: " << msg << endl;
2196 splash->message (msg);
2201 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2203 bool existing_session = false;
2204 Glib::ustring session_name;
2205 Glib::ustring session_path;
2206 Glib::ustring template_name;
2208 int response = Gtk::RESPONSE_NONE;
2210 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2212 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2214 /* don't ever reuse this */
2216 ARDOUR_COMMAND_LINE::session_name = string();
2218 if (existing_session && backend_audio_is_running) {
2220 /* just load the thing already */
2222 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2227 /* make the NSD use whatever information we have */
2229 new_session_dialog->set_session_name (session_name);
2230 new_session_dialog->set_session_folder (session_path);
2233 /* loading failed, or we need the NSD for something */
2235 new_session_dialog->set_modal (false);
2236 new_session_dialog->set_position (WIN_POS_CENTER);
2237 new_session_dialog->set_current_page (0);
2238 new_session_dialog->set_existing_session (existing_session);
2239 new_session_dialog->reset_recent();
2242 new_session_dialog->set_have_engine (backend_audio_is_running);
2243 new_session_dialog->present ();
2244 response = new_session_dialog->run ();
2246 _session_is_new = false;
2248 /* handle possible negative responses */
2251 case Gtk::RESPONSE_CANCEL:
2252 case Gtk::RESPONSE_DELETE_EVENT:
2256 new_session_dialog->hide ();
2259 case Gtk::RESPONSE_NONE:
2260 /* "Clear" was pressed */
2264 fontconfig_dialog();
2266 if (!backend_audio_is_running) {
2267 if (new_session_dialog->engine_control.setup_engine ()) {
2268 new_session_dialog->hide ();
2273 if (create_engine ()) {
2275 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2278 new_session_dialog->set_existing_session (false);
2279 new_session_dialog->set_current_page (2);
2281 response = Gtk::RESPONSE_NONE;
2285 backend_audio_is_running = true;
2287 if (response == Gtk::RESPONSE_OK) {
2289 session_name = new_session_dialog->session_name();
2291 if (session_name.empty()) {
2292 response = Gtk::RESPONSE_NONE;
2296 /* if the user mistakenly typed path information into the session filename entry,
2297 convert what they typed into a path & a name
2300 if (session_name[0] == '/' ||
2301 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2302 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2304 session_path = Glib::path_get_dirname (session_name);
2305 session_name = Glib::path_get_basename (session_name);
2309 session_path = new_session_dialog->session_folder();
2312 template_name = Glib::ustring();
2313 switch (new_session_dialog->which_page()) {
2315 case NewSessionDialog::OpenPage:
2316 case NewSessionDialog::EnginePage:
2320 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2322 should_be_new = true;
2324 //XXX This is needed because session constructor wants a
2325 //non-existant path. hopefully this will be fixed at some point.
2327 session_path = Glib::build_filename (session_path, session_name);
2329 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2331 if (ask_about_loading_existing_session (session_path)) {
2334 response = RESPONSE_NONE;
2339 _session_is_new = true;
2341 if (new_session_dialog->use_session_template()) {
2343 template_name = new_session_dialog->session_template_name();
2347 if (build_session_from_nsd (session_path, session_name)) {
2348 response = RESPONSE_NONE;
2360 new_session_dialog->hide ();
2362 if (load_session (session_path, session_name, template_name)) {
2364 response = Gtk::RESPONSE_NONE;
2368 if (response == Gtk::RESPONSE_NONE) {
2369 new_session_dialog->set_existing_session (false);
2370 new_session_dialog->reset ();
2374 } while (response == Gtk::RESPONSE_NONE);
2378 new_session_dialog->hide();
2379 new_session_dialog->reset();
2380 goto_editor_window ();
2385 ARDOUR_UI::close_session ()
2387 if (!check_audioengine()) {
2391 unload_session (true);
2393 get_session_parameters (true, false);
2397 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2399 Session *new_session;
2403 session_loaded = false;
2405 if (!check_audioengine()) {
2409 unload_status = unload_session ();
2411 if (unload_status < 0) {
2413 } else if (unload_status > 0) {
2418 /* if it already exists, we must have write access */
2420 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2421 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2422 "This prevents the session from being loaded."));
2428 loading_message (_("Please wait while Ardour loads your session"));
2429 disable_screen_updates ();
2432 new_session = new Session (*engine, path, snap_name, mix_template);
2435 /* this one is special */
2437 catch (AudioEngine::PortRegistrationFailure& err) {
2439 MessageDialog msg (err.what(),
2442 Gtk::BUTTONS_OK_CANCEL);
2444 msg.set_title (_("Loading Error"));
2445 msg.set_secondary_text (_("Click the OK button to try again."));
2446 msg.set_position (Gtk::WIN_POS_CENTER);
2450 int response = msg.run ();
2455 case RESPONSE_CANCEL:
2465 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2468 Gtk::BUTTONS_OK_CANCEL);
2470 msg.set_title (_("Loading Error"));
2471 msg.set_secondary_text (_("Click the OK button to try again."));
2472 msg.set_position (Gtk::WIN_POS_CENTER);
2476 int response = msg.run ();
2481 case RESPONSE_CANCEL:
2489 connect_to_session (new_session);
2491 Config->set_current_owner (ConfigVariableBase::Interface);
2493 session_loaded = true;
2495 goto_editor_window ();
2498 session->set_clean ();
2501 enable_screen_updates ();
2510 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2511 uint32_t control_channels,
2512 uint32_t master_channels,
2513 AutoConnectOption input_connect,
2514 AutoConnectOption output_connect,
2517 nframes_t initial_length)
2519 Session *new_session;
2522 if (!check_audioengine()) {
2526 session_loaded = false;
2528 x = unload_session ();
2536 _session_is_new = true;
2539 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2540 control_channels, master_channels, nphysin, nphysout, initial_length);
2545 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2551 connect_to_session (new_session);
2553 session_loaded = true;
2561 editor->show_window ();
2572 ARDOUR_UI::show_about ()
2576 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2583 ARDOUR_UI::hide_about ()
2586 about->get_window()->set_cursor ();
2592 ARDOUR_UI::about_signal_response(int response)
2598 ARDOUR_UI::show_splash ()
2602 splash = new Splash;
2610 splash->queue_draw ();
2611 splash->get_window()->process_updates (true);
2616 ARDOUR_UI::hide_splash ()
2624 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2628 removed = rep.paths.size();
2631 MessageDialog msgd (*editor,
2632 _("No audio files were ready for cleanup"),
2635 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2636 msgd.set_secondary_text (_("If this seems suprising, \n\
2637 check for any existing snapshots.\n\
2638 These may still include regions that\n\
2639 require some unused files to continue to exist."));
2645 ArdourDialog results (_("ardour: cleanup"), true, false);
2647 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2648 CleanupResultsModelColumns() {
2652 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2653 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2657 CleanupResultsModelColumns results_columns;
2658 Glib::RefPtr<Gtk::ListStore> results_model;
2659 Gtk::TreeView results_display;
2661 results_model = ListStore::create (results_columns);
2662 results_display.set_model (results_model);
2663 results_display.append_column (list_title, results_columns.visible_name);
2665 results_display.set_name ("CleanupResultsList");
2666 results_display.set_headers_visible (true);
2667 results_display.set_headers_clickable (false);
2668 results_display.set_reorderable (false);
2670 Gtk::ScrolledWindow list_scroller;
2673 Gtk::HBox dhbox; // the hbox for the image and text
2674 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2675 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2677 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2679 if (rep.space < 1048576.0f) {
2681 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2683 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2687 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2689 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2693 dhbox.pack_start (*dimage, true, false, 5);
2694 dhbox.pack_start (txt, true, false, 5);
2696 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2697 TreeModel::Row row = *(results_model->append());
2698 row[results_columns.visible_name] = *i;
2699 row[results_columns.fullpath] = *i;
2702 list_scroller.add (results_display);
2703 list_scroller.set_size_request (-1, 150);
2704 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2706 dvbox.pack_start (dhbox, true, false, 5);
2707 dvbox.pack_start (list_scroller, true, false, 5);
2708 ddhbox.pack_start (dvbox, true, false, 5);
2710 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2711 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2712 results.set_default_response (RESPONSE_CLOSE);
2713 results.set_position (Gtk::WIN_POS_MOUSE);
2714 results.show_all_children ();
2715 results.set_resizable (false);
2722 ARDOUR_UI::cleanup ()
2725 /* shouldn't happen: menu item is insensitive */
2730 MessageDialog checker (_("Are you sure you want to cleanup?"),
2732 Gtk::MESSAGE_QUESTION,
2733 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2735 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2736 ALL undo/redo information will be lost if you cleanup.\n\
2737 After cleanup, unused audio files will be moved to a \
2738 \"dead sounds\" location."));
2740 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2741 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2742 checker.set_default_response (RESPONSE_CANCEL);
2744 checker.set_name (_("CleanupDialog"));
2745 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2746 checker.set_position (Gtk::WIN_POS_MOUSE);
2748 switch (checker.run()) {
2749 case RESPONSE_ACCEPT:
2755 Session::cleanup_report rep;
2757 editor->prepare_for_cleanup ();
2759 /* do not allow flush until a session is reloaded */
2761 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2763 act->set_sensitive (false);
2766 if (session->cleanup_sources (rep)) {
2771 display_cleanup_results (rep,
2774 The following %1 %2 not in use and \n\
2775 have been moved to:\n\
2777 Flushing the wastebasket will \n\
2778 release an additional\n\
2779 %4 %5bytes of disk space.\n"
2787 ARDOUR_UI::flush_trash ()
2790 /* shouldn't happen: menu item is insensitive */
2794 Session::cleanup_report rep;
2796 if (session->cleanup_trash_sources (rep)) {
2800 display_cleanup_results (rep,
2802 _("The following %1 %2 deleted from\n\
2804 releasing %4 %5bytes of disk space"));
2808 ARDOUR_UI::add_route (Gtk::Window* float_window)
2816 if (add_route_dialog == 0) {
2817 add_route_dialog = new AddRouteDialog;
2819 add_route_dialog->set_transient_for (*float_window);
2823 if (add_route_dialog->is_visible()) {
2824 /* we're already doing this */
2828 ResponseType r = (ResponseType) add_route_dialog->run ();
2830 add_route_dialog->hide();
2833 case RESPONSE_ACCEPT:
2840 if ((count = add_route_dialog->count()) <= 0) {
2844 uint32_t input_chan = add_route_dialog->channels ();
2845 uint32_t output_chan;
2846 string name_template = add_route_dialog->name_template ();
2847 bool track = add_route_dialog->track ();
2849 AutoConnectOption oac = Config->get_output_auto_connect();
2851 if (oac & AutoConnectMaster) {
2852 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2854 output_chan = input_chan;
2857 /* XXX do something with name template */
2860 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2862 session_add_audio_bus (input_chan, output_chan, count);
2867 ARDOUR_UI::mixer_settings () const
2872 node = session->instant_xml(X_("Mixer"), session->path());
2874 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2878 node = new XMLNode (X_("Mixer"));
2885 ARDOUR_UI::editor_settings () const
2890 node = session->instant_xml(X_("Editor"), session->path());
2892 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2896 node = new XMLNode (X_("Editor"));
2902 ARDOUR_UI::keyboard_settings () const
2906 node = Config->extra_xml(X_("Keyboard"));
2909 node = new XMLNode (X_("Keyboard"));
2915 ARDOUR_UI::halt_on_xrun_message ()
2917 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2919 MessageDialog msg (*editor,
2920 _("Recording was stopped because your system could not keep up."));
2925 ARDOUR_UI::disk_overrun_handler ()
2927 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2929 if (!have_disk_speed_dialog_displayed) {
2930 have_disk_speed_dialog_displayed = true;
2931 MessageDialog* msg = new MessageDialog (*editor, _("\
2932 The disk system on your computer\n\
2933 was not able to keep up with Ardour.\n\
2935 Specifically, it failed to write data to disk\n\
2936 quickly enough to keep up with recording.\n"));
2937 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2943 ARDOUR_UI::disk_underrun_handler ()
2945 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2947 if (!have_disk_speed_dialog_displayed) {
2948 have_disk_speed_dialog_displayed = true;
2949 MessageDialog* msg = new MessageDialog (*editor,
2950 _("The disk system on your computer\n\
2951 was not able to keep up with Ardour.\n\
2953 Specifically, it failed to read data from disk\n\
2954 quickly enough to keep up with playback.\n"));
2955 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2961 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2963 have_disk_speed_dialog_displayed = false;
2968 ARDOUR_UI::pending_state_dialog ()
2970 HBox* hbox = new HBox();
2971 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2972 ArdourDialog dialog (_("Crash Recovery"), true);
2974 This session appears to have been in\n\
2975 middle of recording when ardour or\n\
2976 the computer was shutdown.\n\
2978 Ardour can recover any captured audio for\n\
2979 you, or it can ignore it. Please decide\n\
2980 what you would like to do.\n"));
2981 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2982 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2983 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2984 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2985 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2986 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2987 dialog.set_default_response (RESPONSE_ACCEPT);
2988 dialog.set_position (WIN_POS_CENTER);
2993 switch (dialog.run ()) {
2994 case RESPONSE_ACCEPT:
3002 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3004 HBox* hbox = new HBox();
3005 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3006 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3007 Label message (string_compose (_("\
3008 This session was created with a sample rate of %1 Hz\n\
3010 The audioengine is currently running at %2 Hz\n"), desired, actual));
3012 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3013 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3014 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3015 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3016 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3017 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3018 dialog.set_default_response (RESPONSE_ACCEPT);
3019 dialog.set_position (WIN_POS_CENTER);
3024 switch (dialog.run ()) {
3025 case RESPONSE_ACCEPT:
3034 ARDOUR_UI::disconnect_from_jack ()
3037 if( engine->disconnect_from_jack ()) {
3038 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3042 update_sample_rate (0);
3047 ARDOUR_UI::reconnect_to_jack ()
3050 if (engine->reconnect_to_jack ()) {
3051 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3055 update_sample_rate (0);
3060 ARDOUR_UI::use_config ()
3062 Glib::RefPtr<Action> act;
3064 switch (Config->get_native_file_data_format ()) {
3066 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3069 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3072 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3077 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3078 ract->set_active ();
3081 switch (Config->get_native_file_header_format ()) {
3083 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3086 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3089 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3092 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3095 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3098 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3101 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3106 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3107 ract->set_active ();
3110 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3112 set_transport_controllable_state (*node);
3117 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3119 if (Config->get_primary_clock_delta_edit_cursor()) {
3120 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3122 primary_clock.set (pos, 0, true);
3125 if (Config->get_secondary_clock_delta_edit_cursor()) {
3126 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3128 secondary_clock.set (pos);
3131 if (big_clock_window) {
3132 big_clock.set (pos);
3137 ARDOUR_UI::record_state_changed ()
3139 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3141 if (!session || !big_clock_window) {
3142 /* why bother - the clock isn't visible */
3146 switch (session->record_status()) {
3147 case Session::Recording:
3148 big_clock.set_widget_name ("BigClockRecording");
3151 big_clock.set_widget_name ("BigClockNonRecording");
3157 ARDOUR_UI::set_keybindings_path (string path)
3159 keybindings_path = path;
3163 ARDOUR_UI::save_keybindings ()
3165 if (can_save_keybindings) {
3166 AccelMap::save (user_keybindings_path);
3171 ARDOUR_UI::first_idle ()
3174 session->allow_auto_play (true);
3176 can_save_keybindings = true;
3181 ARDOUR_UI::store_clock_modes ()
3183 XMLNode* node = new XMLNode(X_("ClockModes"));
3185 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3186 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3189 session->add_extra_xml (*node);
3190 session->set_dirty ();
3195 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3196 : Controllable (name), ui (u), type(tp)
3202 ARDOUR_UI::TransportControllable::set_value (float val)
3204 if (type == ShuttleControl) {
3211 fract = -((0.5f - val)/0.5f);
3213 fract = ((val - 0.5f)/0.5f);
3217 ui.set_shuttle_fract (fract);
3222 /* do nothing: these are radio-style actions */
3230 action = X_("Roll");
3233 action = X_("Stop");
3236 action = X_("Goto Start");
3239 action = X_("Goto End");
3242 action = X_("Loop");
3245 action = X_("Play Selection");
3248 action = X_("Record");
3258 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3266 ARDOUR_UI::TransportControllable::get_value (void) const
3285 case ShuttleControl:
3295 ARDOUR_UI::TransportControllable::set_id (const string& str)
3301 ARDOUR_UI::setup_profile ()
3303 if (gdk_screen_width() < 1200) {
3304 Profile->set_small_screen ();
3307 if (getenv ("ARDOUR_SAE")) {
3308 Profile->set_sae ();
3309 Profile->set_single_package ();