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.
20 #define __STDC_FORMAT_MACROS 1
34 #include <sys/resource.h>
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include "midi++/manager.h"
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
76 typedef uint64_t microseconds_t;
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
86 #include "add_route_dialog.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
97 #include "engine_dialog.h"
98 #include "processor_box.h"
102 using namespace ARDOUR;
104 using namespace Gtkmm2ext;
106 using namespace sigc;
108 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
109 UIConfiguration *ARDOUR_UI::ui_config = 0;
111 sigc::signal<void,bool> ARDOUR_UI::Blink;
112 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
113 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
114 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
116 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
118 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
120 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
121 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
122 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
123 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
127 preroll_button (_("pre\nroll")),
128 postroll_button (_("post\nroll")),
132 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, true),
136 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
137 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
138 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
139 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
140 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
141 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
142 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
143 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
144 shuttle_controller_binding_proxy (shuttle_controllable),
146 roll_button (roll_controllable),
147 stop_button (stop_controllable),
148 goto_start_button (goto_start_controllable),
149 goto_end_button (goto_end_controllable),
150 auto_loop_button (auto_loop_controllable),
151 play_selection_button (play_selection_controllable),
152 rec_button (rec_controllable),
154 shuttle_units_button (_("% ")),
156 punch_in_button (_("Punch In")),
157 punch_out_button (_("Punch Out")),
158 auto_return_button (_("Auto Return")),
159 auto_play_button (_("Auto Play")),
160 auto_input_button (_("Auto Input")),
161 click_button (_("Click")),
162 time_master_button (_("time\nmaster")),
164 auditioning_alert_button (_("AUDITION")),
165 solo_alert_button (_("SOLO")),
167 error_log_button (_("Errors"))
170 using namespace Gtk::Menu_Helpers;
176 // _auto_display_errors = false;
178 * This was commented out as it wasn't defined
179 * in A3 IIRC. If this is not needed it should
180 * be completely removed.
188 if (theArdourUI == 0) {
192 ui_config = new UIConfiguration();
193 theme_manager = new ThemeManager();
200 _session_is_new = false;
201 big_clock_window = 0;
202 session_selector_window = 0;
203 last_key_press_time = 0;
204 _will_create_new_session_automatically = false;
205 add_route_dialog = 0;
207 rc_option_editor = 0;
208 session_option_editor = 0;
210 open_session_selector = 0;
211 have_configure_timeout = false;
212 have_disk_speed_dialog_displayed = false;
213 session_loaded = false;
214 last_speed_displayed = -1.0f;
215 ignore_dual_punch = false;
216 _mixer_on_top = false;
218 roll_button.unset_flags (Gtk::CAN_FOCUS);
219 stop_button.unset_flags (Gtk::CAN_FOCUS);
220 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
221 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
222 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
223 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
224 rec_button.unset_flags (Gtk::CAN_FOCUS);
226 last_configure_time= 0;
228 shuttle_grabbed = false;
230 shuttle_max_speed = 8.0f;
232 shuttle_style_menu = 0;
233 shuttle_unit_menu = 0;
235 // We do not have jack linked in yet so;
237 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
239 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
240 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
242 /* handle dialog requests */
244 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
246 /* handle pending state with a dialog */
248 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
250 /* handle sr mismatch with a dialog */
252 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
254 /* lets get this party started */
257 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
258 throw failed_constructor ();
261 setup_gtk_ardour_enums ();
264 GainMeter::setup_slider_pix ();
265 RouteTimeAxisView::setup_slider_pix ();
266 SendProcessorEntry::setup_slider_pix ();
268 } catch (failed_constructor& err) {
269 error << _("could not initialize Ardour.") << endmsg;
274 /* we like keyboards */
276 keyboard = new Keyboard;
280 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
281 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
286 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
288 ARDOUR_UI::run_startup (bool should_be_new)
291 _startup = new ArdourStartup ();
294 _startup->set_new_only (should_be_new);
295 _startup->present ();
299 /* we don't return here until the startup assistant is finished */
303 return _startup->applying ();
307 ARDOUR_UI::create_engine ()
309 // this gets called every time by new_session()
315 loading_message (_("Starting audio engine"));
318 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
325 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
326 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
327 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
328 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
336 ARDOUR_UI::post_engine ()
338 /* Things to be done once we create the AudioEngine
341 MIDI::Manager::instance()->set_api_data (engine->jack());
344 ARDOUR::init_post_engine ();
346 ActionManager::init ();
349 if (setup_windows ()) {
350 throw failed_constructor ();
353 check_memory_locking();
355 /* this is the first point at which all the keybindings are available */
357 if (ARDOUR_COMMAND_LINE::show_key_actions) {
358 vector<string> names;
359 vector<string> paths;
361 vector<AccelKey> bindings;
363 ActionManager::get_all_actions (names, paths, keys, bindings);
365 vector<string>::iterator n;
366 vector<string>::iterator k;
367 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
368 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
374 blink_timeout_tag = -1;
376 /* this being a GUI and all, we want peakfiles */
378 AudioFileSource::set_build_peakfiles (true);
379 AudioFileSource::set_build_missing_peakfiles (true);
381 /* set default clock modes */
383 if (Profile->get_sae()) {
384 primary_clock.set_mode (AudioClock::BBT);
385 secondary_clock.set_mode (AudioClock::MinSec);
387 primary_clock.set_mode (AudioClock::Timecode);
388 secondary_clock.set_mode (AudioClock::BBT);
391 /* start the time-of-day-clock */
394 /* OS X provides an always visible wallclock, so don't be stupid */
395 update_wall_clock ();
396 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
399 update_disk_space ();
401 update_sample_rate (engine->frame_rate());
403 Config->ParameterChanged.connect (mem_fun (*this, &ARDOUR_UI::parameter_changed));
404 Config->map_parameters (mem_fun (*this, &ARDOUR_UI::parameter_changed));
406 /* now start and maybe save state */
408 if (do_engine_start () == 0) {
409 if (session && _session_is_new) {
410 /* we need to retain initial visual
411 settings for a new session
413 session->save_state ("");
418 ARDOUR_UI::~ARDOUR_UI ()
420 save_ardour_state ();
425 delete add_route_dialog;
429 ARDOUR_UI::pop_back_splash ()
431 if (Splash::instance()) {
432 // Splash::instance()->pop_back();
433 Splash::instance()->hide ();
438 ARDOUR_UI::configure_timeout ()
440 if (last_configure_time == 0) {
441 /* no configure events yet */
445 /* force a gap of 0.5 seconds since the last configure event
448 if (get_microseconds() - last_configure_time < 500000) {
451 have_configure_timeout = false;
452 save_ardour_state ();
458 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
460 if (have_configure_timeout) {
461 last_configure_time = get_microseconds();
463 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
464 have_configure_timeout = true;
471 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
473 const XMLProperty* prop;
475 if ((prop = node.property ("roll")) != 0) {
476 roll_controllable->set_id (prop->value());
478 if ((prop = node.property ("stop")) != 0) {
479 stop_controllable->set_id (prop->value());
481 if ((prop = node.property ("goto-start")) != 0) {
482 goto_start_controllable->set_id (prop->value());
484 if ((prop = node.property ("goto-end")) != 0) {
485 goto_end_controllable->set_id (prop->value());
487 if ((prop = node.property ("auto-loop")) != 0) {
488 auto_loop_controllable->set_id (prop->value());
490 if ((prop = node.property ("play-selection")) != 0) {
491 play_selection_controllable->set_id (prop->value());
493 if ((prop = node.property ("rec")) != 0) {
494 rec_controllable->set_id (prop->value());
496 if ((prop = node.property ("shuttle")) != 0) {
497 shuttle_controllable->set_id (prop->value());
502 ARDOUR_UI::get_transport_controllable_state ()
504 XMLNode* node = new XMLNode(X_("TransportControllables"));
507 roll_controllable->id().print (buf, sizeof (buf));
508 node->add_property (X_("roll"), buf);
509 stop_controllable->id().print (buf, sizeof (buf));
510 node->add_property (X_("stop"), buf);
511 goto_start_controllable->id().print (buf, sizeof (buf));
512 node->add_property (X_("goto_start"), buf);
513 goto_end_controllable->id().print (buf, sizeof (buf));
514 node->add_property (X_("goto_end"), buf);
515 auto_loop_controllable->id().print (buf, sizeof (buf));
516 node->add_property (X_("auto_loop"), buf);
517 play_selection_controllable->id().print (buf, sizeof (buf));
518 node->add_property (X_("play_selection"), buf);
519 rec_controllable->id().print (buf, sizeof (buf));
520 node->add_property (X_("rec"), buf);
521 shuttle_controllable->id().print (buf, sizeof (buf));
522 node->add_property (X_("shuttle"), buf);
528 ARDOUR_UI::save_ardour_state ()
530 if (!keyboard || !mixer || !editor) {
534 /* XXX this is all a bit dubious. add_extra_xml() uses
535 a different lifetime model from add_instant_xml().
538 XMLNode* node = new XMLNode (keyboard->get_state());
539 Config->add_extra_xml (*node);
540 Config->add_extra_xml (get_transport_controllable_state());
541 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
542 Config->add_extra_xml (_startup->engine_control()->get_state());
544 Config->save_state();
545 ui_config->save_state ();
547 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
548 XMLNode mnode(mixer->get_state());
551 session->add_instant_xml (enode);
552 session->add_instant_xml (mnode);
554 Config->add_instant_xml (enode);
555 Config->add_instant_xml (mnode);
558 Keyboard::save_keybindings ();
562 ARDOUR_UI::autosave_session ()
564 if (g_main_depth() > 1) {
565 /* inside a recursive main loop,
566 give up because we may not be able to
572 if (!Config->get_periodic_safety_backups()) {
577 session->maybe_write_autosave();
584 ARDOUR_UI::update_autosave ()
586 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
588 if (session && session->dirty()) {
589 if (_autosave_connection.connected()) {
590 _autosave_connection.disconnect();
593 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
594 Config->get_periodic_safety_backup_interval() * 1000);
597 if (_autosave_connection.connected()) {
598 _autosave_connection.disconnect();
604 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
608 title = _("Ardour could not start JACK");
610 title = _("Ardour could not connect to JACK.");
613 MessageDialog win (title,
619 win.set_secondary_text(_("There are several possible reasons:\n\
621 1) You requested audio parameters that are not supported..\n\
622 2) JACK is running as another user.\n\
624 Please consider the possibilities, and perhaps try different parameters."));
626 win.set_secondary_text(_("There are several possible reasons:\n\
628 1) JACK is not running.\n\
629 2) JACK is running as another user, perhaps root.\n\
630 3) There is already another client called \"ardour\".\n\
632 Please consider the possibilities, and perhaps (re)start JACK."));
636 win.set_transient_for (*toplevel);
640 win.add_button (Stock::OK, RESPONSE_CLOSE);
642 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
645 win.set_default_response (RESPONSE_CLOSE);
648 win.set_position (Gtk::WIN_POS_CENTER);
651 /* we just don't care about the result, but we want to block */
657 ARDOUR_UI::startup ()
659 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
661 if (audio_setup && _startup && _startup->engine_control()) {
662 _startup->engine_control()->set_state (*audio_setup);
665 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
671 goto_editor_window ();
673 BootMessage (_("Ardour is ready for use"));
678 ARDOUR_UI::no_memory_warning ()
680 XMLNode node (X_("no-memory-warning"));
681 Config->add_instant_xml (node);
685 ARDOUR_UI::check_memory_locking ()
688 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
692 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
694 if (engine->is_realtime() && memory_warning_node == 0) {
696 struct rlimit limits;
698 long pages, page_size;
700 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
703 ram = (int64_t) pages * (int64_t) page_size;
706 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
710 if (limits.rlim_cur != RLIM_INFINITY) {
712 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
715 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
716 "This might cause Ardour to run out of memory before your system "
717 "runs out of memory. \n\n"
718 "You can view the memory limit with 'ulimit -l', "
719 "and it is normally controlled by /etc/security/limits.conf"));
721 VBox* vbox = msg.get_vbox();
723 CheckButton cb (_("Do not show this window again"));
725 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
727 hbox.pack_start (cb, true, false);
728 vbox->pack_start (hbox);
735 editor->ensure_float (msg);
749 if (session->transport_rolling()) {
750 session->request_stop ();
754 if (session->dirty()) {
755 switch (ask_about_saving_session(_("quit"))) {
760 /* use the default name */
761 if (save_state_canfail ("")) {
762 /* failed - don't quit */
763 MessageDialog msg (*editor,
765 Ardour was unable to save your session.\n\n\
766 If you still wish to quit, please use the\n\n\
767 \"Just quit\" option."));
778 second_connection.disconnect ();
779 point_one_second_connection.disconnect ();
780 point_oh_five_second_connection.disconnect ();
781 point_zero_one_second_connection.disconnect();
783 // session->set_deletion_in_progress ();
784 session->remove_pending_capture_state ();
789 ArdourDialog::close_all_dialogs ();
791 save_ardour_state ();
796 ARDOUR_UI::ask_about_saving_session (const string & what)
798 ArdourDialog window (_("ardour: save session?"));
799 Gtk::HBox dhbox; // the hbox for the image and text
800 Gtk::Label prompt_label;
801 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
805 msg = string_compose(_("Don't %1"), what);
806 window.add_button (msg, RESPONSE_REJECT);
807 msg = string_compose(_("Just %1"), what);
808 window.add_button (msg, RESPONSE_APPLY);
809 msg = string_compose(_("Save and %1"), what);
810 window.add_button (msg, RESPONSE_ACCEPT);
812 window.set_default_response (RESPONSE_ACCEPT);
814 Gtk::Button noquit_button (msg);
815 noquit_button.set_name ("EditorGTKButton");
820 if (session->snap_name() == session->name()) {
823 type = _("snapshot");
825 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?"),
826 type, session->snap_name());
828 prompt_label.set_text (prompt);
829 prompt_label.set_name (X_("PrompterLabel"));
830 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
832 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
833 dhbox.set_homogeneous (false);
834 dhbox.pack_start (*dimage, false, false, 5);
835 dhbox.pack_start (prompt_label, true, false, 5);
836 window.get_vbox()->pack_start (dhbox);
838 window.set_name (_("Prompter"));
839 window.set_position (Gtk::WIN_POS_MOUSE);
840 window.set_modal (true);
841 window.set_resizable (false);
847 window.set_keep_above (true);
850 ResponseType r = (ResponseType) window.run();
855 case RESPONSE_ACCEPT: // save and get out of here
857 case RESPONSE_APPLY: // get out of here
867 ARDOUR_UI::every_second ()
870 update_buffer_load ();
871 update_disk_space ();
876 ARDOUR_UI::every_point_one_seconds ()
878 update_speed_display ();
879 RapidScreenUpdate(); /* EMIT_SIGNAL */
884 ARDOUR_UI::every_point_zero_one_seconds ()
886 // august 2007: actual update frequency: 40Hz, not 100Hz
888 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
893 ARDOUR_UI::update_sample_rate (nframes_t ignored)
897 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
899 if (!engine->connected()) {
901 snprintf (buf, sizeof (buf), _("disconnected"));
905 nframes_t rate = engine->frame_rate();
907 if (fmod (rate, 1000.0) != 0.0) {
908 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
909 (float) rate/1000.0f,
910 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
912 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
914 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
918 sample_rate_label.set_text (buf);
922 ARDOUR_UI::update_cpu_load ()
925 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
926 cpu_load_label.set_text (buf);
930 ARDOUR_UI::update_buffer_load ()
936 c = session->capture_load ();
937 p = session->playback_load ();
939 push_buffer_stats (c, p);
941 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
942 session->playback_load(), session->capture_load());
943 buffer_load_label.set_text (buf);
945 buffer_load_label.set_text ("");
950 ARDOUR_UI::count_recenabled_streams (Route& route)
952 Track* track = dynamic_cast<Track*>(&route);
953 if (track && track->diskstream()->record_enabled()) {
954 rec_enabled_streams += track->n_inputs().n_total();
959 ARDOUR_UI::update_disk_space()
965 nframes_t frames = session->available_capture_duration();
967 nframes_t fr = session->frame_rate();
969 if (frames == max_frames) {
970 strcpy (buf, _("Disk: 24hrs+"));
972 rec_enabled_streams = 0;
973 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
975 if (rec_enabled_streams) {
976 frames /= rec_enabled_streams;
983 hrs = frames / (fr * 3600);
984 frames -= hrs * fr * 3600;
985 mins = frames / (fr * 60);
986 frames -= mins * fr * 60;
989 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
992 disk_space_label.set_text (buf);
994 // An attempt to make the disk space label flash red when space has run out.
996 if (frames < fr * 60 * 5) {
997 /* disk_space_box.style ("disk_space_label_empty"); */
999 /* disk_space_box.style ("disk_space_label"); */
1005 ARDOUR_UI::update_wall_clock ()
1012 tm_now = localtime (&now);
1014 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1015 wall_clock_label.set_text (buf);
1021 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1023 session_popup_menu->popup (0, 0);
1028 ARDOUR_UI::redisplay_recent_sessions ()
1030 std::vector<sys::path> session_directories;
1031 RecentSessionsSorter cmp;
1033 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1034 recent_session_model->clear ();
1036 ARDOUR::RecentSessions rs;
1037 ARDOUR::read_recent_sessions (rs);
1040 recent_session_display.set_model (recent_session_model);
1044 // sort them alphabetically
1045 sort (rs.begin(), rs.end(), cmp);
1047 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1048 session_directories.push_back ((*i).second);
1051 for (vector<sys::path>::const_iterator i = session_directories.begin();
1052 i != session_directories.end(); ++i)
1054 std::vector<sys::path> state_file_paths;
1056 // now get available states for this session
1058 get_state_files_in_directory (*i, state_file_paths);
1060 vector<string*>* states;
1061 vector<const gchar*> item;
1062 string fullpath = (*i).to_string();
1064 /* remove any trailing / */
1066 if (fullpath[fullpath.length()-1] == '/') {
1067 fullpath = fullpath.substr (0, fullpath.length()-1);
1070 /* check whether session still exists */
1071 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1072 /* session doesn't exist */
1073 cerr << "skipping non-existent session " << fullpath << endl;
1077 /* now get available states for this session */
1079 if ((states = Session::possible_states (fullpath)) == 0) {
1080 /* no state file? */
1084 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1086 Gtk::TreeModel::Row row = *(recent_session_model->append());
1088 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1089 row[recent_session_columns.fullpath] = fullpath;
1091 if (state_file_names.size() > 1) {
1095 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1096 i2 != state_file_names.end(); ++i2)
1099 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1101 child_row[recent_session_columns.visible_name] = *i2;
1102 child_row[recent_session_columns.fullpath] = fullpath;
1107 recent_session_display.set_model (recent_session_model);
1111 ARDOUR_UI::build_session_selector ()
1113 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1115 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1117 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1118 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1119 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1120 recent_session_model = TreeStore::create (recent_session_columns);
1121 recent_session_display.set_model (recent_session_model);
1122 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1123 recent_session_display.set_headers_visible (false);
1124 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1125 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1127 scroller->add (recent_session_display);
1128 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1130 session_selector_window->set_name ("SessionSelectorWindow");
1131 session_selector_window->set_size_request (200, 400);
1132 session_selector_window->get_vbox()->pack_start (*scroller);
1134 recent_session_display.show();
1136 //session_selector_window->get_vbox()->show();
1140 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1142 session_selector_window->response (RESPONSE_ACCEPT);
1146 ARDOUR_UI::open_recent_session ()
1148 bool can_return = (session != 0);
1150 if (session_selector_window == 0) {
1151 build_session_selector ();
1154 redisplay_recent_sessions ();
1158 session_selector_window->set_position (WIN_POS_MOUSE);
1160 ResponseType r = (ResponseType) session_selector_window->run ();
1163 case RESPONSE_ACCEPT:
1167 session_selector_window->hide();
1174 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1178 session_selector_window->hide();
1180 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1182 if (i == recent_session_model->children().end()) {
1186 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1187 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1189 _session_is_new = false;
1191 if (load_session (path, state) == 0) {
1200 ARDOUR_UI::check_audioengine ()
1203 if (!engine->connected()) {
1204 MessageDialog msg (_("Ardour is not connected to JACK\n"
1205 "You cannot open or close sessions in this condition"));
1217 ARDOUR_UI::open_session ()
1219 if (!check_audioengine()) {
1224 /* popup selector window */
1226 if (open_session_selector == 0) {
1228 /* ardour sessions are folders */
1230 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1231 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1232 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1233 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1235 FileFilter session_filter;
1236 session_filter.add_pattern ("*.ardour");
1237 session_filter.set_name (_("Ardour sessions"));
1238 open_session_selector->add_filter (session_filter);
1239 open_session_selector->set_filter (session_filter);
1242 int response = open_session_selector->run();
1243 open_session_selector->hide ();
1246 case RESPONSE_ACCEPT:
1249 open_session_selector->hide();
1253 open_session_selector->hide();
1254 string session_path = open_session_selector->get_filename();
1258 if (session_path.length() > 0) {
1259 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1260 _session_is_new = isnew;
1261 load_session (path, name);
1268 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1270 list<boost::shared_ptr<MidiTrack> > tracks;
1273 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1280 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1282 if (tracks.size() != how_many) {
1283 if (how_many == 1) {
1284 error << _("could not create a new midi track") << endmsg;
1286 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1290 if ((route = session->new_midi_route ()) == 0) {
1291 error << _("could not create new midi bus") << endmsg;
1297 MessageDialog msg (*editor,
1298 _("There are insufficient JACK ports available\n\
1299 to create a new track or bus.\n\
1300 You should save Ardour, exit and\n\
1301 restart JACK with more ports."));
1308 ARDOUR_UI::session_add_audio_route (bool track, bool aux, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1310 list<boost::shared_ptr<AudioTrack> > tracks;
1314 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1320 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1322 if (tracks.size() != how_many) {
1323 if (how_many == 1) {
1324 error << _("could not create a new audio track") << endmsg;
1326 error << string_compose (_("could only create %1 of %2 new audio %3"),
1327 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1333 routes = session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1335 if (routes.size() != how_many) {
1336 if (how_many == 1) {
1337 error << _("could not create a new audio track") << endmsg;
1339 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1345 if (need_control_room_outs) {
1351 route->set_stereo_control_outs (control_lr_channels);
1352 route->control_outs()->set_stereo_pan (pans, this);
1354 #endif /* CONTROLOUTS */
1358 MessageDialog msg (*editor,
1359 _("There are insufficient JACK ports available\n\
1360 to create a new track or bus.\n\
1361 You should save Ardour, exit and\n\
1362 restart JACK with more ports."));
1369 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1371 nframes_t _preroll = 0;
1374 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1375 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1377 if (new_position > _preroll) {
1378 new_position -= _preroll;
1383 session->request_locate (new_position);
1388 ARDOUR_UI::transport_goto_start ()
1391 session->goto_start();
1393 /* force displayed area in editor to start no matter
1394 what "follow playhead" setting is.
1398 editor->center_screen (session->current_start_frame ());
1404 ARDOUR_UI::transport_goto_zero ()
1407 session->request_locate (0);
1410 /* force displayed area in editor to start no matter
1411 what "follow playhead" setting is.
1415 editor->reset_x_origin (0);
1421 ARDOUR_UI::transport_goto_wallclock ()
1423 if (session && editor) {
1430 localtime_r (&now, &tmnow);
1432 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1433 frames += tmnow.tm_min * (60 * session->frame_rate());
1434 frames += tmnow.tm_sec * session->frame_rate();
1436 session->request_locate (frames);
1438 /* force displayed area in editor to start no matter
1439 what "follow playhead" setting is.
1443 editor->center_screen (frames);
1449 ARDOUR_UI::transport_goto_end ()
1452 nframes_t const frame = session->current_end_frame();
1453 session->request_locate (frame);
1455 /* force displayed area in editor to start no matter
1456 what "follow playhead" setting is.
1460 editor->center_screen (frame);
1466 ARDOUR_UI::transport_stop ()
1472 if (session->is_auditioning()) {
1473 session->cancel_audition ();
1477 session->request_stop ();
1481 ARDOUR_UI::transport_stop_and_forget_capture ()
1484 session->request_stop (true);
1489 ARDOUR_UI::remove_last_capture()
1492 editor->remove_last_capture();
1497 ARDOUR_UI::transport_record (bool roll)
1501 switch (session->record_status()) {
1502 case Session::Disabled:
1503 if (session->ntracks() == 0) {
1504 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1508 session->maybe_enable_record ();
1513 case Session::Recording:
1515 session->request_stop();
1517 session->disable_record (false, true);
1521 case Session::Enabled:
1522 session->disable_record (false, true);
1525 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1529 ARDOUR_UI::transport_roll ()
1535 if (session->is_auditioning()) {
1539 if (session->config.get_external_sync()) {
1540 switch (session->config.get_sync_source()) {
1544 /* transport controlled by the master */
1549 bool rolling = session->transport_rolling();
1551 if (session->get_play_loop()) {
1552 session->request_play_loop (false, true);
1553 } else if (session->get_play_range ()) {
1554 session->request_play_range (false, true);
1558 session->request_transport_speed (1.0f);
1561 map_transport_state ();
1565 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1572 if (session->is_auditioning()) {
1573 session->cancel_audition ();
1577 if (session->config.get_external_sync()) {
1578 switch (session->config.get_sync_source()) {
1582 /* transport controlled by the master */
1587 bool rolling = session->transport_rolling();
1588 bool affect_transport = true;
1590 if (rolling && roll_out_of_bounded_mode) {
1591 /* drop out of loop/range playback but leave transport rolling */
1592 if (session->get_play_loop()) {
1593 if (Config->get_seamless_loop()) {
1594 /* the disk buffers contain copies of the loop - we can't
1595 just keep playing, so stop the transport. the user
1596 can restart as they wish.
1598 affect_transport = true;
1600 /* disk buffers are normal, so we can keep playing */
1601 affect_transport = false;
1603 session->request_play_loop (false, true);
1604 } else if (session->get_play_range ()) {
1605 affect_transport = false;
1606 session->request_play_range (0, true);
1610 if (affect_transport) {
1612 session->request_stop (with_abort, true);
1614 session->request_transport_speed (1.0f);
1618 map_transport_state ();
1622 ARDOUR_UI::toggle_session_auto_loop ()
1625 if (session->get_play_loop()) {
1626 if (session->transport_rolling()) {
1627 Location * looploc = session->locations()->auto_loop_location();
1629 session->request_locate (looploc->start(), true);
1632 session->request_play_loop (false);
1635 Location * looploc = session->locations()->auto_loop_location();
1637 session->request_play_loop (true);
1644 ARDOUR_UI::transport_play_selection ()
1650 editor->play_selection ();
1654 ARDOUR_UI::transport_rewind (int option)
1656 float current_transport_speed;
1659 current_transport_speed = session->transport_speed();
1661 if (current_transport_speed >= 0.0f) {
1664 session->request_transport_speed (-1.0f);
1667 session->request_transport_speed (-4.0f);
1670 session->request_transport_speed (-0.5f);
1675 session->request_transport_speed (current_transport_speed * 1.5f);
1681 ARDOUR_UI::transport_forward (int option)
1683 float current_transport_speed;
1686 current_transport_speed = session->transport_speed();
1688 if (current_transport_speed <= 0.0f) {
1691 session->request_transport_speed (1.0f);
1694 session->request_transport_speed (4.0f);
1697 session->request_transport_speed (0.5f);
1702 session->request_transport_speed (current_transport_speed * 1.5f);
1709 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1715 boost::shared_ptr<Route> r;
1717 if ((r = session->route_by_remote_id (dstream)) != 0) {
1721 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1722 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1731 ARDOUR_UI::map_transport_state ()
1733 ENSURE_GUI_THREAD(mem_fun (*this, &ARDOUR_UI::map_transport_state));
1736 auto_loop_button.set_visual_state (0);
1737 play_selection_button.set_visual_state (0);
1738 roll_button.set_visual_state (0);
1739 stop_button.set_visual_state (1);
1743 float sp = session->transport_speed();
1746 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1747 shuttle_box.queue_draw ();
1748 } else if (sp == 0.0f) {
1750 shuttle_box.queue_draw ();
1751 update_disk_space ();
1756 if (session->get_play_range()) {
1758 play_selection_button.set_visual_state (1);
1759 roll_button.set_visual_state (0);
1760 auto_loop_button.set_visual_state (0);
1762 } else if (session->get_play_loop ()) {
1764 auto_loop_button.set_visual_state (1);
1765 play_selection_button.set_visual_state (0);
1766 roll_button.set_visual_state (0);
1770 roll_button.set_visual_state (1);
1771 play_selection_button.set_visual_state (0);
1772 auto_loop_button.set_visual_state (0);
1775 stop_button.set_visual_state (0);
1779 stop_button.set_visual_state (1);
1780 roll_button.set_visual_state (0);
1781 play_selection_button.set_visual_state (0);
1782 auto_loop_button.set_visual_state (0);
1788 ARDOUR_UI::engine_stopped ()
1790 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1791 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1792 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1796 ARDOUR_UI::engine_running ()
1798 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1799 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1800 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1802 Glib::RefPtr<Action> action;
1803 const char* action_name = 0;
1805 switch (engine->frames_per_cycle()) {
1807 action_name = X_("JACKLatency32");
1810 action_name = X_("JACKLatency64");
1813 action_name = X_("JACKLatency128");
1816 action_name = X_("JACKLatency512");
1819 action_name = X_("JACKLatency1024");
1822 action_name = X_("JACKLatency2048");
1825 action_name = X_("JACKLatency4096");
1828 action_name = X_("JACKLatency8192");
1831 /* XXX can we do anything useful ? */
1837 action = ActionManager::get_action (X_("JACK"), action_name);
1840 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1841 ract->set_active ();
1847 ARDOUR_UI::engine_halted ()
1849 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1851 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1852 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1854 update_sample_rate (0);
1856 MessageDialog msg (*editor,
1858 JACK has either been shutdown or it\n\
1859 disconnected Ardour because Ardour\n\
1860 was not fast enough. Try to restart\n\
1861 JACK, reconnect and save the session."));
1867 ARDOUR_UI::do_engine_start ()
1875 error << _("Unable to start the session running")
1885 ARDOUR_UI::setup_theme ()
1887 theme_manager->setup_theme();
1891 ARDOUR_UI::update_clocks ()
1893 if (!editor || !editor->dragging_playhead()) {
1894 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1899 ARDOUR_UI::start_clocking ()
1901 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1905 ARDOUR_UI::stop_clocking ()
1907 clock_signal_connection.disconnect ();
1911 ARDOUR_UI::toggle_clocking ()
1914 if (clock_button.get_active()) {
1923 ARDOUR_UI::_blink (void *arg)
1926 ((ARDOUR_UI *) arg)->blink ();
1933 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1937 ARDOUR_UI::start_blinking ()
1939 /* Start the blink signal. Everybody with a blinking widget
1940 uses Blink to drive the widget's state.
1943 if (blink_timeout_tag < 0) {
1945 blink_timeout_tag = g_timeout_add (240, _blink, this);
1950 ARDOUR_UI::stop_blinking ()
1952 if (blink_timeout_tag >= 0) {
1953 g_source_remove (blink_timeout_tag);
1954 blink_timeout_tag = -1;
1959 /** Ask the user for the name of a new shapshot and then take it.
1962 ARDOUR_UI::snapshot_session ()
1964 ArdourPrompter prompter (true);
1968 struct tm local_time;
1971 localtime_r (&n, &local_time);
1972 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1974 prompter.set_name ("Prompter");
1975 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1976 prompter.set_title (_("Take Snapshot"));
1977 prompter.set_prompt (_("Name of New Snapshot"));
1978 prompter.set_initial_text (timebuf);
1980 switch (prompter.run()) {
1981 case RESPONSE_ACCEPT:
1983 prompter.get_result (snapname);
1985 bool do_save = (snapname.length() != 0);
1987 vector<sys::path> p;
1988 get_state_files_in_directory (session->session_directory().root_path(), p);
1989 vector<string> n = get_file_names_no_extension (p);
1990 if (find (n.begin(), n.end(), snapname) != n.end()) {
1992 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1993 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1994 confirm.get_vbox()->pack_start (m, true, true);
1995 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1996 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1997 confirm.show_all ();
1998 switch (confirm.run()) {
1999 case RESPONSE_CANCEL:
2005 save_state (snapname);
2016 ARDOUR_UI::save_state (const string & name)
2018 (void) save_state_canfail (name);
2022 ARDOUR_UI::save_state_canfail (string name)
2027 if (name.length() == 0) {
2028 name = session->snap_name();
2031 if ((ret = session->save_state (name)) != 0) {
2035 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2040 ARDOUR_UI::primary_clock_value_changed ()
2043 session->request_locate (primary_clock.current_time ());
2048 ARDOUR_UI::big_clock_value_changed ()
2051 session->request_locate (big_clock.current_time ());
2056 ARDOUR_UI::secondary_clock_value_changed ()
2059 session->request_locate (secondary_clock.current_time ());
2064 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2070 Session::RecordState const r = session->record_status ();
2071 bool const h = session->have_rec_enabled_diskstream ();
2073 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2075 rec_button.set_visual_state (2);
2077 rec_button.set_visual_state (0);
2079 } else if (r == Session::Recording && h) {
2080 rec_button.set_visual_state (1);
2082 rec_button.set_visual_state (0);
2087 ARDOUR_UI::save_template ()
2089 ArdourPrompter prompter (true);
2092 if (!check_audioengine()) {
2096 prompter.set_name (X_("Prompter"));
2097 prompter.set_title (_("Save Mix Template"));
2098 prompter.set_prompt (_("Name for mix template:"));
2099 prompter.set_initial_text(session->name() + _("-template"));
2100 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2102 switch (prompter.run()) {
2103 case RESPONSE_ACCEPT:
2104 prompter.get_result (name);
2106 if (name.length()) {
2107 session->save_template (name);
2117 ARDOUR_UI::edit_metadata ()
2119 SessionMetadataEditor dialog;
2120 dialog.set_session (session);
2121 editor->ensure_float (dialog);
2126 ARDOUR_UI::import_metadata ()
2128 SessionMetadataImporter dialog;
2129 dialog.set_session (session);
2130 editor->ensure_float (dialog);
2135 ARDOUR_UI::fontconfig_dialog ()
2138 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2139 may not and it can take a while to build it. Warn them.
2142 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2144 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2145 MessageDialog msg (*_startup,
2146 _("Welcome to Ardour.\n\n"
2147 "The program will take a bit longer to start up\n"
2148 "while the system fonts are checked.\n\n"
2149 "This will only be done once, and you will\n"
2150 "not see this message again\n"),
2163 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2165 existing_session = false;
2167 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2168 session_path = cmdline_path;
2169 existing_session = true;
2170 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2171 session_path = Glib::path_get_dirname (string (cmdline_path));
2172 existing_session = true;
2174 /* it doesn't exist, assume the best */
2175 session_path = Glib::path_get_dirname (string (cmdline_path));
2178 session_name = basename_nosuffix (string (cmdline_path));
2182 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2184 /* when this is called, the backend audio system must be running */
2186 /* the main idea here is to deal with the fact that a cmdline argument for the session
2187 can be interpreted in different ways - it could be a directory or a file, and before
2188 we load, we need to know both the session directory and the snapshot (statefile) within it
2189 that we are supposed to use.
2192 if (session_name.length() == 0 || session_path.length() == 0) {
2196 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2198 Glib::ustring predicted_session_file;
2200 predicted_session_file = session_path;
2201 predicted_session_file += '/';
2202 predicted_session_file += session_name;
2203 predicted_session_file += ARDOUR::statefile_suffix;
2205 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2206 existing_session = true;
2209 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2211 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2212 /* existing .ardour file */
2213 existing_session = true;
2217 existing_session = false;
2220 /* lets just try to load it */
2222 if (create_engine ()) {
2223 backend_audio_error (false, _startup);
2227 return load_session (session_path, session_name);
2231 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2233 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2235 MessageDialog msg (str,
2237 Gtk::MESSAGE_WARNING,
2238 Gtk::BUTTONS_YES_NO,
2242 msg.set_name (X_("OpenExistingDialog"));
2243 msg.set_title (_("Open Existing Session"));
2244 msg.set_wmclass (X_("existing_session"), "Ardour");
2245 msg.set_position (Gtk::WIN_POS_MOUSE);
2248 switch (msg.run()) {
2257 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2262 AutoConnectOption iconnect;
2263 AutoConnectOption oconnect;
2267 if (Profile->get_sae()) {
2271 iconnect = AutoConnectPhysical;
2272 oconnect = AutoConnectMaster;
2273 nphysin = 0; // use all available
2274 nphysout = 0; // use all available
2278 /* get settings from advanced section of NSD */
2280 if (_startup->create_control_bus()) {
2281 cchns = (uint32_t) _startup->control_channel_count();
2286 if (_startup->create_master_bus()) {
2287 mchns = (uint32_t) _startup->master_channel_count();
2292 if (_startup->connect_inputs()) {
2293 iconnect = AutoConnectPhysical;
2295 iconnect = AutoConnectOption (0);
2298 /// @todo some minor tweaks.
2300 oconnect = AutoConnectOption (0);
2302 if (_startup->connect_outputs ()) {
2303 if (_startup->connect_outs_to_master()) {
2304 oconnect = AutoConnectMaster;
2305 } else if (_startup->connect_outs_to_physical()) {
2306 oconnect = AutoConnectPhysical;
2310 nphysin = (uint32_t) _startup->input_limit_count();
2311 nphysout = (uint32_t) _startup->output_limit_count();
2314 if (build_session (session_path,
2322 engine->frame_rate() * 60 * 5)) {
2331 ARDOUR_UI::idle_load (const Glib::ustring& path)
2334 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2335 /* /path/to/foo => /path/to/foo, foo */
2336 load_session (path, basename_nosuffix (path));
2338 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2339 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2343 ARDOUR_COMMAND_LINE::session_name = path;
2346 * new_session_dialog doens't exist in A3
2347 * Try to remove all references to it to
2348 * see if it will compile. NOTE: this will
2349 * likely cause a runtime issue is my somewhat
2353 //if (new_session_dialog) {
2356 /* make it break out of Dialog::run() and
2360 //new_session_dialog->response (1);
2366 ARDOUR_UI::end_loading_messages ()
2372 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2375 // splash->message (msg);
2379 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2381 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2383 Glib::ustring session_name;
2384 Glib::ustring session_path;
2385 Glib::ustring template_name;
2387 bool likely_new = false;
2391 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2393 /* if they named a specific statefile, use it, otherwise they are
2394 just giving a session folder, and we want to use it as is
2395 to find the session.
2398 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2399 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2401 session_path = ARDOUR_COMMAND_LINE::session_name;
2404 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2408 bool const apply = run_startup (should_be_new);
2410 if (quit_on_cancel) {
2417 /* if we run the startup dialog again, offer more than just "new session" */
2419 should_be_new = false;
2421 session_name = _startup->session_name (likely_new);
2423 /* this shouldn't happen, but we catch it just in case it does */
2425 if (session_name.empty()) {
2428 if (_startup->use_session_template()) {
2429 template_name = _startup->session_template_name();
2430 _session_is_new = true;
2433 if (session_name[0] == '/' ||
2434 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2435 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2437 session_path = Glib::path_get_dirname (session_name);
2438 session_name = Glib::path_get_basename (session_name);
2442 session_path = _startup->session_folder();
2446 if (create_engine ()) {
2450 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2454 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2456 if (!ask_about_loading_existing_session (existing)) {
2457 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2462 _session_is_new = false;
2467 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2469 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2473 _session_is_new = true;
2476 if (likely_new && template_name.empty()) {
2478 ret = build_session_from_nsd (session_path, session_name);
2482 ret = load_session (session_path, session_name, template_name);
2483 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2484 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2494 ARDOUR_UI::close_session()
2496 if (!check_audioengine()) {
2500 unload_session (true);
2502 ARDOUR_COMMAND_LINE::session_name = "";
2503 get_session_parameters (true, false);
2507 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2509 Session *new_session;
2513 session_loaded = false;
2515 if (!check_audioengine()) {
2519 unload_status = unload_session ();
2521 if (unload_status < 0) {
2523 } else if (unload_status > 0) {
2528 loading_message (_("Please wait while Ardour loads your session"));
2531 new_session = new Session (*engine, path, snap_name, mix_template);
2534 /* this one is special */
2536 catch (AudioEngine::PortRegistrationFailure& err) {
2538 MessageDialog msg (err.what(),
2541 Gtk::BUTTONS_CLOSE);
2543 msg.set_title (_("Port Registration Error"));
2544 msg.set_secondary_text (_("Click the Close button to try again."));
2545 msg.set_position (Gtk::WIN_POS_CENTER);
2549 int response = msg.run ();
2554 case RESPONSE_CANCEL:
2564 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2567 Gtk::BUTTONS_CLOSE);
2569 msg.set_title (_("Loading Error"));
2570 msg.set_secondary_text (_("Click the Close button to try again."));
2571 msg.set_position (Gtk::WIN_POS_CENTER);
2575 int response = msg.run ();
2580 case RESPONSE_CANCEL:
2588 connect_to_session (new_session);
2590 session_loaded = true;
2592 goto_editor_window ();
2595 session->set_clean ();
2606 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2607 uint32_t control_channels,
2608 uint32_t master_channels,
2609 AutoConnectOption input_connect,
2610 AutoConnectOption output_connect,
2613 nframes_t initial_length)
2615 Session *new_session;
2618 if (!check_audioengine()) {
2622 session_loaded = false;
2624 x = unload_session ();
2632 _session_is_new = true;
2635 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2636 control_channels, master_channels, nphysin, nphysout, initial_length);
2641 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2647 connect_to_session (new_session);
2649 session_loaded = true;
2651 new_session->save_state(new_session->name());
2660 editor->show_window ();
2671 ARDOUR_UI::show_about ()
2675 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2682 ARDOUR_UI::hide_about ()
2685 about->get_window()->set_cursor ();
2691 ARDOUR_UI::about_signal_response (int /*response*/)
2697 ARDOUR_UI::show_splash ()
2701 splash = new Splash;
2709 splash->queue_draw ();
2710 splash->get_window()->process_updates (true);
2715 ARDOUR_UI::hide_splash ()
2723 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2724 const string& plural_msg, const string& singular_msg)
2728 removed = rep.paths.size();
2731 MessageDialog msgd (*editor,
2732 _("No audio files were ready for cleanup"),
2735 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2736 msgd.set_secondary_text (_("If this seems suprising, \n\
2737 check for any existing snapshots.\n\
2738 These may still include regions that\n\
2739 require some unused files to continue to exist."));
2745 ArdourDialog results (_("ardour: cleanup"), true, false);
2747 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2748 CleanupResultsModelColumns() {
2752 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2753 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2757 CleanupResultsModelColumns results_columns;
2758 Glib::RefPtr<Gtk::ListStore> results_model;
2759 Gtk::TreeView results_display;
2761 results_model = ListStore::create (results_columns);
2762 results_display.set_model (results_model);
2763 results_display.append_column (list_title, results_columns.visible_name);
2765 results_display.set_name ("CleanupResultsList");
2766 results_display.set_headers_visible (true);
2767 results_display.set_headers_clickable (false);
2768 results_display.set_reorderable (false);
2770 Gtk::ScrolledWindow list_scroller;
2773 Gtk::HBox dhbox; // the hbox for the image and text
2774 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2775 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2777 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2779 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2785 %1 - number of files removed
2786 %2 - location of "dead_sounds"
2787 %3 - size of files affected
2788 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2791 const char* bprefix;
2793 if (rep.space < 1048576.0f) {
2794 bprefix = X_("kilo");
2795 } else if (rep.space < 1048576.0f * 1000) {
2796 bprefix = X_("mega");
2798 bprefix = X_("giga");
2802 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2804 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2807 dhbox.pack_start (*dimage, true, false, 5);
2808 dhbox.pack_start (txt, true, false, 5);
2810 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2811 TreeModel::Row row = *(results_model->append());
2812 row[results_columns.visible_name] = *i;
2813 row[results_columns.fullpath] = *i;
2816 list_scroller.add (results_display);
2817 list_scroller.set_size_request (-1, 150);
2818 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2820 dvbox.pack_start (dhbox, true, false, 5);
2821 dvbox.pack_start (list_scroller, true, false, 5);
2822 ddhbox.pack_start (dvbox, true, false, 5);
2824 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2825 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2826 results.set_default_response (RESPONSE_CLOSE);
2827 results.set_position (Gtk::WIN_POS_MOUSE);
2829 results_display.show();
2830 list_scroller.show();
2837 //results.get_vbox()->show();
2838 results.set_resizable (false);
2845 ARDOUR_UI::cleanup ()
2848 /* shouldn't happen: menu item is insensitive */
2853 MessageDialog checker (_("Are you sure you want to cleanup?"),
2855 Gtk::MESSAGE_QUESTION,
2856 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2858 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2859 ALL undo/redo information will be lost if you cleanup.\n\
2860 After cleanup, unused audio files will be moved to a \
2861 \"dead sounds\" location."));
2863 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2864 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2865 checker.set_default_response (RESPONSE_CANCEL);
2867 checker.set_name (_("CleanupDialog"));
2868 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2869 checker.set_position (Gtk::WIN_POS_MOUSE);
2871 switch (checker.run()) {
2872 case RESPONSE_ACCEPT:
2878 ARDOUR::CleanupReport rep;
2880 editor->prepare_for_cleanup ();
2882 /* do not allow flush until a session is reloaded */
2884 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2886 act->set_sensitive (false);
2889 if (session->cleanup_sources (rep)) {
2890 editor->finish_cleanup ();
2894 editor->finish_cleanup ();
2897 display_cleanup_results (rep,
2900 The following %1 files were not in use and \n\
2901 have been moved to:\n\
2903 Flushing the wastebasket will \n\
2904 release an additional\n\
2905 %3 %4bytes of disk space.\n"),
2907 The following file was not in use and \n \
2908 has been moved to:\n \
2910 Flushing the wastebasket will \n\
2911 release an additional\n\
2912 %3 %4bytes of disk space.\n"
2918 ARDOUR_UI::flush_trash ()
2921 /* shouldn't happen: menu item is insensitive */
2925 ARDOUR::CleanupReport rep;
2927 if (session->cleanup_trash_sources (rep)) {
2931 display_cleanup_results (rep,
2933 _("The following %1 files were deleted from\n\
2935 releasing %3 %4bytes of disk space"),
2936 _("The following file was deleted from\n\
2938 releasing %3 %4bytes of disk space"));
2942 ARDOUR_UI::add_route (Gtk::Window* float_window)
2950 if (add_route_dialog == 0) {
2951 add_route_dialog = new AddRouteDialog (*session);
2953 add_route_dialog->set_transient_for (*float_window);
2957 if (add_route_dialog->is_visible()) {
2958 /* we're already doing this */
2962 ResponseType r = (ResponseType) add_route_dialog->run ();
2964 add_route_dialog->hide();
2967 case RESPONSE_ACCEPT:
2974 if ((count = add_route_dialog->count()) <= 0) {
2978 string template_path = add_route_dialog->track_template();
2980 if (!template_path.empty()) {
2981 session->new_route_from_template (count, template_path);
2985 uint32_t input_chan = add_route_dialog->channels ();
2986 uint32_t output_chan;
2987 string name_template = add_route_dialog->name_template ();
2988 bool track = add_route_dialog->track ();
2989 bool aux = !track && add_route_dialog->aux();
2990 RouteGroup* route_group = add_route_dialog->route_group ();
2992 AutoConnectOption oac = Config->get_output_auto_connect();
2994 if (oac & AutoConnectMaster) {
2995 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2997 output_chan = input_chan;
3000 /* XXX do something with name template */
3002 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3004 session_add_midi_track (route_group, count);
3006 MessageDialog msg (*editor,
3007 _("Sorry, MIDI Busses are not supported at this time."));
3009 //session_add_midi_bus();
3013 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3015 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3021 ARDOUR_UI::mixer_settings () const
3026 node = session->instant_xml(X_("Mixer"));
3028 node = Config->instant_xml(X_("Mixer"));
3032 node = new XMLNode (X_("Mixer"));
3039 ARDOUR_UI::editor_settings () const
3044 node = session->instant_xml(X_("Editor"));
3046 node = Config->instant_xml(X_("Editor"));
3050 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3051 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3056 node = new XMLNode (X_("Editor"));
3063 ARDOUR_UI::keyboard_settings () const
3067 node = Config->extra_xml(X_("Keyboard"));
3070 node = new XMLNode (X_("Keyboard"));
3076 ARDOUR_UI::create_xrun_marker(nframes_t where)
3078 editor->mouse_add_new_marker (where, false, true);
3082 ARDOUR_UI::halt_on_xrun_message ()
3084 MessageDialog msg (*editor,
3085 _("Recording was stopped because your system could not keep up."));
3090 ARDOUR_UI::xrun_handler(nframes_t where)
3096 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3098 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3099 create_xrun_marker(where);
3102 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3103 halt_on_xrun_message ();
3108 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3113 while (disk_buffer_stats.size() > 60) {
3114 disk_buffer_stats.pop_front ();
3117 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3121 ARDOUR_UI::write_buffer_stats ()
3127 char path[PATH_MAX+1]; int fd;
3129 strcpy (path, "ardourBufferingXXXXXX");
3131 if ((fd = mkstemp (path )) < 0) {
3132 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3140 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3144 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3145 localtime_r (&(*i).when, &tm);
3146 strftime (buf, sizeof (buf), "%T", &tm);
3147 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3150 disk_buffer_stats.clear ();
3154 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3158 ARDOUR_UI::disk_overrun_handler ()
3160 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3162 write_buffer_stats ();
3164 if (!have_disk_speed_dialog_displayed) {
3165 have_disk_speed_dialog_displayed = true;
3166 MessageDialog* msg = new MessageDialog (*editor, _("\
3167 The disk system on your computer\n\
3168 was not able to keep up with Ardour.\n\
3170 Specifically, it failed to write data to disk\n\
3171 quickly enough to keep up with recording.\n"));
3172 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3178 ARDOUR_UI::disk_underrun_handler ()
3180 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3182 write_buffer_stats ();
3184 if (!have_disk_speed_dialog_displayed) {
3185 have_disk_speed_dialog_displayed = true;
3186 MessageDialog* msg = new MessageDialog (*editor,
3187 _("The disk system on your computer\n\
3188 was not able to keep up with Ardour.\n\
3190 Specifically, it failed to read data from disk\n\
3191 quickly enough to keep up with playback.\n"));
3192 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3198 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3200 have_disk_speed_dialog_displayed = false;
3205 ARDOUR_UI::session_dialog (std::string msg)
3207 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3212 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3214 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3223 ARDOUR_UI::pending_state_dialog ()
3225 HBox* hbox = new HBox();
3226 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3227 ArdourDialog dialog (_("Crash Recovery"), true);
3229 This session appears to have been in\n\
3230 middle of recording when ardour or\n\
3231 the computer was shutdown.\n\
3233 Ardour can recover any captured audio for\n\
3234 you, or it can ignore it. Please decide\n\
3235 what you would like to do.\n"));
3236 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3237 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3238 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3239 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3240 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3241 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3242 dialog.set_default_response (RESPONSE_ACCEPT);
3243 dialog.set_position (WIN_POS_CENTER);
3248 switch (dialog.run ()) {
3249 case RESPONSE_ACCEPT:
3257 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3259 HBox* hbox = new HBox();
3260 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3261 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3262 Label message (string_compose (_("\
3263 This session was created with a sample rate of %1 Hz\n\
3265 The audioengine is currently running at %2 Hz\n"), desired, actual));
3267 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3268 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3269 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3270 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3271 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3272 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3273 dialog.set_default_response (RESPONSE_ACCEPT);
3274 dialog.set_position (WIN_POS_CENTER);
3279 switch (dialog.run ()) {
3280 case RESPONSE_ACCEPT:
3289 ARDOUR_UI::disconnect_from_jack ()
3292 if( engine->disconnect_from_jack ()) {
3293 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3297 update_sample_rate (0);
3302 ARDOUR_UI::reconnect_to_jack ()
3305 if (engine->reconnect_to_jack ()) {
3306 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3310 update_sample_rate (0);
3315 ARDOUR_UI::use_config ()
3318 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3320 set_transport_controllable_state (*node);
3325 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3327 if (Config->get_primary_clock_delta_edit_cursor()) {
3328 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3330 primary_clock.set (pos, 0, true);
3333 if (Config->get_secondary_clock_delta_edit_cursor()) {
3334 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3336 secondary_clock.set (pos);
3339 if (big_clock_window) {
3340 big_clock.set (pos);
3345 ARDOUR_UI::record_state_changed ()
3347 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3349 if (!session || !big_clock_window) {
3350 /* why bother - the clock isn't visible */
3354 Session::RecordState const r = session->record_status ();
3355 bool const h = session->have_rec_enabled_diskstream ();
3357 if (r == Session::Recording && h) {
3358 big_clock.set_widget_name ("BigClockRecording");
3360 big_clock.set_widget_name ("BigClockNonRecording");
3365 ARDOUR_UI::first_idle ()
3368 session->allow_auto_play (true);
3372 editor->first_idle();
3375 Keyboard::set_can_save_keybindings (true);
3380 ARDOUR_UI::store_clock_modes ()
3382 XMLNode* node = new XMLNode(X_("ClockModes"));
3384 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3385 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3388 session->add_extra_xml (*node);
3389 session->set_dirty ();
3394 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3395 : Controllable (name), ui (u), type(tp)
3401 ARDOUR_UI::TransportControllable::set_value (float val)
3403 if (type == ShuttleControl) {
3410 fract = -((0.5f - val)/0.5f);
3412 fract = ((val - 0.5f)/0.5f);
3416 ui.set_shuttle_fract (fract);
3421 /* do nothing: these are radio-style actions */
3425 const char *action = 0;
3429 action = X_("Roll");
3432 action = X_("Stop");
3435 action = X_("Goto Start");
3438 action = X_("Goto End");
3441 action = X_("Loop");
3444 action = X_("Play Selection");
3447 action = X_("Record");
3457 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3465 ARDOUR_UI::TransportControllable::get_value (void) const
3484 case ShuttleControl:
3494 ARDOUR_UI::TransportControllable::set_id (const string& str)
3500 ARDOUR_UI::setup_profile ()
3502 if (gdk_screen_width() < 1200) {
3503 Profile->set_small_screen ();
3507 if (getenv ("ARDOUR_SAE")) {
3508 Profile->set_sae ();
3509 Profile->set_single_package ();