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/openuri.h"
46 #include "pbd/file_utils.h"
48 #include "gtkmm2ext/gtk_ui.h"
49 #include "gtkmm2ext/utils.h"
50 #include "gtkmm2ext/click_box.h"
51 #include "gtkmm2ext/fastmeter.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 (PROGRAM_NAME, 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, false),
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;
217 original_big_clock_width = -1;
218 original_big_clock_height = -1;
219 original_big_clock_font_size = 0;
221 roll_button.unset_flags (Gtk::CAN_FOCUS);
222 stop_button.unset_flags (Gtk::CAN_FOCUS);
223 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
224 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
225 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
226 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
227 rec_button.unset_flags (Gtk::CAN_FOCUS);
229 last_configure_time= 0;
231 shuttle_grabbed = false;
233 shuttle_max_speed = 8.0f;
235 shuttle_style_menu = 0;
236 shuttle_unit_menu = 0;
238 // We do not have jack linked in yet so;
240 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
242 ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
243 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
245 /* handle dialog requests */
247 ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
249 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
251 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
253 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
255 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
257 /* lets get this party started */
260 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
261 throw failed_constructor ();
264 setup_gtk_ardour_enums ();
267 GainMeter::setup_slider_pix ();
268 RouteTimeAxisView::setup_slider_pix ();
269 SendProcessorEntry::setup_slider_pix ();
270 SessionEvent::create_per_thread_pool ("GUI", 512);
272 } catch (failed_constructor& err) {
273 error << _("could not initialize Ardour.") << endmsg;
278 /* we like keyboards */
280 keyboard = new ArdourKeyboard(*this);
282 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
284 keyboard->set_state (*node, Stateful::loading_state_version);
289 starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
290 stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
295 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
297 ARDOUR_UI::run_startup (bool should_be_new)
300 _startup = new ArdourStartup ();
303 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
305 if (audio_setup && _startup->engine_control()) {
306 _startup->engine_control()->set_state (*audio_setup);
309 _startup->set_new_only (should_be_new);
310 _startup->present ();
316 switch (_startup->response()) {
325 ARDOUR_UI::create_engine ()
327 // this gets called every time by new_session()
333 loading_message (_("Starting audio engine"));
336 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
343 engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
344 engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
345 engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
347 engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
355 ARDOUR_UI::post_engine ()
357 /* Things to be done once we create the AudioEngine
360 MIDI::Manager::instance()->set_api_data (engine->jack());
363 ARDOUR::init_post_engine ();
365 ActionManager::init ();
368 if (setup_windows ()) {
369 throw failed_constructor ();
372 check_memory_locking();
374 /* this is the first point at which all the keybindings are available */
376 if (ARDOUR_COMMAND_LINE::show_key_actions) {
377 vector<string> names;
378 vector<string> paths;
380 vector<AccelKey> bindings;
382 ActionManager::get_all_actions (names, paths, keys, bindings);
384 vector<string>::iterator n;
385 vector<string>::iterator k;
386 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
387 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
393 blink_timeout_tag = -1;
395 /* this being a GUI and all, we want peakfiles */
397 AudioFileSource::set_build_peakfiles (true);
398 AudioFileSource::set_build_missing_peakfiles (true);
400 /* set default clock modes */
402 if (Profile->get_sae()) {
403 primary_clock.set_mode (AudioClock::BBT);
404 secondary_clock.set_mode (AudioClock::MinSec);
406 primary_clock.set_mode (AudioClock::Timecode);
407 secondary_clock.set_mode (AudioClock::BBT);
410 /* start the time-of-day-clock */
413 /* OS X provides a nearly-always visible wallclock, so don't be stupid */
414 update_wall_clock ();
415 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
418 update_disk_space ();
420 update_sample_rate (engine->frame_rate());
422 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
423 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
424 Config->map_parameters (pc);
426 /* now start and maybe save state */
428 if (do_engine_start () == 0) {
429 if (_session && _session_is_new) {
430 /* we need to retain initial visual
431 settings for a new session
433 _session->save_state ("");
438 ARDOUR_UI::~ARDOUR_UI ()
443 delete add_route_dialog;
447 ARDOUR_UI::pop_back_splash ()
449 if (Splash::instance()) {
450 // Splash::instance()->pop_back();
451 Splash::instance()->hide ();
456 ARDOUR_UI::configure_timeout ()
458 if (last_configure_time == 0) {
459 /* no configure events yet */
463 /* force a gap of 0.5 seconds since the last configure event
466 if (get_microseconds() - last_configure_time < 500000) {
469 have_configure_timeout = false;
470 cerr << "config event-driven save\n";
471 save_ardour_state ();
477 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
479 if (have_configure_timeout) {
480 last_configure_time = get_microseconds();
482 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
483 have_configure_timeout = true;
490 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
492 const XMLProperty* prop;
494 if ((prop = node.property ("roll")) != 0) {
495 roll_controllable->set_id (prop->value());
497 if ((prop = node.property ("stop")) != 0) {
498 stop_controllable->set_id (prop->value());
500 if ((prop = node.property ("goto-start")) != 0) {
501 goto_start_controllable->set_id (prop->value());
503 if ((prop = node.property ("goto-end")) != 0) {
504 goto_end_controllable->set_id (prop->value());
506 if ((prop = node.property ("auto-loop")) != 0) {
507 auto_loop_controllable->set_id (prop->value());
509 if ((prop = node.property ("play-selection")) != 0) {
510 play_selection_controllable->set_id (prop->value());
512 if ((prop = node.property ("rec")) != 0) {
513 rec_controllable->set_id (prop->value());
515 if ((prop = node.property ("shuttle")) != 0) {
516 shuttle_controllable->set_id (prop->value());
521 ARDOUR_UI::get_transport_controllable_state ()
523 XMLNode* node = new XMLNode(X_("TransportControllables"));
526 roll_controllable->id().print (buf, sizeof (buf));
527 node->add_property (X_("roll"), buf);
528 stop_controllable->id().print (buf, sizeof (buf));
529 node->add_property (X_("stop"), buf);
530 goto_start_controllable->id().print (buf, sizeof (buf));
531 node->add_property (X_("goto_start"), buf);
532 goto_end_controllable->id().print (buf, sizeof (buf));
533 node->add_property (X_("goto_end"), buf);
534 auto_loop_controllable->id().print (buf, sizeof (buf));
535 node->add_property (X_("auto_loop"), buf);
536 play_selection_controllable->id().print (buf, sizeof (buf));
537 node->add_property (X_("play_selection"), buf);
538 rec_controllable->id().print (buf, sizeof (buf));
539 node->add_property (X_("rec"), buf);
540 shuttle_controllable->id().print (buf, sizeof (buf));
541 node->add_property (X_("shuttle"), buf);
548 ARDOUR_UI::autosave_session ()
550 if (g_main_depth() > 1) {
551 /* inside a recursive main loop,
552 give up because we may not be able to
558 if (!Config->get_periodic_safety_backups()) {
563 _session->maybe_write_autosave();
570 ARDOUR_UI::update_autosave ()
572 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
574 if (_session && _session->dirty()) {
575 if (_autosave_connection.connected()) {
576 _autosave_connection.disconnect();
579 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
580 Config->get_periodic_safety_backup_interval() * 1000);
583 if (_autosave_connection.connected()) {
584 _autosave_connection.disconnect();
590 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
594 title = string_compose (_("%1 could not start JACK"), PROGRAM_NAME);
596 title = string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME);
599 MessageDialog win (title,
605 win.set_secondary_text(_("There are several possible reasons:\n\
607 1) You requested audio parameters that are not supported..\n\
608 2) JACK is running as another user.\n\
610 Please consider the possibilities, and perhaps try different parameters."));
612 win.set_secondary_text(_("There are several possible reasons:\n\
614 1) JACK is not running.\n\
615 2) JACK is running as another user, perhaps root.\n\
616 3) There is already another client called \"ardour\".\n\
618 Please consider the possibilities, and perhaps (re)start JACK."));
622 win.set_transient_for (*toplevel);
626 win.add_button (Stock::OK, RESPONSE_CLOSE);
628 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
631 win.set_default_response (RESPONSE_CLOSE);
634 win.set_position (Gtk::WIN_POS_CENTER);
637 /* we just don't care about the result, but we want to block */
643 ARDOUR_UI::startup ()
645 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
651 goto_editor_window ();
653 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
658 ARDOUR_UI::no_memory_warning ()
660 XMLNode node (X_("no-memory-warning"));
661 Config->add_instant_xml (node);
665 ARDOUR_UI::check_memory_locking ()
668 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
672 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
674 if (engine->is_realtime() && memory_warning_node == 0) {
676 struct rlimit limits;
678 long pages, page_size;
680 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
683 ram = (int64_t) pages * (int64_t) page_size;
686 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
690 if (limits.rlim_cur != RLIM_INFINITY) {
692 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
695 MessageDialog msg (string_compose (_("WARNING: Your system has a limit for maximum amount of locked memory. "
696 "This might cause %1 to run out of memory before your system "
697 "runs out of memory. \n\n"
698 "You can view the memory limit with 'ulimit -l', "
699 "and it is normally controlled by /etc/security/limits.conf"),
700 PROGRAM_NAME).c_str());
702 VBox* vbox = msg.get_vbox();
704 CheckButton cb (_("Do not show this window again"));
706 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
708 hbox.pack_start (cb, true, false);
709 vbox->pack_start (hbox);
716 editor->ensure_float (msg);
731 if (_session->transport_rolling() && (++tries < 8)) {
732 _session->request_stop (false, true);
736 if (_session->dirty()) {
737 switch (ask_about_saving_session(_("quit"))) {
742 /* use the default name */
743 if (save_state_canfail ("")) {
744 /* failed - don't quit */
745 MessageDialog msg (*editor,
747 Ardour was unable to save your session.\n\n\
748 If you still wish to quit, please use the\n\n\
749 \"Just quit\" option."));
760 second_connection.disconnect ();
761 point_one_second_connection.disconnect ();
762 point_oh_five_second_connection.disconnect ();
763 point_zero_one_second_connection.disconnect();
765 // _session->set_deletion_in_progress ();
766 _session->remove_pending_capture_state ();
771 cerr << "Save before quit\n";
772 save_ardour_state ();
774 ArdourDialog::close_all_dialogs ();
780 ARDOUR_UI::ask_about_saving_session (const string & what)
782 ArdourDialog window (_("Unsaved Session"));
783 Gtk::HBox dhbox; // the hbox for the image and text
784 Gtk::Label prompt_label;
785 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
789 msg = string_compose(_("Don't %1"), what);
790 window.add_button (msg, RESPONSE_REJECT);
791 msg = string_compose(_("Just %1"), what);
792 window.add_button (msg, RESPONSE_APPLY);
793 msg = string_compose(_("Save and %1"), what);
794 window.add_button (msg, RESPONSE_ACCEPT);
796 window.set_default_response (RESPONSE_ACCEPT);
798 Gtk::Button noquit_button (msg);
799 noquit_button.set_name ("EditorGTKButton");
804 if (_session->snap_name() == _session->name()) {
807 type = _("snapshot");
809 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?"),
810 type, _session->snap_name());
812 prompt_label.set_text (prompt);
813 prompt_label.set_name (X_("PrompterLabel"));
814 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
816 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
817 dhbox.set_homogeneous (false);
818 dhbox.pack_start (*dimage, false, false, 5);
819 dhbox.pack_start (prompt_label, true, false, 5);
820 window.get_vbox()->pack_start (dhbox);
822 window.set_name (_("Prompter"));
823 window.set_position (Gtk::WIN_POS_MOUSE);
824 window.set_modal (true);
825 window.set_resizable (false);
831 window.set_keep_above (true);
834 ResponseType r = (ResponseType) window.run();
839 case RESPONSE_ACCEPT: // save and get out of here
841 case RESPONSE_APPLY: // get out of here
851 ARDOUR_UI::every_second ()
854 update_buffer_load ();
855 update_disk_space ();
860 ARDOUR_UI::every_point_one_seconds ()
862 update_speed_display ();
863 RapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::every_point_zero_one_seconds ()
870 // august 2007: actual update frequency: 40Hz, not 100Hz
872 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
877 ARDOUR_UI::update_sample_rate (nframes_t)
881 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
883 if (!engine->connected()) {
885 snprintf (buf, sizeof (buf), _("disconnected"));
889 nframes_t rate = engine->frame_rate();
891 if (fmod (rate, 1000.0) != 0.0) {
892 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
893 (float) rate/1000.0f,
894 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
896 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
898 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
902 sample_rate_label.set_text (buf);
906 ARDOUR_UI::update_cpu_load ()
909 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
910 cpu_load_label.set_text (buf);
914 ARDOUR_UI::update_buffer_load ()
920 c = _session->capture_load ();
921 p = _session->playback_load ();
923 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
924 _session->playback_load(), _session->capture_load());
925 buffer_load_label.set_text (buf);
927 buffer_load_label.set_text ("");
932 ARDOUR_UI::count_recenabled_streams (Route& route)
934 Track* track = dynamic_cast<Track*>(&route);
935 if (track && track->record_enabled()) {
936 rec_enabled_streams += track->n_inputs().n_total();
941 ARDOUR_UI::update_disk_space()
947 nframes_t frames = _session->available_capture_duration();
949 nframes_t fr = _session->frame_rate();
951 if (frames == max_frames) {
952 strcpy (buf, _("Disk: 24hrs+"));
954 rec_enabled_streams = 0;
955 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
957 if (rec_enabled_streams) {
958 frames /= rec_enabled_streams;
965 hrs = frames / (fr * 3600);
966 frames -= hrs * fr * 3600;
967 mins = frames / (fr * 60);
968 frames -= mins * fr * 60;
971 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
974 disk_space_label.set_text (buf);
976 // An attempt to make the disk space label flash red when space has run out.
978 if (frames < fr * 60 * 5) {
979 /* disk_space_box.style ("disk_space_label_empty"); */
981 /* disk_space_box.style ("disk_space_label"); */
987 ARDOUR_UI::update_wall_clock ()
994 tm_now = localtime (&now);
996 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
997 wall_clock_label.set_text (buf);
1003 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1005 session_popup_menu->popup (0, 0);
1010 ARDOUR_UI::redisplay_recent_sessions ()
1012 std::vector<sys::path> session_directories;
1013 RecentSessionsSorter cmp;
1015 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1016 recent_session_model->clear ();
1018 ARDOUR::RecentSessions rs;
1019 ARDOUR::read_recent_sessions (rs);
1022 recent_session_display.set_model (recent_session_model);
1026 // sort them alphabetically
1027 sort (rs.begin(), rs.end(), cmp);
1029 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1030 session_directories.push_back ((*i).second);
1033 for (vector<sys::path>::const_iterator i = session_directories.begin();
1034 i != session_directories.end(); ++i)
1036 std::vector<sys::path> state_file_paths;
1038 // now get available states for this session
1040 get_state_files_in_directory (*i, state_file_paths);
1042 vector<string*>* states;
1043 vector<const gchar*> item;
1044 string fullpath = (*i).to_string();
1046 /* remove any trailing / */
1048 if (fullpath[fullpath.length()-1] == '/') {
1049 fullpath = fullpath.substr (0, fullpath.length()-1);
1052 /* check whether session still exists */
1053 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1054 /* session doesn't exist */
1055 cerr << "skipping non-existent session " << fullpath << endl;
1059 /* now get available states for this session */
1061 if ((states = Session::possible_states (fullpath)) == 0) {
1062 /* no state file? */
1066 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1068 Gtk::TreeModel::Row row = *(recent_session_model->append());
1070 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1071 row[recent_session_columns.fullpath] = fullpath;
1073 if (state_file_names.size() > 1) {
1077 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1078 i2 != state_file_names.end(); ++i2)
1081 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1083 child_row[recent_session_columns.visible_name] = *i2;
1084 child_row[recent_session_columns.fullpath] = fullpath;
1089 recent_session_display.set_model (recent_session_model);
1093 ARDOUR_UI::build_session_selector ()
1095 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1097 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1099 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1100 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1101 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1102 recent_session_model = TreeStore::create (recent_session_columns);
1103 recent_session_display.set_model (recent_session_model);
1104 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1105 recent_session_display.set_headers_visible (false);
1106 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1107 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1109 scroller->add (recent_session_display);
1110 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1112 session_selector_window->set_name ("SessionSelectorWindow");
1113 session_selector_window->set_size_request (200, 400);
1114 session_selector_window->get_vbox()->pack_start (*scroller);
1116 recent_session_display.show();
1118 //session_selector_window->get_vbox()->show();
1122 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1124 session_selector_window->response (RESPONSE_ACCEPT);
1128 ARDOUR_UI::open_recent_session ()
1130 bool can_return = (_session != 0);
1132 if (session_selector_window == 0) {
1133 build_session_selector ();
1136 redisplay_recent_sessions ();
1140 session_selector_window->set_position (WIN_POS_MOUSE);
1142 ResponseType r = (ResponseType) session_selector_window->run ();
1145 case RESPONSE_ACCEPT:
1149 session_selector_window->hide();
1156 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1160 session_selector_window->hide();
1162 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1164 if (i == recent_session_model->children().end()) {
1168 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1169 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1171 _session_is_new = false;
1173 if (load_session (path, state) == 0) {
1182 ARDOUR_UI::check_audioengine ()
1185 if (!engine->connected()) {
1186 MessageDialog msg (string_compose (_("%1 is not connected to JACK\n"
1187 "You cannot open or close sessions in this condition"),
1200 ARDOUR_UI::open_session ()
1202 if (!check_audioengine()) {
1207 /* popup selector window */
1209 if (open_session_selector == 0) {
1211 /* ardour sessions are folders */
1213 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1214 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1215 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1216 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1218 FileFilter session_filter;
1219 session_filter.add_pattern ("*.ardour");
1220 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1221 open_session_selector->add_filter (session_filter);
1222 open_session_selector->set_filter (session_filter);
1225 int response = open_session_selector->run();
1226 open_session_selector->hide ();
1229 case RESPONSE_ACCEPT:
1232 open_session_selector->hide();
1236 open_session_selector->hide();
1237 string session_path = open_session_selector->get_filename();
1241 if (session_path.length() > 0) {
1242 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1243 _session_is_new = isnew;
1244 load_session (path, name);
1251 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1253 list<boost::shared_ptr<MidiTrack> > tracks;
1255 if (_session == 0) {
1256 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1263 tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1265 if (tracks.size() != how_many) {
1266 if (how_many == 1) {
1267 error << _("could not create a new midi track") << endmsg;
1269 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1273 if ((route = _session->new_midi_route ()) == 0) {
1274 error << _("could not create new midi bus") << endmsg;
1280 MessageDialog msg (*editor,
1281 _("There are insufficient JACK ports available\n\
1282 to create a new track or bus.\n\
1283 You should save Ardour, exit and\n\
1284 restart JACK with more ports."));
1291 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)
1293 list<boost::shared_ptr<AudioTrack> > tracks;
1296 if (_session == 0) {
1297 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1303 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1305 if (tracks.size() != how_many) {
1306 if (how_many == 1) {
1307 error << _("could not create a new audio track") << endmsg;
1309 error << string_compose (_("could only create %1 of %2 new audio %3"),
1310 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1316 routes = _session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1318 if (routes.size() != how_many) {
1319 if (how_many == 1) {
1320 error << _("could not create a new audio track") << endmsg;
1322 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1329 MessageDialog msg (*editor,
1330 _("There are insufficient JACK ports available\n\
1331 to create a new track or bus.\n\
1332 You should save Ardour, exit and\n\
1333 restart JACK with more ports."));
1340 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1342 nframes_t _preroll = 0;
1345 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1346 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1348 if (new_position > _preroll) {
1349 new_position -= _preroll;
1354 _session->request_locate (new_position);
1359 ARDOUR_UI::transport_goto_start ()
1362 _session->goto_start();
1364 /* force displayed area in editor to start no matter
1365 what "follow playhead" setting is.
1369 editor->center_screen (_session->current_start_frame ());
1375 ARDOUR_UI::transport_goto_zero ()
1378 _session->request_locate (0);
1380 /* force displayed area in editor to start no matter
1381 what "follow playhead" setting is.
1385 editor->reset_x_origin (0);
1391 ARDOUR_UI::transport_goto_wallclock ()
1393 if (_session && editor) {
1400 localtime_r (&now, &tmnow);
1402 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1403 frames += tmnow.tm_min * (60 * _session->frame_rate());
1404 frames += tmnow.tm_sec * _session->frame_rate();
1406 _session->request_locate (frames);
1408 /* force displayed area in editor to start no matter
1409 what "follow playhead" setting is.
1413 editor->center_screen (frames);
1419 ARDOUR_UI::transport_goto_end ()
1422 nframes_t const frame = _session->current_end_frame();
1423 _session->request_locate (frame);
1425 /* force displayed area in editor to start no matter
1426 what "follow playhead" setting is.
1430 editor->center_screen (frame);
1436 ARDOUR_UI::transport_stop ()
1442 if (_session->is_auditioning()) {
1443 _session->cancel_audition ();
1447 _session->request_stop (false, true);
1451 ARDOUR_UI::transport_stop_and_forget_capture ()
1454 _session->request_stop (true, true);
1459 ARDOUR_UI::remove_last_capture()
1462 editor->remove_last_capture();
1467 ARDOUR_UI::transport_record (bool roll)
1471 switch (_session->record_status()) {
1472 case Session::Disabled:
1473 if (_session->ntracks() == 0) {
1474 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1478 _session->maybe_enable_record ();
1483 case Session::Recording:
1485 _session->request_stop();
1487 _session->disable_record (false, true);
1491 case Session::Enabled:
1492 _session->disable_record (false, true);
1495 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1499 ARDOUR_UI::transport_roll ()
1505 if (_session->is_auditioning()) {
1509 if (_session->config.get_external_sync()) {
1510 switch (_session->config.get_sync_source()) {
1514 /* transport controlled by the master */
1519 bool rolling = _session->transport_rolling();
1521 if (_session->get_play_loop()) {
1522 /* XXX it is not possible to just leave seamless loop and keep
1523 playing at present (nov 4th 2009)
1525 if (!Config->get_seamless_loop()) {
1526 _session->request_play_loop (false, true);
1528 } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1529 /* stop playing a range if we currently are */
1530 _session->request_play_range (0, true);
1533 if (join_play_range_button.get_active()) {
1534 _session->request_play_range (&editor->get_selection().time, true);
1538 _session->request_transport_speed (1.0f);
1543 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1550 if (_session->is_auditioning()) {
1551 _session->cancel_audition ();
1555 if (_session->config.get_external_sync()) {
1556 switch (_session->config.get_sync_source()) {
1560 /* transport controlled by the master */
1565 bool rolling = _session->transport_rolling();
1566 bool affect_transport = true;
1568 if (rolling && roll_out_of_bounded_mode) {
1569 /* drop out of loop/range playback but leave transport rolling */
1570 if (_session->get_play_loop()) {
1571 if (Config->get_seamless_loop()) {
1572 /* the disk buffers contain copies of the loop - we can't
1573 just keep playing, so stop the transport. the user
1574 can restart as they wish.
1576 affect_transport = true;
1578 /* disk buffers are normal, so we can keep playing */
1579 affect_transport = false;
1581 _session->request_play_loop (false, true);
1582 } else if (_session->get_play_range ()) {
1583 affect_transport = false;
1584 _session->request_play_range (0, true);
1588 if (affect_transport) {
1590 _session->request_stop (with_abort, true);
1592 if (join_play_range_button.get_active()) {
1593 _session->request_play_range (&editor->get_selection().time, true);
1596 _session->request_transport_speed (1.0f);
1602 ARDOUR_UI::toggle_session_auto_loop ()
1605 if (_session->get_play_loop()) {
1606 if (_session->transport_rolling()) {
1607 Location * looploc = _session->locations()->auto_loop_location();
1609 _session->request_locate (looploc->start(), true);
1612 _session->request_play_loop (false);
1615 Location * looploc = _session->locations()->auto_loop_location();
1617 _session->request_play_loop (true);
1624 ARDOUR_UI::transport_play_selection ()
1630 editor->play_selection ();
1634 ARDOUR_UI::transport_rewind (int option)
1636 float current_transport_speed;
1639 current_transport_speed = _session->transport_speed();
1641 if (current_transport_speed >= 0.0f) {
1644 _session->request_transport_speed (-1.0f);
1647 _session->request_transport_speed (-4.0f);
1650 _session->request_transport_speed (-0.5f);
1655 _session->request_transport_speed (current_transport_speed * 1.5f);
1661 ARDOUR_UI::transport_forward (int option)
1663 float current_transport_speed;
1666 current_transport_speed = _session->transport_speed();
1668 if (current_transport_speed <= 0.0f) {
1671 _session->request_transport_speed (1.0f);
1674 _session->request_transport_speed (4.0f);
1677 _session->request_transport_speed (0.5f);
1682 _session->request_transport_speed (current_transport_speed * 1.5f);
1689 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1691 if (_session == 0) {
1695 boost::shared_ptr<Route> r;
1697 if ((r = _session->route_by_remote_id (dstream)) != 0) {
1701 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1702 t->set_record_enabled (!t->record_enabled());
1705 if (_session == 0) {
1711 ARDOUR_UI::map_transport_state ()
1713 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1716 auto_loop_button.set_visual_state (0);
1717 play_selection_button.set_visual_state (0);
1718 roll_button.set_visual_state (0);
1719 stop_button.set_visual_state (1);
1723 float sp = _session->transport_speed();
1726 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1727 shuttle_box.queue_draw ();
1728 } else if (sp == 0.0f) {
1730 shuttle_box.queue_draw ();
1731 update_disk_space ();
1738 if (_session->get_play_range()) {
1740 play_selection_button.set_visual_state (1);
1741 roll_button.set_visual_state (0);
1742 auto_loop_button.set_visual_state (0);
1744 } else if (_session->get_play_loop ()) {
1746 auto_loop_button.set_visual_state (1);
1747 play_selection_button.set_visual_state (0);
1748 roll_button.set_visual_state (0);
1752 roll_button.set_visual_state (1);
1753 play_selection_button.set_visual_state (0);
1754 auto_loop_button.set_visual_state (0);
1757 if (join_play_range_button.get_active()) {
1758 /* light up both roll and play-selection if they are joined */
1759 roll_button.set_visual_state (1);
1760 play_selection_button.set_visual_state (1);
1763 stop_button.set_visual_state (0);
1767 stop_button.set_visual_state (1);
1768 roll_button.set_visual_state (0);
1769 play_selection_button.set_visual_state (0);
1770 auto_loop_button.set_visual_state (0);
1775 ARDOUR_UI::engine_stopped ()
1777 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1778 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1779 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1783 ARDOUR_UI::engine_running ()
1785 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1786 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1787 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1789 Glib::RefPtr<Action> action;
1790 const char* action_name = 0;
1792 switch (engine->frames_per_cycle()) {
1794 action_name = X_("JACKLatency32");
1797 action_name = X_("JACKLatency64");
1800 action_name = X_("JACKLatency128");
1803 action_name = X_("JACKLatency512");
1806 action_name = X_("JACKLatency1024");
1809 action_name = X_("JACKLatency2048");
1812 action_name = X_("JACKLatency4096");
1815 action_name = X_("JACKLatency8192");
1818 /* XXX can we do anything useful ? */
1824 action = ActionManager::get_action (X_("JACK"), action_name);
1827 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1828 ract->set_active ();
1834 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
1836 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1837 /* we can't rely on the original string continuing to exist when we are called
1838 again in the GUI thread, so make a copy and note that we need to
1841 char *copy = strdup (reason);
1842 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
1846 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1847 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1849 update_sample_rate (0);
1853 /* if the reason is a non-empty string, it means that the backend was shutdown
1854 rather than just Ardour.
1857 if (strlen (reason)) {
1858 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
1861 JACK has either been shutdown or it\n\
1862 disconnected Ardour because Ardour\n\
1863 was not fast enough. Try to restart\n\
1864 JACK, reconnect and save the session.");
1867 MessageDialog msg (*editor, msgstr);
1872 free ((char*) reason);
1877 ARDOUR_UI::do_engine_start ()
1885 error << _("Unable to start the session running")
1895 ARDOUR_UI::setup_theme ()
1897 theme_manager->setup_theme();
1901 ARDOUR_UI::update_clocks ()
1903 if (!editor || !editor->dragging_playhead()) {
1904 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1909 ARDOUR_UI::start_clocking ()
1911 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1915 ARDOUR_UI::stop_clocking ()
1917 clock_signal_connection.disconnect ();
1921 ARDOUR_UI::toggle_clocking ()
1924 if (clock_button.get_active()) {
1933 ARDOUR_UI::_blink (void *arg)
1936 ((ARDOUR_UI *) arg)->blink ();
1943 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1947 ARDOUR_UI::start_blinking ()
1949 /* Start the blink signal. Everybody with a blinking widget
1950 uses Blink to drive the widget's state.
1953 if (blink_timeout_tag < 0) {
1955 blink_timeout_tag = g_timeout_add (240, _blink, this);
1960 ARDOUR_UI::stop_blinking ()
1962 if (blink_timeout_tag >= 0) {
1963 g_source_remove (blink_timeout_tag);
1964 blink_timeout_tag = -1;
1969 /** Ask the user for the name of a new shapshot and then take it.
1973 ARDOUR_UI::snapshot_session (bool switch_to_it)
1975 ArdourPrompter prompter (true);
1978 prompter.set_name ("Prompter");
1979 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1980 prompter.set_title (_("Take Snapshot"));
1981 prompter.set_title (_("Take Snapshot"));
1982 prompter.set_prompt (_("Name of new snapshot"));
1984 if (!switch_to_it) {
1987 struct tm local_time;
1990 localtime_r (&n, &local_time);
1991 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1992 prompter.set_initial_text (timebuf);
1996 switch (prompter.run()) {
1997 case RESPONSE_ACCEPT:
1999 prompter.get_result (snapname);
2001 bool do_save = (snapname.length() != 0);
2004 if (snapname.find ('/') != string::npos) {
2005 MessageDialog msg (_("To ensure compatibility with various systems\n"
2006 "snapshot names may not contain a '/' character"));
2010 if (snapname.find ('\\') != string::npos) {
2011 MessageDialog msg (_("To ensure compatibility with various systems\n"
2012 "snapshot names may not contain a '\\' character"));
2018 vector<sys::path> p;
2019 get_state_files_in_directory (_session->session_directory().root_path(), p);
2020 vector<string> n = get_file_names_no_extension (p);
2021 if (find (n.begin(), n.end(), snapname) != n.end()) {
2023 ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2024 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2025 confirm.get_vbox()->pack_start (m, true, true);
2026 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2027 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2028 confirm.show_all ();
2029 switch (confirm.run()) {
2030 case RESPONSE_CANCEL:
2036 save_state (snapname, switch_to_it);
2047 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2049 save_state_canfail (name, switch_to_it);
2053 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2058 if (name.length() == 0) {
2059 name = _session->snap_name();
2062 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2066 cerr << "SS canfail\n";
2067 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2072 ARDOUR_UI::primary_clock_value_changed ()
2075 _session->request_locate (primary_clock.current_time ());
2080 ARDOUR_UI::big_clock_value_changed ()
2083 _session->request_locate (big_clock.current_time ());
2088 ARDOUR_UI::secondary_clock_value_changed ()
2091 _session->request_locate (secondary_clock.current_time ());
2096 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2098 if (_session == 0) {
2102 Session::RecordState const r = _session->record_status ();
2103 bool const h = _session->have_rec_enabled_track ();
2105 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2107 rec_button.set_visual_state (2);
2109 rec_button.set_visual_state (0);
2111 } else if (r == Session::Recording && h) {
2112 rec_button.set_visual_state (1);
2114 rec_button.set_visual_state (0);
2119 ARDOUR_UI::save_template ()
2121 ArdourPrompter prompter (true);
2124 if (!check_audioengine()) {
2128 prompter.set_name (X_("Prompter"));
2129 prompter.set_title (_("Save Mix Template"));
2130 prompter.set_prompt (_("Name for mix template:"));
2131 prompter.set_initial_text(_session->name() + _("-template"));
2132 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2134 switch (prompter.run()) {
2135 case RESPONSE_ACCEPT:
2136 prompter.get_result (name);
2138 if (name.length()) {
2139 _session->save_template (name);
2149 ARDOUR_UI::edit_metadata ()
2151 SessionMetadataEditor dialog;
2152 dialog.set_session (_session);
2153 editor->ensure_float (dialog);
2158 ARDOUR_UI::import_metadata ()
2160 SessionMetadataImporter dialog;
2161 dialog.set_session (_session);
2162 editor->ensure_float (dialog);
2167 ARDOUR_UI::fontconfig_dialog ()
2170 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2171 may not and it can take a while to build it. Warn them.
2174 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2176 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2177 MessageDialog msg (*_startup,
2178 _("Welcome to Ardour.\n\n"
2179 "The program will take a bit longer to start up\n"
2180 "while the system fonts are checked.\n\n"
2181 "This will only be done once, and you will\n"
2182 "not see this message again\n"),
2195 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2197 existing_session = false;
2199 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2200 session_path = cmdline_path;
2201 existing_session = true;
2202 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2203 session_path = Glib::path_get_dirname (string (cmdline_path));
2204 existing_session = true;
2206 /* it doesn't exist, assume the best */
2207 session_path = Glib::path_get_dirname (string (cmdline_path));
2210 session_name = basename_nosuffix (string (cmdline_path));
2214 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2216 /* when this is called, the backend audio system must be running */
2218 /* the main idea here is to deal with the fact that a cmdline argument for the session
2219 can be interpreted in different ways - it could be a directory or a file, and before
2220 we load, we need to know both the session directory and the snapshot (statefile) within it
2221 that we are supposed to use.
2224 if (session_name.length() == 0 || session_path.length() == 0) {
2228 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2230 Glib::ustring predicted_session_file;
2232 predicted_session_file = session_path;
2233 predicted_session_file += '/';
2234 predicted_session_file += session_name;
2235 predicted_session_file += ARDOUR::statefile_suffix;
2237 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2238 existing_session = true;
2241 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2243 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2244 /* existing .ardour file */
2245 existing_session = true;
2249 existing_session = false;
2252 /* lets just try to load it */
2254 if (create_engine ()) {
2255 backend_audio_error (false, _startup);
2259 return load_session (session_path, session_name);
2263 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2265 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2267 MessageDialog msg (str,
2269 Gtk::MESSAGE_WARNING,
2270 Gtk::BUTTONS_YES_NO,
2274 msg.set_name (X_("OpenExistingDialog"));
2275 msg.set_title (_("Open Existing Session"));
2276 msg.set_wmclass (X_("existing_session"), "Ardour");
2277 msg.set_position (Gtk::WIN_POS_MOUSE);
2280 switch (msg.run()) {
2289 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2291 BusProfile bus_profile;
2293 if (Profile->get_sae()) {
2295 bus_profile.master_out_channels = 2;
2296 bus_profile.input_ac = AutoConnectPhysical;
2297 bus_profile.output_ac = AutoConnectMaster;
2298 bus_profile.requested_physical_in = 0; // use all available
2299 bus_profile.requested_physical_out = 0; // use all available
2303 /* get settings from advanced section of NSD */
2305 if (_startup->create_master_bus()) {
2306 bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2308 bus_profile.master_out_channels = 0;
2311 if (_startup->connect_inputs()) {
2312 bus_profile.input_ac = AutoConnectPhysical;
2314 bus_profile.input_ac = AutoConnectOption (0);
2317 /// @todo some minor tweaks.
2319 bus_profile.output_ac = AutoConnectOption (0);
2321 if (_startup->connect_outputs ()) {
2322 if (_startup->connect_outs_to_master()) {
2323 bus_profile.output_ac = AutoConnectMaster;
2324 } else if (_startup->connect_outs_to_physical()) {
2325 bus_profile.output_ac = AutoConnectPhysical;
2329 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2330 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2333 if (build_session (session_path, session_name, bus_profile)) {
2341 ARDOUR_UI::idle_load (const Glib::ustring& path)
2344 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2345 /* /path/to/foo => /path/to/foo, foo */
2346 load_session (path, basename_nosuffix (path));
2348 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2349 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2353 ARDOUR_COMMAND_LINE::session_name = path;
2356 * new_session_dialog doens't exist in A3
2357 * Try to remove all references to it to
2358 * see if it will compile. NOTE: this will
2359 * likely cause a runtime issue is my somewhat
2363 //if (new_session_dialog) {
2366 /* make it break out of Dialog::run() and
2370 //new_session_dialog->response (1);
2376 ARDOUR_UI::end_loading_messages ()
2382 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2385 // splash->message (msg);
2389 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2391 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2393 Glib::ustring session_name;
2394 Glib::ustring session_path;
2395 Glib::ustring template_name;
2397 bool likely_new = false;
2401 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2403 /* if they named a specific statefile, use it, otherwise they are
2404 just giving a session folder, and we want to use it as is
2405 to find the session.
2408 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2409 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2411 session_path = ARDOUR_COMMAND_LINE::session_name;
2414 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2418 bool const apply = run_startup (should_be_new);
2420 if (quit_on_cancel) {
2427 /* if we run the startup dialog again, offer more than just "new session" */
2429 should_be_new = false;
2431 session_name = _startup->session_name (likely_new);
2433 /* this shouldn't happen, but we catch it just in case it does */
2435 if (session_name.empty()) {
2438 if (_startup->use_session_template()) {
2439 template_name = _startup->session_template_name();
2440 _session_is_new = true;
2443 if (session_name[0] == '/' ||
2444 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2445 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2447 /* absolute path or cwd-relative path specified for session name: infer session folder
2448 from what was given.
2451 session_path = Glib::path_get_dirname (session_name);
2452 session_name = Glib::path_get_basename (session_name);
2456 session_path = _startup->session_folder();
2460 if (create_engine ()) {
2464 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2468 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2470 if (!ask_about_loading_existing_session (existing)) {
2471 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2476 _session_is_new = false;
2481 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2483 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2487 if (session_name.find ('/') != Glib::ustring::npos) {
2488 MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
2489 "session names may not contain a '/' character"));
2491 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2495 if (session_name.find ('\\') != Glib::ustring::npos) {
2496 MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
2497 "session names may not contain a '\\' character"));
2499 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2503 _session_is_new = true;
2506 if (likely_new && template_name.empty()) {
2508 ret = build_session_from_nsd (session_path, session_name);
2512 ret = load_session (session_path, session_name, template_name);
2513 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2514 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2524 ARDOUR_UI::close_session()
2526 if (!check_audioengine()) {
2530 if (unload_session (true)) {
2534 ARDOUR_COMMAND_LINE::session_name = "";
2535 get_session_parameters (true, false);
2539 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2541 Session *new_session;
2545 session_loaded = false;
2547 if (!check_audioengine()) {
2551 unload_status = unload_session ();
2553 if (unload_status < 0) {
2555 } else if (unload_status > 0) {
2560 loading_message (string_compose (_("Please wait while %1loads your session"), PROGRAM_NAME));
2563 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2566 /* this one is special */
2568 catch (AudioEngine::PortRegistrationFailure& err) {
2570 MessageDialog msg (err.what(),
2573 Gtk::BUTTONS_CLOSE);
2575 msg.set_title (_("Port Registration Error"));
2576 msg.set_secondary_text (_("Click the Close button to try again."));
2577 msg.set_position (Gtk::WIN_POS_CENTER);
2581 int response = msg.run ();
2586 case RESPONSE_CANCEL:
2596 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2599 Gtk::BUTTONS_CLOSE);
2601 msg.set_title (_("Loading Error"));
2602 msg.set_secondary_text (_("Click the Close button to try again."));
2603 msg.set_position (Gtk::WIN_POS_CENTER);
2607 int response = msg.run ();
2612 case RESPONSE_CANCEL:
2620 set_session (new_session);
2622 session_loaded = true;
2624 goto_editor_window ();
2627 _session->set_clean ();
2638 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, BusProfile& bus_profile)
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, &bus_profile);
2665 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2671 set_session (new_session);
2673 session_loaded = true;
2675 new_session->save_state(new_session->name());
2684 editor->show_window ();
2695 ARDOUR_UI::launch_chat ()
2698 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2700 open_uri("http://webchat.freenode.net/?channels=ardour");
2705 ARDOUR_UI::show_about ()
2709 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2712 about->set_transient_for(*editor);
2717 ARDOUR_UI::hide_about ()
2720 about->get_window()->set_cursor ();
2726 ARDOUR_UI::about_signal_response (int /*response*/)
2732 ARDOUR_UI::show_splash ()
2736 splash = new Splash;
2744 splash->queue_draw ();
2745 splash->get_window()->process_updates (true);
2750 ARDOUR_UI::hide_splash ()
2758 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2759 const string& plural_msg, const string& singular_msg)
2763 removed = rep.paths.size();
2766 MessageDialog msgd (*editor,
2767 _("No audio files were ready for cleanup"),
2770 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2771 msgd.set_secondary_text (_("If this seems suprising, \n\
2772 check for any existing snapshots.\n\
2773 These may still include regions that\n\
2774 require some unused files to continue to exist."));
2780 ArdourDialog results (_("Clean-up"), true, false);
2782 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2783 CleanupResultsModelColumns() {
2787 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2788 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2792 CleanupResultsModelColumns results_columns;
2793 Glib::RefPtr<Gtk::ListStore> results_model;
2794 Gtk::TreeView results_display;
2796 results_model = ListStore::create (results_columns);
2797 results_display.set_model (results_model);
2798 results_display.append_column (list_title, results_columns.visible_name);
2800 results_display.set_name ("CleanupResultsList");
2801 results_display.set_headers_visible (true);
2802 results_display.set_headers_clickable (false);
2803 results_display.set_reorderable (false);
2805 Gtk::ScrolledWindow list_scroller;
2808 Gtk::HBox dhbox; // the hbox for the image and text
2809 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2810 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2812 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2814 const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
2817 %1 - number of files removed
2818 %2 - location of "dead_sounds"
2819 %3 - size of files affected
2820 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2823 const char* bprefix;
2824 double space_adjusted = 0;
2826 if (rep.space < 100000.0f) {
2827 bprefix = X_("kilo");
2828 } else if (rep.space < 1000000.0f * 1000) {
2829 bprefix = X_("mega");
2830 space_adjusted = truncf((float)rep.space / 1000.0);
2832 bprefix = X_("giga");
2833 space_adjusted = truncf((float)rep.space / (1000000.0 * 1000));
2837 txt.set_text (string_compose (plural_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
2839 txt.set_text (string_compose (singular_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
2842 dhbox.pack_start (*dimage, true, false, 5);
2843 dhbox.pack_start (txt, true, false, 5);
2845 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2846 TreeModel::Row row = *(results_model->append());
2847 row[results_columns.visible_name] = *i;
2848 row[results_columns.fullpath] = *i;
2851 list_scroller.add (results_display);
2852 list_scroller.set_size_request (-1, 150);
2853 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2855 dvbox.pack_start (dhbox, true, false, 5);
2856 dvbox.pack_start (list_scroller, true, false, 5);
2857 ddhbox.pack_start (dvbox, true, false, 5);
2859 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2860 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2861 results.set_default_response (RESPONSE_CLOSE);
2862 results.set_position (Gtk::WIN_POS_MOUSE);
2864 results_display.show();
2865 list_scroller.show();
2872 //results.get_vbox()->show();
2873 results.set_resizable (false);
2880 ARDOUR_UI::cleanup ()
2882 if (_session == 0) {
2883 /* shouldn't happen: menu item is insensitive */
2888 MessageDialog checker (_("Are you sure you want to cleanup?"),
2890 Gtk::MESSAGE_QUESTION,
2891 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2893 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2894 ALL undo/redo information will be lost if you cleanup.\n\
2895 After cleanup, unused audio files will be moved to a \
2896 \"dead sounds\" location."));
2898 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2899 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2900 checker.set_default_response (RESPONSE_CANCEL);
2902 checker.set_name (_("CleanupDialog"));
2903 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2904 checker.set_position (Gtk::WIN_POS_MOUSE);
2906 switch (checker.run()) {
2907 case RESPONSE_ACCEPT:
2913 ARDOUR::CleanupReport rep;
2915 editor->prepare_for_cleanup ();
2917 /* do not allow flush until a session is reloaded */
2919 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2921 act->set_sensitive (false);
2924 if (_session->cleanup_sources (rep)) {
2925 editor->finish_cleanup ();
2929 editor->finish_cleanup ();
2932 display_cleanup_results (rep,
2935 The following %1 files were not in use and \n\
2936 have been moved to:\n\
2938 Flushing the wastebasket will \n\
2939 release an additional\n\
2940 %3 %4bytes of disk space.\n"),
2942 The following file was not in use and \n \
2943 has been moved to:\n \
2945 Flushing the wastebasket will \n\
2946 release an additional\n\
2947 %3 %4bytes of disk space.\n"
2953 ARDOUR_UI::flush_trash ()
2955 if (_session == 0) {
2956 /* shouldn't happen: menu item is insensitive */
2960 ARDOUR::CleanupReport rep;
2962 if (_session->cleanup_trash_sources (rep)) {
2966 display_cleanup_results (rep,
2968 _("The following %1 files were deleted from\n\
2970 releasing %3 %4bytes of disk space"),
2971 _("The following file was deleted from\n\
2973 releasing %3 %4bytes of disk space"));
2977 ARDOUR_UI::add_route (Gtk::Window* float_window)
2985 if (add_route_dialog == 0) {
2986 add_route_dialog = new AddRouteDialog (_session);
2988 add_route_dialog->set_transient_for (*float_window);
2992 if (add_route_dialog->is_visible()) {
2993 /* we're already doing this */
2997 ResponseType r = (ResponseType) add_route_dialog->run ();
2999 add_route_dialog->hide();
3002 case RESPONSE_ACCEPT:
3009 if ((count = add_route_dialog->count()) <= 0) {
3013 string template_path = add_route_dialog->track_template();
3015 if (!template_path.empty()) {
3016 _session->new_route_from_template (count, template_path);
3020 uint32_t input_chan = add_route_dialog->channels ();
3021 uint32_t output_chan;
3022 string name_template = add_route_dialog->name_template ();
3023 bool track = add_route_dialog->track ();
3024 bool aux = !track && add_route_dialog->aux();
3025 RouteGroup* route_group = add_route_dialog->route_group ();
3027 AutoConnectOption oac = Config->get_output_auto_connect();
3029 if (oac & AutoConnectMaster) {
3030 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3032 output_chan = input_chan;
3035 /* XXX do something with name template */
3037 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3039 session_add_midi_track (route_group, count);
3041 MessageDialog msg (*editor,
3042 _("Sorry, MIDI Busses are not supported at this time."));
3044 //session_add_midi_bus();
3048 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3050 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3056 ARDOUR_UI::mixer_settings () const
3061 node = _session->instant_xml(X_("Mixer"));
3063 node = Config->instant_xml(X_("Mixer"));
3067 node = new XMLNode (X_("Mixer"));
3074 ARDOUR_UI::editor_settings () const
3079 node = _session->instant_xml(X_("Editor"));
3081 node = Config->instant_xml(X_("Editor"));
3085 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3086 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3091 node = new XMLNode (X_("Editor"));
3098 ARDOUR_UI::keyboard_settings () const
3102 node = Config->extra_xml(X_("Keyboard"));
3105 node = new XMLNode (X_("Keyboard"));
3111 ARDOUR_UI::create_xrun_marker(nframes_t where)
3113 editor->mouse_add_new_marker (where, false, true);
3117 ARDOUR_UI::halt_on_xrun_message ()
3119 MessageDialog msg (*editor,
3120 _("Recording was stopped because your system could not keep up."));
3125 ARDOUR_UI::xrun_handler(nframes_t where)
3131 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3133 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3134 create_xrun_marker(where);
3137 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3138 halt_on_xrun_message ();
3143 ARDOUR_UI::disk_overrun_handler ()
3145 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3147 if (!have_disk_speed_dialog_displayed) {
3148 have_disk_speed_dialog_displayed = true;
3149 MessageDialog* msg = new MessageDialog (*editor, _("\
3150 The disk system on your computer\n\
3151 was not able to keep up with Ardour.\n\
3153 Specifically, it failed to write data to disk\n\
3154 quickly enough to keep up with recording.\n"));
3155 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3161 ARDOUR_UI::disk_underrun_handler ()
3163 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3165 if (!have_disk_speed_dialog_displayed) {
3166 have_disk_speed_dialog_displayed = true;
3167 MessageDialog* msg = new MessageDialog (*editor,
3168 _("The disk system on your computer\n\
3169 was not able to keep up with Ardour.\n\
3171 Specifically, it failed to read data from disk\n\
3172 quickly enough to keep up with playback.\n"));
3173 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3179 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3181 have_disk_speed_dialog_displayed = false;
3186 ARDOUR_UI::session_dialog (std::string msg)
3188 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3193 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3195 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3204 ARDOUR_UI::pending_state_dialog ()
3206 HBox* hbox = new HBox();
3207 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3208 ArdourDialog dialog (_("Crash Recovery"), true);
3210 This session appears to have been in\n\
3211 middle of recording when ardour or\n\
3212 the computer was shutdown.\n\
3214 Ardour can recover any captured audio for\n\
3215 you, or it can ignore it. Please decide\n\
3216 what you would like to do.\n"));
3217 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3218 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3219 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3220 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3221 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3222 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3223 dialog.set_default_response (RESPONSE_ACCEPT);
3224 dialog.set_position (WIN_POS_CENTER);
3229 switch (dialog.run ()) {
3230 case RESPONSE_ACCEPT:
3238 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3240 HBox* hbox = new HBox();
3241 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3242 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3243 Label message (string_compose (_("\
3244 This session was created with a sample rate of %1 Hz\n\
3246 The audioengine is currently running at %2 Hz\n"), desired, actual));
3248 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3249 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3250 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3251 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3252 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3253 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3254 dialog.set_default_response (RESPONSE_ACCEPT);
3255 dialog.set_position (WIN_POS_CENTER);
3260 switch (dialog.run ()) {
3261 case RESPONSE_ACCEPT:
3270 ARDOUR_UI::disconnect_from_jack ()
3273 if( engine->disconnect_from_jack ()) {
3274 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3278 update_sample_rate (0);
3283 ARDOUR_UI::reconnect_to_jack ()
3286 if (engine->reconnect_to_jack ()) {
3287 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3291 update_sample_rate (0);
3296 ARDOUR_UI::use_config ()
3299 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3301 set_transport_controllable_state (*node);
3304 node = Config->extra_xml (X_("UI"));
3307 const XMLProperty* prop = node->property (X_("show-big-clock"));
3308 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
3310 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
3311 tact->set_active (string_is_affirmative (prop->value()));
3317 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3319 if (Config->get_primary_clock_delta_edit_cursor()) {
3320 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3322 primary_clock.set (pos, 0, true);
3325 if (Config->get_secondary_clock_delta_edit_cursor()) {
3326 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3328 secondary_clock.set (pos);
3331 if (big_clock_window) {
3332 big_clock.set (pos);
3337 ARDOUR_UI::record_state_changed ()
3339 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3341 if (!_session || !big_clock_window) {
3342 /* why bother - the clock isn't visible */
3346 Session::RecordState const r = _session->record_status ();
3347 bool const h = _session->have_rec_enabled_track ();
3349 if (r == Session::Recording && h) {
3350 big_clock.set_widget_name ("BigClockRecording");
3352 big_clock.set_widget_name ("BigClockNonRecording");
3357 ARDOUR_UI::first_idle ()
3360 _session->allow_auto_play (true);
3364 editor->first_idle();
3367 Keyboard::set_can_save_keybindings (true);
3372 ARDOUR_UI::store_clock_modes ()
3374 XMLNode* node = new XMLNode(X_("ClockModes"));
3376 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3377 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3380 _session->add_extra_xml (*node);
3381 _session->set_dirty ();
3386 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3387 : Controllable (name), ui (u), type(tp)
3393 ARDOUR_UI::TransportControllable::set_value (float val)
3395 if (type == ShuttleControl) {
3402 fract = -((0.5f - val)/0.5f);
3404 fract = ((val - 0.5f)/0.5f);
3408 ui.set_shuttle_fract (fract);
3413 /* do nothing: these are radio-style actions */
3417 const char *action = 0;
3421 action = X_("Roll");
3424 action = X_("Stop");
3427 action = X_("Goto Start");
3430 action = X_("Goto End");
3433 action = X_("Loop");
3436 action = X_("Play Selection");
3439 action = X_("Record");
3449 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3457 ARDOUR_UI::TransportControllable::get_value (void) const
3476 case ShuttleControl:
3486 ARDOUR_UI::TransportControllable::set_id (const string& str)
3492 ARDOUR_UI::setup_profile ()
3494 if (gdk_screen_width() < 1200) {
3495 Profile->set_small_screen ();
3499 if (getenv ("ARDOUR_SAE")) {
3500 Profile->set_sae ();
3501 Profile->set_single_package ();