2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
34 #include <sys/resource.h>
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include "midi++/manager.h"
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
76 typedef uint64_t microseconds_t;
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
86 #include "add_route_dialog.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
97 #include "engine_dialog.h"
101 using namespace ARDOUR;
103 using namespace Gtkmm2ext;
105 using namespace sigc;
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
119 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
120 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
121 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
122 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
126 preroll_button (_("pre\nroll")),
127 postroll_button (_("post\nroll")),
131 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
135 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143 shuttle_controller_binding_proxy (shuttle_controllable),
145 roll_button (roll_controllable),
146 stop_button (stop_controllable),
147 goto_start_button (goto_start_controllable),
148 goto_end_button (goto_end_controllable),
149 auto_loop_button (auto_loop_controllable),
150 play_selection_button (play_selection_controllable),
151 rec_button (rec_controllable),
153 shuttle_units_button (_("% ")),
155 punch_in_button (_("Punch In")),
156 punch_out_button (_("Punch Out")),
157 auto_return_button (_("Auto Return")),
158 auto_play_button (_("Auto Play")),
159 auto_input_button (_("Auto Input")),
160 click_button (_("Click")),
161 time_master_button (_("time\nmaster")),
163 auditioning_alert_button (_("AUDITION")),
164 solo_alert_button (_("SOLO")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 // _auto_display_errors = false;
177 * This was commented out as it wasn't defined
178 * in A3 IIRC. If this is not needed it should
179 * be completely removed.
187 if (theArdourUI == 0) {
191 ui_config = new UIConfiguration();
192 theme_manager = new ThemeManager();
199 _session_is_new = false;
200 big_clock_window = 0;
201 session_selector_window = 0;
202 last_key_press_time = 0;
203 _will_create_new_session_automatically = false;
204 add_route_dialog = 0;
206 rc_option_editor = 0;
207 session_option_editor = 0;
209 open_session_selector = 0;
210 have_configure_timeout = false;
211 have_disk_speed_dialog_displayed = false;
212 session_loaded = false;
213 last_speed_displayed = -1.0f;
214 ignore_dual_punch = false;
215 _mixer_on_top = false;
217 roll_button.unset_flags (Gtk::CAN_FOCUS);
218 stop_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
220 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
221 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
222 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
223 rec_button.unset_flags (Gtk::CAN_FOCUS);
225 last_configure_time= 0;
227 shuttle_grabbed = false;
229 shuttle_max_speed = 8.0f;
231 shuttle_style_menu = 0;
232 shuttle_unit_menu = 0;
234 // We do not have jack linked in yet so;
236 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
238 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle dialog requests */
243 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
245 /* handle pending state with a dialog */
247 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
249 /* handle sr mismatch with a dialog */
251 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
253 /* lets get this party started */
256 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
257 throw failed_constructor ();
260 setup_gtk_ardour_enums ();
263 GainMeter::setup_slider_pix ();
264 RouteTimeAxisView::setup_slider_pix ();
266 } catch (failed_constructor& err) {
267 error << _("could not initialize Ardour.") << endmsg;
272 /* we like keyboards */
274 keyboard = new Keyboard;
278 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
279 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
284 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
286 ARDOUR_UI::run_startup (bool should_be_new)
289 _startup = new ArdourStartup ();
292 _startup->set_new_only (should_be_new);
293 _startup->present ();
297 /* we don't return here until the startup assistant is finished */
301 return _startup->applying ();
305 ARDOUR_UI::create_engine ()
307 // this gets called every time by new_session()
313 loading_message (_("Starting audio engine"));
316 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
323 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
324 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
325 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
326 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
334 ARDOUR_UI::post_engine ()
336 /* Things to be done once we create the AudioEngine
339 MIDI::Manager::instance()->set_api_data (engine->jack());
342 ARDOUR::init_post_engine ();
344 ActionManager::init ();
347 if (setup_windows ()) {
348 throw failed_constructor ();
351 check_memory_locking();
353 /* this is the first point at which all the keybindings are available */
355 if (ARDOUR_COMMAND_LINE::show_key_actions) {
356 vector<string> names;
357 vector<string> paths;
359 vector<AccelKey> bindings;
361 ActionManager::get_all_actions (names, paths, keys, bindings);
363 vector<string>::iterator n;
364 vector<string>::iterator k;
365 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
366 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
372 blink_timeout_tag = -1;
374 /* this being a GUI and all, we want peakfiles */
376 AudioFileSource::set_build_peakfiles (true);
377 AudioFileSource::set_build_missing_peakfiles (true);
379 /* set default clock modes */
381 if (Profile->get_sae()) {
382 primary_clock.set_mode (AudioClock::BBT);
383 secondary_clock.set_mode (AudioClock::MinSec);
385 primary_clock.set_mode (AudioClock::Timecode);
386 secondary_clock.set_mode (AudioClock::BBT);
389 /* start the time-of-day-clock */
392 /* OS X provides an always visible wallclock, so don't be stupid */
393 update_wall_clock ();
394 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
397 update_disk_space ();
399 update_sample_rate (engine->frame_rate());
401 Config->ParameterChanged.connect (mem_fun (*this, &ARDOUR_UI::parameter_changed));
402 Config->map_parameters (mem_fun (*this, &ARDOUR_UI::parameter_changed));
404 /* now start and maybe save state */
406 if (do_engine_start () == 0) {
407 if (session && _session_is_new) {
408 /* we need to retain initial visual
409 settings for a new session
411 session->save_state ("");
416 ARDOUR_UI::~ARDOUR_UI ()
418 save_ardour_state ();
423 delete add_route_dialog;
427 ARDOUR_UI::pop_back_splash ()
429 if (Splash::instance()) {
430 // Splash::instance()->pop_back();
431 Splash::instance()->hide ();
436 ARDOUR_UI::configure_timeout ()
438 if (last_configure_time == 0) {
439 /* no configure events yet */
443 /* force a gap of 0.5 seconds since the last configure event
446 if (get_microseconds() - last_configure_time < 500000) {
449 have_configure_timeout = false;
450 save_ardour_state ();
456 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
458 if (have_configure_timeout) {
459 last_configure_time = get_microseconds();
461 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
462 have_configure_timeout = true;
469 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
471 const XMLProperty* prop;
473 if ((prop = node.property ("roll")) != 0) {
474 roll_controllable->set_id (prop->value());
476 if ((prop = node.property ("stop")) != 0) {
477 stop_controllable->set_id (prop->value());
479 if ((prop = node.property ("goto-start")) != 0) {
480 goto_start_controllable->set_id (prop->value());
482 if ((prop = node.property ("goto-end")) != 0) {
483 goto_end_controllable->set_id (prop->value());
485 if ((prop = node.property ("auto-loop")) != 0) {
486 auto_loop_controllable->set_id (prop->value());
488 if ((prop = node.property ("play-selection")) != 0) {
489 play_selection_controllable->set_id (prop->value());
491 if ((prop = node.property ("rec")) != 0) {
492 rec_controllable->set_id (prop->value());
494 if ((prop = node.property ("shuttle")) != 0) {
495 shuttle_controllable->set_id (prop->value());
500 ARDOUR_UI::get_transport_controllable_state ()
502 XMLNode* node = new XMLNode(X_("TransportControllables"));
505 roll_controllable->id().print (buf, sizeof (buf));
506 node->add_property (X_("roll"), buf);
507 stop_controllable->id().print (buf, sizeof (buf));
508 node->add_property (X_("stop"), buf);
509 goto_start_controllable->id().print (buf, sizeof (buf));
510 node->add_property (X_("goto_start"), buf);
511 goto_end_controllable->id().print (buf, sizeof (buf));
512 node->add_property (X_("goto_end"), buf);
513 auto_loop_controllable->id().print (buf, sizeof (buf));
514 node->add_property (X_("auto_loop"), buf);
515 play_selection_controllable->id().print (buf, sizeof (buf));
516 node->add_property (X_("play_selection"), buf);
517 rec_controllable->id().print (buf, sizeof (buf));
518 node->add_property (X_("rec"), buf);
519 shuttle_controllable->id().print (buf, sizeof (buf));
520 node->add_property (X_("shuttle"), buf);
526 ARDOUR_UI::save_ardour_state ()
528 if (!keyboard || !mixer || !editor) {
532 /* XXX this is all a bit dubious. add_extra_xml() uses
533 a different lifetime model from add_instant_xml().
536 XMLNode* node = new XMLNode (keyboard->get_state());
537 Config->add_extra_xml (*node);
538 Config->add_extra_xml (get_transport_controllable_state());
539 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
540 Config->add_extra_xml (_startup->engine_control()->get_state());
542 Config->save_state();
543 ui_config->save_state ();
545 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
546 XMLNode mnode(mixer->get_state());
549 session->add_instant_xml (enode);
550 session->add_instant_xml (mnode);
552 Config->add_instant_xml (enode);
553 Config->add_instant_xml (mnode);
556 Keyboard::save_keybindings ();
560 ARDOUR_UI::autosave_session ()
562 if (g_main_depth() > 1) {
563 /* inside a recursive main loop,
564 give up because we may not be able to
570 if (!Config->get_periodic_safety_backups()) {
575 session->maybe_write_autosave();
582 ARDOUR_UI::update_autosave ()
584 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
586 if (session && session->dirty()) {
587 if (_autosave_connection.connected()) {
588 _autosave_connection.disconnect();
591 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
592 Config->get_periodic_safety_backup_interval() * 1000);
595 if (_autosave_connection.connected()) {
596 _autosave_connection.disconnect();
602 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
606 title = _("Ardour could not start JACK");
608 title = _("Ardour could not connect to JACK.");
611 MessageDialog win (title,
617 win.set_secondary_text(_("There are several possible reasons:\n\
619 1) You requested audio parameters that are not supported..\n\
620 2) JACK is running as another user.\n\
622 Please consider the possibilities, and perhaps try different parameters."));
624 win.set_secondary_text(_("There are several possible reasons:\n\
626 1) JACK is not running.\n\
627 2) JACK is running as another user, perhaps root.\n\
628 3) There is already another client called \"ardour\".\n\
630 Please consider the possibilities, and perhaps (re)start JACK."));
634 win.set_transient_for (*toplevel);
638 win.add_button (Stock::OK, RESPONSE_CLOSE);
640 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
643 win.set_default_response (RESPONSE_CLOSE);
646 win.set_position (Gtk::WIN_POS_CENTER);
649 /* we just don't care about the result, but we want to block */
655 ARDOUR_UI::startup ()
657 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
659 if (audio_setup && _startup && _startup->engine_control()) {
660 _startup->engine_control()->set_state (*audio_setup);
663 if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session)) {
669 goto_editor_window ();
671 BootMessage (_("Ardour is ready for use"));
676 ARDOUR_UI::no_memory_warning ()
678 XMLNode node (X_("no-memory-warning"));
679 Config->add_instant_xml (node);
683 ARDOUR_UI::check_memory_locking ()
686 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
690 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
692 if (engine->is_realtime() && memory_warning_node == 0) {
694 struct rlimit limits;
696 long pages, page_size;
698 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
701 ram = (int64_t) pages * (int64_t) page_size;
704 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
708 if (limits.rlim_cur != RLIM_INFINITY) {
710 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
713 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
714 "This might cause Ardour to run out of memory before your system "
715 "runs out of memory. \n\n"
716 "You can view the memory limit with 'ulimit -l', "
717 "and it is normally controlled by /etc/security/limits.conf"));
719 VBox* vbox = msg.get_vbox();
721 CheckButton cb (_("Do not show this window again"));
723 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
725 hbox.pack_start (cb, true, false);
726 vbox->pack_start (hbox);
733 editor->ensure_float (msg);
747 if (session->transport_rolling()) {
748 session->request_stop ();
752 if (session->dirty()) {
753 switch (ask_about_saving_session(_("quit"))) {
758 /* use the default name */
759 if (save_state_canfail ("")) {
760 /* failed - don't quit */
761 MessageDialog msg (*editor,
763 Ardour was unable to save your session.\n\n\
764 If you still wish to quit, please use the\n\n\
765 \"Just quit\" option."));
776 session->set_deletion_in_progress ();
779 ArdourDialog::close_all_dialogs ();
781 save_ardour_state ();
786 ARDOUR_UI::ask_about_saving_session (const string & what)
788 ArdourDialog window (_("ardour: save session?"));
789 Gtk::HBox dhbox; // the hbox for the image and text
790 Gtk::Label prompt_label;
791 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
795 msg = string_compose(_("Don't %1"), what);
796 window.add_button (msg, RESPONSE_REJECT);
797 msg = string_compose(_("Just %1"), what);
798 window.add_button (msg, RESPONSE_APPLY);
799 msg = string_compose(_("Save and %1"), what);
800 window.add_button (msg, RESPONSE_ACCEPT);
802 window.set_default_response (RESPONSE_ACCEPT);
804 Gtk::Button noquit_button (msg);
805 noquit_button.set_name ("EditorGTKButton");
810 if (session->snap_name() == session->name()) {
813 type = _("snapshot");
815 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?"),
816 type, session->snap_name());
818 prompt_label.set_text (prompt);
819 prompt_label.set_name (X_("PrompterLabel"));
820 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
822 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
823 dhbox.set_homogeneous (false);
824 dhbox.pack_start (*dimage, false, false, 5);
825 dhbox.pack_start (prompt_label, true, false, 5);
826 window.get_vbox()->pack_start (dhbox);
828 window.set_name (_("Prompter"));
829 window.set_position (Gtk::WIN_POS_MOUSE);
830 window.set_modal (true);
831 window.set_resizable (false);
837 window.set_keep_above (true);
840 ResponseType r = (ResponseType) window.run();
845 case RESPONSE_ACCEPT: // save and get out of here
847 case RESPONSE_APPLY: // get out of here
857 ARDOUR_UI::every_second ()
860 update_buffer_load ();
861 update_disk_space ();
866 ARDOUR_UI::every_point_one_seconds ()
868 update_speed_display ();
869 RapidScreenUpdate(); /* EMIT_SIGNAL */
874 ARDOUR_UI::every_point_zero_one_seconds ()
876 // august 2007: actual update frequency: 40Hz, not 100Hz
878 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
883 ARDOUR_UI::update_sample_rate (nframes_t ignored)
887 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
889 if (!engine->connected()) {
891 snprintf (buf, sizeof (buf), _("disconnected"));
895 nframes_t rate = engine->frame_rate();
897 if (fmod (rate, 1000.0) != 0.0) {
898 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
899 (float) rate/1000.0f,
900 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
902 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
904 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
908 sample_rate_label.set_text (buf);
912 ARDOUR_UI::update_cpu_load ()
915 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
916 cpu_load_label.set_text (buf);
920 ARDOUR_UI::update_buffer_load ()
926 c = session->capture_load ();
927 p = session->playback_load ();
929 push_buffer_stats (c, p);
931 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
932 session->playback_load(), session->capture_load());
933 buffer_load_label.set_text (buf);
935 buffer_load_label.set_text ("");
940 ARDOUR_UI::count_recenabled_streams (Route& route)
942 Track* track = dynamic_cast<Track*>(&route);
943 if (track && track->diskstream()->record_enabled()) {
944 rec_enabled_streams += track->n_inputs().n_total();
949 ARDOUR_UI::update_disk_space()
955 nframes_t frames = session->available_capture_duration();
957 nframes_t fr = session->frame_rate();
959 if (frames == max_frames) {
960 strcpy (buf, _("Disk: 24hrs+"));
962 rec_enabled_streams = 0;
963 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
965 if (rec_enabled_streams) {
966 frames /= rec_enabled_streams;
973 hrs = frames / (fr * 3600);
974 frames -= hrs * fr * 3600;
975 mins = frames / (fr * 60);
976 frames -= mins * fr * 60;
979 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
982 disk_space_label.set_text (buf);
984 // An attempt to make the disk space label flash red when space has run out.
986 if (frames < fr * 60 * 5) {
987 /* disk_space_box.style ("disk_space_label_empty"); */
989 /* disk_space_box.style ("disk_space_label"); */
995 ARDOUR_UI::update_wall_clock ()
1002 tm_now = localtime (&now);
1004 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1005 wall_clock_label.set_text (buf);
1011 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1013 session_popup_menu->popup (0, 0);
1018 ARDOUR_UI::redisplay_recent_sessions ()
1020 std::vector<sys::path> session_directories;
1021 RecentSessionsSorter cmp;
1023 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1024 recent_session_model->clear ();
1026 ARDOUR::RecentSessions rs;
1027 ARDOUR::read_recent_sessions (rs);
1030 recent_session_display.set_model (recent_session_model);
1034 // sort them alphabetically
1035 sort (rs.begin(), rs.end(), cmp);
1037 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1038 session_directories.push_back ((*i).second);
1041 for (vector<sys::path>::const_iterator i = session_directories.begin();
1042 i != session_directories.end(); ++i)
1044 std::vector<sys::path> state_file_paths;
1046 // now get available states for this session
1048 get_state_files_in_directory (*i, state_file_paths);
1050 vector<string*>* states;
1051 vector<const gchar*> item;
1052 string fullpath = (*i).to_string();
1054 /* remove any trailing / */
1056 if (fullpath[fullpath.length()-1] == '/') {
1057 fullpath = fullpath.substr (0, fullpath.length()-1);
1060 /* check whether session still exists */
1061 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1062 /* session doesn't exist */
1063 cerr << "skipping non-existent session " << fullpath << endl;
1067 /* now get available states for this session */
1069 if ((states = Session::possible_states (fullpath)) == 0) {
1070 /* no state file? */
1074 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1076 Gtk::TreeModel::Row row = *(recent_session_model->append());
1078 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1079 row[recent_session_columns.fullpath] = fullpath;
1081 if (state_file_names.size() > 1) {
1085 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1086 i2 != state_file_names.end(); ++i2)
1089 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1091 child_row[recent_session_columns.visible_name] = *i2;
1092 child_row[recent_session_columns.fullpath] = fullpath;
1097 recent_session_display.set_model (recent_session_model);
1101 ARDOUR_UI::build_session_selector ()
1103 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1105 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1107 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1108 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1109 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1110 recent_session_model = TreeStore::create (recent_session_columns);
1111 recent_session_display.set_model (recent_session_model);
1112 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1113 recent_session_display.set_headers_visible (false);
1114 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1115 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1117 scroller->add (recent_session_display);
1118 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1120 session_selector_window->set_name ("SessionSelectorWindow");
1121 session_selector_window->set_size_request (200, 400);
1122 session_selector_window->get_vbox()->pack_start (*scroller);
1124 recent_session_display.show();
1126 //session_selector_window->get_vbox()->show();
1130 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1132 session_selector_window->response (RESPONSE_ACCEPT);
1136 ARDOUR_UI::open_recent_session ()
1138 bool can_return = (session != 0);
1140 if (session_selector_window == 0) {
1141 build_session_selector ();
1144 redisplay_recent_sessions ();
1148 session_selector_window->set_position (WIN_POS_MOUSE);
1150 ResponseType r = (ResponseType) session_selector_window->run ();
1153 case RESPONSE_ACCEPT:
1157 session_selector_window->hide();
1164 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1168 session_selector_window->hide();
1170 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1172 if (i == recent_session_model->children().end()) {
1176 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1177 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1179 _session_is_new = false;
1181 if (load_session (path, state) == 0) {
1190 ARDOUR_UI::check_audioengine ()
1193 if (!engine->connected()) {
1194 MessageDialog msg (_("Ardour is not connected to JACK\n"
1195 "You cannot open or close sessions in this condition"));
1207 ARDOUR_UI::open_session ()
1209 if (!check_audioengine()) {
1214 /* popup selector window */
1216 if (open_session_selector == 0) {
1218 /* ardour sessions are folders */
1220 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1221 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1222 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1223 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1225 FileFilter session_filter;
1226 session_filter.add_pattern ("*.ardour");
1227 session_filter.set_name (_("Ardour sessions"));
1228 open_session_selector->add_filter (session_filter);
1229 open_session_selector->set_filter (session_filter);
1232 int response = open_session_selector->run();
1233 open_session_selector->hide ();
1236 case RESPONSE_ACCEPT:
1239 open_session_selector->hide();
1243 open_session_selector->hide();
1244 string session_path = open_session_selector->get_filename();
1248 if (session_path.length() > 0) {
1249 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1250 _session_is_new = isnew;
1251 load_session (path, name);
1258 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1260 list<boost::shared_ptr<MidiTrack> > tracks;
1263 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1270 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1272 if (tracks.size() != how_many) {
1273 if (how_many == 1) {
1274 error << _("could not create a new midi track") << endmsg;
1276 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1280 if ((route = session->new_midi_route ()) == 0) {
1281 error << _("could not create new midi bus") << endmsg;
1287 MessageDialog msg (*editor,
1288 _("There are insufficient JACK ports available\n\
1289 to create a new track or bus.\n\
1290 You should save Ardour, exit and\n\
1291 restart JACK with more ports."));
1298 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)
1300 list<boost::shared_ptr<AudioTrack> > tracks;
1304 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1310 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1312 if (tracks.size() != how_many) {
1313 if (how_many == 1) {
1314 error << _("could not create a new audio track") << endmsg;
1316 error << string_compose (_("could only create %1 of %2 new audio %3"),
1317 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1323 routes = session->new_audio_route (aux, input_channels, output_channels, route_group, how_many);
1325 if (routes.size() != how_many) {
1326 if (how_many == 1) {
1327 error << _("could not create a new audio track") << endmsg;
1329 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1335 if (need_control_room_outs) {
1341 route->set_stereo_control_outs (control_lr_channels);
1342 route->control_outs()->set_stereo_pan (pans, this);
1344 #endif /* CONTROLOUTS */
1348 MessageDialog msg (*editor,
1349 _("There are insufficient JACK ports available\n\
1350 to create a new track or bus.\n\
1351 You should save Ardour, exit and\n\
1352 restart JACK with more ports."));
1359 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1361 nframes_t _preroll = 0;
1364 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1365 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1367 if (new_position > _preroll) {
1368 new_position -= _preroll;
1373 session->request_locate (new_position);
1378 ARDOUR_UI::transport_goto_start ()
1381 session->goto_start();
1384 /* force displayed area in editor to start no matter
1385 what "follow playhead" setting is.
1389 editor->reset_x_origin (session->current_start_frame());
1395 ARDOUR_UI::transport_goto_zero ()
1398 session->request_locate (0);
1401 /* force displayed area in editor to start no matter
1402 what "follow playhead" setting is.
1406 editor->reset_x_origin (0);
1412 ARDOUR_UI::transport_goto_wallclock ()
1414 if (session && editor) {
1421 localtime_r (&now, &tmnow);
1423 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1424 frames += tmnow.tm_min * (60 * session->frame_rate());
1425 frames += tmnow.tm_sec * session->frame_rate();
1427 session->request_locate (frames);
1429 /* force displayed area in editor to start no matter
1430 what "follow playhead" setting is.
1434 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1440 ARDOUR_UI::transport_goto_end ()
1443 nframes_t frame = session->current_end_frame();
1444 session->request_locate (frame);
1446 /* force displayed area in editor to start no matter
1447 what "follow playhead" setting is.
1451 editor->reset_x_origin (frame);
1457 ARDOUR_UI::transport_stop ()
1463 if (session->is_auditioning()) {
1464 session->cancel_audition ();
1468 session->request_stop ();
1472 ARDOUR_UI::transport_stop_and_forget_capture ()
1475 session->request_stop (true);
1480 ARDOUR_UI::remove_last_capture()
1483 editor->remove_last_capture();
1488 ARDOUR_UI::transport_record (bool roll)
1492 switch (session->record_status()) {
1493 case Session::Disabled:
1494 if (session->ntracks() == 0) {
1495 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1499 session->maybe_enable_record ();
1504 case Session::Recording:
1506 session->request_stop();
1508 session->disable_record (false, true);
1512 case Session::Enabled:
1513 session->disable_record (false, true);
1516 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1520 ARDOUR_UI::transport_roll ()
1526 if (session->is_auditioning()) {
1530 if (session->config.get_external_sync()) {
1531 switch (session->config.get_sync_source()) {
1535 /* transport controlled by the master */
1540 bool rolling = session->transport_rolling();
1542 if (session->get_play_loop()) {
1543 session->request_play_loop (false, true);
1544 } else if (session->get_play_range ()) {
1545 session->request_play_range (false, true);
1549 session->request_transport_speed (1.0f);
1552 map_transport_state ();
1556 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1563 if (session->is_auditioning()) {
1564 session->cancel_audition ();
1568 if (session->config.get_external_sync()) {
1569 switch (session->config.get_sync_source()) {
1573 /* transport controlled by the master */
1578 bool rolling = session->transport_rolling();
1579 bool affect_transport = true;
1581 if (rolling && roll_out_of_bounded_mode) {
1582 /* drop out of loop/range playback but leave transport rolling */
1583 if (session->get_play_loop()) {
1584 if (Config->get_seamless_loop()) {
1585 /* the disk buffers contain copies of the loop - we can't
1586 just keep playing, so stop the transport. the user
1587 can restart as they wish.
1589 affect_transport = true;
1591 /* disk buffers are normal, so we can keep playing */
1592 affect_transport = false;
1594 session->request_play_loop (false, true);
1595 } else if (session->get_play_range ()) {
1596 affect_transport = false;
1597 session->request_play_range (0, true);
1601 if (affect_transport) {
1603 session->request_stop (with_abort, true);
1605 session->request_transport_speed (1.0f);
1609 map_transport_state ();
1613 ARDOUR_UI::toggle_session_auto_loop ()
1616 if (session->get_play_loop()) {
1617 if (session->transport_rolling()) {
1618 Location * looploc = session->locations()->auto_loop_location();
1620 session->request_locate (looploc->start(), true);
1623 session->request_play_loop (false);
1626 Location * looploc = session->locations()->auto_loop_location();
1628 session->request_play_loop (true);
1635 ARDOUR_UI::transport_play_selection ()
1641 editor->play_selection ();
1645 ARDOUR_UI::transport_rewind (int option)
1647 float current_transport_speed;
1650 current_transport_speed = session->transport_speed();
1652 if (current_transport_speed >= 0.0f) {
1655 session->request_transport_speed (-1.0f);
1658 session->request_transport_speed (-4.0f);
1661 session->request_transport_speed (-0.5f);
1666 session->request_transport_speed (current_transport_speed * 1.5f);
1672 ARDOUR_UI::transport_forward (int option)
1674 float current_transport_speed;
1677 current_transport_speed = session->transport_speed();
1679 if (current_transport_speed <= 0.0f) {
1682 session->request_transport_speed (1.0f);
1685 session->request_transport_speed (4.0f);
1688 session->request_transport_speed (0.5f);
1693 session->request_transport_speed (current_transport_speed * 1.5f);
1700 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1706 boost::shared_ptr<Route> r;
1708 if ((r = session->route_by_remote_id (dstream)) != 0) {
1712 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1713 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1722 ARDOUR_UI::map_transport_state ()
1724 ENSURE_GUI_THREAD(mem_fun (*this, &ARDOUR_UI::map_transport_state));
1727 auto_loop_button.set_visual_state (0);
1728 play_selection_button.set_visual_state (0);
1729 roll_button.set_visual_state (0);
1730 stop_button.set_visual_state (1);
1734 float sp = session->transport_speed();
1737 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1738 shuttle_box.queue_draw ();
1739 } else if (sp == 0.0f) {
1741 shuttle_box.queue_draw ();
1742 update_disk_space ();
1747 if (session->get_play_range()) {
1749 play_selection_button.set_visual_state (1);
1750 roll_button.set_visual_state (0);
1751 auto_loop_button.set_visual_state (0);
1753 } else if (session->get_play_loop ()) {
1755 auto_loop_button.set_visual_state (1);
1756 play_selection_button.set_visual_state (0);
1757 roll_button.set_visual_state (0);
1761 roll_button.set_visual_state (1);
1762 play_selection_button.set_visual_state (0);
1763 auto_loop_button.set_visual_state (0);
1766 stop_button.set_visual_state (0);
1770 stop_button.set_visual_state (1);
1771 roll_button.set_visual_state (0);
1772 play_selection_button.set_visual_state (0);
1773 auto_loop_button.set_visual_state (0);
1779 ARDOUR_UI::engine_stopped ()
1781 ENSURE_GUI_THREAD (mem_fun(*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 (mem_fun(*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 ()
1840 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1842 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1843 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1845 update_sample_rate (0);
1847 MessageDialog msg (*editor,
1849 JACK has either been shutdown or it\n\
1850 disconnected Ardour because Ardour\n\
1851 was not fast enough. Try to restart\n\
1852 JACK, reconnect and save the session."));
1858 ARDOUR_UI::do_engine_start ()
1866 error << _("Unable to start the session running")
1876 ARDOUR_UI::setup_theme ()
1878 theme_manager->setup_theme();
1882 ARDOUR_UI::update_clocks ()
1884 if (!editor || !editor->dragging_playhead()) {
1885 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1890 ARDOUR_UI::start_clocking ()
1892 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1896 ARDOUR_UI::stop_clocking ()
1898 clock_signal_connection.disconnect ();
1902 ARDOUR_UI::toggle_clocking ()
1905 if (clock_button.get_active()) {
1914 ARDOUR_UI::_blink (void *arg)
1917 ((ARDOUR_UI *) arg)->blink ();
1924 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1928 ARDOUR_UI::start_blinking ()
1930 /* Start the blink signal. Everybody with a blinking widget
1931 uses Blink to drive the widget's state.
1934 if (blink_timeout_tag < 0) {
1936 blink_timeout_tag = g_timeout_add (240, _blink, this);
1941 ARDOUR_UI::stop_blinking ()
1943 if (blink_timeout_tag >= 0) {
1944 g_source_remove (blink_timeout_tag);
1945 blink_timeout_tag = -1;
1950 /** Ask the user for the name of a new shapshot and then take it.
1953 ARDOUR_UI::snapshot_session ()
1955 ArdourPrompter prompter (true);
1959 struct tm local_time;
1962 localtime_r (&n, &local_time);
1963 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1965 prompter.set_name ("Prompter");
1966 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1967 prompter.set_title (_("Take Snapshot"));
1968 prompter.set_prompt (_("Name of New Snapshot"));
1969 prompter.set_initial_text (timebuf);
1971 switch (prompter.run()) {
1972 case RESPONSE_ACCEPT:
1974 prompter.get_result (snapname);
1976 bool do_save = (snapname.length() != 0);
1978 vector<sys::path> p;
1979 get_state_files_in_directory (session->session_directory().root_path(), p);
1980 vector<string> n = get_file_names_no_extension (p);
1981 if (find (n.begin(), n.end(), snapname) != n.end()) {
1983 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1984 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1985 confirm.get_vbox()->pack_start (m, true, true);
1986 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1987 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1988 confirm.show_all ();
1989 switch (confirm.run()) {
1990 case RESPONSE_CANCEL:
1996 save_state (snapname);
2007 ARDOUR_UI::save_state (const string & name)
2009 (void) save_state_canfail (name);
2013 ARDOUR_UI::save_state_canfail (string name)
2018 if (name.length() == 0) {
2019 name = session->snap_name();
2022 if ((ret = session->save_state (name)) != 0) {
2026 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2031 ARDOUR_UI::primary_clock_value_changed ()
2034 session->request_locate (primary_clock.current_time ());
2039 ARDOUR_UI::big_clock_value_changed ()
2042 session->request_locate (big_clock.current_time ());
2047 ARDOUR_UI::secondary_clock_value_changed ()
2050 session->request_locate (secondary_clock.current_time ());
2055 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2061 Session::RecordState const r = session->record_status ();
2062 bool const h = session->have_rec_enabled_diskstream ();
2064 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2066 rec_button.set_visual_state (2);
2068 rec_button.set_visual_state (0);
2070 } else if (r == Session::Recording && h) {
2071 rec_button.set_visual_state (1);
2073 rec_button.set_visual_state (0);
2078 ARDOUR_UI::save_template ()
2080 ArdourPrompter prompter (true);
2083 if (!check_audioengine()) {
2087 prompter.set_name (X_("Prompter"));
2088 prompter.set_title (_("Save Mix Template"));
2089 prompter.set_prompt (_("Name for mix template:"));
2090 prompter.set_initial_text(session->name() + _("-template"));
2091 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2093 switch (prompter.run()) {
2094 case RESPONSE_ACCEPT:
2095 prompter.get_result (name);
2097 if (name.length()) {
2098 session->save_template (name);
2108 ARDOUR_UI::edit_metadata ()
2110 SessionMetadataEditor dialog;
2111 dialog.set_session (session);
2112 editor->ensure_float (dialog);
2117 ARDOUR_UI::import_metadata ()
2119 SessionMetadataImporter dialog;
2120 dialog.set_session (session);
2121 editor->ensure_float (dialog);
2126 ARDOUR_UI::fontconfig_dialog ()
2129 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2130 may not and it can take a while to build it. Warn them.
2133 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2135 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2136 MessageDialog msg (*_startup,
2137 _("Welcome to Ardour.\n\n"
2138 "The program will take a bit longer to start up\n"
2139 "while the system fonts are checked.\n\n"
2140 "This will only be done once, and you will\n"
2141 "not see this message again\n"),
2154 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2156 existing_session = false;
2158 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2159 session_path = cmdline_path;
2160 existing_session = true;
2161 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2162 session_path = Glib::path_get_dirname (string (cmdline_path));
2163 existing_session = true;
2165 /* it doesn't exist, assume the best */
2166 session_path = Glib::path_get_dirname (string (cmdline_path));
2169 session_name = basename_nosuffix (string (cmdline_path));
2173 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2175 /* when this is called, the backend audio system must be running */
2177 /* the main idea here is to deal with the fact that a cmdline argument for the session
2178 can be interpreted in different ways - it could be a directory or a file, and before
2179 we load, we need to know both the session directory and the snapshot (statefile) within it
2180 that we are supposed to use.
2183 if (session_name.length() == 0 || session_path.length() == 0) {
2187 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2189 Glib::ustring predicted_session_file;
2191 predicted_session_file = session_path;
2192 predicted_session_file += '/';
2193 predicted_session_file += session_name;
2194 predicted_session_file += ARDOUR::statefile_suffix;
2196 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2197 existing_session = true;
2200 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2202 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2203 /* existing .ardour file */
2204 existing_session = true;
2208 existing_session = false;
2211 /* lets just try to load it */
2213 if (create_engine ()) {
2214 backend_audio_error (false, _startup);
2218 return load_session (session_path, session_name);
2222 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2224 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2226 MessageDialog msg (str,
2228 Gtk::MESSAGE_WARNING,
2229 Gtk::BUTTONS_YES_NO,
2233 msg.set_name (X_("OpenExistingDialog"));
2234 msg.set_title (_("Open Existing Session"));
2235 msg.set_wmclass (X_("existing_session"), "Ardour");
2236 msg.set_position (Gtk::WIN_POS_MOUSE);
2239 switch (msg.run()) {
2248 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2253 AutoConnectOption iconnect;
2254 AutoConnectOption oconnect;
2258 if (Profile->get_sae()) {
2262 iconnect = AutoConnectPhysical;
2263 oconnect = AutoConnectMaster;
2264 nphysin = 0; // use all available
2265 nphysout = 0; // use all available
2269 /* get settings from advanced section of NSD */
2271 if (_startup->create_control_bus()) {
2272 cchns = (uint32_t) _startup->control_channel_count();
2277 if (_startup->create_master_bus()) {
2278 mchns = (uint32_t) _startup->master_channel_count();
2283 if (_startup->connect_inputs()) {
2284 iconnect = AutoConnectPhysical;
2286 iconnect = AutoConnectOption (0);
2289 /// @todo some minor tweaks.
2291 oconnect = AutoConnectOption (0);
2293 if (_startup->connect_outputs ()) {
2294 if (_startup->connect_outs_to_master()) {
2295 oconnect = AutoConnectMaster;
2296 } else if (_startup->connect_outs_to_physical()) {
2297 oconnect = AutoConnectPhysical;
2301 nphysin = (uint32_t) _startup->input_limit_count();
2302 nphysout = (uint32_t) _startup->output_limit_count();
2305 if (build_session (session_path,
2313 engine->frame_rate() * 60 * 5)) {
2322 ARDOUR_UI::idle_load (const Glib::ustring& path)
2325 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2326 /* /path/to/foo => /path/to/foo, foo */
2327 load_session (path, basename_nosuffix (path));
2329 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2330 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2334 ARDOUR_COMMAND_LINE::session_name = path;
2337 * new_session_dialog doens't exist in A3
2338 * Try to remove all references to it to
2339 * see if it will compile. NOTE: this will
2340 * likely cause a runtime issue is my somewhat
2344 //if (new_session_dialog) {
2347 /* make it break out of Dialog::run() and
2351 //new_session_dialog->response (1);
2357 ARDOUR_UI::end_loading_messages ()
2363 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2366 // splash->message (msg);
2370 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2372 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
2374 Glib::ustring session_name;
2375 Glib::ustring session_path;
2376 Glib::ustring template_name;
2378 bool likely_new = false;
2382 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2384 /* if they named a specific statefile, use it, otherwise they are
2385 just giving a session folder, and we want to use it as is
2386 to find the session.
2389 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2390 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2392 session_path = ARDOUR_COMMAND_LINE::session_name;
2395 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2399 bool const apply = run_startup (should_be_new);
2401 if (quit_on_cancel) {
2408 /* if we run the startup dialog again, offer more than just "new session" */
2410 should_be_new = false;
2412 session_name = _startup->session_name (likely_new);
2414 /* this shouldn't happen, but we catch it just in case it does */
2416 if (session_name.empty()) {
2419 if (_startup->use_session_template()) {
2420 template_name = _startup->session_template_name();
2421 _session_is_new = true;
2424 if (session_name[0] == '/' ||
2425 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2426 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2428 session_path = Glib::path_get_dirname (session_name);
2429 session_name = Glib::path_get_basename (session_name);
2433 session_path = _startup->session_folder();
2437 if (create_engine ()) {
2441 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2445 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2447 if (!ask_about_loading_existing_session (existing)) {
2448 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2453 _session_is_new = false;
2458 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2460 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2464 _session_is_new = true;
2467 if (likely_new && template_name.empty()) {
2469 ret = build_session_from_nsd (session_path, session_name);
2473 ret = load_session (session_path, session_name, template_name);
2474 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2475 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2485 ARDOUR_UI::close_session()
2487 if (!check_audioengine()) {
2491 unload_session (true);
2493 ARDOUR_COMMAND_LINE::session_name = "";
2494 get_session_parameters (true, false);
2498 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2500 Session *new_session;
2504 session_loaded = false;
2506 if (!check_audioengine()) {
2510 unload_status = unload_session ();
2512 if (unload_status < 0) {
2514 } else if (unload_status > 0) {
2519 loading_message (_("Please wait while Ardour loads your session"));
2522 new_session = new Session (*engine, path, snap_name, mix_template);
2525 /* this one is special */
2527 catch (AudioEngine::PortRegistrationFailure& err) {
2529 MessageDialog msg (err.what(),
2532 Gtk::BUTTONS_CLOSE);
2534 msg.set_title (_("Port Registration Error"));
2535 msg.set_secondary_text (_("Click the Close button to try again."));
2536 msg.set_position (Gtk::WIN_POS_CENTER);
2540 int response = msg.run ();
2545 case RESPONSE_CANCEL:
2555 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2558 Gtk::BUTTONS_CLOSE);
2560 msg.set_title (_("Loading Error"));
2561 msg.set_secondary_text (_("Click the Close button to try again."));
2562 msg.set_position (Gtk::WIN_POS_CENTER);
2566 int response = msg.run ();
2571 case RESPONSE_CANCEL:
2579 connect_to_session (new_session);
2581 session_loaded = true;
2583 goto_editor_window ();
2586 session->set_clean ();
2597 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2598 uint32_t control_channels,
2599 uint32_t master_channels,
2600 AutoConnectOption input_connect,
2601 AutoConnectOption output_connect,
2604 nframes_t initial_length)
2606 Session *new_session;
2609 if (!check_audioengine()) {
2613 session_loaded = false;
2615 x = unload_session ();
2623 _session_is_new = true;
2626 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2627 control_channels, master_channels, nphysin, nphysout, initial_length);
2632 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2638 connect_to_session (new_session);
2640 session_loaded = true;
2642 new_session->save_state(new_session->name());
2651 editor->show_window ();
2662 ARDOUR_UI::show_about ()
2666 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2673 ARDOUR_UI::hide_about ()
2676 about->get_window()->set_cursor ();
2682 ARDOUR_UI::about_signal_response (int /*response*/)
2688 ARDOUR_UI::show_splash ()
2692 splash = new Splash;
2700 splash->queue_draw ();
2701 splash->get_window()->process_updates (true);
2706 ARDOUR_UI::hide_splash ()
2714 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2715 const string& plural_msg, const string& singular_msg)
2719 removed = rep.paths.size();
2722 MessageDialog msgd (*editor,
2723 _("No audio files were ready for cleanup"),
2726 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2727 msgd.set_secondary_text (_("If this seems suprising, \n\
2728 check for any existing snapshots.\n\
2729 These may still include regions that\n\
2730 require some unused files to continue to exist."));
2736 ArdourDialog results (_("ardour: cleanup"), true, false);
2738 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2739 CleanupResultsModelColumns() {
2743 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2744 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2748 CleanupResultsModelColumns results_columns;
2749 Glib::RefPtr<Gtk::ListStore> results_model;
2750 Gtk::TreeView results_display;
2752 results_model = ListStore::create (results_columns);
2753 results_display.set_model (results_model);
2754 results_display.append_column (list_title, results_columns.visible_name);
2756 results_display.set_name ("CleanupResultsList");
2757 results_display.set_headers_visible (true);
2758 results_display.set_headers_clickable (false);
2759 results_display.set_reorderable (false);
2761 Gtk::ScrolledWindow list_scroller;
2764 Gtk::HBox dhbox; // the hbox for the image and text
2765 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2766 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2768 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2770 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2776 %1 - number of files removed
2777 %2 - location of "dead_sounds"
2778 %3 - size of files affected
2779 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2782 const char* bprefix;
2784 if (rep.space < 1048576.0f) {
2785 bprefix = X_("kilo");
2786 } else if (rep.space < 1048576.0f * 1000) {
2787 bprefix = X_("mega");
2789 bprefix = X_("giga");
2793 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2795 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2798 dhbox.pack_start (*dimage, true, false, 5);
2799 dhbox.pack_start (txt, true, false, 5);
2801 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2802 TreeModel::Row row = *(results_model->append());
2803 row[results_columns.visible_name] = *i;
2804 row[results_columns.fullpath] = *i;
2807 list_scroller.add (results_display);
2808 list_scroller.set_size_request (-1, 150);
2809 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2811 dvbox.pack_start (dhbox, true, false, 5);
2812 dvbox.pack_start (list_scroller, true, false, 5);
2813 ddhbox.pack_start (dvbox, true, false, 5);
2815 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2816 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2817 results.set_default_response (RESPONSE_CLOSE);
2818 results.set_position (Gtk::WIN_POS_MOUSE);
2820 results_display.show();
2821 list_scroller.show();
2828 //results.get_vbox()->show();
2829 results.set_resizable (false);
2836 ARDOUR_UI::cleanup ()
2839 /* shouldn't happen: menu item is insensitive */
2844 MessageDialog checker (_("Are you sure you want to cleanup?"),
2846 Gtk::MESSAGE_QUESTION,
2847 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2849 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2850 ALL undo/redo information will be lost if you cleanup.\n\
2851 After cleanup, unused audio files will be moved to a \
2852 \"dead sounds\" location."));
2854 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2855 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2856 checker.set_default_response (RESPONSE_CANCEL);
2858 checker.set_name (_("CleanupDialog"));
2859 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2860 checker.set_position (Gtk::WIN_POS_MOUSE);
2862 switch (checker.run()) {
2863 case RESPONSE_ACCEPT:
2869 ARDOUR::CleanupReport rep;
2871 editor->prepare_for_cleanup ();
2873 /* do not allow flush until a session is reloaded */
2875 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2877 act->set_sensitive (false);
2880 if (session->cleanup_sources (rep)) {
2881 editor->finish_cleanup ();
2885 editor->finish_cleanup ();
2888 display_cleanup_results (rep,
2891 The following %1 files were not in use and \n\
2892 have been moved to:\n\
2894 Flushing the wastebasket will \n\
2895 release an additional\n\
2896 %3 %4bytes of disk space.\n"),
2898 The following file was not in use and \n \
2899 has been moved to:\n \
2901 Flushing the wastebasket will \n\
2902 release an additional\n\
2903 %3 %4bytes of disk space.\n"
2909 ARDOUR_UI::flush_trash ()
2912 /* shouldn't happen: menu item is insensitive */
2916 ARDOUR::CleanupReport rep;
2918 if (session->cleanup_trash_sources (rep)) {
2922 display_cleanup_results (rep,
2924 _("The following %1 files were deleted from\n\
2926 releasing %3 %4bytes of disk space"),
2927 _("The following file was deleted from\n\
2929 releasing %3 %4bytes of disk space"));
2933 ARDOUR_UI::add_route (Gtk::Window* float_window)
2941 if (add_route_dialog == 0) {
2942 add_route_dialog = new AddRouteDialog (*session);
2944 add_route_dialog->set_transient_for (*float_window);
2948 if (add_route_dialog->is_visible()) {
2949 /* we're already doing this */
2953 ResponseType r = (ResponseType) add_route_dialog->run ();
2955 add_route_dialog->hide();
2958 case RESPONSE_ACCEPT:
2965 if ((count = add_route_dialog->count()) <= 0) {
2969 string template_path = add_route_dialog->track_template();
2971 if (!template_path.empty()) {
2972 session->new_route_from_template (count, template_path);
2976 uint32_t input_chan = add_route_dialog->channels ();
2977 uint32_t output_chan;
2978 string name_template = add_route_dialog->name_template ();
2979 bool track = add_route_dialog->track ();
2980 bool aux = !track && add_route_dialog->aux();
2981 RouteGroup* route_group = add_route_dialog->route_group ();
2983 AutoConnectOption oac = Config->get_output_auto_connect();
2985 if (oac & AutoConnectMaster) {
2986 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2988 output_chan = input_chan;
2991 /* XXX do something with name template */
2993 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2995 session_add_midi_track (route_group, count);
2997 MessageDialog msg (*editor,
2998 _("Sorry, MIDI Busses are not supported at this time."));
3000 //session_add_midi_bus();
3004 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
3006 session_add_audio_bus (aux, input_chan, output_chan, route_group, count);
3012 ARDOUR_UI::mixer_settings () const
3017 node = session->instant_xml(X_("Mixer"));
3019 node = Config->instant_xml(X_("Mixer"));
3023 node = new XMLNode (X_("Mixer"));
3030 ARDOUR_UI::editor_settings () const
3035 node = session->instant_xml(X_("Editor"));
3037 node = Config->instant_xml(X_("Editor"));
3041 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3042 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3047 node = new XMLNode (X_("Editor"));
3054 ARDOUR_UI::keyboard_settings () const
3058 node = Config->extra_xml(X_("Keyboard"));
3061 node = new XMLNode (X_("Keyboard"));
3067 ARDOUR_UI::create_xrun_marker(nframes_t where)
3069 editor->mouse_add_new_marker (where, false, true);
3073 ARDOUR_UI::halt_on_xrun_message ()
3075 MessageDialog msg (*editor,
3076 _("Recording was stopped because your system could not keep up."));
3081 ARDOUR_UI::xrun_handler(nframes_t where)
3087 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3089 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3090 create_xrun_marker(where);
3093 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3094 halt_on_xrun_message ();
3099 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3104 while (disk_buffer_stats.size() > 60) {
3105 disk_buffer_stats.pop_front ();
3108 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3112 ARDOUR_UI::write_buffer_stats ()
3118 char path[PATH_MAX+1]; int fd;
3120 strcpy (path, "ardourBufferingXXXXXX");
3122 if ((fd = mkstemp (path )) < 0) {
3123 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3131 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3135 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3136 localtime_r (&(*i).when, &tm);
3137 strftime (buf, sizeof (buf), "%T", &tm);
3138 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3141 disk_buffer_stats.clear ();
3145 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3149 ARDOUR_UI::disk_overrun_handler ()
3151 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3153 write_buffer_stats ();
3155 if (!have_disk_speed_dialog_displayed) {
3156 have_disk_speed_dialog_displayed = true;
3157 MessageDialog* msg = new MessageDialog (*editor, _("\
3158 The disk system on your computer\n\
3159 was not able to keep up with Ardour.\n\
3161 Specifically, it failed to write data to disk\n\
3162 quickly enough to keep up with recording.\n"));
3163 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3169 ARDOUR_UI::disk_underrun_handler ()
3171 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3173 write_buffer_stats ();
3175 if (!have_disk_speed_dialog_displayed) {
3176 have_disk_speed_dialog_displayed = true;
3177 MessageDialog* msg = new MessageDialog (*editor,
3178 _("The disk system on your computer\n\
3179 was not able to keep up with Ardour.\n\
3181 Specifically, it failed to read data from disk\n\
3182 quickly enough to keep up with playback.\n"));
3183 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3189 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3191 have_disk_speed_dialog_displayed = false;
3196 ARDOUR_UI::session_dialog (std::string msg)
3198 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3203 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3205 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3214 ARDOUR_UI::pending_state_dialog ()
3216 HBox* hbox = new HBox();
3217 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3218 ArdourDialog dialog (_("Crash Recovery"), true);
3220 This session appears to have been in\n\
3221 middle of recording when ardour or\n\
3222 the computer was shutdown.\n\
3224 Ardour can recover any captured audio for\n\
3225 you, or it can ignore it. Please decide\n\
3226 what you would like to do.\n"));
3227 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3228 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3229 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3230 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3231 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3232 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3233 dialog.set_default_response (RESPONSE_ACCEPT);
3234 dialog.set_position (WIN_POS_CENTER);
3239 switch (dialog.run ()) {
3240 case RESPONSE_ACCEPT:
3248 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3250 HBox* hbox = new HBox();
3251 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3252 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3253 Label message (string_compose (_("\
3254 This session was created with a sample rate of %1 Hz\n\
3256 The audioengine is currently running at %2 Hz\n"), desired, actual));
3258 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3259 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3260 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3261 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3262 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3263 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3264 dialog.set_default_response (RESPONSE_ACCEPT);
3265 dialog.set_position (WIN_POS_CENTER);
3270 switch (dialog.run ()) {
3271 case RESPONSE_ACCEPT:
3280 ARDOUR_UI::disconnect_from_jack ()
3283 if( engine->disconnect_from_jack ()) {
3284 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3288 update_sample_rate (0);
3293 ARDOUR_UI::reconnect_to_jack ()
3296 if (engine->reconnect_to_jack ()) {
3297 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3301 update_sample_rate (0);
3306 ARDOUR_UI::use_config ()
3309 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3311 set_transport_controllable_state (*node);
3316 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3318 if (Config->get_primary_clock_delta_edit_cursor()) {
3319 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3321 primary_clock.set (pos, 0, true);
3324 if (Config->get_secondary_clock_delta_edit_cursor()) {
3325 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3327 secondary_clock.set (pos);
3330 if (big_clock_window) {
3331 big_clock.set (pos);
3336 ARDOUR_UI::record_state_changed ()
3338 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3340 if (!session || !big_clock_window) {
3341 /* why bother - the clock isn't visible */
3345 Session::RecordState const r = session->record_status ();
3346 bool const h = session->have_rec_enabled_diskstream ();
3348 if (r == Session::Recording && h) {
3349 big_clock.set_widget_name ("BigClockRecording");
3351 big_clock.set_widget_name ("BigClockNonRecording");
3356 ARDOUR_UI::first_idle ()
3359 session->allow_auto_play (true);
3363 editor->first_idle();
3366 Keyboard::set_can_save_keybindings (true);
3371 ARDOUR_UI::store_clock_modes ()
3373 XMLNode* node = new XMLNode(X_("ClockModes"));
3375 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3376 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3379 session->add_extra_xml (*node);
3380 session->set_dirty ();
3385 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3386 : Controllable (name), ui (u), type(tp)
3392 ARDOUR_UI::TransportControllable::set_value (float val)
3394 if (type == ShuttleControl) {
3401 fract = -((0.5f - val)/0.5f);
3403 fract = ((val - 0.5f)/0.5f);
3407 ui.set_shuttle_fract (fract);
3412 /* do nothing: these are radio-style actions */
3416 const char *action = 0;
3420 action = X_("Roll");
3423 action = X_("Stop");
3426 action = X_("Goto Start");
3429 action = X_("Goto End");
3432 action = X_("Loop");
3435 action = X_("Play Selection");
3438 action = X_("Record");
3448 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3456 ARDOUR_UI::TransportControllable::get_value (void) const
3475 case ShuttleControl:
3485 ARDOUR_UI::TransportControllable::set_id (const string& str)
3491 ARDOUR_UI::setup_profile ()
3493 if (gdk_screen_width() < 1200) {
3494 Profile->set_small_screen ();
3498 if (getenv ("ARDOUR_SAE")) {
3499 Profile->set_sae ();
3500 Profile->set_single_package ();