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"
99 #include "time_axis_view_item.h"
103 using namespace ARDOUR;
105 using namespace Gtkmm2ext;
108 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
109 UIConfiguration *ARDOUR_UI::ui_config = 0;
111 sigc::signal<void,bool> ARDOUR_UI::Blink;
112 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
113 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
114 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
116 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
118 : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp),
120 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
121 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
122 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
123 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
127 preroll_button (_("pre\nroll")),
128 postroll_button (_("post\nroll")),
132 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, false),
136 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
137 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
138 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
139 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
140 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
141 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
142 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
143 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
144 shuttle_controller_binding_proxy (shuttle_controllable),
146 roll_button (roll_controllable),
147 stop_button (stop_controllable),
148 goto_start_button (goto_start_controllable),
149 goto_end_button (goto_end_controllable),
150 auto_loop_button (auto_loop_controllable),
151 play_selection_button (play_selection_controllable),
152 rec_button (rec_controllable),
154 shuttle_units_button (_("% ")),
156 punch_in_button (_("Punch In")),
157 punch_out_button (_("Punch Out")),
158 auto_return_button (_("Auto Return")),
159 auto_play_button (_("Auto Play")),
160 auto_input_button (_("Auto Input")),
161 click_button (_("Click")),
162 time_master_button (_("time\nmaster")),
164 auditioning_alert_button (_("AUDITION")),
165 solo_alert_button (_("SOLO")),
167 error_log_button (_("Errors"))
170 using namespace Gtk::Menu_Helpers;
176 // _auto_display_errors = false;
178 * This was commented out as it wasn't defined
179 * in A3 IIRC. If this is not needed it should
180 * be completely removed.
188 if (theArdourUI == 0) {
192 ui_config = new UIConfiguration();
193 theme_manager = new ThemeManager();
199 _session_is_new = false;
200 big_clock_window = 0;
201 big_clock_height = 0;
202 big_clock_resize_in_progress = false;
203 session_selector_window = 0;
204 last_key_press_time = 0;
205 _will_create_new_session_automatically = false;
206 add_route_dialog = 0;
208 rc_option_editor = 0;
209 session_option_editor = 0;
211 open_session_selector = 0;
212 have_configure_timeout = false;
213 have_disk_speed_dialog_displayed = false;
214 session_loaded = false;
215 last_speed_displayed = -1.0f;
216 ignore_dual_punch = false;
217 _mixer_on_top = false;
218 original_big_clock_width = -1;
219 original_big_clock_height = -1;
220 original_big_clock_font_size = 0;
222 roll_button.unset_flags (Gtk::CAN_FOCUS);
223 stop_button.unset_flags (Gtk::CAN_FOCUS);
224 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
225 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
226 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
227 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
228 rec_button.unset_flags (Gtk::CAN_FOCUS);
230 last_configure_time= 0;
232 shuttle_grabbed = false;
234 shuttle_max_speed = 8.0f;
236 shuttle_style_menu = 0;
237 shuttle_unit_menu = 0;
239 // We do not have jack linked in yet so;
241 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
243 ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
244 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
246 /* handle dialog requests */
248 ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
250 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
252 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
254 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
256 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
258 /* lets get this party started */
261 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
262 throw failed_constructor ();
265 setup_gtk_ardour_enums ();
268 GainMeter::setup_slider_pix ();
269 RouteTimeAxisView::setup_slider_pix ();
270 SendProcessorEntry::setup_slider_pix ();
271 SessionEvent::create_per_thread_pool ("GUI", 512);
273 } catch (failed_constructor& err) {
274 error << _("could not initialize Ardour.") << endmsg;
279 /* we like keyboards */
281 keyboard = new ArdourKeyboard(*this);
283 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
285 keyboard->set_state (*node, Stateful::loading_state_version);
290 TimeAxisViewItem::set_constant_heights ();
292 starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
293 stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
298 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
300 ARDOUR_UI::run_startup (bool should_be_new, string load_template)
303 _startup = new ArdourStartup ();
305 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
307 if (audio_setup && _startup->engine_control()) {
308 _startup->engine_control()->set_state (*audio_setup);
311 _startup->set_new_only (should_be_new);
312 if (!load_template.empty()) {
313 _startup->set_load_template( load_template );
315 _startup->present ();
321 switch (_startup->response()) {
330 ARDOUR_UI::create_engine ()
332 // this gets called every time by new_session()
338 loading_message (_("Starting audio engine"));
341 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
348 engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
349 engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
350 engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
352 engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
354 ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
362 ARDOUR_UI::post_engine ()
364 /* Things to be done once we create the AudioEngine
367 ARDOUR::init_post_engine ();
369 ActionManager::init ();
372 if (setup_windows ()) {
373 throw failed_constructor ();
376 check_memory_locking();
378 /* this is the first point at which all the keybindings are available */
380 if (ARDOUR_COMMAND_LINE::show_key_actions) {
381 vector<string> names;
382 vector<string> paths;
384 vector<AccelKey> bindings;
386 ActionManager::get_all_actions (names, paths, keys, bindings);
388 vector<string>::iterator n;
389 vector<string>::iterator k;
390 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
391 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
397 blink_timeout_tag = -1;
399 /* this being a GUI and all, we want peakfiles */
401 AudioFileSource::set_build_peakfiles (true);
402 AudioFileSource::set_build_missing_peakfiles (true);
404 /* set default clock modes */
406 if (Profile->get_sae()) {
407 primary_clock.set_mode (AudioClock::BBT);
408 secondary_clock.set_mode (AudioClock::MinSec);
410 primary_clock.set_mode (AudioClock::Timecode);
411 secondary_clock.set_mode (AudioClock::BBT);
414 /* start the time-of-day-clock */
417 /* OS X provides a nearly-always visible wallclock, so don't be stupid */
418 update_wall_clock ();
419 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
422 update_disk_space ();
424 update_sample_rate (engine->frame_rate());
426 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
427 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
428 Config->map_parameters (pc);
430 /* now start and maybe save state */
432 if (do_engine_start () == 0) {
433 if (_session && _session_is_new) {
434 /* we need to retain initial visual
435 settings for a new session
437 _session->save_state ("");
442 ARDOUR_UI::~ARDOUR_UI ()
447 delete add_route_dialog;
451 ARDOUR_UI::pop_back_splash ()
453 if (Splash::instance()) {
454 // Splash::instance()->pop_back();
455 Splash::instance()->hide ();
460 ARDOUR_UI::configure_timeout ()
462 if (last_configure_time == 0) {
463 /* no configure events yet */
467 /* force a gap of 0.5 seconds since the last configure event
470 if (get_microseconds() - last_configure_time < 500000) {
473 have_configure_timeout = false;
474 cerr << "config event-driven save\n";
475 save_ardour_state ();
481 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
483 if (have_configure_timeout) {
484 last_configure_time = get_microseconds();
486 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
487 have_configure_timeout = true;
494 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
496 const XMLProperty* prop;
498 if ((prop = node.property ("roll")) != 0) {
499 roll_controllable->set_id (prop->value());
501 if ((prop = node.property ("stop")) != 0) {
502 stop_controllable->set_id (prop->value());
504 if ((prop = node.property ("goto-start")) != 0) {
505 goto_start_controllable->set_id (prop->value());
507 if ((prop = node.property ("goto-end")) != 0) {
508 goto_end_controllable->set_id (prop->value());
510 if ((prop = node.property ("auto-loop")) != 0) {
511 auto_loop_controllable->set_id (prop->value());
513 if ((prop = node.property ("play-selection")) != 0) {
514 play_selection_controllable->set_id (prop->value());
516 if ((prop = node.property ("rec")) != 0) {
517 rec_controllable->set_id (prop->value());
519 if ((prop = node.property ("shuttle")) != 0) {
520 shuttle_controllable->set_id (prop->value());
525 ARDOUR_UI::get_transport_controllable_state ()
527 XMLNode* node = new XMLNode(X_("TransportControllables"));
530 roll_controllable->id().print (buf, sizeof (buf));
531 node->add_property (X_("roll"), buf);
532 stop_controllable->id().print (buf, sizeof (buf));
533 node->add_property (X_("stop"), buf);
534 goto_start_controllable->id().print (buf, sizeof (buf));
535 node->add_property (X_("goto_start"), buf);
536 goto_end_controllable->id().print (buf, sizeof (buf));
537 node->add_property (X_("goto_end"), buf);
538 auto_loop_controllable->id().print (buf, sizeof (buf));
539 node->add_property (X_("auto_loop"), buf);
540 play_selection_controllable->id().print (buf, sizeof (buf));
541 node->add_property (X_("play_selection"), buf);
542 rec_controllable->id().print (buf, sizeof (buf));
543 node->add_property (X_("rec"), buf);
544 shuttle_controllable->id().print (buf, sizeof (buf));
545 node->add_property (X_("shuttle"), buf);
552 ARDOUR_UI::autosave_session ()
554 if (g_main_depth() > 1) {
555 /* inside a recursive main loop,
556 give up because we may not be able to
562 if (!Config->get_periodic_safety_backups()) {
567 _session->maybe_write_autosave();
574 ARDOUR_UI::update_autosave ()
576 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
578 if (_session && _session->dirty()) {
579 if (_autosave_connection.connected()) {
580 _autosave_connection.disconnect();
583 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
584 Config->get_periodic_safety_backup_interval() * 1000);
587 if (_autosave_connection.connected()) {
588 _autosave_connection.disconnect();
594 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
598 title = string_compose (_("%1 could not start JACK"), PROGRAM_NAME);
600 title = string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME);
603 MessageDialog win (title,
609 win.set_secondary_text(_("There are several possible reasons:\n\
611 1) You requested audio parameters that are not supported..\n\
612 2) JACK is running as another user.\n\
614 Please consider the possibilities, and perhaps try different parameters."));
616 win.set_secondary_text(_("There are several possible reasons:\n\
618 1) JACK is not running.\n\
619 2) JACK is running as another user, perhaps root.\n\
620 3) There is already another client called \"ardour\".\n\
622 Please consider the possibilities, and perhaps (re)start JACK."));
626 win.set_transient_for (*toplevel);
630 win.add_button (Stock::OK, RESPONSE_CLOSE);
632 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
635 win.set_default_response (RESPONSE_CLOSE);
638 win.set_position (Gtk::WIN_POS_CENTER);
641 /* we just don't care about the result, but we want to block */
647 ARDOUR_UI::startup ()
649 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
655 goto_editor_window ();
657 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
662 ARDOUR_UI::no_memory_warning ()
664 XMLNode node (X_("no-memory-warning"));
665 Config->add_instant_xml (node);
669 ARDOUR_UI::check_memory_locking ()
672 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
676 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
678 if (engine->is_realtime() && memory_warning_node == 0) {
680 struct rlimit limits;
682 long pages, page_size;
684 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
687 ram = (int64_t) pages * (int64_t) page_size;
690 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
694 if (limits.rlim_cur != RLIM_INFINITY) {
696 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
699 MessageDialog msg (string_compose (_("WARNING: Your system has a limit for maximum amount of locked memory. "
700 "This might cause %1 to run out of memory before your system "
701 "runs out of memory. \n\n"
702 "You can view the memory limit with 'ulimit -l', "
703 "and it is normally controlled by /etc/security/limits.conf"),
704 PROGRAM_NAME).c_str());
706 VBox* vbox = msg.get_vbox();
708 CheckButton cb (_("Do not show this window again"));
710 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
712 hbox.pack_start (cb, true, false);
713 vbox->pack_start (hbox);
720 editor->ensure_float (msg);
735 if (_session->transport_rolling() && (++tries < 8)) {
736 _session->request_stop (false, true);
740 if (_session->dirty()) {
741 switch (ask_about_saving_session(_("quit"))) {
746 /* use the default name */
747 if (save_state_canfail ("")) {
748 /* failed - don't quit */
749 MessageDialog msg (*editor,
751 Ardour was unable to save your session.\n\n\
752 If you still wish to quit, please use the\n\n\
753 \"Just quit\" option."));
764 second_connection.disconnect ();
765 point_one_second_connection.disconnect ();
766 point_oh_five_second_connection.disconnect ();
767 point_zero_one_second_connection.disconnect();
769 // _session->set_deletion_in_progress ();
770 _session->remove_pending_capture_state ();
775 cerr << "Save before quit\n";
776 save_ardour_state ();
778 ArdourDialog::close_all_dialogs ();
784 ARDOUR_UI::ask_about_saving_session (const string & what)
786 ArdourDialog window (_("Unsaved Session"));
787 Gtk::HBox dhbox; // the hbox for the image and text
788 Gtk::Label prompt_label;
789 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
793 msg = string_compose(_("Don't %1"), what);
794 window.add_button (msg, RESPONSE_REJECT);
795 msg = string_compose(_("Just %1"), what);
796 window.add_button (msg, RESPONSE_APPLY);
797 msg = string_compose(_("Save and %1"), what);
798 window.add_button (msg, RESPONSE_ACCEPT);
800 window.set_default_response (RESPONSE_ACCEPT);
802 Gtk::Button noquit_button (msg);
803 noquit_button.set_name ("EditorGTKButton");
808 if (_session->snap_name() == _session->name()) {
811 type = _("snapshot");
813 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?"),
814 type, _session->snap_name());
816 prompt_label.set_text (prompt);
817 prompt_label.set_name (X_("PrompterLabel"));
818 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
820 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
821 dhbox.set_homogeneous (false);
822 dhbox.pack_start (*dimage, false, false, 5);
823 dhbox.pack_start (prompt_label, true, false, 5);
824 window.get_vbox()->pack_start (dhbox);
826 window.set_name (_("Prompter"));
827 window.set_position (Gtk::WIN_POS_MOUSE);
828 window.set_modal (true);
829 window.set_resizable (false);
835 window.set_keep_above (true);
838 ResponseType r = (ResponseType) window.run();
843 case RESPONSE_ACCEPT: // save and get out of here
845 case RESPONSE_APPLY: // get out of here
855 ARDOUR_UI::every_second ()
858 update_buffer_load ();
859 update_disk_space ();
864 ARDOUR_UI::every_point_one_seconds ()
866 update_speed_display ();
867 RapidScreenUpdate(); /* EMIT_SIGNAL */
872 ARDOUR_UI::every_point_zero_one_seconds ()
874 // august 2007: actual update frequency: 40Hz, not 100Hz
876 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
881 ARDOUR_UI::update_sample_rate (nframes_t)
885 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
887 if (!engine->connected()) {
889 snprintf (buf, sizeof (buf), _("disconnected"));
893 nframes_t rate = engine->frame_rate();
895 if (fmod (rate, 1000.0) != 0.0) {
896 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
897 (float) rate/1000.0f,
898 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
900 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
902 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
906 sample_rate_label.set_text (buf);
910 ARDOUR_UI::update_cpu_load ()
913 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
914 cpu_load_label.set_text (buf);
918 ARDOUR_UI::update_buffer_load ()
924 c = _session->capture_load ();
925 p = _session->playback_load ();
927 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
928 _session->playback_load(), _session->capture_load());
929 buffer_load_label.set_text (buf);
931 buffer_load_label.set_text ("");
936 ARDOUR_UI::count_recenabled_streams (Route& route)
938 Track* track = dynamic_cast<Track*>(&route);
939 if (track && track->record_enabled()) {
940 rec_enabled_streams += track->n_inputs().n_total();
945 ARDOUR_UI::update_disk_space()
951 nframes_t frames = _session->available_capture_duration();
953 nframes_t fr = _session->frame_rate();
955 if (frames == max_frames) {
956 strcpy (buf, _("Disk: 24hrs+"));
958 rec_enabled_streams = 0;
959 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
961 if (rec_enabled_streams) {
962 frames /= rec_enabled_streams;
969 hrs = frames / (fr * 3600);
970 frames -= hrs * fr * 3600;
971 mins = frames / (fr * 60);
972 frames -= mins * fr * 60;
975 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
978 disk_space_label.set_text (buf);
980 // An attempt to make the disk space label flash red when space has run out.
982 if (frames < fr * 60 * 5) {
983 /* disk_space_box.style ("disk_space_label_empty"); */
985 /* disk_space_box.style ("disk_space_label"); */
991 ARDOUR_UI::update_wall_clock ()
998 tm_now = localtime (&now);
1000 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1001 wall_clock_label.set_text (buf);
1007 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1009 session_popup_menu->popup (0, 0);
1014 ARDOUR_UI::redisplay_recent_sessions ()
1016 std::vector<sys::path> session_directories;
1017 RecentSessionsSorter cmp;
1019 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1020 recent_session_model->clear ();
1022 ARDOUR::RecentSessions rs;
1023 ARDOUR::read_recent_sessions (rs);
1026 recent_session_display.set_model (recent_session_model);
1030 // sort them alphabetically
1031 sort (rs.begin(), rs.end(), cmp);
1033 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1034 session_directories.push_back ((*i).second);
1037 for (vector<sys::path>::const_iterator i = session_directories.begin();
1038 i != session_directories.end(); ++i)
1040 std::vector<sys::path> state_file_paths;
1042 // now get available states for this session
1044 get_state_files_in_directory (*i, state_file_paths);
1046 vector<string*>* states;
1047 vector<const gchar*> item;
1048 string fullpath = (*i).to_string();
1050 /* remove any trailing / */
1052 if (fullpath[fullpath.length()-1] == '/') {
1053 fullpath = fullpath.substr (0, fullpath.length()-1);
1056 /* check whether session still exists */
1057 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1058 /* session doesn't exist */
1059 cerr << "skipping non-existent session " << fullpath << endl;
1063 /* now get available states for this session */
1065 if ((states = Session::possible_states (fullpath)) == 0) {
1066 /* no state file? */
1070 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1072 Gtk::TreeModel::Row row = *(recent_session_model->append());
1074 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1075 row[recent_session_columns.fullpath] = fullpath;
1077 if (state_file_names.size() > 1) {
1081 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1082 i2 != state_file_names.end(); ++i2)
1085 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1087 child_row[recent_session_columns.visible_name] = *i2;
1088 child_row[recent_session_columns.fullpath] = fullpath;
1093 recent_session_display.set_model (recent_session_model);
1097 ARDOUR_UI::build_session_selector ()
1099 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1101 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1103 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1104 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1105 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1106 recent_session_model = TreeStore::create (recent_session_columns);
1107 recent_session_display.set_model (recent_session_model);
1108 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1109 recent_session_display.set_headers_visible (false);
1110 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1111 recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1113 scroller->add (recent_session_display);
1114 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1116 session_selector_window->set_name ("SessionSelectorWindow");
1117 session_selector_window->set_size_request (200, 400);
1118 session_selector_window->get_vbox()->pack_start (*scroller);
1120 recent_session_display.show();
1122 //session_selector_window->get_vbox()->show();
1126 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1128 session_selector_window->response (RESPONSE_ACCEPT);
1132 ARDOUR_UI::open_recent_session ()
1134 bool can_return = (_session != 0);
1136 if (session_selector_window == 0) {
1137 build_session_selector ();
1140 redisplay_recent_sessions ();
1144 session_selector_window->set_position (WIN_POS_MOUSE);
1146 ResponseType r = (ResponseType) session_selector_window->run ();
1149 case RESPONSE_ACCEPT:
1153 session_selector_window->hide();
1160 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1164 session_selector_window->hide();
1166 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1168 if (i == recent_session_model->children().end()) {
1172 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1173 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1175 _session_is_new = false;
1177 if (load_session (path, state) == 0) {
1186 ARDOUR_UI::check_audioengine ()
1189 if (!engine->connected()) {
1190 MessageDialog msg (string_compose (_("%1 is not connected to JACK\n"
1191 "You cannot open or close sessions in this condition"),
1204 ARDOUR_UI::open_session ()
1206 if (!check_audioengine()) {
1211 /* popup selector window */
1213 if (open_session_selector == 0) {
1215 /* ardour sessions are folders */
1217 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1218 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1219 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1220 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1222 FileFilter session_filter;
1223 session_filter.add_pattern ("*.ardour");
1224 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1225 open_session_selector->add_filter (session_filter);
1226 open_session_selector->set_filter (session_filter);
1229 int response = open_session_selector->run();
1230 open_session_selector->hide ();
1233 case RESPONSE_ACCEPT:
1236 open_session_selector->hide();
1240 open_session_selector->hide();
1241 string session_path = open_session_selector->get_filename();
1245 if (session_path.length() > 0) {
1246 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1247 _session_is_new = isnew;
1248 load_session (path, name);
1255 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1257 list<boost::shared_ptr<MidiTrack> > tracks;
1259 if (_session == 0) {
1260 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1267 tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1269 if (tracks.size() != how_many) {
1270 if (how_many == 1) {
1271 error << _("could not create a new midi track") << endmsg;
1273 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1277 if ((route = _session->new_midi_route ()) == 0) {
1278 error << _("could not create new midi bus") << endmsg;
1284 MessageDialog msg (*editor,
1285 _("There are insufficient JACK ports available\n\
1286 to create a new track or bus.\n\
1287 You should save Ardour, exit and\n\
1288 restart JACK with more ports."));
1295 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)
1297 list<boost::shared_ptr<AudioTrack> > tracks;
1300 if (_session == 0) {
1301 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1307 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1309 if (tracks.size() != how_many) {
1310 if (how_many == 1) {
1311 error << _("could not create a new audio track") << endmsg;
1313 error << string_compose (_("could only create %1 of %2 new audio %3"),
1314 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1320 routes = _session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1322 if (routes.size() != how_many) {
1323 if (how_many == 1) {
1324 error << _("could not create a new audio track") << endmsg;
1326 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1333 MessageDialog msg (*editor,
1334 _("There are insufficient JACK ports available\n\
1335 to create a new track or bus.\n\
1336 You should save Ardour, exit and\n\
1337 restart JACK with more ports."));
1344 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1346 nframes_t _preroll = 0;
1349 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1350 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1352 if (new_position > _preroll) {
1353 new_position -= _preroll;
1358 _session->request_locate (new_position);
1363 ARDOUR_UI::transport_goto_start ()
1366 _session->goto_start();
1368 /* force displayed area in editor to start no matter
1369 what "follow playhead" setting is.
1373 editor->center_screen (_session->current_start_frame ());
1379 ARDOUR_UI::transport_goto_zero ()
1382 _session->request_locate (0);
1384 /* force displayed area in editor to start no matter
1385 what "follow playhead" setting is.
1389 editor->reset_x_origin (0);
1395 ARDOUR_UI::transport_goto_wallclock ()
1397 if (_session && editor) {
1404 localtime_r (&now, &tmnow);
1406 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1407 frames += tmnow.tm_min * (60 * _session->frame_rate());
1408 frames += tmnow.tm_sec * _session->frame_rate();
1410 _session->request_locate (frames);
1412 /* force displayed area in editor to start no matter
1413 what "follow playhead" setting is.
1417 editor->center_screen (frames);
1423 ARDOUR_UI::transport_goto_end ()
1426 nframes_t const frame = _session->current_end_frame();
1427 _session->request_locate (frame);
1429 /* force displayed area in editor to start no matter
1430 what "follow playhead" setting is.
1434 editor->center_screen (frame);
1440 ARDOUR_UI::transport_stop ()
1446 if (_session->is_auditioning()) {
1447 _session->cancel_audition ();
1451 _session->request_stop (false, true);
1455 ARDOUR_UI::transport_stop_and_forget_capture ()
1458 _session->request_stop (true, true);
1463 ARDOUR_UI::remove_last_capture()
1466 editor->remove_last_capture();
1471 ARDOUR_UI::transport_record (bool roll)
1475 switch (_session->record_status()) {
1476 case Session::Disabled:
1477 if (_session->ntracks() == 0) {
1478 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1482 _session->maybe_enable_record ();
1487 case Session::Recording:
1489 _session->request_stop();
1491 _session->disable_record (false, true);
1495 case Session::Enabled:
1496 _session->disable_record (false, true);
1499 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1503 ARDOUR_UI::transport_roll ()
1509 if (_session->is_auditioning()) {
1513 if (_session->config.get_external_sync()) {
1514 switch (_session->config.get_sync_source()) {
1518 /* transport controlled by the master */
1523 bool rolling = _session->transport_rolling();
1525 if (_session->get_play_loop()) {
1526 /* XXX it is not possible to just leave seamless loop and keep
1527 playing at present (nov 4th 2009)
1529 if (!Config->get_seamless_loop()) {
1530 _session->request_play_loop (false, true);
1532 } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1533 /* stop playing a range if we currently are */
1534 _session->request_play_range (0, true);
1537 if (join_play_range_button.get_active()) {
1538 _session->request_play_range (&editor->get_selection().time, true);
1542 _session->request_transport_speed (1.0f);
1547 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1554 if (_session->is_auditioning()) {
1555 _session->cancel_audition ();
1559 if (_session->config.get_external_sync()) {
1560 switch (_session->config.get_sync_source()) {
1564 /* transport controlled by the master */
1569 bool rolling = _session->transport_rolling();
1570 bool affect_transport = true;
1572 if (rolling && roll_out_of_bounded_mode) {
1573 /* drop out of loop/range playback but leave transport rolling */
1574 if (_session->get_play_loop()) {
1575 if (Config->get_seamless_loop()) {
1576 /* the disk buffers contain copies of the loop - we can't
1577 just keep playing, so stop the transport. the user
1578 can restart as they wish.
1580 affect_transport = true;
1582 /* disk buffers are normal, so we can keep playing */
1583 affect_transport = false;
1585 _session->request_play_loop (false, true);
1586 } else if (_session->get_play_range ()) {
1587 affect_transport = false;
1588 _session->request_play_range (0, true);
1592 if (affect_transport) {
1594 _session->request_stop (with_abort, true);
1596 if (join_play_range_button.get_active()) {
1597 _session->request_play_range (&editor->get_selection().time, true);
1600 _session->request_transport_speed (1.0f);
1606 ARDOUR_UI::toggle_session_auto_loop ()
1609 if (_session->get_play_loop()) {
1610 if (_session->transport_rolling()) {
1611 Location * looploc = _session->locations()->auto_loop_location();
1613 _session->request_locate (looploc->start(), true);
1616 _session->request_play_loop (false);
1619 Location * looploc = _session->locations()->auto_loop_location();
1621 _session->request_play_loop (true);
1628 ARDOUR_UI::transport_play_selection ()
1634 editor->play_selection ();
1638 ARDOUR_UI::transport_rewind (int option)
1640 float current_transport_speed;
1643 current_transport_speed = _session->transport_speed();
1645 if (current_transport_speed >= 0.0f) {
1648 _session->request_transport_speed (-1.0f);
1651 _session->request_transport_speed (-4.0f);
1654 _session->request_transport_speed (-0.5f);
1659 _session->request_transport_speed (current_transport_speed * 1.5f);
1665 ARDOUR_UI::transport_forward (int option)
1667 float current_transport_speed;
1670 current_transport_speed = _session->transport_speed();
1672 if (current_transport_speed <= 0.0f) {
1675 _session->request_transport_speed (1.0f);
1678 _session->request_transport_speed (4.0f);
1681 _session->request_transport_speed (0.5f);
1686 _session->request_transport_speed (current_transport_speed * 1.5f);
1693 ARDOUR_UI::toggle_record_enable (uint32_t rid)
1695 if (_session == 0) {
1699 boost::shared_ptr<Route> r;
1701 if ((r = _session->route_by_remote_id (rid)) != 0) {
1705 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1706 t->set_record_enabled (!t->record_enabled(), this);
1709 if (_session == 0) {
1715 ARDOUR_UI::map_transport_state ()
1717 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::map_transport_state)
1720 auto_loop_button.set_visual_state (0);
1721 play_selection_button.set_visual_state (0);
1722 roll_button.set_visual_state (0);
1723 stop_button.set_visual_state (1);
1727 float sp = _session->transport_speed();
1730 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1731 shuttle_box.queue_draw ();
1732 } else if (sp == 0.0f) {
1734 shuttle_box.queue_draw ();
1735 update_disk_space ();
1742 if (_session->get_play_range()) {
1744 play_selection_button.set_visual_state (1);
1745 roll_button.set_visual_state (0);
1746 auto_loop_button.set_visual_state (0);
1748 } else if (_session->get_play_loop ()) {
1750 auto_loop_button.set_visual_state (1);
1751 play_selection_button.set_visual_state (0);
1752 roll_button.set_visual_state (0);
1756 roll_button.set_visual_state (1);
1757 play_selection_button.set_visual_state (0);
1758 auto_loop_button.set_visual_state (0);
1761 if (join_play_range_button.get_active()) {
1762 /* light up both roll and play-selection if they are joined */
1763 roll_button.set_visual_state (1);
1764 play_selection_button.set_visual_state (1);
1767 stop_button.set_visual_state (0);
1771 stop_button.set_visual_state (1);
1772 roll_button.set_visual_state (0);
1773 play_selection_button.set_visual_state (0);
1774 auto_loop_button.set_visual_state (0);
1779 ARDOUR_UI::engine_stopped ()
1781 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1782 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1783 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1787 ARDOUR_UI::engine_running ()
1789 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1790 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1791 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1793 Glib::RefPtr<Action> action;
1794 const char* action_name = 0;
1796 switch (engine->frames_per_cycle()) {
1798 action_name = X_("JACKLatency32");
1801 action_name = X_("JACKLatency64");
1804 action_name = X_("JACKLatency128");
1807 action_name = X_("JACKLatency512");
1810 action_name = X_("JACKLatency1024");
1813 action_name = X_("JACKLatency2048");
1816 action_name = X_("JACKLatency4096");
1819 action_name = X_("JACKLatency8192");
1822 /* XXX can we do anything useful ? */
1828 action = ActionManager::get_action (X_("JACK"), action_name);
1831 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1832 ract->set_active ();
1838 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
1840 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1841 /* we can't rely on the original string continuing to exist when we are called
1842 again in the GUI thread, so make a copy and note that we need to
1845 char *copy = strdup (reason);
1846 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
1850 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1851 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1853 update_sample_rate (0);
1857 /* if the reason is a non-empty string, it means that the backend was shutdown
1858 rather than just Ardour.
1861 if (strlen (reason)) {
1862 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
1865 JACK has either been shutdown or it\n\
1866 disconnected Ardour because Ardour\n\
1867 was not fast enough. Try to restart\n\
1868 JACK, reconnect and save the session.");
1871 MessageDialog msg (*editor, msgstr);
1876 free ((char*) reason);
1881 ARDOUR_UI::do_engine_start ()
1889 error << _("Unable to start the session running")
1899 ARDOUR_UI::setup_theme ()
1901 theme_manager->setup_theme();
1905 ARDOUR_UI::update_clocks ()
1907 if (!editor || !editor->dragging_playhead()) {
1908 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1913 ARDOUR_UI::start_clocking ()
1915 clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
1919 ARDOUR_UI::stop_clocking ()
1921 clock_signal_connection.disconnect ();
1925 ARDOUR_UI::toggle_clocking ()
1928 if (clock_button.get_active()) {
1937 ARDOUR_UI::_blink (void *arg)
1940 ((ARDOUR_UI *) arg)->blink ();
1947 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1951 ARDOUR_UI::start_blinking ()
1953 /* Start the blink signal. Everybody with a blinking widget
1954 uses Blink to drive the widget's state.
1957 if (blink_timeout_tag < 0) {
1959 blink_timeout_tag = g_timeout_add (240, _blink, this);
1964 ARDOUR_UI::stop_blinking ()
1966 if (blink_timeout_tag >= 0) {
1967 g_source_remove (blink_timeout_tag);
1968 blink_timeout_tag = -1;
1973 /** Ask the user for the name of a new shapshot and then take it.
1977 ARDOUR_UI::snapshot_session (bool switch_to_it)
1979 ArdourPrompter prompter (true);
1982 prompter.set_name ("Prompter");
1983 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1984 prompter.set_title (_("Take Snapshot"));
1985 prompter.set_title (_("Take Snapshot"));
1986 prompter.set_prompt (_("Name of new snapshot"));
1988 if (!switch_to_it) {
1991 struct tm local_time;
1994 localtime_r (&n, &local_time);
1995 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1996 prompter.set_initial_text (timebuf);
2000 switch (prompter.run()) {
2001 case RESPONSE_ACCEPT:
2003 prompter.get_result (snapname);
2005 bool do_save = (snapname.length() != 0);
2008 if (snapname.find ('/') != string::npos) {
2009 MessageDialog msg (_("To ensure compatibility with various systems\n"
2010 "snapshot names may not contain a '/' character"));
2014 if (snapname.find ('\\') != string::npos) {
2015 MessageDialog msg (_("To ensure compatibility with various systems\n"
2016 "snapshot names may not contain a '\\' character"));
2022 vector<sys::path> p;
2023 get_state_files_in_directory (_session->session_directory().root_path(), p);
2024 vector<string> n = get_file_names_no_extension (p);
2025 if (find (n.begin(), n.end(), snapname) != n.end()) {
2027 ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2028 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
2029 confirm.get_vbox()->pack_start (m, true, true);
2030 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2031 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2032 confirm.show_all ();
2033 switch (confirm.run()) {
2034 case RESPONSE_CANCEL:
2040 save_state (snapname, switch_to_it);
2051 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2053 save_state_canfail (name, switch_to_it);
2057 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2062 if (name.length() == 0) {
2063 name = _session->snap_name();
2066 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2070 cerr << "SS canfail\n";
2071 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2076 ARDOUR_UI::primary_clock_value_changed ()
2079 _session->request_locate (primary_clock.current_time ());
2084 ARDOUR_UI::big_clock_value_changed ()
2087 _session->request_locate (big_clock.current_time ());
2092 ARDOUR_UI::secondary_clock_value_changed ()
2095 _session->request_locate (secondary_clock.current_time ());
2100 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2102 if (_session == 0) {
2106 if (_session->step_editing()) {
2110 Session::RecordState const r = _session->record_status ();
2111 bool const h = _session->have_rec_enabled_track ();
2113 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2115 rec_button.set_visual_state (2);
2117 rec_button.set_visual_state (0);
2119 } else if (r == Session::Recording && h) {
2120 rec_button.set_visual_state (1);
2122 rec_button.set_visual_state (0);
2127 ARDOUR_UI::save_template ()
2129 ArdourPrompter prompter (true);
2132 if (!check_audioengine()) {
2136 prompter.set_name (X_("Prompter"));
2137 prompter.set_title (_("Save Mix Template"));
2138 prompter.set_prompt (_("Name for mix template:"));
2139 prompter.set_initial_text(_session->name() + _("-template"));
2140 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2142 switch (prompter.run()) {
2143 case RESPONSE_ACCEPT:
2144 prompter.get_result (name);
2146 if (name.length()) {
2147 _session->save_template (name);
2157 ARDOUR_UI::edit_metadata ()
2159 SessionMetadataEditor dialog;
2160 dialog.set_session (_session);
2161 editor->ensure_float (dialog);
2166 ARDOUR_UI::import_metadata ()
2168 SessionMetadataImporter dialog;
2169 dialog.set_session (_session);
2170 editor->ensure_float (dialog);
2175 ARDOUR_UI::fontconfig_dialog ()
2178 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2179 may not and it can take a while to build it. Warn them.
2182 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2184 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2185 MessageDialog msg (*_startup,
2186 _("Welcome to Ardour.\n\n"
2187 "The program will take a bit longer to start up\n"
2188 "while the system fonts are checked.\n\n"
2189 "This will only be done once, and you will\n"
2190 "not see this message again\n"),
2203 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2205 existing_session = false;
2207 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2208 session_path = cmdline_path;
2209 existing_session = true;
2210 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2211 session_path = Glib::path_get_dirname (string (cmdline_path));
2212 existing_session = true;
2214 /* it doesn't exist, assume the best */
2215 session_path = Glib::path_get_dirname (string (cmdline_path));
2218 session_name = basename_nosuffix (string (cmdline_path));
2222 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2224 /* when this is called, the backend audio system must be running */
2226 /* the main idea here is to deal with the fact that a cmdline argument for the session
2227 can be interpreted in different ways - it could be a directory or a file, and before
2228 we load, we need to know both the session directory and the snapshot (statefile) within it
2229 that we are supposed to use.
2232 if (session_name.length() == 0 || session_path.length() == 0) {
2236 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2238 Glib::ustring predicted_session_file;
2240 predicted_session_file = session_path;
2241 predicted_session_file += '/';
2242 predicted_session_file += session_name;
2243 predicted_session_file += ARDOUR::statefile_suffix;
2245 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2246 existing_session = true;
2249 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2251 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2252 /* existing .ardour file */
2253 existing_session = true;
2257 existing_session = false;
2260 /* lets just try to load it */
2262 if (create_engine ()) {
2263 backend_audio_error (false, _startup);
2267 return load_session (session_path, session_name);
2271 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2273 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2275 MessageDialog msg (str,
2277 Gtk::MESSAGE_WARNING,
2278 Gtk::BUTTONS_YES_NO,
2282 msg.set_name (X_("OpenExistingDialog"));
2283 msg.set_title (_("Open Existing Session"));
2284 msg.set_wmclass (X_("existing_session"), "Ardour");
2285 msg.set_position (Gtk::WIN_POS_MOUSE);
2288 switch (msg.run()) {
2297 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2299 BusProfile bus_profile;
2301 if (Profile->get_sae()) {
2303 bus_profile.master_out_channels = 2;
2304 bus_profile.input_ac = AutoConnectPhysical;
2305 bus_profile.output_ac = AutoConnectMaster;
2306 bus_profile.requested_physical_in = 0; // use all available
2307 bus_profile.requested_physical_out = 0; // use all available
2311 /* get settings from advanced section of NSD */
2313 if (_startup->create_master_bus()) {
2314 bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2316 bus_profile.master_out_channels = 0;
2319 if (_startup->connect_inputs()) {
2320 bus_profile.input_ac = AutoConnectPhysical;
2322 bus_profile.input_ac = AutoConnectOption (0);
2325 /// @todo some minor tweaks.
2327 bus_profile.output_ac = AutoConnectOption (0);
2329 if (_startup->connect_outputs ()) {
2330 if (_startup->connect_outs_to_master()) {
2331 bus_profile.output_ac = AutoConnectMaster;
2332 } else if (_startup->connect_outs_to_physical()) {
2333 bus_profile.output_ac = AutoConnectPhysical;
2337 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2338 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2341 if (build_session (session_path, session_name, bus_profile)) {
2349 ARDOUR_UI::idle_load (const Glib::ustring& path)
2352 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2353 /* /path/to/foo => /path/to/foo, foo */
2354 load_session (path, basename_nosuffix (path));
2356 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2357 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2361 ARDOUR_COMMAND_LINE::session_name = path;
2364 * new_session_dialog doens't exist in A3
2365 * Try to remove all references to it to
2366 * see if it will compile. NOTE: this will
2367 * likely cause a runtime issue is my somewhat
2371 //if (new_session_dialog) {
2374 /* make it break out of Dialog::run() and
2378 //new_session_dialog->response (1);
2384 ARDOUR_UI::end_loading_messages ()
2390 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2393 // splash->message (msg);
2397 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2399 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2401 Glib::ustring session_name;
2402 Glib::ustring session_path;
2403 Glib::ustring template_name;
2405 bool likely_new = false;
2407 if (! load_template.empty()) {
2408 should_be_new = true;
2409 template_name = load_template;
2414 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2416 /* if they named a specific statefile, use it, otherwise they are
2417 just giving a session folder, and we want to use it as is
2418 to find the session.
2421 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2422 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2424 session_path = ARDOUR_COMMAND_LINE::session_name;
2427 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2431 bool const apply = run_startup (should_be_new, load_template);
2433 if (quit_on_cancel) {
2440 /* if we run the startup dialog again, offer more than just "new session" */
2442 should_be_new = false;
2444 session_name = _startup->session_name (likely_new);
2446 /* this shouldn't happen, but we catch it just in case it does */
2448 if (session_name.empty()) {
2451 if (_startup->use_session_template()) {
2452 template_name = _startup->session_template_name();
2453 _session_is_new = true;
2456 if (session_name[0] == '/' ||
2457 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2458 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2460 /* absolute path or cwd-relative path specified for session name: infer session folder
2461 from what was given.
2464 session_path = Glib::path_get_dirname (session_name);
2465 session_name = Glib::path_get_basename (session_name);
2469 session_path = _startup->session_folder();
2473 if (create_engine ()) {
2477 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2481 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2483 if (!ask_about_loading_existing_session (existing)) {
2484 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2489 _session_is_new = false;
2494 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2496 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2500 if (session_name.find ('/') != Glib::ustring::npos) {
2501 MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
2502 "session names may not contain a '/' character"));
2504 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2508 if (session_name.find ('\\') != Glib::ustring::npos) {
2509 MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
2510 "session names may not contain a '\\' character"));
2512 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2516 _session_is_new = true;
2519 if (likely_new && template_name.empty()) {
2521 ret = build_session_from_nsd (session_path, session_name);
2525 ret = load_session (session_path, session_name, template_name);
2526 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2527 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2537 ARDOUR_UI::close_session()
2539 if (!check_audioengine()) {
2543 if (unload_session (true)) {
2547 ARDOUR_COMMAND_LINE::session_name = "";
2549 if (get_session_parameters (true, false)) {
2553 goto_editor_window ();
2558 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2560 Session *new_session;
2564 session_loaded = false;
2566 if (!check_audioengine()) {
2570 unload_status = unload_session ();
2572 if (unload_status < 0) {
2574 } else if (unload_status > 0) {
2579 loading_message (string_compose (_("Please wait while %1loads your session"), PROGRAM_NAME));
2582 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2585 /* this one is special */
2587 catch (AudioEngine::PortRegistrationFailure& err) {
2589 MessageDialog msg (err.what(),
2592 Gtk::BUTTONS_CLOSE);
2594 msg.set_title (_("Port Registration 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:
2615 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2618 Gtk::BUTTONS_CLOSE);
2620 msg.set_title (_("Loading Error"));
2621 msg.set_secondary_text (_("Click the Close button to try again."));
2622 msg.set_position (Gtk::WIN_POS_CENTER);
2626 int response = msg.run ();
2631 case RESPONSE_CANCEL:
2639 set_session (new_session);
2641 session_loaded = true;
2643 goto_editor_window ();
2646 _session->set_clean ();
2657 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, BusProfile& bus_profile)
2659 Session *new_session;
2662 if (!check_audioengine()) {
2666 session_loaded = false;
2668 x = unload_session ();
2676 _session_is_new = true;
2679 new_session = new Session (*engine, path, snap_name, &bus_profile);
2684 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2690 set_session (new_session);
2692 session_loaded = true;
2694 new_session->save_state(new_session->name());
2703 editor->show_window ();
2714 ARDOUR_UI::launch_chat ()
2717 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2719 open_uri("http://webchat.freenode.net/?channels=ardour");
2724 ARDOUR_UI::show_about ()
2728 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2731 about->set_transient_for(*editor);
2736 ARDOUR_UI::hide_about ()
2739 about->get_window()->set_cursor ();
2745 ARDOUR_UI::about_signal_response (int /*response*/)
2751 ARDOUR_UI::show_splash ()
2755 splash = new Splash;
2763 splash->queue_draw ();
2764 splash->get_window()->process_updates (true);
2769 ARDOUR_UI::hide_splash ()
2777 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2778 const string& plural_msg, const string& singular_msg)
2782 removed = rep.paths.size();
2785 MessageDialog msgd (*editor,
2786 _("No audio files were ready for cleanup"),
2789 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2790 msgd.set_secondary_text (_("If this seems suprising, \n\
2791 check for any existing snapshots.\n\
2792 These may still include regions that\n\
2793 require some unused files to continue to exist."));
2799 ArdourDialog results (_("Clean-up"), true, false);
2801 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2802 CleanupResultsModelColumns() {
2806 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2807 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2811 CleanupResultsModelColumns results_columns;
2812 Glib::RefPtr<Gtk::ListStore> results_model;
2813 Gtk::TreeView results_display;
2815 results_model = ListStore::create (results_columns);
2816 results_display.set_model (results_model);
2817 results_display.append_column (list_title, results_columns.visible_name);
2819 results_display.set_name ("CleanupResultsList");
2820 results_display.set_headers_visible (true);
2821 results_display.set_headers_clickable (false);
2822 results_display.set_reorderable (false);
2824 Gtk::ScrolledWindow list_scroller;
2827 Gtk::HBox dhbox; // the hbox for the image and text
2828 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2829 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2831 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2833 const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
2836 %1 - number of files removed
2837 %2 - location of "dead_sounds"
2838 %3 - size of files affected
2839 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2842 const char* bprefix;
2843 double space_adjusted = 0;
2845 if (rep.space < 100000.0f) {
2846 bprefix = X_("kilo");
2847 } else if (rep.space < 1000000.0f * 1000) {
2848 bprefix = X_("mega");
2849 space_adjusted = truncf((float)rep.space / 1000.0);
2851 bprefix = X_("giga");
2852 space_adjusted = truncf((float)rep.space / (1000000.0 * 1000));
2856 txt.set_text (string_compose (plural_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
2858 txt.set_text (string_compose (singular_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
2861 dhbox.pack_start (*dimage, true, false, 5);
2862 dhbox.pack_start (txt, true, false, 5);
2864 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2865 TreeModel::Row row = *(results_model->append());
2866 row[results_columns.visible_name] = *i;
2867 row[results_columns.fullpath] = *i;
2870 list_scroller.add (results_display);
2871 list_scroller.set_size_request (-1, 150);
2872 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2874 dvbox.pack_start (dhbox, true, false, 5);
2875 dvbox.pack_start (list_scroller, true, false, 5);
2876 ddhbox.pack_start (dvbox, true, false, 5);
2878 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2879 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2880 results.set_default_response (RESPONSE_CLOSE);
2881 results.set_position (Gtk::WIN_POS_MOUSE);
2883 results_display.show();
2884 list_scroller.show();
2891 //results.get_vbox()->show();
2892 results.set_resizable (false);
2899 ARDOUR_UI::cleanup ()
2901 if (_session == 0) {
2902 /* shouldn't happen: menu item is insensitive */
2907 MessageDialog checker (_("Are you sure you want to cleanup?"),
2909 Gtk::MESSAGE_QUESTION,
2910 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2912 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2913 ALL undo/redo information will be lost if you cleanup.\n\
2914 After cleanup, unused audio files will be moved to a \
2915 \"dead sounds\" location."));
2917 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2918 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2919 checker.set_default_response (RESPONSE_CANCEL);
2921 checker.set_name (_("CleanupDialog"));
2922 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2923 checker.set_position (Gtk::WIN_POS_MOUSE);
2925 switch (checker.run()) {
2926 case RESPONSE_ACCEPT:
2932 ARDOUR::CleanupReport rep;
2934 editor->prepare_for_cleanup ();
2936 /* do not allow flush until a session is reloaded */
2938 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2940 act->set_sensitive (false);
2943 if (_session->cleanup_sources (rep)) {
2944 editor->finish_cleanup ();
2948 editor->finish_cleanup ();
2951 display_cleanup_results (rep,
2954 The following %1 files were not in use and \n\
2955 have been moved to:\n\
2957 Flushing the wastebasket will \n\
2958 release an additional\n\
2959 %3 %4bytes of disk space.\n"),
2961 The following file was not in use and \n \
2962 has been moved to:\n \
2964 Flushing the wastebasket will \n\
2965 release an additional\n\
2966 %3 %4bytes of disk space.\n"
2972 ARDOUR_UI::flush_trash ()
2974 if (_session == 0) {
2975 /* shouldn't happen: menu item is insensitive */
2979 ARDOUR::CleanupReport rep;
2981 if (_session->cleanup_trash_sources (rep)) {
2985 display_cleanup_results (rep,
2987 _("The following %1 files were deleted from\n\
2989 releasing %3 %4bytes of disk space"),
2990 _("The following file was deleted from\n\
2992 releasing %3 %4bytes of disk space"));
2996 ARDOUR_UI::add_route (Gtk::Window* float_window)
3004 if (add_route_dialog == 0) {
3005 add_route_dialog = new AddRouteDialog (_session);
3007 add_route_dialog->set_transient_for (*float_window);
3011 if (add_route_dialog->is_visible()) {
3012 /* we're already doing this */
3016 ResponseType r = (ResponseType) add_route_dialog->run ();
3018 add_route_dialog->hide();
3021 case RESPONSE_ACCEPT:
3028 if ((count = add_route_dialog->count()) <= 0) {
3032 string template_path = add_route_dialog->track_template();
3034 if (!template_path.empty()) {
3035 _session->new_route_from_template (count, template_path);
3039 uint32_t input_chan = add_route_dialog->channels ();
3040 uint32_t output_chan;
3041 string name_template = add_route_dialog->name_template ();
3042 bool track = add_route_dialog->track ();
3043 bool aux = !track && add_route_dialog->aux();
3044 RouteGroup* route_group = add_route_dialog->route_group ();
3046 AutoConnectOption oac = Config->get_output_auto_connect();
3048 if (oac & AutoConnectMaster) {
3049 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3051 output_chan = input_chan;
3054 /* XXX do something with name template */
3056 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3058 session_add_midi_track (route_group, count);
3060 MessageDialog msg (*editor,
3061 _("Sorry, MIDI Busses are not supported at this time."));
3063 //session_add_midi_bus();
3067 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3069 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3075 ARDOUR_UI::mixer_settings () const
3080 node = _session->instant_xml(X_("Mixer"));
3082 node = Config->instant_xml(X_("Mixer"));
3086 node = new XMLNode (X_("Mixer"));
3093 ARDOUR_UI::editor_settings () const
3098 node = _session->instant_xml(X_("Editor"));
3100 node = Config->instant_xml(X_("Editor"));
3104 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3105 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3110 node = new XMLNode (X_("Editor"));
3117 ARDOUR_UI::keyboard_settings () const
3121 node = Config->extra_xml(X_("Keyboard"));
3124 node = new XMLNode (X_("Keyboard"));
3130 ARDOUR_UI::create_xrun_marker(nframes_t where)
3132 editor->mouse_add_new_marker (where, false, true);
3136 ARDOUR_UI::halt_on_xrun_message ()
3138 MessageDialog msg (*editor,
3139 _("Recording was stopped because your system could not keep up."));
3144 ARDOUR_UI::xrun_handler(nframes_t where)
3150 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3152 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3153 create_xrun_marker(where);
3156 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3157 halt_on_xrun_message ();
3162 ARDOUR_UI::disk_overrun_handler ()
3164 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3166 if (!have_disk_speed_dialog_displayed) {
3167 have_disk_speed_dialog_displayed = true;
3168 MessageDialog* msg = new MessageDialog (*editor, _("\
3169 The disk system on your computer\n\
3170 was not able to keep up with Ardour.\n\
3172 Specifically, it failed to write data to disk\n\
3173 quickly enough to keep up with recording.\n"));
3174 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3180 ARDOUR_UI::disk_underrun_handler ()
3182 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3184 if (!have_disk_speed_dialog_displayed) {
3185 have_disk_speed_dialog_displayed = true;
3186 MessageDialog* msg = new MessageDialog (*editor,
3187 _("The disk system on your computer\n\
3188 was not able to keep up with Ardour.\n\
3190 Specifically, it failed to read data from disk\n\
3191 quickly enough to keep up with playback.\n"));
3192 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3198 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3200 have_disk_speed_dialog_displayed = false;
3205 ARDOUR_UI::session_dialog (std::string msg)
3207 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3212 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3214 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3223 ARDOUR_UI::pending_state_dialog ()
3225 HBox* hbox = new HBox();
3226 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3227 ArdourDialog dialog (_("Crash Recovery"), true);
3229 This session appears to have been in\n\
3230 middle of recording when ardour or\n\
3231 the computer was shutdown.\n\
3233 Ardour can recover any captured audio for\n\
3234 you, or it can ignore it. Please decide\n\
3235 what you would like to do.\n"));
3236 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3237 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3238 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3239 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3240 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3241 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3242 dialog.set_default_response (RESPONSE_ACCEPT);
3243 dialog.set_position (WIN_POS_CENTER);
3248 switch (dialog.run ()) {
3249 case RESPONSE_ACCEPT:
3257 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3259 HBox* hbox = new HBox();
3260 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3261 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3262 Label message (string_compose (_("\
3263 This session was created with a sample rate of %1 Hz\n\
3265 The audioengine is currently running at %2 Hz\n"), desired, actual));
3267 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3268 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3269 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3270 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3271 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3272 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3273 dialog.set_default_response (RESPONSE_ACCEPT);
3274 dialog.set_position (WIN_POS_CENTER);
3279 switch (dialog.run ()) {
3280 case RESPONSE_ACCEPT:
3289 ARDOUR_UI::disconnect_from_jack ()
3292 if( engine->disconnect_from_jack ()) {
3293 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3297 update_sample_rate (0);
3302 ARDOUR_UI::reconnect_to_jack ()
3305 if (engine->reconnect_to_jack ()) {
3306 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3310 update_sample_rate (0);
3315 ARDOUR_UI::use_config ()
3318 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3320 set_transport_controllable_state (*node);
3323 node = Config->extra_xml (X_("UI"));
3326 const XMLProperty* prop = node->property (X_("show-big-clock"));
3327 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
3329 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
3330 tact->set_active (string_is_affirmative (prop->value()));
3336 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3338 if (Config->get_primary_clock_delta_edit_cursor()) {
3339 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3341 primary_clock.set (pos, 0, true);
3344 if (Config->get_secondary_clock_delta_edit_cursor()) {
3345 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3347 secondary_clock.set (pos);
3350 if (big_clock_window) {
3351 big_clock.set (pos);
3357 ARDOUR_UI::step_edit_status_change (bool yn)
3359 // XXX should really store pre-step edit status of things
3360 // we make insensitive
3363 rec_button.set_visual_state (3);
3364 rec_button.set_sensitive (false);
3366 rec_button.set_visual_state (0);
3367 rec_button.set_sensitive (true);
3372 ARDOUR_UI::record_state_changed ()
3374 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3376 if (!_session || !big_clock_window) {
3377 /* why bother - the clock isn't visible */
3381 Session::RecordState const r = _session->record_status ();
3382 bool const h = _session->have_rec_enabled_track ();
3384 if (r == Session::Recording && h) {
3385 big_clock.set_widget_name ("BigClockRecording");
3387 big_clock.set_widget_name ("BigClockNonRecording");
3392 ARDOUR_UI::first_idle ()
3395 _session->allow_auto_play (true);
3399 editor->first_idle();
3402 Keyboard::set_can_save_keybindings (true);
3407 ARDOUR_UI::store_clock_modes ()
3409 XMLNode* node = new XMLNode(X_("ClockModes"));
3411 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3412 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3415 _session->add_extra_xml (*node);
3416 _session->set_dirty ();
3421 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3422 : Controllable (name), ui (u), type(tp)
3428 ARDOUR_UI::TransportControllable::set_value (double val)
3430 if (type == ShuttleControl) {
3437 fract = -((0.5 - val)/0.5);
3439 fract = ((val - 0.5)/0.5);
3443 ui.set_shuttle_fract (fract);
3448 /* do nothing: these are radio-style actions */
3452 const char *action = 0;
3456 action = X_("Roll");
3459 action = X_("Stop");
3462 action = X_("Goto Start");
3465 action = X_("Goto End");
3468 action = X_("Loop");
3471 action = X_("Play Selection");
3474 action = X_("Record");
3484 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3492 ARDOUR_UI::TransportControllable::get_value (void) const
3511 case ShuttleControl:
3521 ARDOUR_UI::TransportControllable::set_id (const string& str)
3527 ARDOUR_UI::setup_profile ()
3529 if (gdk_screen_width() < 1200) {
3530 Profile->set_small_screen ();
3534 if (getenv ("ARDOUR_SAE")) {
3535 Profile->set_sae ();
3536 Profile->set_single_package ();