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 session_selector_window = 0;
201 last_key_press_time = 0;
202 _will_create_new_session_automatically = false;
203 add_route_dialog = 0;
205 rc_option_editor = 0;
206 session_option_editor = 0;
208 open_session_selector = 0;
209 have_configure_timeout = false;
210 have_disk_speed_dialog_displayed = false;
211 session_loaded = false;
212 last_speed_displayed = -1.0f;
213 ignore_dual_punch = false;
214 _mixer_on_top = false;
216 roll_button.unset_flags (Gtk::CAN_FOCUS);
217 stop_button.unset_flags (Gtk::CAN_FOCUS);
218 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
220 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
221 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
222 rec_button.unset_flags (Gtk::CAN_FOCUS);
224 last_configure_time= 0;
226 shuttle_grabbed = false;
228 shuttle_max_speed = 8.0f;
230 shuttle_style_menu = 0;
231 shuttle_unit_menu = 0;
233 // We do not have jack linked in yet so;
235 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
237 ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
238 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
240 /* handle dialog requests */
242 ARDOUR::Session::Dialog.connect (forever_connections, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
244 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
246 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
248 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
250 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
252 /* lets get this party started */
255 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
256 throw failed_constructor ();
259 setup_gtk_ardour_enums ();
262 GainMeter::setup_slider_pix ();
263 RouteTimeAxisView::setup_slider_pix ();
264 SendProcessorEntry::setup_slider_pix ();
265 SessionEvent::create_per_thread_pool ("GUI", 512);
267 } catch (failed_constructor& err) {
268 error << _("could not initialize Ardour.") << endmsg;
273 /* we like keyboards */
275 keyboard = new ArdourKeyboard;
277 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
279 keyboard->set_state (*node, Stateful::loading_state_version);
284 starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
285 stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
290 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
292 ARDOUR_UI::run_startup (bool should_be_new)
295 _startup = new ArdourStartup ();
298 _startup->set_new_only (should_be_new);
299 _startup->present ();
305 switch (_startup->response()) {
314 ARDOUR_UI::create_engine ()
316 // this gets called every time by new_session()
322 loading_message (_("Starting audio engine"));
325 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
332 engine->Stopped.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
333 engine->Running.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
334 engine->Halted.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
335 engine->SampleRateChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
343 ARDOUR_UI::post_engine ()
345 /* Things to be done once we create the AudioEngine
348 MIDI::Manager::instance()->set_api_data (engine->jack());
351 ARDOUR::init_post_engine ();
353 ActionManager::init ();
356 if (setup_windows ()) {
357 throw failed_constructor ();
360 check_memory_locking();
362 /* this is the first point at which all the keybindings are available */
364 if (ARDOUR_COMMAND_LINE::show_key_actions) {
365 vector<string> names;
366 vector<string> paths;
368 vector<AccelKey> bindings;
370 ActionManager::get_all_actions (names, paths, keys, bindings);
372 vector<string>::iterator n;
373 vector<string>::iterator k;
374 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
375 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
381 blink_timeout_tag = -1;
383 /* this being a GUI and all, we want peakfiles */
385 AudioFileSource::set_build_peakfiles (true);
386 AudioFileSource::set_build_missing_peakfiles (true);
388 /* set default clock modes */
390 if (Profile->get_sae()) {
391 primary_clock.set_mode (AudioClock::BBT);
392 secondary_clock.set_mode (AudioClock::MinSec);
394 primary_clock.set_mode (AudioClock::Timecode);
395 secondary_clock.set_mode (AudioClock::BBT);
398 /* start the time-of-day-clock */
401 /* OS X provides an always visible wallclock, so don't be stupid */
402 update_wall_clock ();
403 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
406 update_disk_space ();
408 update_sample_rate (engine->frame_rate());
410 Config->ParameterChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
411 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
412 Config->map_parameters (pc);
414 /* now start and maybe save state */
416 if (do_engine_start () == 0) {
417 if (_session && _session_is_new) {
418 /* we need to retain initial visual
419 settings for a new session
421 _session->save_state ("");
426 ARDOUR_UI::~ARDOUR_UI ()
428 save_ardour_state ();
433 delete add_route_dialog;
437 ARDOUR_UI::pop_back_splash ()
439 if (Splash::instance()) {
440 // Splash::instance()->pop_back();
441 Splash::instance()->hide ();
446 ARDOUR_UI::configure_timeout ()
448 if (last_configure_time == 0) {
449 /* no configure events yet */
453 /* force a gap of 0.5 seconds since the last configure event
456 if (get_microseconds() - last_configure_time < 500000) {
459 have_configure_timeout = false;
460 save_ardour_state ();
466 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
468 if (have_configure_timeout) {
469 last_configure_time = get_microseconds();
471 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
472 have_configure_timeout = true;
479 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
481 const XMLProperty* prop;
483 if ((prop = node.property ("roll")) != 0) {
484 roll_controllable->set_id (prop->value());
486 if ((prop = node.property ("stop")) != 0) {
487 stop_controllable->set_id (prop->value());
489 if ((prop = node.property ("goto-start")) != 0) {
490 goto_start_controllable->set_id (prop->value());
492 if ((prop = node.property ("goto-end")) != 0) {
493 goto_end_controllable->set_id (prop->value());
495 if ((prop = node.property ("auto-loop")) != 0) {
496 auto_loop_controllable->set_id (prop->value());
498 if ((prop = node.property ("play-selection")) != 0) {
499 play_selection_controllable->set_id (prop->value());
501 if ((prop = node.property ("rec")) != 0) {
502 rec_controllable->set_id (prop->value());
504 if ((prop = node.property ("shuttle")) != 0) {
505 shuttle_controllable->set_id (prop->value());
510 ARDOUR_UI::get_transport_controllable_state ()
512 XMLNode* node = new XMLNode(X_("TransportControllables"));
515 roll_controllable->id().print (buf, sizeof (buf));
516 node->add_property (X_("roll"), buf);
517 stop_controllable->id().print (buf, sizeof (buf));
518 node->add_property (X_("stop"), buf);
519 goto_start_controllable->id().print (buf, sizeof (buf));
520 node->add_property (X_("goto_start"), buf);
521 goto_end_controllable->id().print (buf, sizeof (buf));
522 node->add_property (X_("goto_end"), buf);
523 auto_loop_controllable->id().print (buf, sizeof (buf));
524 node->add_property (X_("auto_loop"), buf);
525 play_selection_controllable->id().print (buf, sizeof (buf));
526 node->add_property (X_("play_selection"), buf);
527 rec_controllable->id().print (buf, sizeof (buf));
528 node->add_property (X_("rec"), buf);
529 shuttle_controllable->id().print (buf, sizeof (buf));
530 node->add_property (X_("shuttle"), buf);
536 ARDOUR_UI::save_ardour_state ()
538 if (!keyboard || !mixer || !editor) {
542 /* XXX this is all a bit dubious. add_extra_xml() uses
543 a different lifetime model from add_instant_xml().
546 XMLNode* node = new XMLNode (keyboard->get_state());
547 Config->add_extra_xml (*node);
548 Config->add_extra_xml (get_transport_controllable_state());
549 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
550 Config->add_extra_xml (_startup->engine_control()->get_state());
552 Config->save_state();
553 ui_config->save_state ();
555 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
556 XMLNode mnode(mixer->get_state());
559 _session->add_instant_xml (enode);
560 _session->add_instant_xml (mnode);
562 Config->add_instant_xml (enode);
563 Config->add_instant_xml (mnode);
566 Keyboard::save_keybindings ();
570 ARDOUR_UI::autosave_session ()
572 if (g_main_depth() > 1) {
573 /* inside a recursive main loop,
574 give up because we may not be able to
580 if (!Config->get_periodic_safety_backups()) {
585 _session->maybe_write_autosave();
592 ARDOUR_UI::update_autosave ()
594 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
596 if (_session && _session->dirty()) {
597 if (_autosave_connection.connected()) {
598 _autosave_connection.disconnect();
601 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
602 Config->get_periodic_safety_backup_interval() * 1000);
605 if (_autosave_connection.connected()) {
606 _autosave_connection.disconnect();
612 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
616 title = _("Ardour could not start JACK");
618 title = _("Ardour could not connect to JACK.");
621 MessageDialog win (title,
627 win.set_secondary_text(_("There are several possible reasons:\n\
629 1) You requested audio parameters that are not supported..\n\
630 2) JACK is running as another user.\n\
632 Please consider the possibilities, and perhaps try different parameters."));
634 win.set_secondary_text(_("There are several possible reasons:\n\
636 1) JACK is not running.\n\
637 2) JACK is running as another user, perhaps root.\n\
638 3) There is already another client called \"ardour\".\n\
640 Please consider the possibilities, and perhaps (re)start JACK."));
644 win.set_transient_for (*toplevel);
648 win.add_button (Stock::OK, RESPONSE_CLOSE);
650 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
653 win.set_default_response (RESPONSE_CLOSE);
656 win.set_position (Gtk::WIN_POS_CENTER);
659 /* we just don't care about the result, but we want to block */
665 ARDOUR_UI::startup ()
667 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
669 if (audio_setup && _startup && _startup->engine_control()) {
670 _startup->engine_control()->set_state (*audio_setup);
673 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
679 goto_editor_window ();
681 BootMessage (_("Ardour is ready for use"));
686 ARDOUR_UI::no_memory_warning ()
688 XMLNode node (X_("no-memory-warning"));
689 Config->add_instant_xml (node);
693 ARDOUR_UI::check_memory_locking ()
696 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
700 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
702 if (engine->is_realtime() && memory_warning_node == 0) {
704 struct rlimit limits;
706 long pages, page_size;
708 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
711 ram = (int64_t) pages * (int64_t) page_size;
714 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
718 if (limits.rlim_cur != RLIM_INFINITY) {
720 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
723 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
724 "This might cause Ardour to run out of memory before your system "
725 "runs out of memory. \n\n"
726 "You can view the memory limit with 'ulimit -l', "
727 "and it is normally controlled by /etc/security/limits.conf"));
729 VBox* vbox = msg.get_vbox();
731 CheckButton cb (_("Do not show this window again"));
733 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
735 hbox.pack_start (cb, true, false);
736 vbox->pack_start (hbox);
743 editor->ensure_float (msg);
757 if (_session->transport_rolling()) {
758 _session->request_stop ();
762 if (_session->dirty()) {
763 switch (ask_about_saving_session(_("quit"))) {
768 /* use the default name */
769 if (save_state_canfail ("")) {
770 /* failed - don't quit */
771 MessageDialog msg (*editor,
773 Ardour was unable to save your session.\n\n\
774 If you still wish to quit, please use the\n\n\
775 \"Just quit\" option."));
786 second_connection.disconnect ();
787 point_one_second_connection.disconnect ();
788 point_oh_five_second_connection.disconnect ();
789 point_zero_one_second_connection.disconnect();
791 // _session->set_deletion_in_progress ();
792 _session->remove_pending_capture_state ();
797 ArdourDialog::close_all_dialogs ();
799 save_ardour_state ();
804 ARDOUR_UI::ask_about_saving_session (const string & what)
806 ArdourDialog window (_("ardour: save session?"));
807 Gtk::HBox dhbox; // the hbox for the image and text
808 Gtk::Label prompt_label;
809 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
813 msg = string_compose(_("Don't %1"), what);
814 window.add_button (msg, RESPONSE_REJECT);
815 msg = string_compose(_("Just %1"), what);
816 window.add_button (msg, RESPONSE_APPLY);
817 msg = string_compose(_("Save and %1"), what);
818 window.add_button (msg, RESPONSE_ACCEPT);
820 window.set_default_response (RESPONSE_ACCEPT);
822 Gtk::Button noquit_button (msg);
823 noquit_button.set_name ("EditorGTKButton");
828 if (_session->snap_name() == _session->name()) {
831 type = _("snapshot");
833 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?"),
834 type, _session->snap_name());
836 prompt_label.set_text (prompt);
837 prompt_label.set_name (X_("PrompterLabel"));
838 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
840 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
841 dhbox.set_homogeneous (false);
842 dhbox.pack_start (*dimage, false, false, 5);
843 dhbox.pack_start (prompt_label, true, false, 5);
844 window.get_vbox()->pack_start (dhbox);
846 window.set_name (_("Prompter"));
847 window.set_position (Gtk::WIN_POS_MOUSE);
848 window.set_modal (true);
849 window.set_resizable (false);
855 window.set_keep_above (true);
858 ResponseType r = (ResponseType) window.run();
863 case RESPONSE_ACCEPT: // save and get out of here
865 case RESPONSE_APPLY: // get out of here
875 ARDOUR_UI::every_second ()
878 update_buffer_load ();
879 update_disk_space ();
884 ARDOUR_UI::every_point_one_seconds ()
886 update_speed_display ();
887 RapidScreenUpdate(); /* EMIT_SIGNAL */
892 ARDOUR_UI::every_point_zero_one_seconds ()
894 // august 2007: actual update frequency: 40Hz, not 100Hz
896 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
901 ARDOUR_UI::update_sample_rate (nframes_t)
905 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
907 if (!engine->connected()) {
909 snprintf (buf, sizeof (buf), _("disconnected"));
913 nframes_t rate = engine->frame_rate();
915 if (fmod (rate, 1000.0) != 0.0) {
916 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
917 (float) rate/1000.0f,
918 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
920 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
922 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
926 sample_rate_label.set_text (buf);
930 ARDOUR_UI::update_cpu_load ()
933 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
934 cpu_load_label.set_text (buf);
938 ARDOUR_UI::update_buffer_load ()
944 c = _session->capture_load ();
945 p = _session->playback_load ();
947 push_buffer_stats (c, p);
949 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
950 _session->playback_load(), _session->capture_load());
951 buffer_load_label.set_text (buf);
953 buffer_load_label.set_text ("");
958 ARDOUR_UI::count_recenabled_streams (Route& route)
960 Track* track = dynamic_cast<Track*>(&route);
961 if (track && track->diskstream()->record_enabled()) {
962 rec_enabled_streams += track->n_inputs().n_total();
967 ARDOUR_UI::update_disk_space()
973 nframes_t frames = _session->available_capture_duration();
975 nframes_t fr = _session->frame_rate();
977 if (frames == max_frames) {
978 strcpy (buf, _("Disk: 24hrs+"));
980 rec_enabled_streams = 0;
981 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
983 if (rec_enabled_streams) {
984 frames /= rec_enabled_streams;
991 hrs = frames / (fr * 3600);
992 frames -= hrs * fr * 3600;
993 mins = frames / (fr * 60);
994 frames -= mins * fr * 60;
997 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1000 disk_space_label.set_text (buf);
1002 // An attempt to make the disk space label flash red when space has run out.
1004 if (frames < fr * 60 * 5) {
1005 /* disk_space_box.style ("disk_space_label_empty"); */
1007 /* disk_space_box.style ("disk_space_label"); */
1013 ARDOUR_UI::update_wall_clock ()
1020 tm_now = localtime (&now);
1022 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1023 wall_clock_label.set_text (buf);
1029 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1031 session_popup_menu->popup (0, 0);
1036 ARDOUR_UI::redisplay_recent_sessions ()
1038 std::vector<sys::path> session_directories;
1039 RecentSessionsSorter cmp;
1041 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1042 recent_session_model->clear ();
1044 ARDOUR::RecentSessions rs;
1045 ARDOUR::read_recent_sessions (rs);
1048 recent_session_display.set_model (recent_session_model);
1052 // sort them alphabetically
1053 sort (rs.begin(), rs.end(), cmp);
1055 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1056 session_directories.push_back ((*i).second);
1059 for (vector<sys::path>::const_iterator i = session_directories.begin();
1060 i != session_directories.end(); ++i)
1062 std::vector<sys::path> state_file_paths;
1064 // now get available states for this session
1066 get_state_files_in_directory (*i, state_file_paths);
1068 vector<string*>* states;
1069 vector<const gchar*> item;
1070 string fullpath = (*i).to_string();
1072 /* remove any trailing / */
1074 if (fullpath[fullpath.length()-1] == '/') {
1075 fullpath = fullpath.substr (0, fullpath.length()-1);
1078 /* check whether session still exists */
1079 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1080 /* session doesn't exist */
1081 cerr << "skipping non-existent session " << fullpath << endl;
1085 /* now get available states for this session */
1087 if ((states = Session::possible_states (fullpath)) == 0) {
1088 /* no state file? */
1092 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1094 Gtk::TreeModel::Row row = *(recent_session_model->append());
1096 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1097 row[recent_session_columns.fullpath] = fullpath;
1099 if (state_file_names.size() > 1) {
1103 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1104 i2 != state_file_names.end(); ++i2)
1107 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1109 child_row[recent_session_columns.visible_name] = *i2;
1110 child_row[recent_session_columns.fullpath] = fullpath;
1115 recent_session_display.set_model (recent_session_model);
1119 ARDOUR_UI::build_session_selector ()
1121 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1123 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1125 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1126 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1127 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1128 recent_session_model = TreeStore::create (recent_session_columns);
1129 recent_session_display.set_model (recent_session_model);
1130 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1131 recent_session_display.set_headers_visible (false);
1132 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1133 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1135 scroller->add (recent_session_display);
1136 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1138 session_selector_window->set_name ("SessionSelectorWindow");
1139 session_selector_window->set_size_request (200, 400);
1140 session_selector_window->get_vbox()->pack_start (*scroller);
1142 recent_session_display.show();
1144 //session_selector_window->get_vbox()->show();
1148 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1150 session_selector_window->response (RESPONSE_ACCEPT);
1154 ARDOUR_UI::open_recent_session ()
1156 bool can_return = (_session != 0);
1158 if (session_selector_window == 0) {
1159 build_session_selector ();
1162 redisplay_recent_sessions ();
1166 session_selector_window->set_position (WIN_POS_MOUSE);
1168 ResponseType r = (ResponseType) session_selector_window->run ();
1171 case RESPONSE_ACCEPT:
1175 session_selector_window->hide();
1182 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1186 session_selector_window->hide();
1188 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1190 if (i == recent_session_model->children().end()) {
1194 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1195 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1197 _session_is_new = false;
1199 if (load_session (path, state) == 0) {
1208 ARDOUR_UI::check_audioengine ()
1211 if (!engine->connected()) {
1212 MessageDialog msg (_("Ardour is not connected to JACK\n"
1213 "You cannot open or close sessions in this condition"));
1225 ARDOUR_UI::open_session ()
1227 if (!check_audioengine()) {
1232 /* popup selector window */
1234 if (open_session_selector == 0) {
1236 /* ardour sessions are folders */
1238 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1239 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1240 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1241 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1243 FileFilter session_filter;
1244 session_filter.add_pattern ("*.ardour");
1245 session_filter.set_name (_("Ardour sessions"));
1246 open_session_selector->add_filter (session_filter);
1247 open_session_selector->set_filter (session_filter);
1250 int response = open_session_selector->run();
1251 open_session_selector->hide ();
1254 case RESPONSE_ACCEPT:
1257 open_session_selector->hide();
1261 open_session_selector->hide();
1262 string session_path = open_session_selector->get_filename();
1266 if (session_path.length() > 0) {
1267 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1268 _session_is_new = isnew;
1269 load_session (path, name);
1276 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1278 list<boost::shared_ptr<MidiTrack> > tracks;
1280 if (_session == 0) {
1281 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1288 tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1290 if (tracks.size() != how_many) {
1291 if (how_many == 1) {
1292 error << _("could not create a new midi track") << endmsg;
1294 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1298 if ((route = _session->new_midi_route ()) == 0) {
1299 error << _("could not create new midi bus") << endmsg;
1305 MessageDialog msg (*editor,
1306 _("There are insufficient JACK ports available\n\
1307 to create a new track or bus.\n\
1308 You should save Ardour, exit and\n\
1309 restart JACK with more ports."));
1316 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)
1318 list<boost::shared_ptr<AudioTrack> > tracks;
1321 if (_session == 0) {
1322 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1328 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1330 if (tracks.size() != how_many) {
1331 if (how_many == 1) {
1332 error << _("could not create a new audio track") << endmsg;
1334 error << string_compose (_("could only create %1 of %2 new audio %3"),
1335 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1341 routes = _session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1343 if (routes.size() != how_many) {
1344 if (how_many == 1) {
1345 error << _("could not create a new audio track") << endmsg;
1347 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1353 if (need_control_room_outs) {
1359 route->set_stereo_control_outs (control_lr_channels);
1360 route->control_outs()->set_stereo_pan (pans, this);
1362 #endif /* CONTROLOUTS */
1366 MessageDialog msg (*editor,
1367 _("There are insufficient JACK ports available\n\
1368 to create a new track or bus.\n\
1369 You should save Ardour, exit and\n\
1370 restart JACK with more ports."));
1377 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1379 nframes_t _preroll = 0;
1382 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1383 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1385 if (new_position > _preroll) {
1386 new_position -= _preroll;
1391 _session->request_locate (new_position);
1396 ARDOUR_UI::transport_goto_start ()
1399 _session->goto_start();
1401 /* force displayed area in editor to start no matter
1402 what "follow playhead" setting is.
1406 editor->center_screen (_session->current_start_frame ());
1412 ARDOUR_UI::transport_goto_zero ()
1415 _session->request_locate (0);
1418 /* force displayed area in editor to start no matter
1419 what "follow playhead" setting is.
1423 editor->reset_x_origin (0);
1429 ARDOUR_UI::transport_goto_wallclock ()
1431 if (_session && editor) {
1438 localtime_r (&now, &tmnow);
1440 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1441 frames += tmnow.tm_min * (60 * _session->frame_rate());
1442 frames += tmnow.tm_sec * _session->frame_rate();
1444 _session->request_locate (frames);
1446 /* force displayed area in editor to start no matter
1447 what "follow playhead" setting is.
1451 editor->center_screen (frames);
1457 ARDOUR_UI::transport_goto_end ()
1460 nframes_t const frame = _session->current_end_frame();
1461 _session->request_locate (frame);
1463 /* force displayed area in editor to start no matter
1464 what "follow playhead" setting is.
1468 editor->center_screen (frame);
1474 ARDOUR_UI::transport_stop ()
1480 if (_session->is_auditioning()) {
1481 _session->cancel_audition ();
1485 _session->request_stop ();
1489 ARDOUR_UI::transport_stop_and_forget_capture ()
1492 _session->request_stop (true);
1497 ARDOUR_UI::remove_last_capture()
1500 editor->remove_last_capture();
1505 ARDOUR_UI::transport_record (bool roll)
1509 switch (_session->record_status()) {
1510 case Session::Disabled:
1511 if (_session->ntracks() == 0) {
1512 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1516 _session->maybe_enable_record ();
1521 case Session::Recording:
1523 _session->request_stop();
1525 _session->disable_record (false, true);
1529 case Session::Enabled:
1530 _session->disable_record (false, true);
1533 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1537 ARDOUR_UI::transport_roll ()
1543 if (_session->is_auditioning()) {
1547 if (_session->config.get_external_sync()) {
1548 switch (_session->config.get_sync_source()) {
1552 /* transport controlled by the master */
1557 bool rolling = _session->transport_rolling();
1559 if (_session->get_play_loop()) {
1560 _session->request_play_loop (false, true);
1561 } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1562 /* stop playing a range if we currently are */
1563 _session->request_play_range (0, true);
1566 if (join_play_range_button.get_active()) {
1567 _session->request_play_range (&editor->get_selection().time, true);
1571 _session->request_transport_speed (1.0f);
1574 map_transport_state ();
1578 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1585 if (_session->is_auditioning()) {
1586 _session->cancel_audition ();
1590 if (_session->config.get_external_sync()) {
1591 switch (_session->config.get_sync_source()) {
1595 /* transport controlled by the master */
1600 bool rolling = _session->transport_rolling();
1601 bool affect_transport = true;
1603 if (rolling && roll_out_of_bounded_mode) {
1604 /* drop out of loop/range playback but leave transport rolling */
1605 if (_session->get_play_loop()) {
1606 if (Config->get_seamless_loop()) {
1607 /* the disk buffers contain copies of the loop - we can't
1608 just keep playing, so stop the transport. the user
1609 can restart as they wish.
1611 affect_transport = true;
1613 /* disk buffers are normal, so we can keep playing */
1614 affect_transport = false;
1616 _session->request_play_loop (false, true);
1617 } else if (_session->get_play_range ()) {
1618 affect_transport = false;
1619 _session->request_play_range (0, true);
1623 if (affect_transport) {
1625 _session->request_stop (with_abort, true);
1627 if (join_play_range_button.get_active()) {
1628 _session->request_play_range (&editor->get_selection().time, true);
1631 _session->request_transport_speed (1.0f);
1635 map_transport_state ();
1639 ARDOUR_UI::toggle_session_auto_loop ()
1642 if (_session->get_play_loop()) {
1643 if (_session->transport_rolling()) {
1644 Location * looploc = _session->locations()->auto_loop_location();
1646 _session->request_locate (looploc->start(), true);
1649 _session->request_play_loop (false);
1652 Location * looploc = _session->locations()->auto_loop_location();
1654 _session->request_play_loop (true);
1661 ARDOUR_UI::transport_play_selection ()
1667 editor->play_selection ();
1671 ARDOUR_UI::transport_rewind (int option)
1673 float current_transport_speed;
1676 current_transport_speed = _session->transport_speed();
1678 if (current_transport_speed >= 0.0f) {
1681 _session->request_transport_speed (-1.0f);
1684 _session->request_transport_speed (-4.0f);
1687 _session->request_transport_speed (-0.5f);
1692 _session->request_transport_speed (current_transport_speed * 1.5f);
1698 ARDOUR_UI::transport_forward (int option)
1700 float current_transport_speed;
1703 current_transport_speed = _session->transport_speed();
1705 if (current_transport_speed <= 0.0f) {
1708 _session->request_transport_speed (1.0f);
1711 _session->request_transport_speed (4.0f);
1714 _session->request_transport_speed (0.5f);
1719 _session->request_transport_speed (current_transport_speed * 1.5f);
1726 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1728 if (_session == 0) {
1732 boost::shared_ptr<Route> r;
1734 if ((r = _session->route_by_remote_id (dstream)) != 0) {
1738 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1739 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1742 if (_session == 0) {
1748 ARDOUR_UI::map_transport_state ()
1750 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1753 auto_loop_button.set_visual_state (0);
1754 play_selection_button.set_visual_state (0);
1755 roll_button.set_visual_state (0);
1756 stop_button.set_visual_state (1);
1760 float sp = _session->transport_speed();
1763 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1764 shuttle_box.queue_draw ();
1765 } else if (sp == 0.0f) {
1767 shuttle_box.queue_draw ();
1768 update_disk_space ();
1775 if (_session->get_play_range()) {
1777 play_selection_button.set_visual_state (1);
1778 roll_button.set_visual_state (0);
1779 auto_loop_button.set_visual_state (0);
1781 } else if (_session->get_play_loop ()) {
1783 auto_loop_button.set_visual_state (1);
1784 play_selection_button.set_visual_state (0);
1785 roll_button.set_visual_state (0);
1789 roll_button.set_visual_state (1);
1790 play_selection_button.set_visual_state (0);
1791 auto_loop_button.set_visual_state (0);
1794 if (join_play_range_button.get_active()) {
1795 /* light up both roll and play-selection if they are joined */
1796 roll_button.set_visual_state (1);
1797 play_selection_button.set_visual_state (1);
1800 stop_button.set_visual_state (0);
1804 stop_button.set_visual_state (1);
1805 roll_button.set_visual_state (0);
1806 play_selection_button.set_visual_state (0);
1807 auto_loop_button.set_visual_state (0);
1813 ARDOUR_UI::engine_stopped ()
1815 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1816 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1817 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1821 ARDOUR_UI::engine_running ()
1823 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1824 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1825 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1827 Glib::RefPtr<Action> action;
1828 const char* action_name = 0;
1830 switch (engine->frames_per_cycle()) {
1832 action_name = X_("JACKLatency32");
1835 action_name = X_("JACKLatency64");
1838 action_name = X_("JACKLatency128");
1841 action_name = X_("JACKLatency512");
1844 action_name = X_("JACKLatency1024");
1847 action_name = X_("JACKLatency2048");
1850 action_name = X_("JACKLatency4096");
1853 action_name = X_("JACKLatency8192");
1856 /* XXX can we do anything useful ? */
1862 action = ActionManager::get_action (X_("JACK"), action_name);
1865 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1866 ract->set_active ();
1872 ARDOUR_UI::engine_halted ()
1874 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
1876 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1877 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1879 update_sample_rate (0);
1881 MessageDialog msg (*editor,
1883 JACK has either been shutdown or it\n\
1884 disconnected Ardour because Ardour\n\
1885 was not fast enough. Try to restart\n\
1886 JACK, reconnect and save the session."));
1892 ARDOUR_UI::do_engine_start ()
1900 error << _("Unable to start the session running")
1910 ARDOUR_UI::setup_theme ()
1912 theme_manager->setup_theme();
1916 ARDOUR_UI::update_clocks ()
1918 if (!editor || !editor->dragging_playhead()) {
1919 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1924 ARDOUR_UI::start_clocking ()
1926 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1930 ARDOUR_UI::stop_clocking ()
1932 clock_signal_connection.disconnect ();
1936 ARDOUR_UI::toggle_clocking ()
1939 if (clock_button.get_active()) {
1948 ARDOUR_UI::_blink (void *arg)
1951 ((ARDOUR_UI *) arg)->blink ();
1958 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1962 ARDOUR_UI::start_blinking ()
1964 /* Start the blink signal. Everybody with a blinking widget
1965 uses Blink to drive the widget's state.
1968 if (blink_timeout_tag < 0) {
1970 blink_timeout_tag = g_timeout_add (240, _blink, this);
1975 ARDOUR_UI::stop_blinking ()
1977 if (blink_timeout_tag >= 0) {
1978 g_source_remove (blink_timeout_tag);
1979 blink_timeout_tag = -1;
1984 /** Ask the user for the name of a new shapshot and then take it.
1987 ARDOUR_UI::snapshot_session ()
1989 ArdourPrompter prompter (true);
1993 struct tm local_time;
1996 localtime_r (&n, &local_time);
1997 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1999 prompter.set_name ("Prompter");
2000 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2001 prompter.set_title (_("Take Snapshot"));
2002 prompter.set_prompt (_("Name of New Snapshot"));
2003 prompter.set_initial_text (timebuf);
2005 switch (prompter.run()) {
2006 case RESPONSE_ACCEPT:
2008 prompter.get_result (snapname);
2010 bool do_save = (snapname.length() != 0);
2012 vector<sys::path> p;
2013 get_state_files_in_directory (_session->session_directory().root_path(), p);
2014 vector<string> n = get_file_names_no_extension (p);
2015 if (find (n.begin(), n.end(), snapname) != n.end()) {
2017 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
2018 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2019 confirm.get_vbox()->pack_start (m, true, true);
2020 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2021 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2022 confirm.show_all ();
2023 switch (confirm.run()) {
2024 case RESPONSE_CANCEL:
2030 save_state (snapname);
2041 ARDOUR_UI::save_state (const string & name)
2043 (void) save_state_canfail (name);
2047 ARDOUR_UI::save_state_canfail (string name)
2052 if (name.length() == 0) {
2053 name = _session->snap_name();
2056 if ((ret = _session->save_state (name)) != 0) {
2060 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2065 ARDOUR_UI::primary_clock_value_changed ()
2068 _session->request_locate (primary_clock.current_time ());
2073 ARDOUR_UI::big_clock_value_changed ()
2076 _session->request_locate (big_clock.current_time ());
2081 ARDOUR_UI::secondary_clock_value_changed ()
2084 _session->request_locate (secondary_clock.current_time ());
2089 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2091 if (_session == 0) {
2095 Session::RecordState const r = _session->record_status ();
2096 bool const h = _session->have_rec_enabled_diskstream ();
2098 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2100 rec_button.set_visual_state (2);
2102 rec_button.set_visual_state (0);
2104 } else if (r == Session::Recording && h) {
2105 rec_button.set_visual_state (1);
2107 rec_button.set_visual_state (0);
2112 ARDOUR_UI::save_template ()
2114 ArdourPrompter prompter (true);
2117 if (!check_audioengine()) {
2121 prompter.set_name (X_("Prompter"));
2122 prompter.set_title (_("Save Mix Template"));
2123 prompter.set_prompt (_("Name for mix template:"));
2124 prompter.set_initial_text(_session->name() + _("-template"));
2125 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2127 switch (prompter.run()) {
2128 case RESPONSE_ACCEPT:
2129 prompter.get_result (name);
2131 if (name.length()) {
2132 _session->save_template (name);
2142 ARDOUR_UI::edit_metadata ()
2144 SessionMetadataEditor dialog;
2145 dialog.set_session (_session);
2146 editor->ensure_float (dialog);
2151 ARDOUR_UI::import_metadata ()
2153 SessionMetadataImporter dialog;
2154 dialog.set_session (_session);
2155 editor->ensure_float (dialog);
2160 ARDOUR_UI::fontconfig_dialog ()
2163 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2164 may not and it can take a while to build it. Warn them.
2167 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2169 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2170 MessageDialog msg (*_startup,
2171 _("Welcome to Ardour.\n\n"
2172 "The program will take a bit longer to start up\n"
2173 "while the system fonts are checked.\n\n"
2174 "This will only be done once, and you will\n"
2175 "not see this message again\n"),
2188 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2190 existing_session = false;
2192 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2193 session_path = cmdline_path;
2194 existing_session = true;
2195 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2196 session_path = Glib::path_get_dirname (string (cmdline_path));
2197 existing_session = true;
2199 /* it doesn't exist, assume the best */
2200 session_path = Glib::path_get_dirname (string (cmdline_path));
2203 session_name = basename_nosuffix (string (cmdline_path));
2207 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2209 /* when this is called, the backend audio system must be running */
2211 /* the main idea here is to deal with the fact that a cmdline argument for the session
2212 can be interpreted in different ways - it could be a directory or a file, and before
2213 we load, we need to know both the session directory and the snapshot (statefile) within it
2214 that we are supposed to use.
2217 if (session_name.length() == 0 || session_path.length() == 0) {
2221 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2223 Glib::ustring predicted_session_file;
2225 predicted_session_file = session_path;
2226 predicted_session_file += '/';
2227 predicted_session_file += session_name;
2228 predicted_session_file += ARDOUR::statefile_suffix;
2230 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2231 existing_session = true;
2234 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2236 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2237 /* existing .ardour file */
2238 existing_session = true;
2242 existing_session = false;
2245 /* lets just try to load it */
2247 if (create_engine ()) {
2248 backend_audio_error (false, _startup);
2252 return load_session (session_path, session_name);
2256 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2258 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2260 MessageDialog msg (str,
2262 Gtk::MESSAGE_WARNING,
2263 Gtk::BUTTONS_YES_NO,
2267 msg.set_name (X_("OpenExistingDialog"));
2268 msg.set_title (_("Open Existing Session"));
2269 msg.set_wmclass (X_("existing_session"), "Ardour");
2270 msg.set_position (Gtk::WIN_POS_MOUSE);
2273 switch (msg.run()) {
2282 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2287 AutoConnectOption iconnect;
2288 AutoConnectOption oconnect;
2292 if (Profile->get_sae()) {
2296 iconnect = AutoConnectPhysical;
2297 oconnect = AutoConnectMaster;
2298 nphysin = 0; // use all available
2299 nphysout = 0; // use all available
2303 /* get settings from advanced section of NSD */
2305 if (_startup->create_control_bus()) {
2306 cchns = (uint32_t) _startup->control_channel_count();
2311 if (_startup->create_master_bus()) {
2312 mchns = (uint32_t) _startup->master_channel_count();
2317 if (_startup->connect_inputs()) {
2318 iconnect = AutoConnectPhysical;
2320 iconnect = AutoConnectOption (0);
2323 /// @todo some minor tweaks.
2325 oconnect = AutoConnectOption (0);
2327 if (_startup->connect_outputs ()) {
2328 if (_startup->connect_outs_to_master()) {
2329 oconnect = AutoConnectMaster;
2330 } else if (_startup->connect_outs_to_physical()) {
2331 oconnect = AutoConnectPhysical;
2335 nphysin = (uint32_t) _startup->input_limit_count();
2336 nphysout = (uint32_t) _startup->output_limit_count();
2339 if (build_session (session_path,
2347 engine->frame_rate() * 60 * 5)) {
2356 ARDOUR_UI::idle_load (const Glib::ustring& path)
2359 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2360 /* /path/to/foo => /path/to/foo, foo */
2361 load_session (path, basename_nosuffix (path));
2363 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2364 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2368 ARDOUR_COMMAND_LINE::session_name = path;
2371 * new_session_dialog doens't exist in A3
2372 * Try to remove all references to it to
2373 * see if it will compile. NOTE: this will
2374 * likely cause a runtime issue is my somewhat
2378 //if (new_session_dialog) {
2381 /* make it break out of Dialog::run() and
2385 //new_session_dialog->response (1);
2391 ARDOUR_UI::end_loading_messages ()
2397 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2400 // splash->message (msg);
2404 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2406 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2408 Glib::ustring session_name;
2409 Glib::ustring session_path;
2410 Glib::ustring template_name;
2412 bool likely_new = false;
2416 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2418 /* if they named a specific statefile, use it, otherwise they are
2419 just giving a session folder, and we want to use it as is
2420 to find the session.
2423 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2424 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2426 session_path = ARDOUR_COMMAND_LINE::session_name;
2429 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2433 bool const apply = run_startup (should_be_new);
2435 if (quit_on_cancel) {
2442 /* if we run the startup dialog again, offer more than just "new session" */
2444 should_be_new = false;
2446 session_name = _startup->session_name (likely_new);
2448 /* this shouldn't happen, but we catch it just in case it does */
2450 if (session_name.empty()) {
2453 if (_startup->use_session_template()) {
2454 template_name = _startup->session_template_name();
2455 _session_is_new = true;
2458 if (session_name[0] == '/' ||
2459 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2460 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2462 session_path = Glib::path_get_dirname (session_name);
2463 session_name = Glib::path_get_basename (session_name);
2467 session_path = _startup->session_folder();
2471 if (create_engine ()) {
2475 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2479 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2481 if (!ask_about_loading_existing_session (existing)) {
2482 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2487 _session_is_new = false;
2492 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2494 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2498 _session_is_new = true;
2501 if (likely_new && template_name.empty()) {
2503 ret = build_session_from_nsd (session_path, session_name);
2507 ret = load_session (session_path, session_name, template_name);
2508 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2509 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2519 ARDOUR_UI::close_session()
2521 if (!check_audioengine()) {
2525 unload_session (true);
2527 ARDOUR_COMMAND_LINE::session_name = "";
2528 get_session_parameters (true, false);
2532 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2534 Session *new_session;
2538 session_loaded = false;
2540 if (!check_audioengine()) {
2544 unload_status = unload_session ();
2546 if (unload_status < 0) {
2548 } else if (unload_status > 0) {
2553 loading_message (_("Please wait while Ardour loads your session"));
2556 new_session = new Session (*engine, path, snap_name, mix_template);
2559 /* this one is special */
2561 catch (AudioEngine::PortRegistrationFailure& err) {
2563 MessageDialog msg (err.what(),
2566 Gtk::BUTTONS_CLOSE);
2568 msg.set_title (_("Port Registration Error"));
2569 msg.set_secondary_text (_("Click the Close button to try again."));
2570 msg.set_position (Gtk::WIN_POS_CENTER);
2574 int response = msg.run ();
2579 case RESPONSE_CANCEL:
2589 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2592 Gtk::BUTTONS_CLOSE);
2594 msg.set_title (_("Loading Error"));
2595 msg.set_secondary_text (_("Click the Close button to try again."));
2596 msg.set_position (Gtk::WIN_POS_CENTER);
2600 int response = msg.run ();
2605 case RESPONSE_CANCEL:
2613 set_session (new_session);
2615 session_loaded = true;
2617 goto_editor_window ();
2620 _session->set_clean ();
2631 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2632 uint32_t control_channels,
2633 uint32_t master_channels,
2634 AutoConnectOption input_connect,
2635 AutoConnectOption output_connect,
2638 nframes_t initial_length)
2640 Session *new_session;
2643 if (!check_audioengine()) {
2647 session_loaded = false;
2649 x = unload_session ();
2657 _session_is_new = true;
2660 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2661 control_channels, master_channels, nphysin, nphysout, initial_length);
2666 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2672 set_session (new_session);
2674 session_loaded = true;
2676 new_session->save_state(new_session->name());
2685 editor->show_window ();
2696 ARDOUR_UI::show_about ()
2700 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2707 ARDOUR_UI::hide_about ()
2710 about->get_window()->set_cursor ();
2716 ARDOUR_UI::about_signal_response (int /*response*/)
2722 ARDOUR_UI::show_splash ()
2726 splash = new Splash;
2734 splash->queue_draw ();
2735 splash->get_window()->process_updates (true);
2740 ARDOUR_UI::hide_splash ()
2748 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2749 const string& plural_msg, const string& singular_msg)
2753 removed = rep.paths.size();
2756 MessageDialog msgd (*editor,
2757 _("No audio files were ready for cleanup"),
2760 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2761 msgd.set_secondary_text (_("If this seems suprising, \n\
2762 check for any existing snapshots.\n\
2763 These may still include regions that\n\
2764 require some unused files to continue to exist."));
2770 ArdourDialog results (_("ardour: cleanup"), true, false);
2772 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2773 CleanupResultsModelColumns() {
2777 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2778 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2782 CleanupResultsModelColumns results_columns;
2783 Glib::RefPtr<Gtk::ListStore> results_model;
2784 Gtk::TreeView results_display;
2786 results_model = ListStore::create (results_columns);
2787 results_display.set_model (results_model);
2788 results_display.append_column (list_title, results_columns.visible_name);
2790 results_display.set_name ("CleanupResultsList");
2791 results_display.set_headers_visible (true);
2792 results_display.set_headers_clickable (false);
2793 results_display.set_reorderable (false);
2795 Gtk::ScrolledWindow list_scroller;
2798 Gtk::HBox dhbox; // the hbox for the image and text
2799 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2800 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2802 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2804 const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
2810 %1 - number of files removed
2811 %2 - location of "dead_sounds"
2812 %3 - size of files affected
2813 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2816 const char* bprefix;
2818 if (rep.space < 1048576.0f) {
2819 bprefix = X_("kilo");
2820 } else if (rep.space < 1048576.0f * 1000) {
2821 bprefix = X_("mega");
2823 bprefix = X_("giga");
2827 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2829 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2832 dhbox.pack_start (*dimage, true, false, 5);
2833 dhbox.pack_start (txt, true, false, 5);
2835 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2836 TreeModel::Row row = *(results_model->append());
2837 row[results_columns.visible_name] = *i;
2838 row[results_columns.fullpath] = *i;
2841 list_scroller.add (results_display);
2842 list_scroller.set_size_request (-1, 150);
2843 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2845 dvbox.pack_start (dhbox, true, false, 5);
2846 dvbox.pack_start (list_scroller, true, false, 5);
2847 ddhbox.pack_start (dvbox, true, false, 5);
2849 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2850 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2851 results.set_default_response (RESPONSE_CLOSE);
2852 results.set_position (Gtk::WIN_POS_MOUSE);
2854 results_display.show();
2855 list_scroller.show();
2862 //results.get_vbox()->show();
2863 results.set_resizable (false);
2870 ARDOUR_UI::cleanup ()
2872 if (_session == 0) {
2873 /* shouldn't happen: menu item is insensitive */
2878 MessageDialog checker (_("Are you sure you want to cleanup?"),
2880 Gtk::MESSAGE_QUESTION,
2881 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2883 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2884 ALL undo/redo information will be lost if you cleanup.\n\
2885 After cleanup, unused audio files will be moved to a \
2886 \"dead sounds\" location."));
2888 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2889 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2890 checker.set_default_response (RESPONSE_CANCEL);
2892 checker.set_name (_("CleanupDialog"));
2893 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2894 checker.set_position (Gtk::WIN_POS_MOUSE);
2896 switch (checker.run()) {
2897 case RESPONSE_ACCEPT:
2903 ARDOUR::CleanupReport rep;
2905 editor->prepare_for_cleanup ();
2907 /* do not allow flush until a session is reloaded */
2909 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2911 act->set_sensitive (false);
2914 if (_session->cleanup_sources (rep)) {
2915 editor->finish_cleanup ();
2919 editor->finish_cleanup ();
2922 display_cleanup_results (rep,
2925 The following %1 files were not in use and \n\
2926 have been moved to:\n\
2928 Flushing the wastebasket will \n\
2929 release an additional\n\
2930 %3 %4bytes of disk space.\n"),
2932 The following file was not in use and \n \
2933 has been moved to:\n \
2935 Flushing the wastebasket will \n\
2936 release an additional\n\
2937 %3 %4bytes of disk space.\n"
2943 ARDOUR_UI::flush_trash ()
2945 if (_session == 0) {
2946 /* shouldn't happen: menu item is insensitive */
2950 ARDOUR::CleanupReport rep;
2952 if (_session->cleanup_trash_sources (rep)) {
2956 display_cleanup_results (rep,
2958 _("The following %1 files were deleted from\n\
2960 releasing %3 %4bytes of disk space"),
2961 _("The following file was deleted from\n\
2963 releasing %3 %4bytes of disk space"));
2967 ARDOUR_UI::add_route (Gtk::Window* float_window)
2975 if (add_route_dialog == 0) {
2976 add_route_dialog = new AddRouteDialog (_session);
2978 add_route_dialog->set_transient_for (*float_window);
2982 if (add_route_dialog->is_visible()) {
2983 /* we're already doing this */
2987 ResponseType r = (ResponseType) add_route_dialog->run ();
2989 add_route_dialog->hide();
2992 case RESPONSE_ACCEPT:
2999 if ((count = add_route_dialog->count()) <= 0) {
3003 string template_path = add_route_dialog->track_template();
3005 if (!template_path.empty()) {
3006 _session->new_route_from_template (count, template_path);
3010 uint32_t input_chan = add_route_dialog->channels ();
3011 uint32_t output_chan;
3012 string name_template = add_route_dialog->name_template ();
3013 bool track = add_route_dialog->track ();
3014 bool aux = !track && add_route_dialog->aux();
3015 RouteGroup* route_group = add_route_dialog->route_group ();
3017 AutoConnectOption oac = Config->get_output_auto_connect();
3019 if (oac & AutoConnectMaster) {
3020 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3022 output_chan = input_chan;
3025 /* XXX do something with name template */
3027 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3029 session_add_midi_track (route_group, count);
3031 MessageDialog msg (*editor,
3032 _("Sorry, MIDI Busses are not supported at this time."));
3034 //session_add_midi_bus();
3038 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3040 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3046 ARDOUR_UI::mixer_settings () const
3051 node = _session->instant_xml(X_("Mixer"));
3053 node = Config->instant_xml(X_("Mixer"));
3057 node = new XMLNode (X_("Mixer"));
3064 ARDOUR_UI::editor_settings () const
3069 node = _session->instant_xml(X_("Editor"));
3071 node = Config->instant_xml(X_("Editor"));
3075 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3076 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3081 node = new XMLNode (X_("Editor"));
3088 ARDOUR_UI::keyboard_settings () const
3092 node = Config->extra_xml(X_("Keyboard"));
3095 node = new XMLNode (X_("Keyboard"));
3101 ARDOUR_UI::create_xrun_marker(nframes_t where)
3103 editor->mouse_add_new_marker (where, false, true);
3107 ARDOUR_UI::halt_on_xrun_message ()
3109 MessageDialog msg (*editor,
3110 _("Recording was stopped because your system could not keep up."));
3115 ARDOUR_UI::xrun_handler(nframes_t where)
3121 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3123 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3124 create_xrun_marker(where);
3127 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3128 halt_on_xrun_message ();
3133 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3138 while (disk_buffer_stats.size() > 60) {
3139 disk_buffer_stats.pop_front ();
3142 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3146 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 ();