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;
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);
1420 /* force displayed area in editor to start no matter
1421 what "follow playhead" setting is.
1425 editor->reset_x_origin (0);
1431 ARDOUR_UI::transport_goto_wallclock ()
1433 if (_session && editor) {
1440 localtime_r (&now, &tmnow);
1442 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1443 frames += tmnow.tm_min * (60 * _session->frame_rate());
1444 frames += tmnow.tm_sec * _session->frame_rate();
1446 _session->request_locate (frames);
1448 /* force displayed area in editor to start no matter
1449 what "follow playhead" setting is.
1453 editor->center_screen (frames);
1459 ARDOUR_UI::transport_goto_end ()
1462 nframes_t const frame = _session->current_end_frame();
1463 _session->request_locate (frame);
1465 /* force displayed area in editor to start no matter
1466 what "follow playhead" setting is.
1470 editor->center_screen (frame);
1476 ARDOUR_UI::transport_stop ()
1482 if (_session->is_auditioning()) {
1483 _session->cancel_audition ();
1487 _session->request_stop ();
1491 ARDOUR_UI::transport_stop_and_forget_capture ()
1494 _session->request_stop (true);
1499 ARDOUR_UI::remove_last_capture()
1502 editor->remove_last_capture();
1507 ARDOUR_UI::transport_record (bool roll)
1511 switch (_session->record_status()) {
1512 case Session::Disabled:
1513 if (_session->ntracks() == 0) {
1514 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1518 _session->maybe_enable_record ();
1523 case Session::Recording:
1525 _session->request_stop();
1527 _session->disable_record (false, true);
1531 case Session::Enabled:
1532 _session->disable_record (false, true);
1535 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1539 ARDOUR_UI::transport_roll ()
1545 if (_session->is_auditioning()) {
1549 if (_session->config.get_external_sync()) {
1550 switch (_session->config.get_sync_source()) {
1554 /* transport controlled by the master */
1559 bool rolling = _session->transport_rolling();
1561 if (_session->get_play_loop()) {
1562 _session->request_play_loop (false, true);
1563 } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1564 /* stop playing a range if we currently are */
1565 _session->request_play_range (0, true);
1568 if (join_play_range_button.get_active()) {
1569 _session->request_play_range (&editor->get_selection().time, true);
1573 _session->request_transport_speed (1.0f);
1576 map_transport_state ();
1580 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1587 if (_session->is_auditioning()) {
1588 _session->cancel_audition ();
1592 if (_session->config.get_external_sync()) {
1593 switch (_session->config.get_sync_source()) {
1597 /* transport controlled by the master */
1602 bool rolling = _session->transport_rolling();
1603 bool affect_transport = true;
1605 if (rolling && roll_out_of_bounded_mode) {
1606 /* drop out of loop/range playback but leave transport rolling */
1607 if (_session->get_play_loop()) {
1608 if (Config->get_seamless_loop()) {
1609 /* the disk buffers contain copies of the loop - we can't
1610 just keep playing, so stop the transport. the user
1611 can restart as they wish.
1613 affect_transport = true;
1615 /* disk buffers are normal, so we can keep playing */
1616 affect_transport = false;
1618 _session->request_play_loop (false, true);
1619 } else if (_session->get_play_range ()) {
1620 affect_transport = false;
1621 _session->request_play_range (0, true);
1625 if (affect_transport) {
1627 _session->request_stop (with_abort, true);
1629 if (join_play_range_button.get_active()) {
1630 _session->request_play_range (&editor->get_selection().time, true);
1633 _session->request_transport_speed (1.0f);
1637 map_transport_state ();
1641 ARDOUR_UI::toggle_session_auto_loop ()
1644 if (_session->get_play_loop()) {
1645 if (_session->transport_rolling()) {
1646 Location * looploc = _session->locations()->auto_loop_location();
1648 _session->request_locate (looploc->start(), true);
1651 _session->request_play_loop (false);
1654 Location * looploc = _session->locations()->auto_loop_location();
1656 _session->request_play_loop (true);
1663 ARDOUR_UI::transport_play_selection ()
1669 editor->play_selection ();
1673 ARDOUR_UI::transport_rewind (int option)
1675 float current_transport_speed;
1678 current_transport_speed = _session->transport_speed();
1680 if (current_transport_speed >= 0.0f) {
1683 _session->request_transport_speed (-1.0f);
1686 _session->request_transport_speed (-4.0f);
1689 _session->request_transport_speed (-0.5f);
1694 _session->request_transport_speed (current_transport_speed * 1.5f);
1700 ARDOUR_UI::transport_forward (int option)
1702 float current_transport_speed;
1705 current_transport_speed = _session->transport_speed();
1707 if (current_transport_speed <= 0.0f) {
1710 _session->request_transport_speed (1.0f);
1713 _session->request_transport_speed (4.0f);
1716 _session->request_transport_speed (0.5f);
1721 _session->request_transport_speed (current_transport_speed * 1.5f);
1728 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1730 if (_session == 0) {
1734 boost::shared_ptr<Route> r;
1736 if ((r = _session->route_by_remote_id (dstream)) != 0) {
1740 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1741 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1744 if (_session == 0) {
1750 ARDOUR_UI::map_transport_state ()
1752 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1755 auto_loop_button.set_visual_state (0);
1756 play_selection_button.set_visual_state (0);
1757 roll_button.set_visual_state (0);
1758 stop_button.set_visual_state (1);
1762 float sp = _session->transport_speed();
1765 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1766 shuttle_box.queue_draw ();
1767 } else if (sp == 0.0f) {
1769 shuttle_box.queue_draw ();
1770 update_disk_space ();
1777 if (_session->get_play_range()) {
1779 play_selection_button.set_visual_state (1);
1780 roll_button.set_visual_state (0);
1781 auto_loop_button.set_visual_state (0);
1783 } else if (_session->get_play_loop ()) {
1785 auto_loop_button.set_visual_state (1);
1786 play_selection_button.set_visual_state (0);
1787 roll_button.set_visual_state (0);
1791 roll_button.set_visual_state (1);
1792 play_selection_button.set_visual_state (0);
1793 auto_loop_button.set_visual_state (0);
1796 if (join_play_range_button.get_active()) {
1797 /* light up both roll and play-selection if they are joined */
1798 roll_button.set_visual_state (1);
1799 play_selection_button.set_visual_state (1);
1802 stop_button.set_visual_state (0);
1806 stop_button.set_visual_state (1);
1807 roll_button.set_visual_state (0);
1808 play_selection_button.set_visual_state (0);
1809 auto_loop_button.set_visual_state (0);
1815 ARDOUR_UI::engine_stopped ()
1817 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1818 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1819 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1823 ARDOUR_UI::engine_running ()
1825 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1826 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1827 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1829 Glib::RefPtr<Action> action;
1830 const char* action_name = 0;
1832 switch (engine->frames_per_cycle()) {
1834 action_name = X_("JACKLatency32");
1837 action_name = X_("JACKLatency64");
1840 action_name = X_("JACKLatency128");
1843 action_name = X_("JACKLatency512");
1846 action_name = X_("JACKLatency1024");
1849 action_name = X_("JACKLatency2048");
1852 action_name = X_("JACKLatency4096");
1855 action_name = X_("JACKLatency8192");
1858 /* XXX can we do anything useful ? */
1864 action = ActionManager::get_action (X_("JACK"), action_name);
1867 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1868 ract->set_active ();
1874 ARDOUR_UI::engine_halted ()
1876 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
1878 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1879 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1881 update_sample_rate (0);
1883 MessageDialog msg (*editor,
1885 JACK has either been shutdown or it\n\
1886 disconnected Ardour because Ardour\n\
1887 was not fast enough. Try to restart\n\
1888 JACK, reconnect and save the session."));
1894 ARDOUR_UI::do_engine_start ()
1902 error << _("Unable to start the session running")
1912 ARDOUR_UI::setup_theme ()
1914 theme_manager->setup_theme();
1918 ARDOUR_UI::update_clocks ()
1920 if (!editor || !editor->dragging_playhead()) {
1921 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1926 ARDOUR_UI::start_clocking ()
1928 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1932 ARDOUR_UI::stop_clocking ()
1934 clock_signal_connection.disconnect ();
1938 ARDOUR_UI::toggle_clocking ()
1941 if (clock_button.get_active()) {
1950 ARDOUR_UI::_blink (void *arg)
1953 ((ARDOUR_UI *) arg)->blink ();
1960 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1964 ARDOUR_UI::start_blinking ()
1966 /* Start the blink signal. Everybody with a blinking widget
1967 uses Blink to drive the widget's state.
1970 if (blink_timeout_tag < 0) {
1972 blink_timeout_tag = g_timeout_add (240, _blink, this);
1977 ARDOUR_UI::stop_blinking ()
1979 if (blink_timeout_tag >= 0) {
1980 g_source_remove (blink_timeout_tag);
1981 blink_timeout_tag = -1;
1986 /** Ask the user for the name of a new shapshot and then take it.
1989 ARDOUR_UI::snapshot_session ()
1991 ArdourPrompter prompter (true);
1995 struct tm local_time;
1998 localtime_r (&n, &local_time);
1999 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
2001 prompter.set_name ("Prompter");
2002 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2003 prompter.set_title (_("Take Snapshot"));
2004 prompter.set_prompt (_("Name of New Snapshot"));
2005 prompter.set_initial_text (timebuf);
2007 switch (prompter.run()) {
2008 case RESPONSE_ACCEPT:
2010 prompter.get_result (snapname);
2012 bool do_save = (snapname.length() != 0);
2014 vector<sys::path> p;
2015 get_state_files_in_directory (_session->session_directory().root_path(), p);
2016 vector<string> n = get_file_names_no_extension (p);
2017 if (find (n.begin(), n.end(), snapname) != n.end()) {
2019 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
2020 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2021 confirm.get_vbox()->pack_start (m, true, true);
2022 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2023 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2024 confirm.show_all ();
2025 switch (confirm.run()) {
2026 case RESPONSE_CANCEL:
2032 save_state (snapname);
2043 ARDOUR_UI::save_state (const string & name)
2045 (void) save_state_canfail (name);
2049 ARDOUR_UI::save_state_canfail (string name)
2054 if (name.length() == 0) {
2055 name = _session->snap_name();
2058 if ((ret = _session->save_state (name)) != 0) {
2062 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2067 ARDOUR_UI::primary_clock_value_changed ()
2070 _session->request_locate (primary_clock.current_time ());
2075 ARDOUR_UI::big_clock_value_changed ()
2078 _session->request_locate (big_clock.current_time ());
2083 ARDOUR_UI::secondary_clock_value_changed ()
2086 _session->request_locate (secondary_clock.current_time ());
2091 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2093 if (_session == 0) {
2097 Session::RecordState const r = _session->record_status ();
2098 bool const h = _session->have_rec_enabled_diskstream ();
2100 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2102 rec_button.set_visual_state (2);
2104 rec_button.set_visual_state (0);
2106 } else if (r == Session::Recording && h) {
2107 rec_button.set_visual_state (1);
2109 rec_button.set_visual_state (0);
2114 ARDOUR_UI::save_template ()
2116 ArdourPrompter prompter (true);
2119 if (!check_audioengine()) {
2123 prompter.set_name (X_("Prompter"));
2124 prompter.set_title (_("Save Mix Template"));
2125 prompter.set_prompt (_("Name for mix template:"));
2126 prompter.set_initial_text(_session->name() + _("-template"));
2127 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2129 switch (prompter.run()) {
2130 case RESPONSE_ACCEPT:
2131 prompter.get_result (name);
2133 if (name.length()) {
2134 _session->save_template (name);
2144 ARDOUR_UI::edit_metadata ()
2146 SessionMetadataEditor dialog;
2147 dialog.set_session (_session);
2148 editor->ensure_float (dialog);
2153 ARDOUR_UI::import_metadata ()
2155 SessionMetadataImporter dialog;
2156 dialog.set_session (_session);
2157 editor->ensure_float (dialog);
2162 ARDOUR_UI::fontconfig_dialog ()
2165 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2166 may not and it can take a while to build it. Warn them.
2169 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2171 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2172 MessageDialog msg (*_startup,
2173 _("Welcome to Ardour.\n\n"
2174 "The program will take a bit longer to start up\n"
2175 "while the system fonts are checked.\n\n"
2176 "This will only be done once, and you will\n"
2177 "not see this message again\n"),
2190 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2192 existing_session = false;
2194 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2195 session_path = cmdline_path;
2196 existing_session = true;
2197 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2198 session_path = Glib::path_get_dirname (string (cmdline_path));
2199 existing_session = true;
2201 /* it doesn't exist, assume the best */
2202 session_path = Glib::path_get_dirname (string (cmdline_path));
2205 session_name = basename_nosuffix (string (cmdline_path));
2209 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2211 /* when this is called, the backend audio system must be running */
2213 /* the main idea here is to deal with the fact that a cmdline argument for the session
2214 can be interpreted in different ways - it could be a directory or a file, and before
2215 we load, we need to know both the session directory and the snapshot (statefile) within it
2216 that we are supposed to use.
2219 if (session_name.length() == 0 || session_path.length() == 0) {
2223 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2225 Glib::ustring predicted_session_file;
2227 predicted_session_file = session_path;
2228 predicted_session_file += '/';
2229 predicted_session_file += session_name;
2230 predicted_session_file += ARDOUR::statefile_suffix;
2232 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2233 existing_session = true;
2236 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2238 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2239 /* existing .ardour file */
2240 existing_session = true;
2244 existing_session = false;
2247 /* lets just try to load it */
2249 if (create_engine ()) {
2250 backend_audio_error (false, _startup);
2254 return load_session (session_path, session_name);
2258 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2260 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2262 MessageDialog msg (str,
2264 Gtk::MESSAGE_WARNING,
2265 Gtk::BUTTONS_YES_NO,
2269 msg.set_name (X_("OpenExistingDialog"));
2270 msg.set_title (_("Open Existing Session"));
2271 msg.set_wmclass (X_("existing_session"), "Ardour");
2272 msg.set_position (Gtk::WIN_POS_MOUSE);
2275 switch (msg.run()) {
2284 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2289 AutoConnectOption iconnect;
2290 AutoConnectOption oconnect;
2294 if (Profile->get_sae()) {
2298 iconnect = AutoConnectPhysical;
2299 oconnect = AutoConnectMaster;
2300 nphysin = 0; // use all available
2301 nphysout = 0; // use all available
2305 /* get settings from advanced section of NSD */
2307 if (_startup->create_control_bus()) {
2308 cchns = (uint32_t) _startup->control_channel_count();
2313 if (_startup->create_master_bus()) {
2314 mchns = (uint32_t) _startup->master_channel_count();
2319 if (_startup->connect_inputs()) {
2320 iconnect = AutoConnectPhysical;
2322 iconnect = AutoConnectOption (0);
2325 /// @todo some minor tweaks.
2327 oconnect = AutoConnectOption (0);
2329 if (_startup->connect_outputs ()) {
2330 if (_startup->connect_outs_to_master()) {
2331 oconnect = AutoConnectMaster;
2332 } else if (_startup->connect_outs_to_physical()) {
2333 oconnect = AutoConnectPhysical;
2337 nphysin = (uint32_t) _startup->input_limit_count();
2338 nphysout = (uint32_t) _startup->output_limit_count();
2341 if (build_session (session_path,
2349 engine->frame_rate() * 60 * 5)) {
2358 ARDOUR_UI::idle_load (const Glib::ustring& path)
2361 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2362 /* /path/to/foo => /path/to/foo, foo */
2363 load_session (path, basename_nosuffix (path));
2365 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2366 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2370 ARDOUR_COMMAND_LINE::session_name = path;
2373 * new_session_dialog doens't exist in A3
2374 * Try to remove all references to it to
2375 * see if it will compile. NOTE: this will
2376 * likely cause a runtime issue is my somewhat
2380 //if (new_session_dialog) {
2383 /* make it break out of Dialog::run() and
2387 //new_session_dialog->response (1);
2393 ARDOUR_UI::end_loading_messages ()
2399 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2402 // splash->message (msg);
2406 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2408 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2410 Glib::ustring session_name;
2411 Glib::ustring session_path;
2412 Glib::ustring template_name;
2414 bool likely_new = false;
2418 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2420 /* if they named a specific statefile, use it, otherwise they are
2421 just giving a session folder, and we want to use it as is
2422 to find the session.
2425 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2426 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2428 session_path = ARDOUR_COMMAND_LINE::session_name;
2431 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2435 bool const apply = run_startup (should_be_new);
2437 if (quit_on_cancel) {
2444 /* if we run the startup dialog again, offer more than just "new session" */
2446 should_be_new = false;
2448 session_name = _startup->session_name (likely_new);
2450 /* this shouldn't happen, but we catch it just in case it does */
2452 if (session_name.empty()) {
2455 if (_startup->use_session_template()) {
2456 template_name = _startup->session_template_name();
2457 _session_is_new = true;
2460 if (session_name[0] == '/' ||
2461 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2462 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2464 session_path = Glib::path_get_dirname (session_name);
2465 session_name = Glib::path_get_basename (session_name);
2469 session_path = _startup->session_folder();
2473 if (create_engine ()) {
2477 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2481 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2483 if (!ask_about_loading_existing_session (existing)) {
2484 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2489 _session_is_new = false;
2494 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2496 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2500 _session_is_new = true;
2503 if (likely_new && template_name.empty()) {
2505 ret = build_session_from_nsd (session_path, session_name);
2509 ret = load_session (session_path, session_name, template_name);
2510 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2511 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2521 ARDOUR_UI::close_session()
2523 if (!check_audioengine()) {
2527 unload_session (true);
2529 ARDOUR_COMMAND_LINE::session_name = "";
2530 get_session_parameters (true, false);
2534 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2536 Session *new_session;
2540 session_loaded = false;
2542 if (!check_audioengine()) {
2546 unload_status = unload_session ();
2548 if (unload_status < 0) {
2550 } else if (unload_status > 0) {
2555 loading_message (_("Please wait while Ardour loads your session"));
2558 new_session = new Session (*engine, path, snap_name, mix_template);
2561 /* this one is special */
2563 catch (AudioEngine::PortRegistrationFailure& err) {
2565 MessageDialog msg (err.what(),
2568 Gtk::BUTTONS_CLOSE);
2570 msg.set_title (_("Port Registration Error"));
2571 msg.set_secondary_text (_("Click the Close button to try again."));
2572 msg.set_position (Gtk::WIN_POS_CENTER);
2576 int response = msg.run ();
2581 case RESPONSE_CANCEL:
2591 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2594 Gtk::BUTTONS_CLOSE);
2596 msg.set_title (_("Loading Error"));
2597 msg.set_secondary_text (_("Click the Close button to try again."));
2598 msg.set_position (Gtk::WIN_POS_CENTER);
2602 int response = msg.run ();
2607 case RESPONSE_CANCEL:
2615 set_session (new_session);
2617 session_loaded = true;
2619 goto_editor_window ();
2622 _session->set_clean ();
2633 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2634 uint32_t control_channels,
2635 uint32_t master_channels,
2636 AutoConnectOption input_connect,
2637 AutoConnectOption output_connect,
2640 nframes_t initial_length)
2642 Session *new_session;
2645 if (!check_audioengine()) {
2649 session_loaded = false;
2651 x = unload_session ();
2659 _session_is_new = true;
2662 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2663 control_channels, master_channels, nphysin, nphysout, initial_length);
2668 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2674 set_session (new_session);
2676 session_loaded = true;
2678 new_session->save_state(new_session->name());
2687 editor->show_window ();
2698 ARDOUR_UI::show_about ()
2702 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2709 ARDOUR_UI::hide_about ()
2712 about->get_window()->set_cursor ();
2718 ARDOUR_UI::about_signal_response (int /*response*/)
2724 ARDOUR_UI::show_splash ()
2728 splash = new Splash;
2736 splash->queue_draw ();
2737 splash->get_window()->process_updates (true);
2742 ARDOUR_UI::hide_splash ()
2750 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2751 const string& plural_msg, const string& singular_msg)
2755 removed = rep.paths.size();
2758 MessageDialog msgd (*editor,
2759 _("No audio files were ready for cleanup"),
2762 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2763 msgd.set_secondary_text (_("If this seems suprising, \n\
2764 check for any existing snapshots.\n\
2765 These may still include regions that\n\
2766 require some unused files to continue to exist."));
2772 ArdourDialog results (_("ardour: cleanup"), true, false);
2774 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2775 CleanupResultsModelColumns() {
2779 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2780 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2784 CleanupResultsModelColumns results_columns;
2785 Glib::RefPtr<Gtk::ListStore> results_model;
2786 Gtk::TreeView results_display;
2788 results_model = ListStore::create (results_columns);
2789 results_display.set_model (results_model);
2790 results_display.append_column (list_title, results_columns.visible_name);
2792 results_display.set_name ("CleanupResultsList");
2793 results_display.set_headers_visible (true);
2794 results_display.set_headers_clickable (false);
2795 results_display.set_reorderable (false);
2797 Gtk::ScrolledWindow list_scroller;
2800 Gtk::HBox dhbox; // the hbox for the image and text
2801 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2802 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2804 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2806 const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
2812 %1 - number of files removed
2813 %2 - location of "dead_sounds"
2814 %3 - size of files affected
2815 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2818 const char* bprefix;
2820 if (rep.space < 1048576.0f) {
2821 bprefix = X_("kilo");
2822 } else if (rep.space < 1048576.0f * 1000) {
2823 bprefix = X_("mega");
2825 bprefix = X_("giga");
2829 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2831 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2834 dhbox.pack_start (*dimage, true, false, 5);
2835 dhbox.pack_start (txt, true, false, 5);
2837 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2838 TreeModel::Row row = *(results_model->append());
2839 row[results_columns.visible_name] = *i;
2840 row[results_columns.fullpath] = *i;
2843 list_scroller.add (results_display);
2844 list_scroller.set_size_request (-1, 150);
2845 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2847 dvbox.pack_start (dhbox, true, false, 5);
2848 dvbox.pack_start (list_scroller, true, false, 5);
2849 ddhbox.pack_start (dvbox, true, false, 5);
2851 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2852 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2853 results.set_default_response (RESPONSE_CLOSE);
2854 results.set_position (Gtk::WIN_POS_MOUSE);
2856 results_display.show();
2857 list_scroller.show();
2864 //results.get_vbox()->show();
2865 results.set_resizable (false);
2872 ARDOUR_UI::cleanup ()
2874 if (_session == 0) {
2875 /* shouldn't happen: menu item is insensitive */
2880 MessageDialog checker (_("Are you sure you want to cleanup?"),
2882 Gtk::MESSAGE_QUESTION,
2883 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2885 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2886 ALL undo/redo information will be lost if you cleanup.\n\
2887 After cleanup, unused audio files will be moved to a \
2888 \"dead sounds\" location."));
2890 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2891 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2892 checker.set_default_response (RESPONSE_CANCEL);
2894 checker.set_name (_("CleanupDialog"));
2895 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2896 checker.set_position (Gtk::WIN_POS_MOUSE);
2898 switch (checker.run()) {
2899 case RESPONSE_ACCEPT:
2905 ARDOUR::CleanupReport rep;
2907 editor->prepare_for_cleanup ();
2909 /* do not allow flush until a session is reloaded */
2911 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2913 act->set_sensitive (false);
2916 if (_session->cleanup_sources (rep)) {
2917 editor->finish_cleanup ();
2921 editor->finish_cleanup ();
2924 display_cleanup_results (rep,
2927 The following %1 files were not in use and \n\
2928 have been moved to:\n\
2930 Flushing the wastebasket will \n\
2931 release an additional\n\
2932 %3 %4bytes of disk space.\n"),
2934 The following file was not in use and \n \
2935 has been moved to:\n \
2937 Flushing the wastebasket will \n\
2938 release an additional\n\
2939 %3 %4bytes of disk space.\n"
2945 ARDOUR_UI::flush_trash ()
2947 if (_session == 0) {
2948 /* shouldn't happen: menu item is insensitive */
2952 ARDOUR::CleanupReport rep;
2954 if (_session->cleanup_trash_sources (rep)) {
2958 display_cleanup_results (rep,
2960 _("The following %1 files were deleted from\n\
2962 releasing %3 %4bytes of disk space"),
2963 _("The following file was deleted from\n\
2965 releasing %3 %4bytes of disk space"));
2969 ARDOUR_UI::add_route (Gtk::Window* float_window)
2977 if (add_route_dialog == 0) {
2978 add_route_dialog = new AddRouteDialog (_session);
2980 add_route_dialog->set_transient_for (*float_window);
2984 if (add_route_dialog->is_visible()) {
2985 /* we're already doing this */
2989 ResponseType r = (ResponseType) add_route_dialog->run ();
2991 add_route_dialog->hide();
2994 case RESPONSE_ACCEPT:
3001 if ((count = add_route_dialog->count()) <= 0) {
3005 string template_path = add_route_dialog->track_template();
3007 if (!template_path.empty()) {
3008 _session->new_route_from_template (count, template_path);
3012 uint32_t input_chan = add_route_dialog->channels ();
3013 uint32_t output_chan;
3014 string name_template = add_route_dialog->name_template ();
3015 bool track = add_route_dialog->track ();
3016 bool aux = !track && add_route_dialog->aux();
3017 RouteGroup* route_group = add_route_dialog->route_group ();
3019 AutoConnectOption oac = Config->get_output_auto_connect();
3021 if (oac & AutoConnectMaster) {
3022 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3024 output_chan = input_chan;
3027 /* XXX do something with name template */
3029 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3031 session_add_midi_track (route_group, count);
3033 MessageDialog msg (*editor,
3034 _("Sorry, MIDI Busses are not supported at this time."));
3036 //session_add_midi_bus();
3040 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3042 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3048 ARDOUR_UI::mixer_settings () const
3053 node = _session->instant_xml(X_("Mixer"));
3055 node = Config->instant_xml(X_("Mixer"));
3059 node = new XMLNode (X_("Mixer"));
3066 ARDOUR_UI::editor_settings () const
3071 node = _session->instant_xml(X_("Editor"));
3073 node = Config->instant_xml(X_("Editor"));
3077 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3078 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3083 node = new XMLNode (X_("Editor"));
3090 ARDOUR_UI::keyboard_settings () const
3094 node = Config->extra_xml(X_("Keyboard"));
3097 node = new XMLNode (X_("Keyboard"));
3103 ARDOUR_UI::create_xrun_marker(nframes_t where)
3105 editor->mouse_add_new_marker (where, false, true);
3109 ARDOUR_UI::halt_on_xrun_message ()
3111 MessageDialog msg (*editor,
3112 _("Recording was stopped because your system could not keep up."));
3117 ARDOUR_UI::xrun_handler(nframes_t where)
3123 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3125 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3126 create_xrun_marker(where);
3129 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3130 halt_on_xrun_message ();
3135 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3140 while (disk_buffer_stats.size() > 60) {
3141 disk_buffer_stats.pop_front ();
3144 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3148 ARDOUR_UI::write_buffer_stats ()
3154 char path[PATH_MAX+1]; int fd;
3156 strcpy (path, "ardourBufferingXXXXXX");
3158 if ((fd = mkstemp (path )) < 0) {
3159 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3167 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3171 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3172 localtime_r (&(*i).when, &tm);
3173 strftime (buf, sizeof (buf), "%T", &tm);
3174 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3177 disk_buffer_stats.clear ();
3181 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3185 ARDOUR_UI::disk_overrun_handler ()
3187 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3189 write_buffer_stats ();
3191 if (!have_disk_speed_dialog_displayed) {
3192 have_disk_speed_dialog_displayed = true;
3193 MessageDialog* msg = new MessageDialog (*editor, _("\
3194 The disk system on your computer\n\
3195 was not able to keep up with Ardour.\n\
3197 Specifically, it failed to write data to disk\n\
3198 quickly enough to keep up with recording.\n"));
3199 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3205 ARDOUR_UI::disk_underrun_handler ()
3207 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3209 write_buffer_stats ();
3211 if (!have_disk_speed_dialog_displayed) {
3212 have_disk_speed_dialog_displayed = true;
3213 MessageDialog* msg = new MessageDialog (*editor,
3214 _("The disk system on your computer\n\
3215 was not able to keep up with Ardour.\n\
3217 Specifically, it failed to read data from disk\n\
3218 quickly enough to keep up with playback.\n"));
3219 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3225 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3227 have_disk_speed_dialog_displayed = false;
3232 ARDOUR_UI::session_dialog (std::string msg)
3234 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3239 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3241 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3250 ARDOUR_UI::pending_state_dialog ()
3252 HBox* hbox = new HBox();
3253 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3254 ArdourDialog dialog (_("Crash Recovery"), true);
3256 This session appears to have been in\n\
3257 middle of recording when ardour or\n\
3258 the computer was shutdown.\n\
3260 Ardour can recover any captured audio for\n\
3261 you, or it can ignore it. Please decide\n\
3262 what you would like to do.\n"));
3263 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3264 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3265 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3266 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3267 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3268 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3269 dialog.set_default_response (RESPONSE_ACCEPT);
3270 dialog.set_position (WIN_POS_CENTER);
3275 switch (dialog.run ()) {
3276 case RESPONSE_ACCEPT:
3284 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3286 HBox* hbox = new HBox();
3287 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3288 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3289 Label message (string_compose (_("\
3290 This session was created with a sample rate of %1 Hz\n\
3292 The audioengine is currently running at %2 Hz\n"), desired, actual));
3294 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3295 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3296 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3297 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3298 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3299 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3300 dialog.set_default_response (RESPONSE_ACCEPT);
3301 dialog.set_position (WIN_POS_CENTER);
3306 switch (dialog.run ()) {
3307 case RESPONSE_ACCEPT:
3316 ARDOUR_UI::disconnect_from_jack ()
3319 if( engine->disconnect_from_jack ()) {
3320 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3324 update_sample_rate (0);
3329 ARDOUR_UI::reconnect_to_jack ()
3332 if (engine->reconnect_to_jack ()) {
3333 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3337 update_sample_rate (0);
3342 ARDOUR_UI::use_config ()
3345 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3347 set_transport_controllable_state (*node);
3352 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3354 if (Config->get_primary_clock_delta_edit_cursor()) {
3355 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3357 primary_clock.set (pos, 0, true);
3360 if (Config->get_secondary_clock_delta_edit_cursor()) {
3361 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3363 secondary_clock.set (pos);
3366 if (big_clock_window) {
3367 big_clock.set (pos);
3372 ARDOUR_UI::record_state_changed ()
3374 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3376 if (!_session || !big_clock_window) {
3377 /* why bother - the clock isn't visible */
3381 Session::RecordState const r = _session->record_status ();
3382 bool const h = _session->have_rec_enabled_diskstream ();
3384 if (r == Session::Recording && h) {
3385 big_clock.set_widget_name ("BigClockRecording");
3387 big_clock.set_widget_name ("BigClockNonRecording");
3392 ARDOUR_UI::first_idle ()
3395 _session->allow_auto_play (true);
3399 editor->first_idle();
3402 Keyboard::set_can_save_keybindings (true);
3407 ARDOUR_UI::store_clock_modes ()
3409 XMLNode* node = new XMLNode(X_("ClockModes"));
3411 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3412 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3415 _session->add_extra_xml (*node);
3416 _session->set_dirty ();
3421 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3422 : Controllable (name), ui (u), type(tp)
3428 ARDOUR_UI::TransportControllable::set_value (float val)
3430 if (type == ShuttleControl) {
3437 fract = -((0.5f - val)/0.5f);
3439 fract = ((val - 0.5f)/0.5f);
3443 ui.set_shuttle_fract (fract);
3448 /* do nothing: these are radio-style actions */
3452 const char *action = 0;
3456 action = X_("Roll");
3459 action = X_("Stop");
3462 action = X_("Goto Start");
3465 action = X_("Goto End");
3468 action = X_("Loop");
3471 action = X_("Play Selection");
3474 action = X_("Record");
3484 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3492 ARDOUR_UI::TransportControllable::get_value (void) const
3511 case ShuttleControl:
3521 ARDOUR_UI::TransportControllable::set_id (const string& str)
3527 ARDOUR_UI::setup_profile ()
3529 if (gdk_screen_width() < 1200) {
3530 Profile->set_small_screen ();
3534 if (getenv ("ARDOUR_SAE")) {
3535 Profile->set_sae ();
3536 Profile->set_single_package ();