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;
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117 : Gtkmm2ext::UI (X_("gui"), argcp, argvp),
119 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
120 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
121 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
122 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
126 preroll_button (_("pre\nroll")),
127 postroll_button (_("post\nroll")),
131 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, true),
135 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143 shuttle_controller_binding_proxy (shuttle_controllable),
145 roll_button (roll_controllable),
146 stop_button (stop_controllable),
147 goto_start_button (goto_start_controllable),
148 goto_end_button (goto_end_controllable),
149 auto_loop_button (auto_loop_controllable),
150 play_selection_button (play_selection_controllable),
151 rec_button (rec_controllable),
153 shuttle_units_button (_("% ")),
155 punch_in_button (_("Punch In")),
156 punch_out_button (_("Punch Out")),
157 auto_return_button (_("Auto Return")),
158 auto_play_button (_("Auto Play")),
159 auto_input_button (_("Auto Input")),
160 click_button (_("Click")),
161 time_master_button (_("time\nmaster")),
163 auditioning_alert_button (_("AUDITION")),
164 solo_alert_button (_("SOLO")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 // _auto_display_errors = false;
177 * This was commented out as it wasn't defined
178 * in A3 IIRC. If this is not needed it should
179 * be completely removed.
187 if (theArdourUI == 0) {
191 ui_config = new UIConfiguration();
192 theme_manager = new ThemeManager();
199 _session_is_new = false;
200 big_clock_window = 0;
201 session_selector_window = 0;
202 last_key_press_time = 0;
203 _will_create_new_session_automatically = false;
204 add_route_dialog = 0;
206 rc_option_editor = 0;
207 session_option_editor = 0;
209 open_session_selector = 0;
210 have_configure_timeout = false;
211 have_disk_speed_dialog_displayed = false;
212 session_loaded = false;
213 last_speed_displayed = -1.0f;
214 ignore_dual_punch = false;
215 _mixer_on_top = false;
217 roll_button.unset_flags (Gtk::CAN_FOCUS);
218 stop_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
220 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
221 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
222 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
223 rec_button.unset_flags (Gtk::CAN_FOCUS);
225 last_configure_time= 0;
227 shuttle_grabbed = false;
229 shuttle_max_speed = 8.0f;
231 shuttle_style_menu = 0;
232 shuttle_unit_menu = 0;
234 // We do not have jack linked in yet so;
236 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
238 ARDOUR::Diskstream::DiskOverrun.connect (sigc::mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (sigc::mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle dialog requests */
243 ARDOUR::Session::Dialog.connect (sigc::mem_fun(*this, &ARDOUR_UI::session_dialog));
245 /* handle pending state with a dialog */
247 ARDOUR::Session::AskAboutPendingState.connect (sigc::mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
249 /* handle sr mismatch with a dialog */
251 ARDOUR::Session::AskAboutSampleRateMismatch.connect (sigc::mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
253 /* lets get this party started */
256 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
257 throw failed_constructor ();
260 setup_gtk_ardour_enums ();
263 GainMeter::setup_slider_pix ();
264 RouteTimeAxisView::setup_slider_pix ();
265 SendProcessorEntry::setup_slider_pix ();
266 SessionEvent::create_per_thread_pool ("GUI", 512);
268 } catch (failed_constructor& err) {
269 error << _("could not initialize Ardour.") << endmsg;
274 /* we like keyboards */
276 keyboard = new ArdourKeyboard;
278 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
280 keyboard->set_state (*node, Stateful::loading_state_version);
285 starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
286 stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
291 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
293 ARDOUR_UI::run_startup (bool should_be_new)
296 _startup = new ArdourStartup ();
299 _startup->set_new_only (should_be_new);
300 _startup->present ();
306 switch (_startup->response()) {
315 ARDOUR_UI::create_engine ()
317 // this gets called every time by new_session()
323 loading_message (_("Starting audio engine"));
326 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
333 engine->Stopped.connect (sigc::mem_fun(*this, &ARDOUR_UI::engine_stopped));
334 engine->Running.connect (sigc::mem_fun(*this, &ARDOUR_UI::engine_running));
335 engine->Halted.connect (sigc::mem_fun(*this, &ARDOUR_UI::engine_halted));
336 engine->SampleRateChanged.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_sample_rate));
344 ARDOUR_UI::post_engine ()
346 /* Things to be done once we create the AudioEngine
349 MIDI::Manager::instance()->set_api_data (engine->jack());
352 ARDOUR::init_post_engine ();
354 ActionManager::init ();
357 if (setup_windows ()) {
358 throw failed_constructor ();
361 check_memory_locking();
363 /* this is the first point at which all the keybindings are available */
365 if (ARDOUR_COMMAND_LINE::show_key_actions) {
366 vector<string> names;
367 vector<string> paths;
369 vector<AccelKey> bindings;
371 ActionManager::get_all_actions (names, paths, keys, bindings);
373 vector<string>::iterator n;
374 vector<string>::iterator k;
375 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
376 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
382 blink_timeout_tag = -1;
384 /* this being a GUI and all, we want peakfiles */
386 AudioFileSource::set_build_peakfiles (true);
387 AudioFileSource::set_build_missing_peakfiles (true);
389 /* set default clock modes */
391 if (Profile->get_sae()) {
392 primary_clock.set_mode (AudioClock::BBT);
393 secondary_clock.set_mode (AudioClock::MinSec);
395 primary_clock.set_mode (AudioClock::Timecode);
396 secondary_clock.set_mode (AudioClock::BBT);
399 /* start the time-of-day-clock */
402 /* OS X provides an always visible wallclock, so don't be stupid */
403 update_wall_clock ();
404 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
407 update_disk_space ();
409 update_sample_rate (engine->frame_rate());
411 Config->ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
412 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
413 Config->map_parameters (pc);
415 /* now start and maybe save state */
417 if (do_engine_start () == 0) {
418 if (session && _session_is_new) {
419 /* we need to retain initial visual
420 settings for a new session
422 session->save_state ("");
427 ARDOUR_UI::~ARDOUR_UI ()
429 save_ardour_state ();
434 delete add_route_dialog;
438 ARDOUR_UI::pop_back_splash ()
440 if (Splash::instance()) {
441 // Splash::instance()->pop_back();
442 Splash::instance()->hide ();
447 ARDOUR_UI::configure_timeout ()
449 if (last_configure_time == 0) {
450 /* no configure events yet */
454 /* force a gap of 0.5 seconds since the last configure event
457 if (get_microseconds() - last_configure_time < 500000) {
460 have_configure_timeout = false;
461 save_ardour_state ();
467 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
469 if (have_configure_timeout) {
470 last_configure_time = get_microseconds();
472 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
473 have_configure_timeout = true;
480 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
482 const XMLProperty* prop;
484 if ((prop = node.property ("roll")) != 0) {
485 roll_controllable->set_id (prop->value());
487 if ((prop = node.property ("stop")) != 0) {
488 stop_controllable->set_id (prop->value());
490 if ((prop = node.property ("goto-start")) != 0) {
491 goto_start_controllable->set_id (prop->value());
493 if ((prop = node.property ("goto-end")) != 0) {
494 goto_end_controllable->set_id (prop->value());
496 if ((prop = node.property ("auto-loop")) != 0) {
497 auto_loop_controllable->set_id (prop->value());
499 if ((prop = node.property ("play-selection")) != 0) {
500 play_selection_controllable->set_id (prop->value());
502 if ((prop = node.property ("rec")) != 0) {
503 rec_controllable->set_id (prop->value());
505 if ((prop = node.property ("shuttle")) != 0) {
506 shuttle_controllable->set_id (prop->value());
511 ARDOUR_UI::get_transport_controllable_state ()
513 XMLNode* node = new XMLNode(X_("TransportControllables"));
516 roll_controllable->id().print (buf, sizeof (buf));
517 node->add_property (X_("roll"), buf);
518 stop_controllable->id().print (buf, sizeof (buf));
519 node->add_property (X_("stop"), buf);
520 goto_start_controllable->id().print (buf, sizeof (buf));
521 node->add_property (X_("goto_start"), buf);
522 goto_end_controllable->id().print (buf, sizeof (buf));
523 node->add_property (X_("goto_end"), buf);
524 auto_loop_controllable->id().print (buf, sizeof (buf));
525 node->add_property (X_("auto_loop"), buf);
526 play_selection_controllable->id().print (buf, sizeof (buf));
527 node->add_property (X_("play_selection"), buf);
528 rec_controllable->id().print (buf, sizeof (buf));
529 node->add_property (X_("rec"), buf);
530 shuttle_controllable->id().print (buf, sizeof (buf));
531 node->add_property (X_("shuttle"), buf);
537 ARDOUR_UI::save_ardour_state ()
539 if (!keyboard || !mixer || !editor) {
543 /* XXX this is all a bit dubious. add_extra_xml() uses
544 a different lifetime model from add_instant_xml().
547 XMLNode* node = new XMLNode (keyboard->get_state());
548 Config->add_extra_xml (*node);
549 Config->add_extra_xml (get_transport_controllable_state());
550 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
551 Config->add_extra_xml (_startup->engine_control()->get_state());
553 Config->save_state();
554 ui_config->save_state ();
556 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
557 XMLNode mnode(mixer->get_state());
560 session->add_instant_xml (enode);
561 session->add_instant_xml (mnode);
563 Config->add_instant_xml (enode);
564 Config->add_instant_xml (mnode);
567 Keyboard::save_keybindings ();
571 ARDOUR_UI::autosave_session ()
573 if (g_main_depth() > 1) {
574 /* inside a recursive main loop,
575 give up because we may not be able to
581 if (!Config->get_periodic_safety_backups()) {
586 session->maybe_write_autosave();
593 ARDOUR_UI::update_autosave ()
595 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
597 if (session && session->dirty()) {
598 if (_autosave_connection.connected()) {
599 _autosave_connection.disconnect();
602 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
603 Config->get_periodic_safety_backup_interval() * 1000);
606 if (_autosave_connection.connected()) {
607 _autosave_connection.disconnect();
613 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
617 title = _("Ardour could not start JACK");
619 title = _("Ardour could not connect to JACK.");
622 MessageDialog win (title,
628 win.set_secondary_text(_("There are several possible reasons:\n\
630 1) You requested audio parameters that are not supported..\n\
631 2) JACK is running as another user.\n\
633 Please consider the possibilities, and perhaps try different parameters."));
635 win.set_secondary_text(_("There are several possible reasons:\n\
637 1) JACK is not running.\n\
638 2) JACK is running as another user, perhaps root.\n\
639 3) There is already another client called \"ardour\".\n\
641 Please consider the possibilities, and perhaps (re)start JACK."));
645 win.set_transient_for (*toplevel);
649 win.add_button (Stock::OK, RESPONSE_CLOSE);
651 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
654 win.set_default_response (RESPONSE_CLOSE);
657 win.set_position (Gtk::WIN_POS_CENTER);
660 /* we just don't care about the result, but we want to block */
666 ARDOUR_UI::startup ()
668 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
670 if (audio_setup && _startup && _startup->engine_control()) {
671 _startup->engine_control()->set_state (*audio_setup);
674 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
680 goto_editor_window ();
682 BootMessage (_("Ardour is ready for use"));
687 ARDOUR_UI::no_memory_warning ()
689 XMLNode node (X_("no-memory-warning"));
690 Config->add_instant_xml (node);
694 ARDOUR_UI::check_memory_locking ()
697 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
701 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
703 if (engine->is_realtime() && memory_warning_node == 0) {
705 struct rlimit limits;
707 long pages, page_size;
709 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
712 ram = (int64_t) pages * (int64_t) page_size;
715 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
719 if (limits.rlim_cur != RLIM_INFINITY) {
721 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
724 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
725 "This might cause Ardour to run out of memory before your system "
726 "runs out of memory. \n\n"
727 "You can view the memory limit with 'ulimit -l', "
728 "and it is normally controlled by /etc/security/limits.conf"));
730 VBox* vbox = msg.get_vbox();
732 CheckButton cb (_("Do not show this window again"));
734 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
736 hbox.pack_start (cb, true, false);
737 vbox->pack_start (hbox);
744 editor->ensure_float (msg);
758 if (session->transport_rolling()) {
759 session->request_stop ();
763 if (session->dirty()) {
764 switch (ask_about_saving_session(_("quit"))) {
769 /* use the default name */
770 if (save_state_canfail ("")) {
771 /* failed - don't quit */
772 MessageDialog msg (*editor,
774 Ardour was unable to save your session.\n\n\
775 If you still wish to quit, please use the\n\n\
776 \"Just quit\" option."));
787 second_connection.disconnect ();
788 point_one_second_connection.disconnect ();
789 point_oh_five_second_connection.disconnect ();
790 point_zero_one_second_connection.disconnect();
792 // session->set_deletion_in_progress ();
793 session->remove_pending_capture_state ();
798 ArdourDialog::close_all_dialogs ();
800 save_ardour_state ();
805 ARDOUR_UI::ask_about_saving_session (const string & what)
807 ArdourDialog window (_("ardour: save session?"));
808 Gtk::HBox dhbox; // the hbox for the image and text
809 Gtk::Label prompt_label;
810 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
814 msg = string_compose(_("Don't %1"), what);
815 window.add_button (msg, RESPONSE_REJECT);
816 msg = string_compose(_("Just %1"), what);
817 window.add_button (msg, RESPONSE_APPLY);
818 msg = string_compose(_("Save and %1"), what);
819 window.add_button (msg, RESPONSE_ACCEPT);
821 window.set_default_response (RESPONSE_ACCEPT);
823 Gtk::Button noquit_button (msg);
824 noquit_button.set_name ("EditorGTKButton");
829 if (session->snap_name() == session->name()) {
832 type = _("snapshot");
834 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?"),
835 type, session->snap_name());
837 prompt_label.set_text (prompt);
838 prompt_label.set_name (X_("PrompterLabel"));
839 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
841 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
842 dhbox.set_homogeneous (false);
843 dhbox.pack_start (*dimage, false, false, 5);
844 dhbox.pack_start (prompt_label, true, false, 5);
845 window.get_vbox()->pack_start (dhbox);
847 window.set_name (_("Prompter"));
848 window.set_position (Gtk::WIN_POS_MOUSE);
849 window.set_modal (true);
850 window.set_resizable (false);
856 window.set_keep_above (true);
859 ResponseType r = (ResponseType) window.run();
864 case RESPONSE_ACCEPT: // save and get out of here
866 case RESPONSE_APPLY: // get out of here
876 ARDOUR_UI::every_second ()
879 update_buffer_load ();
880 update_disk_space ();
885 ARDOUR_UI::every_point_one_seconds ()
887 update_speed_display ();
888 RapidScreenUpdate(); /* EMIT_SIGNAL */
893 ARDOUR_UI::every_point_zero_one_seconds ()
895 // august 2007: actual update frequency: 40Hz, not 100Hz
897 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
902 ARDOUR_UI::update_sample_rate (nframes_t ignored)
906 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
908 if (!engine->connected()) {
910 snprintf (buf, sizeof (buf), _("disconnected"));
914 nframes_t rate = engine->frame_rate();
916 if (fmod (rate, 1000.0) != 0.0) {
917 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
918 (float) rate/1000.0f,
919 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
921 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
923 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
927 sample_rate_label.set_text (buf);
931 ARDOUR_UI::update_cpu_load ()
934 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
935 cpu_load_label.set_text (buf);
939 ARDOUR_UI::update_buffer_load ()
945 c = session->capture_load ();
946 p = session->playback_load ();
948 push_buffer_stats (c, p);
950 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
951 session->playback_load(), session->capture_load());
952 buffer_load_label.set_text (buf);
954 buffer_load_label.set_text ("");
959 ARDOUR_UI::count_recenabled_streams (Route& route)
961 Track* track = dynamic_cast<Track*>(&route);
962 if (track && track->diskstream()->record_enabled()) {
963 rec_enabled_streams += track->n_inputs().n_total();
968 ARDOUR_UI::update_disk_space()
974 nframes_t frames = session->available_capture_duration();
976 nframes_t fr = session->frame_rate();
978 if (frames == max_frames) {
979 strcpy (buf, _("Disk: 24hrs+"));
981 rec_enabled_streams = 0;
982 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
984 if (rec_enabled_streams) {
985 frames /= rec_enabled_streams;
992 hrs = frames / (fr * 3600);
993 frames -= hrs * fr * 3600;
994 mins = frames / (fr * 60);
995 frames -= mins * fr * 60;
998 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1001 disk_space_label.set_text (buf);
1003 // An attempt to make the disk space label flash red when space has run out.
1005 if (frames < fr * 60 * 5) {
1006 /* disk_space_box.style ("disk_space_label_empty"); */
1008 /* disk_space_box.style ("disk_space_label"); */
1014 ARDOUR_UI::update_wall_clock ()
1021 tm_now = localtime (&now);
1023 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1024 wall_clock_label.set_text (buf);
1030 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1032 session_popup_menu->popup (0, 0);
1037 ARDOUR_UI::redisplay_recent_sessions ()
1039 std::vector<sys::path> session_directories;
1040 RecentSessionsSorter cmp;
1042 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1043 recent_session_model->clear ();
1045 ARDOUR::RecentSessions rs;
1046 ARDOUR::read_recent_sessions (rs);
1049 recent_session_display.set_model (recent_session_model);
1053 // sort them alphabetically
1054 sort (rs.begin(), rs.end(), cmp);
1056 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1057 session_directories.push_back ((*i).second);
1060 for (vector<sys::path>::const_iterator i = session_directories.begin();
1061 i != session_directories.end(); ++i)
1063 std::vector<sys::path> state_file_paths;
1065 // now get available states for this session
1067 get_state_files_in_directory (*i, state_file_paths);
1069 vector<string*>* states;
1070 vector<const gchar*> item;
1071 string fullpath = (*i).to_string();
1073 /* remove any trailing / */
1075 if (fullpath[fullpath.length()-1] == '/') {
1076 fullpath = fullpath.substr (0, fullpath.length()-1);
1079 /* check whether session still exists */
1080 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1081 /* session doesn't exist */
1082 cerr << "skipping non-existent session " << fullpath << endl;
1086 /* now get available states for this session */
1088 if ((states = Session::possible_states (fullpath)) == 0) {
1089 /* no state file? */
1093 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1095 Gtk::TreeModel::Row row = *(recent_session_model->append());
1097 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1098 row[recent_session_columns.fullpath] = fullpath;
1100 if (state_file_names.size() > 1) {
1104 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1105 i2 != state_file_names.end(); ++i2)
1108 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1110 child_row[recent_session_columns.visible_name] = *i2;
1111 child_row[recent_session_columns.fullpath] = fullpath;
1116 recent_session_display.set_model (recent_session_model);
1120 ARDOUR_UI::build_session_selector ()
1122 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1124 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1126 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1127 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1128 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1129 recent_session_model = TreeStore::create (recent_session_columns);
1130 recent_session_display.set_model (recent_session_model);
1131 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1132 recent_session_display.set_headers_visible (false);
1133 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1134 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1136 scroller->add (recent_session_display);
1137 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1139 session_selector_window->set_name ("SessionSelectorWindow");
1140 session_selector_window->set_size_request (200, 400);
1141 session_selector_window->get_vbox()->pack_start (*scroller);
1143 recent_session_display.show();
1145 //session_selector_window->get_vbox()->show();
1149 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1151 session_selector_window->response (RESPONSE_ACCEPT);
1155 ARDOUR_UI::open_recent_session ()
1157 bool can_return = (session != 0);
1159 if (session_selector_window == 0) {
1160 build_session_selector ();
1163 redisplay_recent_sessions ();
1167 session_selector_window->set_position (WIN_POS_MOUSE);
1169 ResponseType r = (ResponseType) session_selector_window->run ();
1172 case RESPONSE_ACCEPT:
1176 session_selector_window->hide();
1183 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1187 session_selector_window->hide();
1189 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1191 if (i == recent_session_model->children().end()) {
1195 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1196 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1198 _session_is_new = false;
1200 if (load_session (path, state) == 0) {
1209 ARDOUR_UI::check_audioengine ()
1212 if (!engine->connected()) {
1213 MessageDialog msg (_("Ardour is not connected to JACK\n"
1214 "You cannot open or close sessions in this condition"));
1226 ARDOUR_UI::open_session ()
1228 if (!check_audioengine()) {
1233 /* popup selector window */
1235 if (open_session_selector == 0) {
1237 /* ardour sessions are folders */
1239 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1240 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1241 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1242 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1244 FileFilter session_filter;
1245 session_filter.add_pattern ("*.ardour");
1246 session_filter.set_name (_("Ardour sessions"));
1247 open_session_selector->add_filter (session_filter);
1248 open_session_selector->set_filter (session_filter);
1251 int response = open_session_selector->run();
1252 open_session_selector->hide ();
1255 case RESPONSE_ACCEPT:
1258 open_session_selector->hide();
1262 open_session_selector->hide();
1263 string session_path = open_session_selector->get_filename();
1267 if (session_path.length() > 0) {
1268 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1269 _session_is_new = isnew;
1270 load_session (path, name);
1277 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1279 list<boost::shared_ptr<MidiTrack> > tracks;
1282 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1289 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1291 if (tracks.size() != how_many) {
1292 if (how_many == 1) {
1293 error << _("could not create a new midi track") << endmsg;
1295 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1299 if ((route = session->new_midi_route ()) == 0) {
1300 error << _("could not create new midi bus") << endmsg;
1306 MessageDialog msg (*editor,
1307 _("There are insufficient JACK ports available\n\
1308 to create a new track or bus.\n\
1309 You should save Ardour, exit and\n\
1310 restart JACK with more ports."));
1317 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)
1319 list<boost::shared_ptr<AudioTrack> > tracks;
1323 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1329 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1331 if (tracks.size() != how_many) {
1332 if (how_many == 1) {
1333 error << _("could not create a new audio track") << endmsg;
1335 error << string_compose (_("could only create %1 of %2 new audio %3"),
1336 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1342 routes = session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1344 if (routes.size() != how_many) {
1345 if (how_many == 1) {
1346 error << _("could not create a new audio track") << endmsg;
1348 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1354 if (need_control_room_outs) {
1360 route->set_stereo_control_outs (control_lr_channels);
1361 route->control_outs()->set_stereo_pan (pans, this);
1363 #endif /* CONTROLOUTS */
1367 MessageDialog msg (*editor,
1368 _("There are insufficient JACK ports available\n\
1369 to create a new track or bus.\n\
1370 You should save Ardour, exit and\n\
1371 restart JACK with more ports."));
1378 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1380 nframes_t _preroll = 0;
1383 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1384 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1386 if (new_position > _preroll) {
1387 new_position -= _preroll;
1392 session->request_locate (new_position);
1397 ARDOUR_UI::transport_goto_start ()
1400 session->goto_start();
1402 /* force displayed area in editor to start no matter
1403 what "follow playhead" setting is.
1407 editor->center_screen (session->current_start_frame ());
1413 ARDOUR_UI::transport_goto_zero ()
1416 session->request_locate (0);
1419 /* force displayed area in editor to start no matter
1420 what "follow playhead" setting is.
1424 editor->reset_x_origin (0);
1430 ARDOUR_UI::transport_goto_wallclock ()
1432 if (session && editor) {
1439 localtime_r (&now, &tmnow);
1441 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1442 frames += tmnow.tm_min * (60 * session->frame_rate());
1443 frames += tmnow.tm_sec * session->frame_rate();
1445 session->request_locate (frames);
1447 /* force displayed area in editor to start no matter
1448 what "follow playhead" setting is.
1452 editor->center_screen (frames);
1458 ARDOUR_UI::transport_goto_end ()
1461 nframes_t const frame = session->current_end_frame();
1462 session->request_locate (frame);
1464 /* force displayed area in editor to start no matter
1465 what "follow playhead" setting is.
1469 editor->center_screen (frame);
1475 ARDOUR_UI::transport_stop ()
1481 if (session->is_auditioning()) {
1482 session->cancel_audition ();
1486 session->request_stop ();
1490 ARDOUR_UI::transport_stop_and_forget_capture ()
1493 session->request_stop (true);
1498 ARDOUR_UI::remove_last_capture()
1501 editor->remove_last_capture();
1506 ARDOUR_UI::transport_record (bool roll)
1510 switch (session->record_status()) {
1511 case Session::Disabled:
1512 if (session->ntracks() == 0) {
1513 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1517 session->maybe_enable_record ();
1522 case Session::Recording:
1524 session->request_stop();
1526 session->disable_record (false, true);
1530 case Session::Enabled:
1531 session->disable_record (false, true);
1534 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1538 ARDOUR_UI::transport_roll ()
1544 if (session->is_auditioning()) {
1548 if (session->config.get_external_sync()) {
1549 switch (session->config.get_sync_source()) {
1553 /* transport controlled by the master */
1558 bool rolling = session->transport_rolling();
1560 if (session->get_play_loop()) {
1561 session->request_play_loop (false, true);
1562 } else if (session->get_play_range ()) {
1563 session->request_play_range (false, true);
1567 session->request_transport_speed (1.0f);
1570 map_transport_state ();
1574 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1581 if (session->is_auditioning()) {
1582 session->cancel_audition ();
1586 if (session->config.get_external_sync()) {
1587 switch (session->config.get_sync_source()) {
1591 /* transport controlled by the master */
1596 bool rolling = session->transport_rolling();
1597 bool affect_transport = true;
1599 if (rolling && roll_out_of_bounded_mode) {
1600 /* drop out of loop/range playback but leave transport rolling */
1601 if (session->get_play_loop()) {
1602 if (Config->get_seamless_loop()) {
1603 /* the disk buffers contain copies of the loop - we can't
1604 just keep playing, so stop the transport. the user
1605 can restart as they wish.
1607 affect_transport = true;
1609 /* disk buffers are normal, so we can keep playing */
1610 affect_transport = false;
1612 session->request_play_loop (false, true);
1613 } else if (session->get_play_range ()) {
1614 affect_transport = false;
1615 session->request_play_range (0, true);
1619 if (affect_transport) {
1621 session->request_stop (with_abort, true);
1623 session->request_transport_speed (1.0f);
1627 map_transport_state ();
1631 ARDOUR_UI::toggle_session_auto_loop ()
1634 if (session->get_play_loop()) {
1635 if (session->transport_rolling()) {
1636 Location * looploc = session->locations()->auto_loop_location();
1638 session->request_locate (looploc->start(), true);
1641 session->request_play_loop (false);
1644 Location * looploc = session->locations()->auto_loop_location();
1646 session->request_play_loop (true);
1653 ARDOUR_UI::transport_play_selection ()
1659 editor->play_selection ();
1663 ARDOUR_UI::transport_rewind (int option)
1665 float current_transport_speed;
1668 current_transport_speed = session->transport_speed();
1670 if (current_transport_speed >= 0.0f) {
1673 session->request_transport_speed (-1.0f);
1676 session->request_transport_speed (-4.0f);
1679 session->request_transport_speed (-0.5f);
1684 session->request_transport_speed (current_transport_speed * 1.5f);
1690 ARDOUR_UI::transport_forward (int option)
1692 float current_transport_speed;
1695 current_transport_speed = session->transport_speed();
1697 if (current_transport_speed <= 0.0f) {
1700 session->request_transport_speed (1.0f);
1703 session->request_transport_speed (4.0f);
1706 session->request_transport_speed (0.5f);
1711 session->request_transport_speed (current_transport_speed * 1.5f);
1718 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1724 boost::shared_ptr<Route> r;
1726 if ((r = session->route_by_remote_id (dstream)) != 0) {
1730 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1731 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1740 ARDOUR_UI::map_transport_state ()
1742 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1745 auto_loop_button.set_visual_state (0);
1746 play_selection_button.set_visual_state (0);
1747 roll_button.set_visual_state (0);
1748 stop_button.set_visual_state (1);
1752 float sp = session->transport_speed();
1755 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1756 shuttle_box.queue_draw ();
1757 } else if (sp == 0.0f) {
1759 shuttle_box.queue_draw ();
1760 update_disk_space ();
1765 if (session->get_play_range()) {
1767 play_selection_button.set_visual_state (1);
1768 roll_button.set_visual_state (0);
1769 auto_loop_button.set_visual_state (0);
1771 } else if (session->get_play_loop ()) {
1773 auto_loop_button.set_visual_state (1);
1774 play_selection_button.set_visual_state (0);
1775 roll_button.set_visual_state (0);
1779 roll_button.set_visual_state (1);
1780 play_selection_button.set_visual_state (0);
1781 auto_loop_button.set_visual_state (0);
1784 stop_button.set_visual_state (0);
1788 stop_button.set_visual_state (1);
1789 roll_button.set_visual_state (0);
1790 play_selection_button.set_visual_state (0);
1791 auto_loop_button.set_visual_state (0);
1797 ARDOUR_UI::engine_stopped ()
1799 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1800 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1801 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1805 ARDOUR_UI::engine_running ()
1807 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1808 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1809 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1811 Glib::RefPtr<Action> action;
1812 const char* action_name = 0;
1814 switch (engine->frames_per_cycle()) {
1816 action_name = X_("JACKLatency32");
1819 action_name = X_("JACKLatency64");
1822 action_name = X_("JACKLatency128");
1825 action_name = X_("JACKLatency512");
1828 action_name = X_("JACKLatency1024");
1831 action_name = X_("JACKLatency2048");
1834 action_name = X_("JACKLatency4096");
1837 action_name = X_("JACKLatency8192");
1840 /* XXX can we do anything useful ? */
1846 action = ActionManager::get_action (X_("JACK"), action_name);
1849 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1850 ract->set_active ();
1856 ARDOUR_UI::engine_halted ()
1858 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
1860 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1861 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1863 update_sample_rate (0);
1865 MessageDialog msg (*editor,
1867 JACK has either been shutdown or it\n\
1868 disconnected Ardour because Ardour\n\
1869 was not fast enough. Try to restart\n\
1870 JACK, reconnect and save the session."));
1876 ARDOUR_UI::do_engine_start ()
1884 error << _("Unable to start the session running")
1894 ARDOUR_UI::setup_theme ()
1896 theme_manager->setup_theme();
1900 ARDOUR_UI::update_clocks ()
1902 if (!editor || !editor->dragging_playhead()) {
1903 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1908 ARDOUR_UI::start_clocking ()
1910 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1914 ARDOUR_UI::stop_clocking ()
1916 clock_signal_connection.disconnect ();
1920 ARDOUR_UI::toggle_clocking ()
1923 if (clock_button.get_active()) {
1932 ARDOUR_UI::_blink (void *arg)
1935 ((ARDOUR_UI *) arg)->blink ();
1942 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1946 ARDOUR_UI::start_blinking ()
1948 /* Start the blink signal. Everybody with a blinking widget
1949 uses Blink to drive the widget's state.
1952 if (blink_timeout_tag < 0) {
1954 blink_timeout_tag = g_timeout_add (240, _blink, this);
1959 ARDOUR_UI::stop_blinking ()
1961 if (blink_timeout_tag >= 0) {
1962 g_source_remove (blink_timeout_tag);
1963 blink_timeout_tag = -1;
1968 /** Ask the user for the name of a new shapshot and then take it.
1971 ARDOUR_UI::snapshot_session ()
1973 ArdourPrompter prompter (true);
1977 struct tm local_time;
1980 localtime_r (&n, &local_time);
1981 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1983 prompter.set_name ("Prompter");
1984 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1985 prompter.set_title (_("Take Snapshot"));
1986 prompter.set_prompt (_("Name of New Snapshot"));
1987 prompter.set_initial_text (timebuf);
1989 switch (prompter.run()) {
1990 case RESPONSE_ACCEPT:
1992 prompter.get_result (snapname);
1994 bool do_save = (snapname.length() != 0);
1996 vector<sys::path> p;
1997 get_state_files_in_directory (session->session_directory().root_path(), p);
1998 vector<string> n = get_file_names_no_extension (p);
1999 if (find (n.begin(), n.end(), snapname) != n.end()) {
2001 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
2002 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2003 confirm.get_vbox()->pack_start (m, true, true);
2004 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2005 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2006 confirm.show_all ();
2007 switch (confirm.run()) {
2008 case RESPONSE_CANCEL:
2014 save_state (snapname);
2025 ARDOUR_UI::save_state (const string & name)
2027 (void) save_state_canfail (name);
2031 ARDOUR_UI::save_state_canfail (string name)
2036 if (name.length() == 0) {
2037 name = session->snap_name();
2040 if ((ret = session->save_state (name)) != 0) {
2044 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2049 ARDOUR_UI::primary_clock_value_changed ()
2052 session->request_locate (primary_clock.current_time ());
2057 ARDOUR_UI::big_clock_value_changed ()
2060 session->request_locate (big_clock.current_time ());
2065 ARDOUR_UI::secondary_clock_value_changed ()
2068 session->request_locate (secondary_clock.current_time ());
2073 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2079 Session::RecordState const r = session->record_status ();
2080 bool const h = session->have_rec_enabled_diskstream ();
2082 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2084 rec_button.set_visual_state (2);
2086 rec_button.set_visual_state (0);
2088 } else if (r == Session::Recording && h) {
2089 rec_button.set_visual_state (1);
2091 rec_button.set_visual_state (0);
2096 ARDOUR_UI::save_template ()
2098 ArdourPrompter prompter (true);
2101 if (!check_audioengine()) {
2105 prompter.set_name (X_("Prompter"));
2106 prompter.set_title (_("Save Mix Template"));
2107 prompter.set_prompt (_("Name for mix template:"));
2108 prompter.set_initial_text(session->name() + _("-template"));
2109 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2111 switch (prompter.run()) {
2112 case RESPONSE_ACCEPT:
2113 prompter.get_result (name);
2115 if (name.length()) {
2116 session->save_template (name);
2126 ARDOUR_UI::edit_metadata ()
2128 SessionMetadataEditor dialog;
2129 dialog.set_session (session);
2130 editor->ensure_float (dialog);
2135 ARDOUR_UI::import_metadata ()
2137 SessionMetadataImporter dialog;
2138 dialog.set_session (session);
2139 editor->ensure_float (dialog);
2144 ARDOUR_UI::fontconfig_dialog ()
2147 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2148 may not and it can take a while to build it. Warn them.
2151 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2153 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2154 MessageDialog msg (*_startup,
2155 _("Welcome to Ardour.\n\n"
2156 "The program will take a bit longer to start up\n"
2157 "while the system fonts are checked.\n\n"
2158 "This will only be done once, and you will\n"
2159 "not see this message again\n"),
2172 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2174 existing_session = false;
2176 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2177 session_path = cmdline_path;
2178 existing_session = true;
2179 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2180 session_path = Glib::path_get_dirname (string (cmdline_path));
2181 existing_session = true;
2183 /* it doesn't exist, assume the best */
2184 session_path = Glib::path_get_dirname (string (cmdline_path));
2187 session_name = basename_nosuffix (string (cmdline_path));
2191 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2193 /* when this is called, the backend audio system must be running */
2195 /* the main idea here is to deal with the fact that a cmdline argument for the session
2196 can be interpreted in different ways - it could be a directory or a file, and before
2197 we load, we need to know both the session directory and the snapshot (statefile) within it
2198 that we are supposed to use.
2201 if (session_name.length() == 0 || session_path.length() == 0) {
2205 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2207 Glib::ustring predicted_session_file;
2209 predicted_session_file = session_path;
2210 predicted_session_file += '/';
2211 predicted_session_file += session_name;
2212 predicted_session_file += ARDOUR::statefile_suffix;
2214 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2215 existing_session = true;
2218 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2220 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2221 /* existing .ardour file */
2222 existing_session = true;
2226 existing_session = false;
2229 /* lets just try to load it */
2231 if (create_engine ()) {
2232 backend_audio_error (false, _startup);
2236 return load_session (session_path, session_name);
2240 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2242 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2244 MessageDialog msg (str,
2246 Gtk::MESSAGE_WARNING,
2247 Gtk::BUTTONS_YES_NO,
2251 msg.set_name (X_("OpenExistingDialog"));
2252 msg.set_title (_("Open Existing Session"));
2253 msg.set_wmclass (X_("existing_session"), "Ardour");
2254 msg.set_position (Gtk::WIN_POS_MOUSE);
2257 switch (msg.run()) {
2266 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2271 AutoConnectOption iconnect;
2272 AutoConnectOption oconnect;
2276 if (Profile->get_sae()) {
2280 iconnect = AutoConnectPhysical;
2281 oconnect = AutoConnectMaster;
2282 nphysin = 0; // use all available
2283 nphysout = 0; // use all available
2287 /* get settings from advanced section of NSD */
2289 if (_startup->create_control_bus()) {
2290 cchns = (uint32_t) _startup->control_channel_count();
2295 if (_startup->create_master_bus()) {
2296 mchns = (uint32_t) _startup->master_channel_count();
2301 if (_startup->connect_inputs()) {
2302 iconnect = AutoConnectPhysical;
2304 iconnect = AutoConnectOption (0);
2307 /// @todo some minor tweaks.
2309 oconnect = AutoConnectOption (0);
2311 if (_startup->connect_outputs ()) {
2312 if (_startup->connect_outs_to_master()) {
2313 oconnect = AutoConnectMaster;
2314 } else if (_startup->connect_outs_to_physical()) {
2315 oconnect = AutoConnectPhysical;
2319 nphysin = (uint32_t) _startup->input_limit_count();
2320 nphysout = (uint32_t) _startup->output_limit_count();
2323 if (build_session (session_path,
2331 engine->frame_rate() * 60 * 5)) {
2340 ARDOUR_UI::idle_load (const Glib::ustring& path)
2343 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2344 /* /path/to/foo => /path/to/foo, foo */
2345 load_session (path, basename_nosuffix (path));
2347 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2348 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2352 ARDOUR_COMMAND_LINE::session_name = path;
2355 * new_session_dialog doens't exist in A3
2356 * Try to remove all references to it to
2357 * see if it will compile. NOTE: this will
2358 * likely cause a runtime issue is my somewhat
2362 //if (new_session_dialog) {
2365 /* make it break out of Dialog::run() and
2369 //new_session_dialog->response (1);
2375 ARDOUR_UI::end_loading_messages ()
2381 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2384 // splash->message (msg);
2388 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2390 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2392 Glib::ustring session_name;
2393 Glib::ustring session_path;
2394 Glib::ustring template_name;
2396 bool likely_new = false;
2400 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2402 /* if they named a specific statefile, use it, otherwise they are
2403 just giving a session folder, and we want to use it as is
2404 to find the session.
2407 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2408 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2410 session_path = ARDOUR_COMMAND_LINE::session_name;
2413 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2417 bool const apply = run_startup (should_be_new);
2419 if (quit_on_cancel) {
2426 /* if we run the startup dialog again, offer more than just "new session" */
2428 should_be_new = false;
2430 session_name = _startup->session_name (likely_new);
2432 /* this shouldn't happen, but we catch it just in case it does */
2434 if (session_name.empty()) {
2437 if (_startup->use_session_template()) {
2438 template_name = _startup->session_template_name();
2439 _session_is_new = true;
2442 if (session_name[0] == '/' ||
2443 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2444 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2446 session_path = Glib::path_get_dirname (session_name);
2447 session_name = Glib::path_get_basename (session_name);
2451 session_path = _startup->session_folder();
2455 if (create_engine ()) {
2459 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2463 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2465 if (!ask_about_loading_existing_session (existing)) {
2466 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2471 _session_is_new = false;
2476 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2478 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2482 _session_is_new = true;
2485 if (likely_new && template_name.empty()) {
2487 ret = build_session_from_nsd (session_path, session_name);
2491 ret = load_session (session_path, session_name, template_name);
2492 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2493 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2503 ARDOUR_UI::close_session()
2505 if (!check_audioengine()) {
2509 unload_session (true);
2511 ARDOUR_COMMAND_LINE::session_name = "";
2512 get_session_parameters (true, false);
2516 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2518 Session *new_session;
2522 session_loaded = false;
2524 if (!check_audioengine()) {
2528 unload_status = unload_session ();
2530 if (unload_status < 0) {
2532 } else if (unload_status > 0) {
2537 loading_message (_("Please wait while Ardour loads your session"));
2540 new_session = new Session (*engine, path, snap_name, mix_template);
2543 /* this one is special */
2545 catch (AudioEngine::PortRegistrationFailure& err) {
2547 MessageDialog msg (err.what(),
2550 Gtk::BUTTONS_CLOSE);
2552 msg.set_title (_("Port Registration Error"));
2553 msg.set_secondary_text (_("Click the Close button to try again."));
2554 msg.set_position (Gtk::WIN_POS_CENTER);
2558 int response = msg.run ();
2563 case RESPONSE_CANCEL:
2573 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2576 Gtk::BUTTONS_CLOSE);
2578 msg.set_title (_("Loading Error"));
2579 msg.set_secondary_text (_("Click the Close button to try again."));
2580 msg.set_position (Gtk::WIN_POS_CENTER);
2584 int response = msg.run ();
2589 case RESPONSE_CANCEL:
2597 connect_to_session (new_session);
2599 session_loaded = true;
2601 goto_editor_window ();
2604 session->set_clean ();
2615 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2616 uint32_t control_channels,
2617 uint32_t master_channels,
2618 AutoConnectOption input_connect,
2619 AutoConnectOption output_connect,
2622 nframes_t initial_length)
2624 Session *new_session;
2627 if (!check_audioengine()) {
2631 session_loaded = false;
2633 x = unload_session ();
2641 _session_is_new = true;
2644 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2645 control_channels, master_channels, nphysin, nphysout, initial_length);
2650 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2656 connect_to_session (new_session);
2658 session_loaded = true;
2660 new_session->save_state(new_session->name());
2669 editor->show_window ();
2680 ARDOUR_UI::show_about ()
2684 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2691 ARDOUR_UI::hide_about ()
2694 about->get_window()->set_cursor ();
2700 ARDOUR_UI::about_signal_response (int /*response*/)
2706 ARDOUR_UI::show_splash ()
2710 splash = new Splash;
2718 splash->queue_draw ();
2719 splash->get_window()->process_updates (true);
2724 ARDOUR_UI::hide_splash ()
2732 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2733 const string& plural_msg, const string& singular_msg)
2737 removed = rep.paths.size();
2740 MessageDialog msgd (*editor,
2741 _("No audio files were ready for cleanup"),
2744 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2745 msgd.set_secondary_text (_("If this seems suprising, \n\
2746 check for any existing snapshots.\n\
2747 These may still include regions that\n\
2748 require some unused files to continue to exist."));
2754 ArdourDialog results (_("ardour: cleanup"), true, false);
2756 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2757 CleanupResultsModelColumns() {
2761 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2762 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2766 CleanupResultsModelColumns results_columns;
2767 Glib::RefPtr<Gtk::ListStore> results_model;
2768 Gtk::TreeView results_display;
2770 results_model = ListStore::create (results_columns);
2771 results_display.set_model (results_model);
2772 results_display.append_column (list_title, results_columns.visible_name);
2774 results_display.set_name ("CleanupResultsList");
2775 results_display.set_headers_visible (true);
2776 results_display.set_headers_clickable (false);
2777 results_display.set_reorderable (false);
2779 Gtk::ScrolledWindow list_scroller;
2782 Gtk::HBox dhbox; // the hbox for the image and text
2783 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2784 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2786 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2788 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2794 %1 - number of files removed
2795 %2 - location of "dead_sounds"
2796 %3 - size of files affected
2797 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2800 const char* bprefix;
2802 if (rep.space < 1048576.0f) {
2803 bprefix = X_("kilo");
2804 } else if (rep.space < 1048576.0f * 1000) {
2805 bprefix = X_("mega");
2807 bprefix = X_("giga");
2811 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2813 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2816 dhbox.pack_start (*dimage, true, false, 5);
2817 dhbox.pack_start (txt, true, false, 5);
2819 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2820 TreeModel::Row row = *(results_model->append());
2821 row[results_columns.visible_name] = *i;
2822 row[results_columns.fullpath] = *i;
2825 list_scroller.add (results_display);
2826 list_scroller.set_size_request (-1, 150);
2827 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2829 dvbox.pack_start (dhbox, true, false, 5);
2830 dvbox.pack_start (list_scroller, true, false, 5);
2831 ddhbox.pack_start (dvbox, true, false, 5);
2833 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2834 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2835 results.set_default_response (RESPONSE_CLOSE);
2836 results.set_position (Gtk::WIN_POS_MOUSE);
2838 results_display.show();
2839 list_scroller.show();
2846 //results.get_vbox()->show();
2847 results.set_resizable (false);
2854 ARDOUR_UI::cleanup ()
2857 /* shouldn't happen: menu item is insensitive */
2862 MessageDialog checker (_("Are you sure you want to cleanup?"),
2864 Gtk::MESSAGE_QUESTION,
2865 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2867 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2868 ALL undo/redo information will be lost if you cleanup.\n\
2869 After cleanup, unused audio files will be moved to a \
2870 \"dead sounds\" location."));
2872 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2873 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2874 checker.set_default_response (RESPONSE_CANCEL);
2876 checker.set_name (_("CleanupDialog"));
2877 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2878 checker.set_position (Gtk::WIN_POS_MOUSE);
2880 switch (checker.run()) {
2881 case RESPONSE_ACCEPT:
2887 ARDOUR::CleanupReport rep;
2889 editor->prepare_for_cleanup ();
2891 /* do not allow flush until a session is reloaded */
2893 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2895 act->set_sensitive (false);
2898 if (session->cleanup_sources (rep)) {
2899 editor->finish_cleanup ();
2903 editor->finish_cleanup ();
2906 display_cleanup_results (rep,
2909 The following %1 files were not in use and \n\
2910 have been moved to:\n\
2912 Flushing the wastebasket will \n\
2913 release an additional\n\
2914 %3 %4bytes of disk space.\n"),
2916 The following file was not in use and \n \
2917 has been moved to:\n \
2919 Flushing the wastebasket will \n\
2920 release an additional\n\
2921 %3 %4bytes of disk space.\n"
2927 ARDOUR_UI::flush_trash ()
2930 /* shouldn't happen: menu item is insensitive */
2934 ARDOUR::CleanupReport rep;
2936 if (session->cleanup_trash_sources (rep)) {
2940 display_cleanup_results (rep,
2942 _("The following %1 files were deleted from\n\
2944 releasing %3 %4bytes of disk space"),
2945 _("The following file was deleted from\n\
2947 releasing %3 %4bytes of disk space"));
2951 ARDOUR_UI::add_route (Gtk::Window* float_window)
2959 if (add_route_dialog == 0) {
2960 add_route_dialog = new AddRouteDialog (*session);
2962 add_route_dialog->set_transient_for (*float_window);
2966 if (add_route_dialog->is_visible()) {
2967 /* we're already doing this */
2971 ResponseType r = (ResponseType) add_route_dialog->run ();
2973 add_route_dialog->hide();
2976 case RESPONSE_ACCEPT:
2983 if ((count = add_route_dialog->count()) <= 0) {
2987 string template_path = add_route_dialog->track_template();
2989 if (!template_path.empty()) {
2990 session->new_route_from_template (count, template_path);
2994 uint32_t input_chan = add_route_dialog->channels ();
2995 uint32_t output_chan;
2996 string name_template = add_route_dialog->name_template ();
2997 bool track = add_route_dialog->track ();
2998 bool aux = !track && add_route_dialog->aux();
2999 RouteGroup* route_group = add_route_dialog->route_group ();
3001 AutoConnectOption oac = Config->get_output_auto_connect();
3003 if (oac & AutoConnectMaster) {
3004 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
3006 output_chan = input_chan;
3009 /* XXX do something with name template */
3011 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3013 session_add_midi_track (route_group, count);
3015 MessageDialog msg (*editor,
3016 _("Sorry, MIDI Busses are not supported at this time."));
3018 //session_add_midi_bus();
3022 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3024 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3030 ARDOUR_UI::mixer_settings () const
3035 node = session->instant_xml(X_("Mixer"));
3037 node = Config->instant_xml(X_("Mixer"));
3041 node = new XMLNode (X_("Mixer"));
3048 ARDOUR_UI::editor_settings () const
3053 node = session->instant_xml(X_("Editor"));
3055 node = Config->instant_xml(X_("Editor"));
3059 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3060 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3065 node = new XMLNode (X_("Editor"));
3072 ARDOUR_UI::keyboard_settings () const
3076 node = Config->extra_xml(X_("Keyboard"));
3079 node = new XMLNode (X_("Keyboard"));
3085 ARDOUR_UI::create_xrun_marker(nframes_t where)
3087 editor->mouse_add_new_marker (where, false, true);
3091 ARDOUR_UI::halt_on_xrun_message ()
3093 MessageDialog msg (*editor,
3094 _("Recording was stopped because your system could not keep up."));
3099 ARDOUR_UI::xrun_handler(nframes_t where)
3105 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3107 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3108 create_xrun_marker(where);
3111 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3112 halt_on_xrun_message ();
3117 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3122 while (disk_buffer_stats.size() > 60) {
3123 disk_buffer_stats.pop_front ();
3126 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3130 ARDOUR_UI::write_buffer_stats ()
3136 char path[PATH_MAX+1]; int fd;
3138 strcpy (path, "ardourBufferingXXXXXX");
3140 if ((fd = mkstemp (path )) < 0) {
3141 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3149 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3153 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3154 localtime_r (&(*i).when, &tm);
3155 strftime (buf, sizeof (buf), "%T", &tm);
3156 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3159 disk_buffer_stats.clear ();
3163 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3167 ARDOUR_UI::disk_overrun_handler ()
3169 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3171 write_buffer_stats ();
3173 if (!have_disk_speed_dialog_displayed) {
3174 have_disk_speed_dialog_displayed = true;
3175 MessageDialog* msg = new MessageDialog (*editor, _("\
3176 The disk system on your computer\n\
3177 was not able to keep up with Ardour.\n\
3179 Specifically, it failed to write data to disk\n\
3180 quickly enough to keep up with recording.\n"));
3181 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3187 ARDOUR_UI::disk_underrun_handler ()
3189 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3191 write_buffer_stats ();
3193 if (!have_disk_speed_dialog_displayed) {
3194 have_disk_speed_dialog_displayed = true;
3195 MessageDialog* msg = new MessageDialog (*editor,
3196 _("The disk system on your computer\n\
3197 was not able to keep up with Ardour.\n\
3199 Specifically, it failed to read data from disk\n\
3200 quickly enough to keep up with playback.\n"));
3201 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3207 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3209 have_disk_speed_dialog_displayed = false;
3214 ARDOUR_UI::session_dialog (std::string msg)
3216 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3221 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3223 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3232 ARDOUR_UI::pending_state_dialog ()
3234 HBox* hbox = new HBox();
3235 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3236 ArdourDialog dialog (_("Crash Recovery"), true);
3238 This session appears to have been in\n\
3239 middle of recording when ardour or\n\
3240 the computer was shutdown.\n\
3242 Ardour can recover any captured audio for\n\
3243 you, or it can ignore it. Please decide\n\
3244 what you would like to do.\n"));
3245 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3246 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3247 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3248 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3249 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3250 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3251 dialog.set_default_response (RESPONSE_ACCEPT);
3252 dialog.set_position (WIN_POS_CENTER);
3257 switch (dialog.run ()) {
3258 case RESPONSE_ACCEPT:
3266 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3268 HBox* hbox = new HBox();
3269 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3270 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3271 Label message (string_compose (_("\
3272 This session was created with a sample rate of %1 Hz\n\
3274 The audioengine is currently running at %2 Hz\n"), desired, actual));
3276 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3277 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3278 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3279 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3280 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3281 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3282 dialog.set_default_response (RESPONSE_ACCEPT);
3283 dialog.set_position (WIN_POS_CENTER);
3288 switch (dialog.run ()) {
3289 case RESPONSE_ACCEPT:
3298 ARDOUR_UI::disconnect_from_jack ()
3301 if( engine->disconnect_from_jack ()) {
3302 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3306 update_sample_rate (0);
3311 ARDOUR_UI::reconnect_to_jack ()
3314 if (engine->reconnect_to_jack ()) {
3315 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3319 update_sample_rate (0);
3324 ARDOUR_UI::use_config ()
3327 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3329 set_transport_controllable_state (*node);
3334 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3336 if (Config->get_primary_clock_delta_edit_cursor()) {
3337 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3339 primary_clock.set (pos, 0, true);
3342 if (Config->get_secondary_clock_delta_edit_cursor()) {
3343 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3345 secondary_clock.set (pos);
3348 if (big_clock_window) {
3349 big_clock.set (pos);
3354 ARDOUR_UI::record_state_changed ()
3356 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed)
3358 if (!session || !big_clock_window) {
3359 /* why bother - the clock isn't visible */
3363 Session::RecordState const r = session->record_status ();
3364 bool const h = session->have_rec_enabled_diskstream ();
3366 if (r == Session::Recording && h) {
3367 big_clock.set_widget_name ("BigClockRecording");
3369 big_clock.set_widget_name ("BigClockNonRecording");
3374 ARDOUR_UI::first_idle ()
3377 session->allow_auto_play (true);
3381 editor->first_idle();
3384 Keyboard::set_can_save_keybindings (true);
3389 ARDOUR_UI::store_clock_modes ()
3391 XMLNode* node = new XMLNode(X_("ClockModes"));
3393 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3394 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3397 session->add_extra_xml (*node);
3398 session->set_dirty ();
3403 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3404 : Controllable (name, string() /* missing URI */), ui (u), type(tp)
3410 ARDOUR_UI::TransportControllable::set_value (float val)
3412 if (type == ShuttleControl) {
3419 fract = -((0.5f - val)/0.5f);
3421 fract = ((val - 0.5f)/0.5f);
3425 ui.set_shuttle_fract (fract);
3430 /* do nothing: these are radio-style actions */
3434 const char *action = 0;
3438 action = X_("Roll");
3441 action = X_("Stop");
3444 action = X_("Goto Start");
3447 action = X_("Goto End");
3450 action = X_("Loop");
3453 action = X_("Play Selection");
3456 action = X_("Record");
3466 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3474 ARDOUR_UI::TransportControllable::get_value (void) const
3493 case ShuttleControl:
3503 ARDOUR_UI::TransportControllable::set_id (const string& str)
3509 ARDOUR_UI::setup_profile ()
3511 if (gdk_screen_width() < 1200) {
3512 Profile->set_small_screen ();
3516 if (getenv ("ARDOUR_SAE")) {
3517 Profile->set_sae ();
3518 Profile->set_single_package ();