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 if (Profile->get_sae()) {
342 primary_clock.set_mode (AudioClock::MinSec);
344 primary_clock.set_mode (AudioClock::SMPTE);
346 secondary_clock.set_mode (AudioClock::BBT);
348 /* start the time-of-day-clock */
351 /* OS X provides an always visible wallclock, so don't be stupid */
352 update_wall_clock ();
353 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
356 update_disk_space ();
358 update_sample_rate (engine->frame_rate());
360 platform_specific ();
362 /* now start and maybe save state */
364 if (do_engine_start () == 0) {
365 if (session && _session_is_new) {
366 /* we need to retain initial visual
367 settings for a new session
369 session->save_state ("");
374 ARDOUR_UI::~ARDOUR_UI ()
376 save_ardour_state ();
390 if (add_route_dialog) {
391 delete add_route_dialog;
394 if (new_session_dialog) {
395 delete new_session_dialog;
400 ARDOUR_UI::pop_back_splash ()
402 if (Splash::instance()) {
403 // Splash::instance()->pop_back();
404 Splash::instance()->hide ();
409 ARDOUR_UI::configure_timeout ()
414 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
415 /* no configure events yet */
419 gettimeofday (&now, 0);
420 timersub (&now, &last_configure_time, &diff);
422 /* force a gap of 0.5 seconds since the last configure event
425 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
428 have_configure_timeout = false;
429 save_ardour_state ();
435 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
437 if (have_configure_timeout) {
438 gettimeofday (&last_configure_time, 0);
440 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
441 have_configure_timeout = true;
448 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
450 const XMLProperty* prop;
452 if ((prop = node.property ("roll")) != 0) {
453 roll_controllable.set_id (prop->value());
455 if ((prop = node.property ("stop")) != 0) {
456 stop_controllable.set_id (prop->value());
458 if ((prop = node.property ("goto_start")) != 0) {
459 goto_start_controllable.set_id (prop->value());
461 if ((prop = node.property ("goto_end")) != 0) {
462 goto_end_controllable.set_id (prop->value());
464 if ((prop = node.property ("auto_loop")) != 0) {
465 auto_loop_controllable.set_id (prop->value());
467 if ((prop = node.property ("play_selection")) != 0) {
468 play_selection_controllable.set_id (prop->value());
470 if ((prop = node.property ("rec")) != 0) {
471 rec_controllable.set_id (prop->value());
473 if ((prop = node.property ("shuttle")) != 0) {
474 shuttle_controllable.set_id (prop->value());
479 ARDOUR_UI::get_transport_controllable_state ()
481 XMLNode* node = new XMLNode(X_("TransportControllables"));
484 roll_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("roll"), buf);
486 stop_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("stop"), buf);
488 goto_start_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("goto_start"), buf);
490 goto_end_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("goto_end"), buf);
492 auto_loop_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("auto_loop"), buf);
494 play_selection_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("play_selection"), buf);
496 rec_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("rec"), buf);
498 shuttle_controllable.id().print (buf, sizeof (buf));
499 node->add_property (X_("shuttle"), buf);
505 ARDOUR_UI::save_ardour_state ()
507 if (!keyboard || !mixer || !editor) {
511 /* XXX this is all a bit dubious. add_extra_xml() uses
512 a different lifetime model from add_instant_xml().
515 XMLNode* node = new XMLNode (keyboard->get_state());
516 Config->add_extra_xml (*node);
517 Config->add_extra_xml (get_transport_controllable_state());
518 if (new_session_dialog) {
519 if (new_session_dialog->engine_control.was_used()) {
520 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
523 Config->save_state();
524 ui_config->save_state ();
526 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
527 XMLNode mnode(mixer->get_state());
530 session->add_instant_xml (enode, session->path());
531 session->add_instant_xml (mnode, session->path());
533 Config->add_instant_xml (enode, get_user_ardour_path());
534 Config->add_instant_xml (mnode, get_user_ardour_path());
541 ARDOUR_UI::autosave_session ()
543 if (!Config->get_periodic_safety_backups())
547 session->maybe_write_autosave();
554 ARDOUR_UI::update_autosave ()
556 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
558 if (session->dirty()) {
559 if (_autosave_connection.connected()) {
560 _autosave_connection.disconnect();
563 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
564 Config->get_periodic_safety_backup_interval() * 1000);
567 if (_autosave_connection.connected()) {
568 _autosave_connection.disconnect();
574 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
578 title = _("Ardour could not start JACK");
580 title = _("Ardour could not connect to JACK.");
583 MessageDialog win (title,
589 win.set_secondary_text(_("There are several possible reasons:\n\
591 1) You requested audio parameters that are not supported..\n\
592 2) JACK is running as another user.\n\
594 Please consider the possibilities, and perhaps try different parameters."));
596 win.set_secondary_text(_("There are several possible reasons:\n\
598 1) JACK is not running.\n\
599 2) JACK is running as another user, perhaps root.\n\
600 3) There is already another client called \"ardour\".\n\
602 Please consider the possibilities, and perhaps (re)start JACK."));
606 win.set_transient_for (*toplevel);
610 win.add_button (Stock::OK, RESPONSE_CLOSE);
612 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
615 win.set_default_response (RESPONSE_CLOSE);
618 win.set_position (Gtk::WIN_POS_CENTER);
621 /* we just don't care about the result, but we want to block */
627 ARDOUR_UI::startup ()
631 new_session_dialog = new NewSessionDialog();
633 bool backend_audio_is_running = EngineControl::engine_running();
634 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
637 new_session_dialog->engine_control.set_state (*audio_setup);
640 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
648 ARDOUR_UI::no_memory_warning ()
650 XMLNode node (X_("no-memory-warning"));
651 Config->add_instant_xml (node, get_user_ardour_path());
655 ARDOUR_UI::check_memory_locking ()
658 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
662 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
664 if (engine->is_realtime() && memory_warning_node == 0) {
666 struct rlimit limits;
668 long pages, page_size;
670 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
673 ram = (int64_t) pages * (int64_t) page_size;
676 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
680 if (limits.rlim_cur != RLIM_INFINITY) {
682 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
685 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
686 "This might cause Ardour to run out of memory before your system "
687 "runs out of memory. \n\n"
688 "You can view the memory limit with 'ulimit -l', "
689 "and it is normally controlled by /etc/security/limits.conf"));
691 VBox* vbox = msg.get_vbox();
693 CheckButton cb (_("Do not show this window again"));
695 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
697 hbox.pack_start (cb, true, false);
698 vbox->pack_start (hbox);
716 if (session->transport_rolling()) {
717 session->request_stop ();
721 if (session->dirty()) {
722 switch (ask_about_saving_session(_("quit"))) {
727 /* use the default name */
728 if (save_state_canfail ("")) {
729 /* failed - don't quit */
730 MessageDialog msg (*editor,
732 Ardour was unable to save your session.\n\n\
733 If you still wish to quit, please use the\n\n\
734 \"Just quit\" option."));
745 session->set_deletion_in_progress ();
749 save_ardour_state ();
754 ARDOUR_UI::ask_about_saving_session (const string & what)
756 ArdourDialog window (_("ardour: save session?"));
757 Gtk::HBox dhbox; // the hbox for the image and text
758 Gtk::Label prompt_label;
759 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
763 msg = string_compose(_("Don't %1"), what);
764 window.add_button (msg, RESPONSE_REJECT);
765 msg = string_compose(_("Just %1"), what);
766 window.add_button (msg, RESPONSE_APPLY);
767 msg = string_compose(_("Save and %1"), what);
768 window.add_button (msg, RESPONSE_ACCEPT);
770 window.set_default_response (RESPONSE_ACCEPT);
772 Gtk::Button noquit_button (msg);
773 noquit_button.set_name ("EditorGTKButton");
778 if (session->snap_name() == session->name()) {
781 type = _("snapshot");
783 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?"),
784 type, session->snap_name());
786 prompt_label.set_text (prompt);
787 prompt_label.set_name (X_("PrompterLabel"));
788 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
790 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
792 dhbox.set_homogeneous (false);
793 dhbox.pack_start (*dimage, false, false, 5);
794 dhbox.pack_start (prompt_label, true, false, 5);
795 window.get_vbox()->pack_start (dhbox);
797 window.set_name (_("Prompter"));
798 window.set_position (Gtk::WIN_POS_MOUSE);
799 window.set_modal (true);
800 window.set_resizable (false);
803 save_the_session = 0;
805 window.set_keep_above (true);
808 ResponseType r = (ResponseType) window.run();
813 case RESPONSE_ACCEPT: // save and get out of here
815 case RESPONSE_APPLY: // get out of here
825 ARDOUR_UI::every_second ()
828 update_buffer_load ();
829 update_disk_space ();
834 ARDOUR_UI::every_point_one_seconds ()
836 update_speed_display ();
837 RapidScreenUpdate(); /* EMIT_SIGNAL */
842 ARDOUR_UI::every_point_zero_one_seconds ()
844 // august 2007: actual update frequency: 40Hz, not 100Hz
846 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
851 ARDOUR_UI::update_sample_rate (nframes_t ignored)
855 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
857 if (!engine->connected()) {
859 snprintf (buf, sizeof (buf), _("disconnected"));
863 nframes_t rate = engine->frame_rate();
865 if (fmod (rate, 1000.0) != 0.0) {
866 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
867 (float) rate/1000.0f,
868 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
870 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
872 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
876 sample_rate_label.set_text (buf);
880 ARDOUR_UI::update_cpu_load ()
883 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
884 cpu_load_label.set_text (buf);
888 ARDOUR_UI::update_buffer_load ()
893 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
894 session->playback_load(), session->capture_load());
895 buffer_load_label.set_text (buf);
897 buffer_load_label.set_text ("");
902 ARDOUR_UI::count_recenabled_streams (Route& route)
904 Track* track = dynamic_cast<Track*>(&route);
905 if (track && track->diskstream()->record_enabled()) {
906 rec_enabled_streams += track->n_inputs();
911 ARDOUR_UI::update_disk_space()
917 nframes_t frames = session->available_capture_duration();
920 if (frames == max_frames) {
921 strcpy (buf, _("Disk: 24hrs+"));
926 nframes_t fr = session->frame_rate();
928 rec_enabled_streams = 0;
929 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
931 if (rec_enabled_streams) {
932 frames /= rec_enabled_streams;
935 hrs = frames / (fr * 3600);
936 frames -= hrs * fr * 3600;
937 mins = frames / (fr * 60);
938 frames -= mins * fr * 60;
941 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
944 disk_space_label.set_text (buf);
948 ARDOUR_UI::update_wall_clock ()
955 tm_now = localtime (&now);
957 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
958 wall_clock_label.set_text (buf);
964 ARDOUR_UI::session_menu (GdkEventButton *ev)
966 session_popup_menu->popup (0, 0);
971 ARDOUR_UI::redisplay_recent_sessions ()
973 vector<string *> *sessions;
974 vector<string *>::iterator i;
975 RecentSessionsSorter cmp;
977 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
978 recent_session_model->clear ();
981 ARDOUR::read_recent_sessions (rs);
984 recent_session_display.set_model (recent_session_model);
988 /* sort them alphabetically */
989 sort (rs.begin(), rs.end(), cmp);
990 sessions = new vector<string*>;
992 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
993 sessions->push_back (new string ((*i).second));
996 for (i = sessions->begin(); i != sessions->end(); ++i) {
998 vector<string*>* states;
999 vector<const gchar*> item;
1000 string fullpath = *(*i);
1002 /* remove any trailing / */
1004 if (fullpath[fullpath.length()-1] == '/') {
1005 fullpath = fullpath.substr (0, fullpath.length()-1);
1008 /* check whether session still exists */
1009 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1010 /* session doesn't exist */
1011 cerr << "skipping non-existent session " << fullpath << endl;
1015 /* now get available states for this session */
1017 if ((states = Session::possible_states (fullpath)) == 0) {
1018 /* no state file? */
1022 TreeModel::Row row = *(recent_session_model->append());
1024 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1025 row[recent_session_columns.fullpath] = fullpath;
1027 if (states->size() > 1) {
1029 /* add the children */
1031 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1033 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1035 child_row[recent_session_columns.visible_name] = **i2;
1036 child_row[recent_session_columns.fullpath] = fullpath;
1045 recent_session_display.set_model (recent_session_model);
1050 ARDOUR_UI::build_session_selector ()
1052 session_selector_window = new ArdourDialog ("session selector");
1054 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1056 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1057 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1058 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1059 recent_session_model = TreeStore::create (recent_session_columns);
1060 recent_session_display.set_model (recent_session_model);
1061 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1062 recent_session_display.set_headers_visible (false);
1063 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1064 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1066 scroller->add (recent_session_display);
1067 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1069 session_selector_window->set_name ("SessionSelectorWindow");
1070 session_selector_window->set_size_request (200, 400);
1071 session_selector_window->get_vbox()->pack_start (*scroller);
1072 session_selector_window->show_all_children();
1076 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1078 session_selector_window->response (RESPONSE_ACCEPT);
1082 ARDOUR_UI::open_recent_session ()
1084 bool can_return = (session != 0);
1086 if (session_selector_window == 0) {
1087 build_session_selector ();
1090 redisplay_recent_sessions ();
1094 session_selector_window->set_position (WIN_POS_MOUSE);
1096 ResponseType r = (ResponseType) session_selector_window->run ();
1099 case RESPONSE_ACCEPT:
1103 session_selector_window->hide();
1110 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1114 session_selector_window->hide();
1116 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1118 if (i == recent_session_model->children().end()) {
1122 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1123 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1125 _session_is_new = false;
1127 if (load_session (path, state) == 0) {
1136 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1138 struct stat statbuf;
1140 if (stat (info.filename.c_str(), &statbuf) != 0) {
1144 if (!S_ISDIR(statbuf.st_mode)) {
1150 string session_file = info.filename;
1151 session_file += '/';
1152 session_file += Glib::path_get_basename (info.filename);
1153 session_file += ".ardour";
1155 if (stat (session_file.c_str(), &statbuf) != 0) {
1159 return S_ISREG (statbuf.st_mode);
1163 ARDOUR_UI::check_audioengine ()
1166 if (!engine->connected()) {
1167 MessageDialog msg (_("Ardour is not connected to JACK\n"
1168 "You cannot open or close sessions in this condition"));
1180 ARDOUR_UI::open_session ()
1182 if (!check_audioengine()) {
1186 /* popup selector window */
1188 if (open_session_selector == 0) {
1190 /* ardour sessions are folders */
1192 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1193 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1194 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1195 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1197 FileFilter session_filter;
1198 session_filter.add_pattern ("*.ardour");
1199 session_filter.set_name (_("Ardour sessions"));
1200 open_session_selector->add_filter (session_filter);
1201 open_session_selector->set_filter (session_filter);
1204 int response = open_session_selector->run();
1205 open_session_selector->hide ();
1208 case RESPONSE_ACCEPT:
1211 open_session_selector->hide();
1215 open_session_selector->hide();
1216 string session_path = open_session_selector->get_filename();
1220 if (session_path.length() > 0) {
1221 if (Session::find_session (session_path, path, name, isnew) == 0) {
1222 _session_is_new = isnew;
1223 load_session (path, name);
1230 ARDOUR_UI::session_add_midi_track ()
1232 cerr << _("Patience is a virtue.\n");
1236 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1238 list<boost::shared_ptr<AudioTrack> > tracks;
1239 Session::RouteList routes;
1242 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1248 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1250 if (tracks.size() != how_many) {
1251 if (how_many == 1) {
1252 error << _("could not create a new audio track") << endmsg;
1254 error << string_compose (_("could only create %1 of %2 new audio %3"),
1255 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1261 routes = session->new_audio_route (input_channels, output_channels, how_many);
1263 if (routes.size() != how_many) {
1264 if (how_many == 1) {
1265 error << _("could not create a new audio track") << endmsg;
1267 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1273 if (need_control_room_outs) {
1279 route->set_stereo_control_outs (control_lr_channels);
1280 route->control_outs()->set_stereo_pan (pans, this);
1282 #endif /* CONTROLOUTS */
1286 MessageDialog msg (*editor,
1287 _("There are insufficient JACK ports available\n\
1288 to create a new track or bus.\n\
1289 You should save Ardour, exit and\n\
1290 restart JACK with more ports."));
1297 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1299 nframes_t _preroll = 0;
1302 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1303 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1305 if (new_position > _preroll) {
1306 new_position -= _preroll;
1311 session->request_locate (new_position);
1316 ARDOUR_UI::transport_goto_start ()
1319 session->goto_start();
1322 /* force displayed area in editor to start no matter
1323 what "follow playhead" setting is.
1327 editor->reset_x_origin (session->current_start_frame());
1333 ARDOUR_UI::transport_goto_zero ()
1336 session->request_locate (0);
1339 /* force displayed area in editor to start no matter
1340 what "follow playhead" setting is.
1344 editor->reset_x_origin (0);
1350 ARDOUR_UI::transport_goto_end ()
1353 nframes_t frame = session->current_end_frame();
1354 session->request_locate (frame);
1356 /* force displayed area in editor to start no matter
1357 what "follow playhead" setting is.
1361 editor->reset_x_origin (frame);
1367 ARDOUR_UI::transport_stop ()
1373 if (session->is_auditioning()) {
1374 session->cancel_audition ();
1378 if (session->get_play_loop ()) {
1379 session->request_play_loop (false);
1382 session->request_stop ();
1386 ARDOUR_UI::transport_stop_and_forget_capture ()
1389 session->request_stop (true);
1394 ARDOUR_UI::remove_last_capture()
1397 editor->remove_last_capture();
1402 ARDOUR_UI::transport_record (bool roll)
1405 switch (session->record_status()) {
1406 case Session::Disabled:
1407 if (session->ntracks() == 0) {
1408 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1412 session->maybe_enable_record ();
1417 case Session::Recording:
1419 session->request_stop();
1421 session->disable_record (false, true);
1425 case Session::Enabled:
1426 session->disable_record (false, true);
1432 ARDOUR_UI::transport_roll ()
1440 rolling = session->transport_rolling ();
1442 if (session->get_play_loop()) {
1443 session->request_play_loop (false);
1444 auto_loop_button.set_visual_state (1);
1445 roll_button.set_visual_state (1);
1446 } else if (session->get_play_range ()) {
1447 session->request_play_range (false);
1448 play_selection_button.set_visual_state (0);
1449 } else if (rolling) {
1450 session->request_locate (session->last_transport_start(), true);
1453 session->request_transport_speed (1.0f);
1457 ARDOUR_UI::transport_loop()
1460 if (session->get_play_loop()) {
1461 if (session->transport_rolling()) {
1462 Location * looploc = session->locations()->auto_loop_location();
1464 session->request_locate (looploc->start(), true);
1469 session->request_play_loop (true);
1475 ARDOUR_UI::transport_play_selection ()
1481 if (!session->get_play_range()) {
1482 session->request_stop ();
1485 editor->play_selection ();
1489 ARDOUR_UI::transport_rewind (int option)
1491 float current_transport_speed;
1494 current_transport_speed = session->transport_speed();
1496 if (current_transport_speed >= 0.0f) {
1499 session->request_transport_speed (-1.0f);
1502 session->request_transport_speed (-4.0f);
1505 session->request_transport_speed (-0.5f);
1510 session->request_transport_speed (current_transport_speed * 1.5f);
1516 ARDOUR_UI::transport_forward (int option)
1518 float current_transport_speed;
1521 current_transport_speed = session->transport_speed();
1523 if (current_transport_speed <= 0.0f) {
1526 session->request_transport_speed (1.0f);
1529 session->request_transport_speed (4.0f);
1532 session->request_transport_speed (0.5f);
1537 session->request_transport_speed (current_transport_speed * 1.5f);
1543 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1549 boost::shared_ptr<Route> r;
1551 if ((r = session->route_by_remote_id (dstream)) != 0) {
1555 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1556 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1565 ARDOUR_UI::queue_transport_change ()
1567 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1571 ARDOUR_UI::map_transport_state ()
1573 float sp = session->transport_speed();
1576 transport_rolling ();
1577 } else if (sp < 0.0f) {
1578 transport_rewinding ();
1579 } else if (sp > 0.0f) {
1580 transport_forwarding ();
1582 transport_stopped ();
1587 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1589 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1590 (int) adj.get_value()].c_str());
1594 ARDOUR_UI::engine_stopped ()
1596 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1597 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1598 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1602 ARDOUR_UI::engine_running ()
1604 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1605 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1606 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1608 Glib::RefPtr<Action> action;
1609 char* action_name = 0;
1611 switch (engine->frames_per_cycle()) {
1613 action_name = X_("JACKLatency32");
1616 action_name = X_("JACKLatency64");
1619 action_name = X_("JACKLatency128");
1622 action_name = X_("JACKLatency512");
1625 action_name = X_("JACKLatency1024");
1628 action_name = X_("JACKLatency2048");
1631 action_name = X_("JACKLatency4096");
1634 action_name = X_("JACKLatency8192");
1637 /* XXX can we do anything useful ? */
1643 action = ActionManager::get_action (X_("JACK"), action_name);
1646 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1647 ract->set_active ();
1653 ARDOUR_UI::engine_halted ()
1655 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1657 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1658 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1660 update_sample_rate (0);
1662 MessageDialog msg (*editor,
1664 JACK has either been shutdown or it\n\
1665 disconnected Ardour because Ardour\n\
1666 was not fast enough. You can save the\n\
1667 session and/or try to reconnect to JACK ."));
1673 ARDOUR_UI::do_engine_start ()
1681 error << _("Unable to start the session running")
1691 ARDOUR_UI::setup_theme ()
1693 theme_manager->setup_theme();
1697 ARDOUR_UI::update_clocks ()
1699 if (!editor || !editor->dragging_playhead()) {
1700 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1705 ARDOUR_UI::start_clocking ()
1707 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1711 ARDOUR_UI::stop_clocking ()
1713 clock_signal_connection.disconnect ();
1717 ARDOUR_UI::toggle_clocking ()
1720 if (clock_button.get_active()) {
1729 ARDOUR_UI::_blink (void *arg)
1732 ((ARDOUR_UI *) arg)->blink ();
1739 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1743 ARDOUR_UI::start_blinking ()
1745 /* Start the blink signal. Everybody with a blinking widget
1746 uses Blink to drive the widget's state.
1749 if (blink_timeout_tag < 0) {
1751 blink_timeout_tag = g_timeout_add (240, _blink, this);
1756 ARDOUR_UI::stop_blinking ()
1758 if (blink_timeout_tag >= 0) {
1759 g_source_remove (blink_timeout_tag);
1760 blink_timeout_tag = -1;
1765 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1771 if (io.n_inputs() == 0) {
1776 /* XXX we're not handling multiple ports yet. */
1778 const char **connections = io.input(0)->get_connections();
1780 if (connections == 0 || connections[0] == '\0') {
1783 buf = connections[0];
1790 if (io.n_outputs() == 0) {
1795 /* XXX we're not handling multiple ports yet. */
1797 const char **connections = io.output(0)->get_connections();
1799 if (connections == 0 || connections[0] == '\0') {
1802 buf = connections[0];
1809 /** Ask the user for the name of a new shapshot and then take it.
1812 ARDOUR_UI::snapshot_session ()
1814 ArdourPrompter prompter (true);
1818 struct tm local_time;
1821 localtime_r (&n, &local_time);
1822 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1824 prompter.set_name ("Prompter");
1825 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1826 prompter.set_prompt (_("Name of New Snapshot"));
1827 prompter.set_initial_text (timebuf);
1829 switch (prompter.run()) {
1830 case RESPONSE_ACCEPT:
1831 prompter.get_result (snapname);
1832 if (snapname.length()){
1833 save_state (snapname);
1843 ARDOUR_UI::save_state (const string & name)
1845 (void) save_state_canfail (name);
1849 ARDOUR_UI::save_state_canfail (string name)
1854 if (name.length() == 0) {
1855 name = session->snap_name();
1858 if ((ret = session->save_state (name)) != 0) {
1862 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1867 ARDOUR_UI::restore_state (string name)
1870 if (name.length() == 0) {
1871 name = session->name();
1873 session->restore_state (name);
1878 ARDOUR_UI::primary_clock_value_changed ()
1881 session->request_locate (primary_clock.current_time ());
1886 ARDOUR_UI::big_clock_value_changed ()
1889 session->request_locate (big_clock.current_time ());
1894 ARDOUR_UI::secondary_clock_value_changed ()
1897 session->request_locate (secondary_clock.current_time ());
1902 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1904 if (session && dstream && dstream->record_enabled()) {
1906 Session::RecordState rs;
1908 rs = session->record_status ();
1911 case Session::Disabled:
1912 case Session::Enabled:
1913 if (w->get_state() != STATE_SELECTED) {
1914 w->set_state (STATE_SELECTED);
1918 case Session::Recording:
1919 if (w->get_state() != STATE_ACTIVE) {
1920 w->set_state (STATE_ACTIVE);
1926 if (w->get_state() != STATE_NORMAL) {
1927 w->set_state (STATE_NORMAL);
1933 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1939 switch (session->record_status()) {
1940 case Session::Enabled:
1942 rec_button.set_visual_state (2);
1944 rec_button.set_visual_state (0);
1948 case Session::Recording:
1949 rec_button.set_visual_state (1);
1953 rec_button.set_visual_state (0);
1959 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1967 ARDOUR_UI::save_template ()
1970 ArdourPrompter prompter (true);
1973 if (!check_audioengine()) {
1977 prompter.set_name (X_("Prompter"));
1978 prompter.set_prompt (_("Name for mix template:"));
1979 prompter.set_initial_text(session->name() + _("-template"));
1980 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1982 switch (prompter.run()) {
1983 case RESPONSE_ACCEPT:
1984 prompter.get_result (name);
1986 if (name.length()) {
1987 session->save_template (name);
1997 ARDOUR_UI::fontconfig_dialog ()
2000 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2001 may not and it can take a while to build it. Warn them.
2004 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2006 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2007 MessageDialog msg (*new_session_dialog,
2008 _("Welcome to Ardour.\n\n"
2009 "The program will take a bit longer to start up\n"
2010 "while the system fonts are checked.\n\n"
2011 "This will only be done once, and you will\n"
2012 "not see this message again\n"),
2025 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2027 existing_session = false;
2029 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2030 session_path = cmdline_path;
2031 existing_session = true;
2032 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2033 session_path = Glib::path_get_dirname (string (cmdline_path));
2034 existing_session = true;
2036 /* it doesn't exist, assume the best */
2037 session_path = Glib::path_get_dirname (string (cmdline_path));
2040 session_name = basename_nosuffix (string (cmdline_path));
2044 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2046 /* when this is called, the backend audio system must be running */
2048 /* the main idea here is to deal with the fact that a cmdline argument for the session
2049 can be interpreted in different ways - it could be a directory or a file, and before
2050 we load, we need to know both the session directory and the snapshot (statefile) within it
2051 that we are supposed to use.
2054 if (session_name.length() == 0 || session_path.length() == 0) {
2058 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2060 Glib::ustring predicted_session_file;
2062 predicted_session_file = session_path;
2063 predicted_session_file += '/';
2064 predicted_session_file += session_name;
2065 predicted_session_file += Session::statefile_suffix();
2067 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2068 existing_session = true;
2071 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2073 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2074 /* existing .ardour file */
2075 existing_session = true;
2079 existing_session = false;
2082 /* lets just try to load it */
2084 if (create_engine ()) {
2085 backend_audio_error (false, new_session_dialog);
2089 return load_session (session_path, session_name);
2093 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2095 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2097 MessageDialog msg (str,
2099 Gtk::MESSAGE_WARNING,
2100 Gtk::BUTTONS_YES_NO,
2104 msg.set_name (X_("CleanupDialog"));
2105 msg.set_wmclass (X_("existing_session"), "Ardour");
2106 msg.set_position (Gtk::WIN_POS_MOUSE);
2109 switch (msg.run()) {
2118 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2123 AutoConnectOption iconnect;
2124 AutoConnectOption oconnect;
2128 if (Profile->get_sae()) {
2132 iconnect = AutoConnectPhysical;
2133 oconnect = AutoConnectMaster;
2134 nphysin = 0; // use all available
2135 nphysout = 0; // use all available
2139 /* get settings from advanced section of NSD */
2141 if (new_session_dialog->create_control_bus()) {
2142 cchns = (uint32_t) new_session_dialog->control_channel_count();
2147 if (new_session_dialog->create_master_bus()) {
2148 mchns = (uint32_t) new_session_dialog->master_channel_count();
2153 if (new_session_dialog->connect_inputs()) {
2154 iconnect = AutoConnectPhysical;
2156 iconnect = AutoConnectOption (0);
2159 /// @todo some minor tweaks.
2161 if (new_session_dialog->connect_outs_to_master()) {
2162 oconnect = AutoConnectMaster;
2163 } else if (new_session_dialog->connect_outs_to_physical()) {
2164 oconnect = AutoConnectPhysical;
2166 oconnect = AutoConnectOption (0);
2169 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2170 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2173 if (build_session (session_path,
2181 engine->frame_rate() * 60 * 5)) {
2190 ARDOUR_UI::end_loading_messages ()
2196 ARDOUR_UI::loading_message (const std::string& msg)
2199 splash->message (msg);
2204 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2206 bool existing_session = false;
2207 Glib::ustring session_name;
2208 Glib::ustring session_path;
2209 Glib::ustring template_name;
2211 int response = Gtk::RESPONSE_NONE;
2213 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2215 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2217 /* don't ever reuse this */
2219 ARDOUR_COMMAND_LINE::session_name = string();
2221 if (existing_session && backend_audio_is_running) {
2223 /* just load the thing already */
2225 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2230 /* make the NSD use whatever information we have */
2232 new_session_dialog->set_session_name (session_name);
2233 new_session_dialog->set_session_folder (session_path);
2236 /* loading failed, or we need the NSD for something */
2238 new_session_dialog->set_modal (false);
2239 new_session_dialog->set_position (WIN_POS_CENTER);
2240 new_session_dialog->set_current_page (0);
2241 new_session_dialog->set_existing_session (existing_session);
2242 new_session_dialog->reset_recent();
2245 new_session_dialog->set_have_engine (backend_audio_is_running);
2246 new_session_dialog->present ();
2247 response = new_session_dialog->run ();
2249 _session_is_new = false;
2251 /* handle possible negative responses */
2254 case Gtk::RESPONSE_CANCEL:
2255 case Gtk::RESPONSE_DELETE_EVENT:
2259 new_session_dialog->hide ();
2262 case Gtk::RESPONSE_NONE:
2263 /* "Clear" was pressed */
2267 fontconfig_dialog();
2269 if (!backend_audio_is_running) {
2270 if (new_session_dialog->engine_control.setup_engine ()) {
2271 new_session_dialog->hide ();
2276 if (create_engine ()) {
2278 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2281 new_session_dialog->set_existing_session (false);
2282 new_session_dialog->set_current_page (2);
2284 response = Gtk::RESPONSE_NONE;
2288 backend_audio_is_running = true;
2290 if (response == Gtk::RESPONSE_OK) {
2292 session_name = new_session_dialog->session_name();
2294 if (session_name.empty()) {
2295 response = Gtk::RESPONSE_NONE;
2299 /* if the user mistakenly typed path information into the session filename entry,
2300 convert what they typed into a path & a name
2303 if (session_name[0] == '/' ||
2304 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2305 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2307 session_path = Glib::path_get_dirname (session_name);
2308 session_name = Glib::path_get_basename (session_name);
2312 session_path = new_session_dialog->session_folder();
2315 template_name = Glib::ustring();
2316 switch (new_session_dialog->which_page()) {
2318 case NewSessionDialog::OpenPage:
2319 case NewSessionDialog::EnginePage:
2323 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2325 should_be_new = true;
2327 //XXX This is needed because session constructor wants a
2328 //non-existant path. hopefully this will be fixed at some point.
2330 session_path = Glib::build_filename (session_path, session_name);
2332 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2334 if (ask_about_loading_existing_session (session_path)) {
2337 response = RESPONSE_NONE;
2342 _session_is_new = true;
2344 if (new_session_dialog->use_session_template()) {
2346 template_name = new_session_dialog->session_template_name();
2350 if (build_session_from_nsd (session_path, session_name)) {
2351 response = RESPONSE_NONE;
2363 new_session_dialog->hide ();
2365 if (load_session (session_path, session_name, template_name)) {
2367 response = Gtk::RESPONSE_NONE;
2371 if (response == Gtk::RESPONSE_NONE) {
2372 new_session_dialog->set_existing_session (false);
2373 new_session_dialog->reset ();
2377 } while (response == Gtk::RESPONSE_NONE);
2381 new_session_dialog->hide();
2382 new_session_dialog->reset();
2383 goto_editor_window ();
2388 ARDOUR_UI::close_session ()
2390 if (!check_audioengine()) {
2394 unload_session (true);
2396 get_session_parameters (true, false);
2400 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2402 Session *new_session;
2406 session_loaded = false;
2408 if (!check_audioengine()) {
2412 unload_status = unload_session ();
2414 if (unload_status < 0) {
2416 } else if (unload_status > 0) {
2421 /* if it already exists, we must have write access */
2423 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2424 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2425 "This prevents the session from being loaded."));
2431 loading_message (_("Please wait while Ardour loads your session"));
2432 disable_screen_updates ();
2435 new_session = new Session (*engine, path, snap_name, mix_template);
2438 /* this one is special */
2440 catch (AudioEngine::PortRegistrationFailure& err) {
2442 MessageDialog msg (err.what(),
2445 Gtk::BUTTONS_OK_CANCEL);
2447 msg.set_title (_("Loading Error"));
2448 msg.set_secondary_text (_("Click the OK button to try again."));
2449 msg.set_position (Gtk::WIN_POS_CENTER);
2453 int response = msg.run ();
2458 case RESPONSE_CANCEL:
2468 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2471 Gtk::BUTTONS_OK_CANCEL);
2473 msg.set_title (_("Loading Error"));
2474 msg.set_secondary_text (_("Click the OK button to try again."));
2475 msg.set_position (Gtk::WIN_POS_CENTER);
2479 int response = msg.run ();
2484 case RESPONSE_CANCEL:
2492 connect_to_session (new_session);
2494 Config->set_current_owner (ConfigVariableBase::Interface);
2496 session_loaded = true;
2498 goto_editor_window ();
2501 session->set_clean ();
2504 enable_screen_updates ();
2513 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2514 uint32_t control_channels,
2515 uint32_t master_channels,
2516 AutoConnectOption input_connect,
2517 AutoConnectOption output_connect,
2520 nframes_t initial_length)
2522 Session *new_session;
2525 if (!check_audioengine()) {
2529 session_loaded = false;
2531 x = unload_session ();
2539 _session_is_new = true;
2542 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2543 control_channels, master_channels, nphysin, nphysout, initial_length);
2548 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2554 connect_to_session (new_session);
2556 session_loaded = true;
2564 editor->show_window ();
2575 ARDOUR_UI::show_about ()
2579 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2586 ARDOUR_UI::hide_about ()
2589 about->get_window()->set_cursor ();
2595 ARDOUR_UI::about_signal_response(int response)
2601 ARDOUR_UI::show_splash ()
2605 splash = new Splash;
2613 splash->queue_draw ();
2614 splash->get_window()->process_updates (true);
2619 ARDOUR_UI::hide_splash ()
2627 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2631 removed = rep.paths.size();
2634 MessageDialog msgd (*editor,
2635 _("No audio files were ready for cleanup"),
2638 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2639 msgd.set_secondary_text (_("If this seems suprising, \n\
2640 check for any existing snapshots.\n\
2641 These may still include regions that\n\
2642 require some unused files to continue to exist."));
2648 ArdourDialog results (_("ardour: cleanup"), true, false);
2650 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2651 CleanupResultsModelColumns() {
2655 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2656 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2660 CleanupResultsModelColumns results_columns;
2661 Glib::RefPtr<Gtk::ListStore> results_model;
2662 Gtk::TreeView results_display;
2664 results_model = ListStore::create (results_columns);
2665 results_display.set_model (results_model);
2666 results_display.append_column (list_title, results_columns.visible_name);
2668 results_display.set_name ("CleanupResultsList");
2669 results_display.set_headers_visible (true);
2670 results_display.set_headers_clickable (false);
2671 results_display.set_reorderable (false);
2673 Gtk::ScrolledWindow list_scroller;
2676 Gtk::HBox dhbox; // the hbox for the image and text
2677 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2678 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2680 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2682 if (rep.space < 1048576.0f) {
2684 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2686 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2690 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2692 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2696 dhbox.pack_start (*dimage, true, false, 5);
2697 dhbox.pack_start (txt, true, false, 5);
2699 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2700 TreeModel::Row row = *(results_model->append());
2701 row[results_columns.visible_name] = *i;
2702 row[results_columns.fullpath] = *i;
2705 list_scroller.add (results_display);
2706 list_scroller.set_size_request (-1, 150);
2707 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2709 dvbox.pack_start (dhbox, true, false, 5);
2710 dvbox.pack_start (list_scroller, true, false, 5);
2711 ddhbox.pack_start (dvbox, true, false, 5);
2713 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2714 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2715 results.set_default_response (RESPONSE_CLOSE);
2716 results.set_position (Gtk::WIN_POS_MOUSE);
2717 results.show_all_children ();
2718 results.set_resizable (false);
2725 ARDOUR_UI::cleanup ()
2728 /* shouldn't happen: menu item is insensitive */
2733 MessageDialog checker (_("Are you sure you want to cleanup?"),
2735 Gtk::MESSAGE_QUESTION,
2736 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2738 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2739 ALL undo/redo information will be lost if you cleanup.\n\
2740 After cleanup, unused audio files will be moved to a \
2741 \"dead sounds\" location."));
2743 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2744 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2745 checker.set_default_response (RESPONSE_CANCEL);
2747 checker.set_name (_("CleanupDialog"));
2748 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2749 checker.set_position (Gtk::WIN_POS_MOUSE);
2751 switch (checker.run()) {
2752 case RESPONSE_ACCEPT:
2758 Session::cleanup_report rep;
2760 editor->prepare_for_cleanup ();
2762 /* do not allow flush until a session is reloaded */
2764 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2766 act->set_sensitive (false);
2769 if (session->cleanup_sources (rep)) {
2774 display_cleanup_results (rep,
2777 The following %1 %2 not in use and \n\
2778 have been moved to:\n\
2780 Flushing the wastebasket will \n\
2781 release an additional\n\
2782 %4 %5bytes of disk space.\n"
2790 ARDOUR_UI::flush_trash ()
2793 /* shouldn't happen: menu item is insensitive */
2797 Session::cleanup_report rep;
2799 if (session->cleanup_trash_sources (rep)) {
2803 display_cleanup_results (rep,
2805 _("The following %1 %2 deleted from\n\
2807 releasing %4 %5bytes of disk space"));
2811 ARDOUR_UI::add_route (Gtk::Window* float_window)
2819 if (add_route_dialog == 0) {
2820 add_route_dialog = new AddRouteDialog;
2822 add_route_dialog->set_transient_for (*float_window);
2826 if (add_route_dialog->is_visible()) {
2827 /* we're already doing this */
2831 ResponseType r = (ResponseType) add_route_dialog->run ();
2833 add_route_dialog->hide();
2836 case RESPONSE_ACCEPT:
2843 if ((count = add_route_dialog->count()) <= 0) {
2847 uint32_t input_chan = add_route_dialog->channels ();
2848 uint32_t output_chan;
2849 string name_template = add_route_dialog->name_template ();
2850 bool track = add_route_dialog->track ();
2852 AutoConnectOption oac = Config->get_output_auto_connect();
2854 if (oac & AutoConnectMaster) {
2855 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2857 output_chan = input_chan;
2860 /* XXX do something with name template */
2863 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2865 session_add_audio_bus (input_chan, output_chan, count);
2870 ARDOUR_UI::mixer_settings () const
2875 node = session->instant_xml(X_("Mixer"), session->path());
2877 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2881 node = new XMLNode (X_("Mixer"));
2888 ARDOUR_UI::editor_settings () const
2893 node = session->instant_xml(X_("Editor"), session->path());
2895 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2899 node = new XMLNode (X_("Editor"));
2905 ARDOUR_UI::keyboard_settings () const
2909 node = Config->extra_xml(X_("Keyboard"));
2912 node = new XMLNode (X_("Keyboard"));
2918 ARDOUR_UI::halt_on_xrun_message ()
2920 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2922 MessageDialog msg (*editor,
2923 _("Recording was stopped because your system could not keep up."));
2928 ARDOUR_UI::disk_overrun_handler ()
2930 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2932 if (!have_disk_speed_dialog_displayed) {
2933 have_disk_speed_dialog_displayed = true;
2934 MessageDialog* msg = new MessageDialog (*editor, _("\
2935 The disk system on your computer\n\
2936 was not able to keep up with Ardour.\n\
2938 Specifically, it failed to write data to disk\n\
2939 quickly enough to keep up with recording.\n"));
2940 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2946 ARDOUR_UI::disk_underrun_handler ()
2948 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2950 if (!have_disk_speed_dialog_displayed) {
2951 have_disk_speed_dialog_displayed = true;
2952 MessageDialog* msg = new MessageDialog (*editor,
2953 _("The disk system on your computer\n\
2954 was not able to keep up with Ardour.\n\
2956 Specifically, it failed to read data from disk\n\
2957 quickly enough to keep up with playback.\n"));
2958 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2964 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2966 have_disk_speed_dialog_displayed = false;
2971 ARDOUR_UI::pending_state_dialog ()
2973 HBox* hbox = new HBox();
2974 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2975 ArdourDialog dialog (_("Crash Recovery"), true);
2977 This session appears to have been in\n\
2978 middle of recording when ardour or\n\
2979 the computer was shutdown.\n\
2981 Ardour can recover any captured audio for\n\
2982 you, or it can ignore it. Please decide\n\
2983 what you would like to do.\n"));
2984 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2985 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2986 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2987 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2988 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2989 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2990 dialog.set_default_response (RESPONSE_ACCEPT);
2991 dialog.set_position (WIN_POS_CENTER);
2996 switch (dialog.run ()) {
2997 case RESPONSE_ACCEPT:
3005 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3007 HBox* hbox = new HBox();
3008 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3009 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3010 Label message (string_compose (_("\
3011 This session was created with a sample rate of %1 Hz\n\
3013 The audioengine is currently running at %2 Hz\n"), desired, actual));
3015 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3016 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3017 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3018 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3019 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3020 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3021 dialog.set_default_response (RESPONSE_ACCEPT);
3022 dialog.set_position (WIN_POS_CENTER);
3027 switch (dialog.run ()) {
3028 case RESPONSE_ACCEPT:
3037 ARDOUR_UI::disconnect_from_jack ()
3040 if( engine->disconnect_from_jack ()) {
3041 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3045 update_sample_rate (0);
3050 ARDOUR_UI::reconnect_to_jack ()
3053 if (engine->reconnect_to_jack ()) {
3054 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3058 update_sample_rate (0);
3063 ARDOUR_UI::use_config ()
3065 Glib::RefPtr<Action> act;
3067 switch (Config->get_native_file_data_format ()) {
3069 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3072 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3075 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3080 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3081 ract->set_active ();
3084 switch (Config->get_native_file_header_format ()) {
3086 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3089 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3092 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3095 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3098 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3101 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3104 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3109 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3110 ract->set_active ();
3113 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3115 set_transport_controllable_state (*node);
3120 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3122 if (Config->get_primary_clock_delta_edit_cursor()) {
3123 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3125 primary_clock.set (pos, 0, true);
3128 if (Config->get_secondary_clock_delta_edit_cursor()) {
3129 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3131 secondary_clock.set (pos);
3134 if (big_clock_window) {
3135 big_clock.set (pos);
3140 ARDOUR_UI::record_state_changed ()
3142 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3144 if (!session || !big_clock_window) {
3145 /* why bother - the clock isn't visible */
3149 switch (session->record_status()) {
3150 case Session::Recording:
3151 big_clock.set_widget_name ("BigClockRecording");
3154 big_clock.set_widget_name ("BigClockNonRecording");
3160 ARDOUR_UI::set_keybindings_path (string path)
3162 keybindings_path = path;
3166 ARDOUR_UI::save_keybindings ()
3168 if (can_save_keybindings) {
3169 AccelMap::save (user_keybindings_path);
3174 ARDOUR_UI::first_idle ()
3177 session->allow_auto_play (true);
3179 can_save_keybindings = true;
3184 ARDOUR_UI::store_clock_modes ()
3186 XMLNode* node = new XMLNode(X_("ClockModes"));
3188 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3189 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3192 session->add_extra_xml (*node);
3193 session->set_dirty ();
3198 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3199 : Controllable (name), ui (u), type(tp)
3205 ARDOUR_UI::TransportControllable::set_value (float val)
3207 if (type == ShuttleControl) {
3214 fract = -((0.5f - val)/0.5f);
3216 fract = ((val - 0.5f)/0.5f);
3220 ui.set_shuttle_fract (fract);
3225 /* do nothing: these are radio-style actions */
3233 action = X_("Roll");
3236 action = X_("Stop");
3239 action = X_("Goto Start");
3242 action = X_("Goto End");
3245 action = X_("Loop");
3248 action = X_("Play Selection");
3251 action = X_("Record");
3261 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3269 ARDOUR_UI::TransportControllable::get_value (void) const
3288 case ShuttleControl:
3298 ARDOUR_UI::TransportControllable::set_id (const string& str)
3304 ARDOUR_UI::setup_profile ()
3306 if (gdk_screen_width() < 1200) {
3307 Profile->set_small_screen ();
3310 if (getenv ("ARDOUR_SAE")) {
3311 Profile->set_sae ();
3312 Profile->set_single_package ();