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();
198 _session_is_new = false;
199 big_clock_window = 0;
200 big_clock_height = 0;
201 big_clock_resize_in_progress = false;
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 (forever_connections, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
240 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
242 /* handle dialog requests */
244 ARDOUR::Session::Dialog.connect (forever_connections, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
246 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
248 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
250 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
252 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
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 ();
267 SessionEvent::create_per_thread_pool ("GUI", 512);
269 } catch (failed_constructor& err) {
270 error << _("could not initialize Ardour.") << endmsg;
275 /* we like keyboards */
277 keyboard = new ArdourKeyboard(*this);
279 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
281 keyboard->set_state (*node, Stateful::loading_state_version);
286 starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
287 stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
292 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
294 ARDOUR_UI::run_startup (bool should_be_new)
297 _startup = new ArdourStartup ();
300 _startup->set_new_only (should_be_new);
301 _startup->present ();
307 switch (_startup->response()) {
316 ARDOUR_UI::create_engine ()
318 // this gets called every time by new_session()
324 loading_message (_("Starting audio engine"));
327 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
334 engine->Stopped.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
335 engine->Running.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
336 engine->Halted.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
337 engine->SampleRateChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
345 ARDOUR_UI::post_engine ()
347 /* Things to be done once we create the AudioEngine
350 MIDI::Manager::instance()->set_api_data (engine->jack());
353 ARDOUR::init_post_engine ();
355 ActionManager::init ();
358 if (setup_windows ()) {
359 throw failed_constructor ();
362 check_memory_locking();
364 /* this is the first point at which all the keybindings are available */
366 if (ARDOUR_COMMAND_LINE::show_key_actions) {
367 vector<string> names;
368 vector<string> paths;
370 vector<AccelKey> bindings;
372 ActionManager::get_all_actions (names, paths, keys, bindings);
374 vector<string>::iterator n;
375 vector<string>::iterator k;
376 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
377 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
383 blink_timeout_tag = -1;
385 /* this being a GUI and all, we want peakfiles */
387 AudioFileSource::set_build_peakfiles (true);
388 AudioFileSource::set_build_missing_peakfiles (true);
390 /* set default clock modes */
392 if (Profile->get_sae()) {
393 primary_clock.set_mode (AudioClock::BBT);
394 secondary_clock.set_mode (AudioClock::MinSec);
396 primary_clock.set_mode (AudioClock::Timecode);
397 secondary_clock.set_mode (AudioClock::BBT);
400 /* start the time-of-day-clock */
403 /* OS X provides an always visible wallclock, so don't be stupid */
404 update_wall_clock ();
405 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
408 update_disk_space ();
410 update_sample_rate (engine->frame_rate());
412 Config->ParameterChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
413 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
414 Config->map_parameters (pc);
416 /* now start and maybe save state */
418 if (do_engine_start () == 0) {
419 if (_session && _session_is_new) {
420 /* we need to retain initial visual
421 settings for a new session
423 _session->save_state ("");
428 ARDOUR_UI::~ARDOUR_UI ()
430 save_ardour_state ();
435 delete add_route_dialog;
439 ARDOUR_UI::pop_back_splash ()
441 if (Splash::instance()) {
442 // Splash::instance()->pop_back();
443 Splash::instance()->hide ();
448 ARDOUR_UI::configure_timeout ()
450 if (last_configure_time == 0) {
451 /* no configure events yet */
455 /* force a gap of 0.5 seconds since the last configure event
458 if (get_microseconds() - last_configure_time < 500000) {
461 have_configure_timeout = false;
462 save_ardour_state ();
468 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
470 if (have_configure_timeout) {
471 last_configure_time = get_microseconds();
473 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
474 have_configure_timeout = true;
481 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
483 const XMLProperty* prop;
485 if ((prop = node.property ("roll")) != 0) {
486 roll_controllable->set_id (prop->value());
488 if ((prop = node.property ("stop")) != 0) {
489 stop_controllable->set_id (prop->value());
491 if ((prop = node.property ("goto-start")) != 0) {
492 goto_start_controllable->set_id (prop->value());
494 if ((prop = node.property ("goto-end")) != 0) {
495 goto_end_controllable->set_id (prop->value());
497 if ((prop = node.property ("auto-loop")) != 0) {
498 auto_loop_controllable->set_id (prop->value());
500 if ((prop = node.property ("play-selection")) != 0) {
501 play_selection_controllable->set_id (prop->value());
503 if ((prop = node.property ("rec")) != 0) {
504 rec_controllable->set_id (prop->value());
506 if ((prop = node.property ("shuttle")) != 0) {
507 shuttle_controllable->set_id (prop->value());
512 ARDOUR_UI::get_transport_controllable_state ()
514 XMLNode* node = new XMLNode(X_("TransportControllables"));
517 roll_controllable->id().print (buf, sizeof (buf));
518 node->add_property (X_("roll"), buf);
519 stop_controllable->id().print (buf, sizeof (buf));
520 node->add_property (X_("stop"), buf);
521 goto_start_controllable->id().print (buf, sizeof (buf));
522 node->add_property (X_("goto_start"), buf);
523 goto_end_controllable->id().print (buf, sizeof (buf));
524 node->add_property (X_("goto_end"), buf);
525 auto_loop_controllable->id().print (buf, sizeof (buf));
526 node->add_property (X_("auto_loop"), buf);
527 play_selection_controllable->id().print (buf, sizeof (buf));
528 node->add_property (X_("play_selection"), buf);
529 rec_controllable->id().print (buf, sizeof (buf));
530 node->add_property (X_("rec"), buf);
531 shuttle_controllable->id().print (buf, sizeof (buf));
532 node->add_property (X_("shuttle"), buf);
538 ARDOUR_UI::save_ardour_state ()
540 if (!keyboard || !mixer || !editor) {
544 /* XXX this is all a bit dubious. add_extra_xml() uses
545 a different lifetime model from add_instant_xml().
548 XMLNode* node = new XMLNode (keyboard->get_state());
549 Config->add_extra_xml (*node);
550 Config->add_extra_xml (get_transport_controllable_state());
551 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
552 Config->add_extra_xml (_startup->engine_control()->get_state());
554 Config->save_state();
555 ui_config->save_state ();
557 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
558 XMLNode mnode(mixer->get_state());
561 _session->add_instant_xml (enode);
562 _session->add_instant_xml (mnode);
564 Config->add_instant_xml (enode);
565 Config->add_instant_xml (mnode);
568 Keyboard::save_keybindings ();
572 ARDOUR_UI::autosave_session ()
574 if (g_main_depth() > 1) {
575 /* inside a recursive main loop,
576 give up because we may not be able to
582 if (!Config->get_periodic_safety_backups()) {
587 _session->maybe_write_autosave();
594 ARDOUR_UI::update_autosave ()
596 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
598 if (_session && _session->dirty()) {
599 if (_autosave_connection.connected()) {
600 _autosave_connection.disconnect();
603 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
604 Config->get_periodic_safety_backup_interval() * 1000);
607 if (_autosave_connection.connected()) {
608 _autosave_connection.disconnect();
614 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
618 title = _("Ardour could not start JACK");
620 title = _("Ardour could not connect to JACK.");
623 MessageDialog win (title,
629 win.set_secondary_text(_("There are several possible reasons:\n\
631 1) You requested audio parameters that are not supported..\n\
632 2) JACK is running as another user.\n\
634 Please consider the possibilities, and perhaps try different parameters."));
636 win.set_secondary_text(_("There are several possible reasons:\n\
638 1) JACK is not running.\n\
639 2) JACK is running as another user, perhaps root.\n\
640 3) There is already another client called \"ardour\".\n\
642 Please consider the possibilities, and perhaps (re)start JACK."));
646 win.set_transient_for (*toplevel);
650 win.add_button (Stock::OK, RESPONSE_CLOSE);
652 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
655 win.set_default_response (RESPONSE_CLOSE);
658 win.set_position (Gtk::WIN_POS_CENTER);
661 /* we just don't care about the result, but we want to block */
667 ARDOUR_UI::startup ()
669 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
671 if (audio_setup && _startup && _startup->engine_control()) {
672 _startup->engine_control()->set_state (*audio_setup);
675 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
681 goto_editor_window ();
683 BootMessage (_("Ardour is ready for use"));
688 ARDOUR_UI::no_memory_warning ()
690 XMLNode node (X_("no-memory-warning"));
691 Config->add_instant_xml (node);
695 ARDOUR_UI::check_memory_locking ()
698 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
702 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
704 if (engine->is_realtime() && memory_warning_node == 0) {
706 struct rlimit limits;
708 long pages, page_size;
710 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
713 ram = (int64_t) pages * (int64_t) page_size;
716 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
720 if (limits.rlim_cur != RLIM_INFINITY) {
722 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
725 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
726 "This might cause Ardour to run out of memory before your system "
727 "runs out of memory. \n\n"
728 "You can view the memory limit with 'ulimit -l', "
729 "and it is normally controlled by /etc/security/limits.conf"));
731 VBox* vbox = msg.get_vbox();
733 CheckButton cb (_("Do not show this window again"));
735 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
737 hbox.pack_start (cb, true, false);
738 vbox->pack_start (hbox);
745 editor->ensure_float (msg);
759 if (_session->transport_rolling()) {
760 _session->request_stop ();
764 if (_session->dirty()) {
765 switch (ask_about_saving_session(_("quit"))) {
770 /* use the default name */
771 if (save_state_canfail ("")) {
772 /* failed - don't quit */
773 MessageDialog msg (*editor,
775 Ardour was unable to save your session.\n\n\
776 If you still wish to quit, please use the\n\n\
777 \"Just quit\" option."));
788 second_connection.disconnect ();
789 point_one_second_connection.disconnect ();
790 point_oh_five_second_connection.disconnect ();
791 point_zero_one_second_connection.disconnect();
793 // _session->set_deletion_in_progress ();
794 _session->remove_pending_capture_state ();
799 ArdourDialog::close_all_dialogs ();
801 save_ardour_state ();
806 ARDOUR_UI::ask_about_saving_session (const string & what)
808 ArdourDialog window (_("ardour: save session?"));
809 Gtk::HBox dhbox; // the hbox for the image and text
810 Gtk::Label prompt_label;
811 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
815 msg = string_compose(_("Don't %1"), what);
816 window.add_button (msg, RESPONSE_REJECT);
817 msg = string_compose(_("Just %1"), what);
818 window.add_button (msg, RESPONSE_APPLY);
819 msg = string_compose(_("Save and %1"), what);
820 window.add_button (msg, RESPONSE_ACCEPT);
822 window.set_default_response (RESPONSE_ACCEPT);
824 Gtk::Button noquit_button (msg);
825 noquit_button.set_name ("EditorGTKButton");
830 if (_session->snap_name() == _session->name()) {
833 type = _("snapshot");
835 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?"),
836 type, _session->snap_name());
838 prompt_label.set_text (prompt);
839 prompt_label.set_name (X_("PrompterLabel"));
840 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
842 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
843 dhbox.set_homogeneous (false);
844 dhbox.pack_start (*dimage, false, false, 5);
845 dhbox.pack_start (prompt_label, true, false, 5);
846 window.get_vbox()->pack_start (dhbox);
848 window.set_name (_("Prompter"));
849 window.set_position (Gtk::WIN_POS_MOUSE);
850 window.set_modal (true);
851 window.set_resizable (false);
857 window.set_keep_above (true);
860 ResponseType r = (ResponseType) window.run();
865 case RESPONSE_ACCEPT: // save and get out of here
867 case RESPONSE_APPLY: // get out of here
877 ARDOUR_UI::every_second ()
880 update_buffer_load ();
881 update_disk_space ();
886 ARDOUR_UI::every_point_one_seconds ()
888 update_speed_display ();
889 RapidScreenUpdate(); /* EMIT_SIGNAL */
894 ARDOUR_UI::every_point_zero_one_seconds ()
896 // august 2007: actual update frequency: 40Hz, not 100Hz
898 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
903 ARDOUR_UI::update_sample_rate (nframes_t)
907 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
909 if (!engine->connected()) {
911 snprintf (buf, sizeof (buf), _("disconnected"));
915 nframes_t rate = engine->frame_rate();
917 if (fmod (rate, 1000.0) != 0.0) {
918 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
919 (float) rate/1000.0f,
920 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
922 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
924 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
928 sample_rate_label.set_text (buf);
932 ARDOUR_UI::update_cpu_load ()
935 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
936 cpu_load_label.set_text (buf);
940 ARDOUR_UI::update_buffer_load ()
946 c = _session->capture_load ();
947 p = _session->playback_load ();
949 push_buffer_stats (c, p);
951 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
952 _session->playback_load(), _session->capture_load());
953 buffer_load_label.set_text (buf);
955 buffer_load_label.set_text ("");
960 ARDOUR_UI::count_recenabled_streams (Route& route)
962 Track* track = dynamic_cast<Track*>(&route);
963 if (track && track->diskstream()->record_enabled()) {
964 rec_enabled_streams += track->n_inputs().n_total();
969 ARDOUR_UI::update_disk_space()
975 nframes_t frames = _session->available_capture_duration();
977 nframes_t fr = _session->frame_rate();
979 if (frames == max_frames) {
980 strcpy (buf, _("Disk: 24hrs+"));
982 rec_enabled_streams = 0;
983 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
985 if (rec_enabled_streams) {
986 frames /= rec_enabled_streams;
993 hrs = frames / (fr * 3600);
994 frames -= hrs * fr * 3600;
995 mins = frames / (fr * 60);
996 frames -= mins * fr * 60;
999 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1002 disk_space_label.set_text (buf);
1004 // An attempt to make the disk space label flash red when space has run out.
1006 if (frames < fr * 60 * 5) {
1007 /* disk_space_box.style ("disk_space_label_empty"); */
1009 /* disk_space_box.style ("disk_space_label"); */
1015 ARDOUR_UI::update_wall_clock ()
1022 tm_now = localtime (&now);
1024 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1025 wall_clock_label.set_text (buf);
1031 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1033 session_popup_menu->popup (0, 0);
1038 ARDOUR_UI::redisplay_recent_sessions ()
1040 std::vector<sys::path> session_directories;
1041 RecentSessionsSorter cmp;
1043 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1044 recent_session_model->clear ();
1046 ARDOUR::RecentSessions rs;
1047 ARDOUR::read_recent_sessions (rs);
1050 recent_session_display.set_model (recent_session_model);
1054 // sort them alphabetically
1055 sort (rs.begin(), rs.end(), cmp);
1057 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1058 session_directories.push_back ((*i).second);
1061 for (vector<sys::path>::const_iterator i = session_directories.begin();
1062 i != session_directories.end(); ++i)
1064 std::vector<sys::path> state_file_paths;
1066 // now get available states for this session
1068 get_state_files_in_directory (*i, state_file_paths);
1070 vector<string*>* states;
1071 vector<const gchar*> item;
1072 string fullpath = (*i).to_string();
1074 /* remove any trailing / */
1076 if (fullpath[fullpath.length()-1] == '/') {
1077 fullpath = fullpath.substr (0, fullpath.length()-1);
1080 /* check whether session still exists */
1081 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1082 /* session doesn't exist */
1083 cerr << "skipping non-existent session " << fullpath << endl;
1087 /* now get available states for this session */
1089 if ((states = Session::possible_states (fullpath)) == 0) {
1090 /* no state file? */
1094 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1096 Gtk::TreeModel::Row row = *(recent_session_model->append());
1098 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1099 row[recent_session_columns.fullpath] = fullpath;
1101 if (state_file_names.size() > 1) {
1105 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1106 i2 != state_file_names.end(); ++i2)
1109 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1111 child_row[recent_session_columns.visible_name] = *i2;
1112 child_row[recent_session_columns.fullpath] = fullpath;
1117 recent_session_display.set_model (recent_session_model);
1121 ARDOUR_UI::build_session_selector ()
1123 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1125 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1127 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1128 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1129 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1130 recent_session_model = TreeStore::create (recent_session_columns);
1131 recent_session_display.set_model (recent_session_model);
1132 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1133 recent_session_display.set_headers_visible (false);
1134 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1135 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1137 scroller->add (recent_session_display);
1138 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1140 session_selector_window->set_name ("SessionSelectorWindow");
1141 session_selector_window->set_size_request (200, 400);
1142 session_selector_window->get_vbox()->pack_start (*scroller);
1144 recent_session_display.show();
1146 //session_selector_window->get_vbox()->show();
1150 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1152 session_selector_window->response (RESPONSE_ACCEPT);
1156 ARDOUR_UI::open_recent_session ()
1158 bool can_return = (_session != 0);
1160 if (session_selector_window == 0) {
1161 build_session_selector ();
1164 redisplay_recent_sessions ();
1168 session_selector_window->set_position (WIN_POS_MOUSE);
1170 ResponseType r = (ResponseType) session_selector_window->run ();
1173 case RESPONSE_ACCEPT:
1177 session_selector_window->hide();
1184 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1188 session_selector_window->hide();
1190 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1192 if (i == recent_session_model->children().end()) {
1196 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1197 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1199 _session_is_new = false;
1201 if (load_session (path, state) == 0) {
1210 ARDOUR_UI::check_audioengine ()
1213 if (!engine->connected()) {
1214 MessageDialog msg (_("Ardour is not connected to JACK\n"
1215 "You cannot open or close sessions in this condition"));
1227 ARDOUR_UI::open_session ()
1229 if (!check_audioengine()) {
1234 /* popup selector window */
1236 if (open_session_selector == 0) {
1238 /* ardour sessions are folders */
1240 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1241 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1242 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1243 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1245 FileFilter session_filter;
1246 session_filter.add_pattern ("*.ardour");
1247 session_filter.set_name (_("Ardour sessions"));
1248 open_session_selector->add_filter (session_filter);
1249 open_session_selector->set_filter (session_filter);
1252 int response = open_session_selector->run();
1253 open_session_selector->hide ();
1256 case RESPONSE_ACCEPT:
1259 open_session_selector->hide();
1263 open_session_selector->hide();
1264 string session_path = open_session_selector->get_filename();
1268 if (session_path.length() > 0) {
1269 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1270 _session_is_new = isnew;
1271 load_session (path, name);
1278 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1280 list<boost::shared_ptr<MidiTrack> > tracks;
1282 if (_session == 0) {
1283 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1290 tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1292 if (tracks.size() != how_many) {
1293 if (how_many == 1) {
1294 error << _("could not create a new midi track") << endmsg;
1296 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1300 if ((route = _session->new_midi_route ()) == 0) {
1301 error << _("could not create new midi bus") << endmsg;
1307 MessageDialog msg (*editor,
1308 _("There are insufficient JACK ports available\n\
1309 to create a new track or bus.\n\
1310 You should save Ardour, exit and\n\
1311 restart JACK with more ports."));
1318 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)
1320 list<boost::shared_ptr<AudioTrack> > tracks;
1323 if (_session == 0) {
1324 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1330 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1332 if (tracks.size() != how_many) {
1333 if (how_many == 1) {
1334 error << _("could not create a new audio track") << endmsg;
1336 error << string_compose (_("could only create %1 of %2 new audio %3"),
1337 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1343 routes = _session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1345 if (routes.size() != how_many) {
1346 if (how_many == 1) {
1347 error << _("could not create a new audio track") << endmsg;
1349 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1355 if (need_control_room_outs) {
1361 route->set_stereo_control_outs (control_lr_channels);
1362 route->control_outs()->set_stereo_pan (pans, this);
1364 #endif /* CONTROLOUTS */
1368 MessageDialog msg (*editor,
1369 _("There are insufficient JACK ports available\n\
1370 to create a new track or bus.\n\
1371 You should save Ardour, exit and\n\
1372 restart JACK with more ports."));
1379 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1381 nframes_t _preroll = 0;
1384 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1385 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1387 if (new_position > _preroll) {
1388 new_position -= _preroll;
1393 _session->request_locate (new_position);
1398 ARDOUR_UI::transport_goto_start ()
1401 _session->goto_start();
1403 /* force displayed area in editor to start no matter
1404 what "follow playhead" setting is.
1408 editor->center_screen (_session->current_start_frame ());
1414 ARDOUR_UI::transport_goto_zero ()
1417 _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 () && !join_play_range_button.get_active()) {
1563 /* stop playing a range if we currently are */
1564 _session->request_play_range (0, true);
1567 if (join_play_range_button.get_active()) {
1568 _session->request_play_range (&editor->get_selection().time, true);
1572 _session->request_transport_speed (1.0f);
1575 map_transport_state ();
1579 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1586 if (_session->is_auditioning()) {
1587 _session->cancel_audition ();
1591 if (_session->config.get_external_sync()) {
1592 switch (_session->config.get_sync_source()) {
1596 /* transport controlled by the master */
1601 bool rolling = _session->transport_rolling();
1602 bool affect_transport = true;
1604 if (rolling && roll_out_of_bounded_mode) {
1605 /* drop out of loop/range playback but leave transport rolling */
1606 if (_session->get_play_loop()) {
1607 if (Config->get_seamless_loop()) {
1608 /* the disk buffers contain copies of the loop - we can't
1609 just keep playing, so stop the transport. the user
1610 can restart as they wish.
1612 affect_transport = true;
1614 /* disk buffers are normal, so we can keep playing */
1615 affect_transport = false;
1617 _session->request_play_loop (false, true);
1618 } else if (_session->get_play_range ()) {
1619 affect_transport = false;
1620 _session->request_play_range (0, true);
1624 if (affect_transport) {
1626 _session->request_stop (with_abort, true);
1628 if (join_play_range_button.get_active()) {
1629 _session->request_play_range (&editor->get_selection().time, true);
1632 _session->request_transport_speed (1.0f);
1636 map_transport_state ();
1640 ARDOUR_UI::toggle_session_auto_loop ()
1643 if (_session->get_play_loop()) {
1644 if (_session->transport_rolling()) {
1645 Location * looploc = _session->locations()->auto_loop_location();
1647 _session->request_locate (looploc->start(), true);
1650 _session->request_play_loop (false);
1653 Location * looploc = _session->locations()->auto_loop_location();
1655 _session->request_play_loop (true);
1662 ARDOUR_UI::transport_play_selection ()
1668 editor->play_selection ();
1672 ARDOUR_UI::transport_rewind (int option)
1674 float current_transport_speed;
1677 current_transport_speed = _session->transport_speed();
1679 if (current_transport_speed >= 0.0f) {
1682 _session->request_transport_speed (-1.0f);
1685 _session->request_transport_speed (-4.0f);
1688 _session->request_transport_speed (-0.5f);
1693 _session->request_transport_speed (current_transport_speed * 1.5f);
1699 ARDOUR_UI::transport_forward (int option)
1701 float current_transport_speed;
1704 current_transport_speed = _session->transport_speed();
1706 if (current_transport_speed <= 0.0f) {
1709 _session->request_transport_speed (1.0f);
1712 _session->request_transport_speed (4.0f);
1715 _session->request_transport_speed (0.5f);
1720 _session->request_transport_speed (current_transport_speed * 1.5f);
1727 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1729 if (_session == 0) {
1733 boost::shared_ptr<Route> r;
1735 if ((r = _session->route_by_remote_id (dstream)) != 0) {
1739 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1740 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1743 if (_session == 0) {
1749 ARDOUR_UI::map_transport_state ()
1751 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1754 auto_loop_button.set_visual_state (0);
1755 play_selection_button.set_visual_state (0);
1756 roll_button.set_visual_state (0);
1757 stop_button.set_visual_state (1);
1761 float sp = _session->transport_speed();
1764 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1765 shuttle_box.queue_draw ();
1766 } else if (sp == 0.0f) {
1768 shuttle_box.queue_draw ();
1769 update_disk_space ();
1776 if (_session->get_play_range()) {
1778 play_selection_button.set_visual_state (1);
1779 roll_button.set_visual_state (0);
1780 auto_loop_button.set_visual_state (0);
1782 } else if (_session->get_play_loop ()) {
1784 auto_loop_button.set_visual_state (1);
1785 play_selection_button.set_visual_state (0);
1786 roll_button.set_visual_state (0);
1790 roll_button.set_visual_state (1);
1791 play_selection_button.set_visual_state (0);
1792 auto_loop_button.set_visual_state (0);
1795 if (join_play_range_button.get_active()) {
1796 /* light up both roll and play-selection if they are joined */
1797 roll_button.set_visual_state (1);
1798 play_selection_button.set_visual_state (1);
1801 stop_button.set_visual_state (0);
1805 stop_button.set_visual_state (1);
1806 roll_button.set_visual_state (0);
1807 play_selection_button.set_visual_state (0);
1808 auto_loop_button.set_visual_state (0);
1814 ARDOUR_UI::engine_stopped ()
1816 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1817 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1818 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1822 ARDOUR_UI::engine_running ()
1824 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1825 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1826 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1828 Glib::RefPtr<Action> action;
1829 const char* action_name = 0;
1831 switch (engine->frames_per_cycle()) {
1833 action_name = X_("JACKLatency32");
1836 action_name = X_("JACKLatency64");
1839 action_name = X_("JACKLatency128");
1842 action_name = X_("JACKLatency512");
1845 action_name = X_("JACKLatency1024");
1848 action_name = X_("JACKLatency2048");
1851 action_name = X_("JACKLatency4096");
1854 action_name = X_("JACKLatency8192");
1857 /* XXX can we do anything useful ? */
1863 action = ActionManager::get_action (X_("JACK"), action_name);
1866 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1867 ract->set_active ();
1873 ARDOUR_UI::engine_halted ()
1875 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
1877 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1878 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1880 update_sample_rate (0);
1882 MessageDialog msg (*editor,
1884 JACK has either been shutdown or it\n\
1885 disconnected Ardour because Ardour\n\
1886 was not fast enough. Try to restart\n\
1887 JACK, reconnect and save the session."));
1893 ARDOUR_UI::do_engine_start ()
1901 error << _("Unable to start the session running")
1911 ARDOUR_UI::setup_theme ()
1913 theme_manager->setup_theme();
1917 ARDOUR_UI::update_clocks ()
1919 if (!editor || !editor->dragging_playhead()) {
1920 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1925 ARDOUR_UI::start_clocking ()
1927 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1931 ARDOUR_UI::stop_clocking ()
1933 clock_signal_connection.disconnect ();
1937 ARDOUR_UI::toggle_clocking ()
1940 if (clock_button.get_active()) {
1949 ARDOUR_UI::_blink (void *arg)
1952 ((ARDOUR_UI *) arg)->blink ();
1959 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1963 ARDOUR_UI::start_blinking ()
1965 /* Start the blink signal. Everybody with a blinking widget
1966 uses Blink to drive the widget's state.
1969 if (blink_timeout_tag < 0) {
1971 blink_timeout_tag = g_timeout_add (240, _blink, this);
1976 ARDOUR_UI::stop_blinking ()
1978 if (blink_timeout_tag >= 0) {
1979 g_source_remove (blink_timeout_tag);
1980 blink_timeout_tag = -1;
1985 /** Ask the user for the name of a new shapshot and then take it.
1988 ARDOUR_UI::snapshot_session ()
1990 ArdourPrompter prompter (true);
1994 struct tm local_time;
1997 localtime_r (&n, &local_time);
1998 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
2000 prompter.set_name ("Prompter");
2001 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2002 prompter.set_title (_("Take Snapshot"));
2003 prompter.set_prompt (_("Name of New Snapshot"));
2004 prompter.set_initial_text (timebuf);
2006 switch (prompter.run()) {
2007 case RESPONSE_ACCEPT:
2009 prompter.get_result (snapname);
2011 bool do_save = (snapname.length() != 0);
2013 vector<sys::path> p;
2014 get_state_files_in_directory (_session->session_directory().root_path(), p);
2015 vector<string> n = get_file_names_no_extension (p);
2016 if (find (n.begin(), n.end(), snapname) != n.end()) {
2018 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
2019 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2020 confirm.get_vbox()->pack_start (m, true, true);
2021 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2022 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2023 confirm.show_all ();
2024 switch (confirm.run()) {
2025 case RESPONSE_CANCEL:
2031 save_state (snapname);
2042 ARDOUR_UI::save_state (const string & name)
2044 (void) save_state_canfail (name);
2048 ARDOUR_UI::save_state_canfail (string name)
2053 if (name.length() == 0) {
2054 name = _session->snap_name();
2057 if ((ret = _session->save_state (name)) != 0) {
2061 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2066 ARDOUR_UI::primary_clock_value_changed ()
2069 _session->request_locate (primary_clock.current_time ());
2074 ARDOUR_UI::big_clock_value_changed ()
2077 _session->request_locate (big_clock.current_time ());
2082 ARDOUR_UI::secondary_clock_value_changed ()
2085 _session->request_locate (secondary_clock.current_time ());
2090 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2092 if (_session == 0) {
2096 Session::RecordState const r = _session->record_status ();
2097 bool const h = _session->have_rec_enabled_diskstream ();
2099 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2101 rec_button.set_visual_state (2);
2103 rec_button.set_visual_state (0);
2105 } else if (r == Session::Recording && h) {
2106 rec_button.set_visual_state (1);
2108 rec_button.set_visual_state (0);
2113 ARDOUR_UI::save_template ()
2115 ArdourPrompter prompter (true);
2118 if (!check_audioengine()) {
2122 prompter.set_name (X_("Prompter"));
2123 prompter.set_title (_("Save Mix Template"));
2124 prompter.set_prompt (_("Name for mix template:"));
2125 prompter.set_initial_text(_session->name() + _("-template"));
2126 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2128 switch (prompter.run()) {
2129 case RESPONSE_ACCEPT:
2130 prompter.get_result (name);
2132 if (name.length()) {
2133 _session->save_template (name);
2143 ARDOUR_UI::edit_metadata ()
2145 SessionMetadataEditor dialog;
2146 dialog.set_session (_session);
2147 editor->ensure_float (dialog);
2152 ARDOUR_UI::import_metadata ()
2154 SessionMetadataImporter dialog;
2155 dialog.set_session (_session);
2156 editor->ensure_float (dialog);
2161 ARDOUR_UI::fontconfig_dialog ()
2164 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2165 may not and it can take a while to build it. Warn them.
2168 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2170 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2171 MessageDialog msg (*_startup,
2172 _("Welcome to Ardour.\n\n"
2173 "The program will take a bit longer to start up\n"
2174 "while the system fonts are checked.\n\n"
2175 "This will only be done once, and you will\n"
2176 "not see this message again\n"),
2189 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2191 existing_session = false;
2193 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2194 session_path = cmdline_path;
2195 existing_session = true;
2196 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2197 session_path = Glib::path_get_dirname (string (cmdline_path));
2198 existing_session = true;
2200 /* it doesn't exist, assume the best */
2201 session_path = Glib::path_get_dirname (string (cmdline_path));
2204 session_name = basename_nosuffix (string (cmdline_path));
2208 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2210 /* when this is called, the backend audio system must be running */
2212 /* the main idea here is to deal with the fact that a cmdline argument for the session
2213 can be interpreted in different ways - it could be a directory or a file, and before
2214 we load, we need to know both the session directory and the snapshot (statefile) within it
2215 that we are supposed to use.
2218 if (session_name.length() == 0 || session_path.length() == 0) {
2222 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2224 Glib::ustring predicted_session_file;
2226 predicted_session_file = session_path;
2227 predicted_session_file += '/';
2228 predicted_session_file += session_name;
2229 predicted_session_file += ARDOUR::statefile_suffix;
2231 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2232 existing_session = true;
2235 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2237 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2238 /* existing .ardour file */
2239 existing_session = true;
2243 existing_session = false;
2246 /* lets just try to load it */
2248 if (create_engine ()) {
2249 backend_audio_error (false, _startup);
2253 return load_session (session_path, session_name);
2257 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2259 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2261 MessageDialog msg (str,
2263 Gtk::MESSAGE_WARNING,
2264 Gtk::BUTTONS_YES_NO,
2268 msg.set_name (X_("OpenExistingDialog"));
2269 msg.set_title (_("Open Existing Session"));
2270 msg.set_wmclass (X_("existing_session"), "Ardour");
2271 msg.set_position (Gtk::WIN_POS_MOUSE);
2274 switch (msg.run()) {
2283 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2288 AutoConnectOption iconnect;
2289 AutoConnectOption oconnect;
2293 if (Profile->get_sae()) {
2297 iconnect = AutoConnectPhysical;
2298 oconnect = AutoConnectMaster;
2299 nphysin = 0; // use all available
2300 nphysout = 0; // use all available
2304 /* get settings from advanced section of NSD */
2306 if (_startup->create_control_bus()) {
2307 cchns = (uint32_t) _startup->control_channel_count();
2312 if (_startup->create_master_bus()) {
2313 mchns = (uint32_t) _startup->master_channel_count();
2318 if (_startup->connect_inputs()) {
2319 iconnect = AutoConnectPhysical;
2321 iconnect = AutoConnectOption (0);
2324 /// @todo some minor tweaks.
2326 oconnect = AutoConnectOption (0);
2328 if (_startup->connect_outputs ()) {
2329 if (_startup->connect_outs_to_master()) {
2330 oconnect = AutoConnectMaster;
2331 } else if (_startup->connect_outs_to_physical()) {
2332 oconnect = AutoConnectPhysical;
2336 nphysin = (uint32_t) _startup->input_limit_count();
2337 nphysout = (uint32_t) _startup->output_limit_count();
2340 if (build_session (session_path,
2348 engine->frame_rate() * 60 * 5)) {
2357 ARDOUR_UI::idle_load (const Glib::ustring& path)
2360 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2361 /* /path/to/foo => /path/to/foo, foo */
2362 load_session (path, basename_nosuffix (path));
2364 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2365 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2369 ARDOUR_COMMAND_LINE::session_name = path;
2372 * new_session_dialog doens't exist in A3
2373 * Try to remove all references to it to
2374 * see if it will compile. NOTE: this will
2375 * likely cause a runtime issue is my somewhat
2379 //if (new_session_dialog) {
2382 /* make it break out of Dialog::run() and
2386 //new_session_dialog->response (1);
2392 ARDOUR_UI::end_loading_messages ()
2398 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2401 // splash->message (msg);
2405 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2407 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2409 Glib::ustring session_name;
2410 Glib::ustring session_path;
2411 Glib::ustring template_name;
2413 bool likely_new = false;
2417 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2419 /* if they named a specific statefile, use it, otherwise they are
2420 just giving a session folder, and we want to use it as is
2421 to find the session.
2424 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2425 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2427 session_path = ARDOUR_COMMAND_LINE::session_name;
2430 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2434 bool const apply = run_startup (should_be_new);
2436 if (quit_on_cancel) {
2443 /* if we run the startup dialog again, offer more than just "new session" */
2445 should_be_new = false;
2447 session_name = _startup->session_name (likely_new);
2449 /* this shouldn't happen, but we catch it just in case it does */
2451 if (session_name.empty()) {
2454 if (_startup->use_session_template()) {
2455 template_name = _startup->session_template_name();
2456 _session_is_new = true;
2459 if (session_name[0] == '/' ||
2460 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2461 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2463 session_path = Glib::path_get_dirname (session_name);
2464 session_name = Glib::path_get_basename (session_name);
2468 session_path = _startup->session_folder();
2472 if (create_engine ()) {
2476 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2480 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2482 if (!ask_about_loading_existing_session (existing)) {
2483 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2488 _session_is_new = false;
2493 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2495 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2499 _session_is_new = true;
2502 if (likely_new && template_name.empty()) {
2504 ret = build_session_from_nsd (session_path, session_name);
2508 ret = load_session (session_path, session_name, template_name);
2509 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2510 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2520 ARDOUR_UI::close_session()
2522 if (!check_audioengine()) {
2526 unload_session (true);
2528 ARDOUR_COMMAND_LINE::session_name = "";
2529 get_session_parameters (true, false);
2533 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2535 Session *new_session;
2539 session_loaded = false;
2541 if (!check_audioengine()) {
2545 unload_status = unload_session ();
2547 if (unload_status < 0) {
2549 } else if (unload_status > 0) {
2554 loading_message (_("Please wait while Ardour loads your session"));
2557 new_session = new Session (*engine, path, snap_name, mix_template);
2560 /* this one is special */
2562 catch (AudioEngine::PortRegistrationFailure& err) {
2564 MessageDialog msg (err.what(),
2567 Gtk::BUTTONS_CLOSE);
2569 msg.set_title (_("Port Registration 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:
2590 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2593 Gtk::BUTTONS_CLOSE);
2595 msg.set_title (_("Loading Error"));
2596 msg.set_secondary_text (_("Click the Close button to try again."));
2597 msg.set_position (Gtk::WIN_POS_CENTER);
2601 int response = msg.run ();
2606 case RESPONSE_CANCEL:
2614 set_session (new_session);
2616 session_loaded = true;
2618 goto_editor_window ();
2621 _session->set_clean ();
2632 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2633 uint32_t control_channels,
2634 uint32_t master_channels,
2635 AutoConnectOption input_connect,
2636 AutoConnectOption output_connect,
2639 nframes_t initial_length)
2641 Session *new_session;
2644 if (!check_audioengine()) {
2648 session_loaded = false;
2650 x = unload_session ();
2658 _session_is_new = true;
2661 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2662 control_channels, master_channels, nphysin, nphysout, initial_length);
2667 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2673 set_session (new_session);
2675 session_loaded = true;
2677 new_session->save_state(new_session->name());
2686 editor->show_window ();
2697 ARDOUR_UI::show_about ()
2701 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2708 ARDOUR_UI::hide_about ()
2711 about->get_window()->set_cursor ();
2717 ARDOUR_UI::about_signal_response (int /*response*/)
2723 ARDOUR_UI::show_splash ()
2727 splash = new Splash;
2735 splash->queue_draw ();
2736 splash->get_window()->process_updates (true);
2741 ARDOUR_UI::hide_splash ()
2749 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2750 const string& plural_msg, const string& singular_msg)
2754 removed = rep.paths.size();
2757 MessageDialog msgd (*editor,
2758 _("No audio files were ready for cleanup"),
2761 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2762 msgd.set_secondary_text (_("If this seems suprising, \n\
2763 check for any existing snapshots.\n\
2764 These may still include regions that\n\
2765 require some unused files to continue to exist."));
2771 ArdourDialog results (_("ardour: cleanup"), true, false);
2773 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2774 CleanupResultsModelColumns() {
2778 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2779 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2783 CleanupResultsModelColumns results_columns;
2784 Glib::RefPtr<Gtk::ListStore> results_model;
2785 Gtk::TreeView results_display;
2787 results_model = ListStore::create (results_columns);
2788 results_display.set_model (results_model);
2789 results_display.append_column (list_title, results_columns.visible_name);
2791 results_display.set_name ("CleanupResultsList");
2792 results_display.set_headers_visible (true);
2793 results_display.set_headers_clickable (false);
2794 results_display.set_reorderable (false);
2796 Gtk::ScrolledWindow list_scroller;
2799 Gtk::HBox dhbox; // the hbox for the image and text
2800 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2801 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2803 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2805 const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
2811 %1 - number of files removed
2812 %2 - location of "dead_sounds"
2813 %3 - size of files affected
2814 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2817 const char* bprefix;
2819 if (rep.space < 1048576.0f) {
2820 bprefix = X_("kilo");
2821 } else if (rep.space < 1048576.0f * 1000) {
2822 bprefix = X_("mega");
2824 bprefix = X_("giga");
2828 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2830 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2833 dhbox.pack_start (*dimage, true, false, 5);
2834 dhbox.pack_start (txt, true, false, 5);
2836 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2837 TreeModel::Row row = *(results_model->append());
2838 row[results_columns.visible_name] = *i;
2839 row[results_columns.fullpath] = *i;
2842 list_scroller.add (results_display);
2843 list_scroller.set_size_request (-1, 150);
2844 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2846 dvbox.pack_start (dhbox, true, false, 5);
2847 dvbox.pack_start (list_scroller, true, false, 5);
2848 ddhbox.pack_start (dvbox, true, false, 5);
2850 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2851 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2852 results.set_default_response (RESPONSE_CLOSE);
2853 results.set_position (Gtk::WIN_POS_MOUSE);
2855 results_display.show();
2856 list_scroller.show();
2863 //results.get_vbox()->show();
2864 results.set_resizable (false);
2871 ARDOUR_UI::cleanup ()
2873 if (_session == 0) {
2874 /* shouldn't happen: menu item is insensitive */
2879 MessageDialog checker (_("Are you sure you want to cleanup?"),
2881 Gtk::MESSAGE_QUESTION,
2882 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2884 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2885 ALL undo/redo information will be lost if you cleanup.\n\
2886 After cleanup, unused audio files will be moved to a \
2887 \"dead sounds\" location."));
2889 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2890 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2891 checker.set_default_response (RESPONSE_CANCEL);
2893 checker.set_name (_("CleanupDialog"));
2894 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2895 checker.set_position (Gtk::WIN_POS_MOUSE);
2897 switch (checker.run()) {
2898 case RESPONSE_ACCEPT:
2904 ARDOUR::CleanupReport rep;
2906 editor->prepare_for_cleanup ();
2908 /* do not allow flush until a session is reloaded */
2910 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2912 act->set_sensitive (false);
2915 if (_session->cleanup_sources (rep)) {
2916 editor->finish_cleanup ();
2920 editor->finish_cleanup ();
2923 display_cleanup_results (rep,
2926 The following %1 files were not in use and \n\
2927 have been moved to:\n\
2929 Flushing the wastebasket will \n\
2930 release an additional\n\
2931 %3 %4bytes of disk space.\n"),
2933 The following file was not in use and \n \
2934 has been moved to:\n \
2936 Flushing the wastebasket will \n\
2937 release an additional\n\
2938 %3 %4bytes of disk space.\n"
2944 ARDOUR_UI::flush_trash ()
2946 if (_session == 0) {
2947 /* shouldn't happen: menu item is insensitive */
2951 ARDOUR::CleanupReport rep;
2953 if (_session->cleanup_trash_sources (rep)) {
2957 display_cleanup_results (rep,
2959 _("The following %1 files were deleted from\n\
2961 releasing %3 %4bytes of disk space"),
2962 _("The following file was deleted from\n\
2964 releasing %3 %4bytes of disk space"));
2968 ARDOUR_UI::add_route (Gtk::Window* float_window)
2976 if (add_route_dialog == 0) {
2977 add_route_dialog = new AddRouteDialog (_session);
2979 add_route_dialog->set_transient_for (*float_window);
2983 if (add_route_dialog->is_visible()) {
2984 /* we're already doing this */
2988 ResponseType r = (ResponseType) add_route_dialog->run ();
2990 add_route_dialog->hide();
2993 case RESPONSE_ACCEPT:
3000 if ((count = add_route_dialog->count()) <= 0) {
3004 string template_path = add_route_dialog->track_template();
3006 if (!template_path.empty()) {
3007 _session->new_route_from_template (count, template_path);
3011 uint32_t input_chan = add_route_dialog->channels ();
3012 uint32_t output_chan;
3013 string name_template = add_route_dialog->name_template ();
3014 bool track = add_route_dialog->track ();
3015 bool aux = !track && add_route_dialog->aux();
3016 RouteGroup* route_group = add_route_dialog->route_group ();
3018 AutoConnectOption oac = Config->get_output_auto_connect();
3020 if (oac & AutoConnectMaster) {
3021 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3023 output_chan = input_chan;
3026 /* XXX do something with name template */
3028 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3030 session_add_midi_track (route_group, count);
3032 MessageDialog msg (*editor,
3033 _("Sorry, MIDI Busses are not supported at this time."));
3035 //session_add_midi_bus();
3039 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3041 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3047 ARDOUR_UI::mixer_settings () const
3052 node = _session->instant_xml(X_("Mixer"));
3054 node = Config->instant_xml(X_("Mixer"));
3058 node = new XMLNode (X_("Mixer"));
3065 ARDOUR_UI::editor_settings () const
3070 node = _session->instant_xml(X_("Editor"));
3072 node = Config->instant_xml(X_("Editor"));
3076 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3077 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3082 node = new XMLNode (X_("Editor"));
3089 ARDOUR_UI::keyboard_settings () const
3093 node = Config->extra_xml(X_("Keyboard"));
3096 node = new XMLNode (X_("Keyboard"));
3102 ARDOUR_UI::create_xrun_marker(nframes_t where)
3104 editor->mouse_add_new_marker (where, false, true);
3108 ARDOUR_UI::halt_on_xrun_message ()
3110 MessageDialog msg (*editor,
3111 _("Recording was stopped because your system could not keep up."));
3116 ARDOUR_UI::xrun_handler(nframes_t where)
3122 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3124 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3125 create_xrun_marker(where);
3128 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3129 halt_on_xrun_message ();
3134 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3139 while (disk_buffer_stats.size() > 60) {
3140 disk_buffer_stats.pop_front ();
3143 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3147 ARDOUR_UI::write_buffer_stats ()
3152 char path[PATH_MAX+1]; int fd;
3154 strcpy (path, "ardourBufferingXXXXXX");
3156 if ((fd = mkstemp (path )) < 0) {
3157 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3165 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3169 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3170 localtime_r (&(*i).when, &tm);
3171 strftime (buf, sizeof (buf), "%T", &tm);
3172 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3175 disk_buffer_stats.clear ();
3179 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3183 ARDOUR_UI::disk_overrun_handler ()
3185 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3187 write_buffer_stats ();
3189 if (!have_disk_speed_dialog_displayed) {
3190 have_disk_speed_dialog_displayed = true;
3191 MessageDialog* msg = new MessageDialog (*editor, _("\
3192 The disk system on your computer\n\
3193 was not able to keep up with Ardour.\n\
3195 Specifically, it failed to write data to disk\n\
3196 quickly enough to keep up with recording.\n"));
3197 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3203 ARDOUR_UI::disk_underrun_handler ()
3205 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3207 write_buffer_stats ();
3209 if (!have_disk_speed_dialog_displayed) {
3210 have_disk_speed_dialog_displayed = true;
3211 MessageDialog* msg = new MessageDialog (*editor,
3212 _("The disk system on your computer\n\
3213 was not able to keep up with Ardour.\n\
3215 Specifically, it failed to read data from disk\n\
3216 quickly enough to keep up with playback.\n"));
3217 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3223 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3225 have_disk_speed_dialog_displayed = false;
3230 ARDOUR_UI::session_dialog (std::string msg)
3232 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3237 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3239 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3248 ARDOUR_UI::pending_state_dialog ()
3250 HBox* hbox = new HBox();
3251 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3252 ArdourDialog dialog (_("Crash Recovery"), true);
3254 This session appears to have been in\n\
3255 middle of recording when ardour or\n\
3256 the computer was shutdown.\n\
3258 Ardour can recover any captured audio for\n\
3259 you, or it can ignore it. Please decide\n\
3260 what you would like to do.\n"));
3261 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3262 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3263 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3264 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3265 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3266 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3267 dialog.set_default_response (RESPONSE_ACCEPT);
3268 dialog.set_position (WIN_POS_CENTER);
3273 switch (dialog.run ()) {
3274 case RESPONSE_ACCEPT:
3282 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3284 HBox* hbox = new HBox();
3285 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3286 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3287 Label message (string_compose (_("\
3288 This session was created with a sample rate of %1 Hz\n\
3290 The audioengine is currently running at %2 Hz\n"), desired, actual));
3292 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3293 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3294 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3295 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3296 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3297 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3298 dialog.set_default_response (RESPONSE_ACCEPT);
3299 dialog.set_position (WIN_POS_CENTER);
3304 switch (dialog.run ()) {
3305 case RESPONSE_ACCEPT:
3314 ARDOUR_UI::disconnect_from_jack ()
3317 if( engine->disconnect_from_jack ()) {
3318 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3322 update_sample_rate (0);
3327 ARDOUR_UI::reconnect_to_jack ()
3330 if (engine->reconnect_to_jack ()) {
3331 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3335 update_sample_rate (0);
3340 ARDOUR_UI::use_config ()
3343 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3345 set_transport_controllable_state (*node);
3350 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3352 if (Config->get_primary_clock_delta_edit_cursor()) {
3353 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3355 primary_clock.set (pos, 0, true);
3358 if (Config->get_secondary_clock_delta_edit_cursor()) {
3359 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3361 secondary_clock.set (pos);
3364 if (big_clock_window) {
3365 big_clock.set (pos);
3370 ARDOUR_UI::record_state_changed ()
3372 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3374 if (!_session || !big_clock_window) {
3375 /* why bother - the clock isn't visible */
3379 Session::RecordState const r = _session->record_status ();
3380 bool const h = _session->have_rec_enabled_diskstream ();
3382 if (r == Session::Recording && h) {
3383 big_clock.set_widget_name ("BigClockRecording");
3385 big_clock.set_widget_name ("BigClockNonRecording");
3390 ARDOUR_UI::first_idle ()
3393 _session->allow_auto_play (true);
3397 editor->first_idle();
3400 Keyboard::set_can_save_keybindings (true);
3405 ARDOUR_UI::store_clock_modes ()
3407 XMLNode* node = new XMLNode(X_("ClockModes"));
3409 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3410 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3413 _session->add_extra_xml (*node);
3414 _session->set_dirty ();
3419 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3420 : Controllable (name), ui (u), type(tp)
3426 ARDOUR_UI::TransportControllable::set_value (float val)
3428 if (type == ShuttleControl) {
3435 fract = -((0.5f - val)/0.5f);
3437 fract = ((val - 0.5f)/0.5f);
3441 ui.set_shuttle_fract (fract);
3446 /* do nothing: these are radio-style actions */
3450 const char *action = 0;
3454 action = X_("Roll");
3457 action = X_("Stop");
3460 action = X_("Goto Start");
3463 action = X_("Goto End");
3466 action = X_("Loop");
3469 action = X_("Play Selection");
3472 action = X_("Record");
3482 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3490 ARDOUR_UI::TransportControllable::get_value (void) const
3509 case ShuttleControl:
3519 ARDOUR_UI::TransportControllable::set_id (const string& str)
3525 ARDOUR_UI::setup_profile ()
3527 if (gdk_screen_width() < 1200) {
3528 Profile->set_small_screen ();
3532 if (getenv ("ARDOUR_SAE")) {
3533 Profile->set_sae ();
3534 Profile->set_single_package ();