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;
182 if (theArdourUI == 0) {
186 ui_config = new UIConfiguration();
187 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 _will_create_new_session_automatically = false;
199 add_route_dialog = 0;
201 rc_option_editor = 0;
202 session_option_editor = 0;
204 open_session_selector = 0;
205 have_configure_timeout = false;
206 have_disk_speed_dialog_displayed = false;
207 session_loaded = false;
208 last_speed_displayed = -1.0f;
209 ignore_dual_punch = false;
210 _mixer_on_top = false;
212 roll_button.unset_flags (Gtk::CAN_FOCUS);
213 stop_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
215 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
216 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
217 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
218 rec_button.unset_flags (Gtk::CAN_FOCUS);
220 last_configure_time= 0;
222 shuttle_grabbed = false;
224 shuttle_max_speed = 8.0f;
226 shuttle_style_menu = 0;
227 shuttle_unit_menu = 0;
229 // We do not have jack linked in yet so;
231 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
233 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
234 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
236 /* handle dialog requests */
238 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
240 /* handle pending state with a dialog */
242 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
244 /* handle sr mismatch with a dialog */
246 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
248 /* lets get this party started */
251 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
252 throw failed_constructor ();
255 setup_gtk_ardour_enums ();
258 GainMeter::setup_slider_pix ();
259 RouteTimeAxisView::setup_slider_pix ();
261 } catch (failed_constructor& err) {
262 error << _("could not initialize Ardour.") << endmsg;
267 /* we like keyboards */
269 keyboard = new Keyboard;
273 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
274 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
280 ARDOUR_UI::run_startup (bool should_be_new)
283 _startup = new ArdourStartup ();
286 _startup->set_new_only (should_be_new);
287 _startup->present ();
291 /* we don't return here until the startup assistant is finished */
297 ARDOUR_UI::create_engine ()
299 // this gets called every time by new_session()
305 loading_message (_("Starting audio engine"));
308 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
315 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
316 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
317 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
318 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
326 ARDOUR_UI::post_engine ()
328 /* Things to be done once we create the AudioEngine
331 MIDI::Manager::instance()->set_api_data (engine->jack());
334 ActionManager::init ();
337 if (setup_windows ()) {
338 throw failed_constructor ();
341 check_memory_locking();
343 /* this is the first point at which all the keybindings are available */
345 if (ARDOUR_COMMAND_LINE::show_key_actions) {
346 vector<string> names;
347 vector<string> paths;
349 vector<AccelKey> bindings;
351 ActionManager::get_all_actions (names, paths, keys, bindings);
353 vector<string>::iterator n;
354 vector<string>::iterator k;
355 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
356 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
362 blink_timeout_tag = -1;
364 /* this being a GUI and all, we want peakfiles */
366 AudioFileSource::set_build_peakfiles (true);
367 AudioFileSource::set_build_missing_peakfiles (true);
369 /* set default clock modes */
371 if (Profile->get_sae()) {
372 primary_clock.set_mode (AudioClock::BBT);
373 secondary_clock.set_mode (AudioClock::MinSec);
375 primary_clock.set_mode (AudioClock::SMPTE);
376 secondary_clock.set_mode (AudioClock::BBT);
379 /* start the time-of-day-clock */
382 /* OS X provides an always visible wallclock, so don't be stupid */
383 update_wall_clock ();
384 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
387 update_disk_space ();
389 update_sample_rate (engine->frame_rate());
391 /* now start and maybe save state */
393 if (do_engine_start () == 0) {
394 if (session && _session_is_new) {
395 /* we need to retain initial visual
396 settings for a new session
398 session->save_state ("");
403 ARDOUR_UI::~ARDOUR_UI ()
405 save_ardour_state ();
410 delete add_route_dialog;
414 ARDOUR_UI::pop_back_splash ()
416 if (Splash::instance()) {
417 // Splash::instance()->pop_back();
418 Splash::instance()->hide ();
423 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time == 0) {
426 /* no configure events yet */
430 /* force a gap of 0.5 seconds since the last configure event
433 if (get_microseconds() - last_configure_time < 500000) {
436 have_configure_timeout = false;
437 save_ardour_state ();
443 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
445 if (have_configure_timeout) {
446 last_configure_time = get_microseconds();
448 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
449 have_configure_timeout = true;
456 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
458 const XMLProperty* prop;
460 if ((prop = node.property ("roll")) != 0) {
461 roll_controllable->set_id (prop->value());
463 if ((prop = node.property ("stop")) != 0) {
464 stop_controllable->set_id (prop->value());
466 if ((prop = node.property ("goto-start")) != 0) {
467 goto_start_controllable->set_id (prop->value());
469 if ((prop = node.property ("goto-end")) != 0) {
470 goto_end_controllable->set_id (prop->value());
472 if ((prop = node.property ("auto-loop")) != 0) {
473 auto_loop_controllable->set_id (prop->value());
475 if ((prop = node.property ("play-selection")) != 0) {
476 play_selection_controllable->set_id (prop->value());
478 if ((prop = node.property ("rec")) != 0) {
479 rec_controllable->set_id (prop->value());
481 if ((prop = node.property ("shuttle")) != 0) {
482 shuttle_controllable->set_id (prop->value());
487 ARDOUR_UI::get_transport_controllable_state ()
489 XMLNode* node = new XMLNode(X_("TransportControllables"));
492 roll_controllable->id().print (buf, sizeof (buf));
493 node->add_property (X_("roll"), buf);
494 stop_controllable->id().print (buf, sizeof (buf));
495 node->add_property (X_("stop"), buf);
496 goto_start_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_start"), buf);
498 goto_end_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("goto_end"), buf);
500 auto_loop_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("auto_loop"), buf);
502 play_selection_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("play_selection"), buf);
504 rec_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("rec"), buf);
506 shuttle_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("shuttle"), buf);
513 ARDOUR_UI::save_ardour_state ()
515 if (!keyboard || !mixer || !editor) {
519 /* XXX this is all a bit dubious. add_extra_xml() uses
520 a different lifetime model from add_instant_xml().
523 XMLNode* node = new XMLNode (keyboard->get_state());
524 Config->add_extra_xml (*node);
525 Config->add_extra_xml (get_transport_controllable_state());
526 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
527 Config->add_extra_xml (_startup->engine_control()->get_state());
529 Config->save_state();
530 ui_config->save_state ();
532 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
533 XMLNode mnode(mixer->get_state());
536 session->add_instant_xml (enode);
537 session->add_instant_xml (mnode);
539 Config->add_instant_xml (enode);
540 Config->add_instant_xml (mnode);
543 Keyboard::save_keybindings ();
547 ARDOUR_UI::autosave_session ()
549 if (g_main_depth() > 1) {
550 /* inside a recursive main loop,
551 give up because we may not be able to
557 if (!Config->get_periodic_safety_backups()) {
562 session->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
573 if (session->dirty()) {
574 if (_autosave_connection.connected()) {
575 _autosave_connection.disconnect();
578 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
579 Config->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection.connected()) {
583 _autosave_connection.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
593 title = _("Ardour could not start JACK");
595 title = _("Ardour could not connect to JACK.");
598 MessageDialog win (title,
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win.set_transient_for (*toplevel);
625 win.add_button (Stock::OK, RESPONSE_CLOSE);
627 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
630 win.set_default_response (RESPONSE_CLOSE);
633 win.set_position (Gtk::WIN_POS_CENTER);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
644 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
646 if (audio_setup && _startup && _startup->engine_control()) {
647 _startup->engine_control()->set_state (*audio_setup);
650 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
656 goto_editor_window ();
658 BootMessage (_("Ardour is ready for use"));
663 ARDOUR_UI::no_memory_warning ()
665 XMLNode node (X_("no-memory-warning"));
666 Config->add_instant_xml (node);
670 ARDOUR_UI::check_memory_locking ()
673 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
677 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
679 if (engine->is_realtime() && memory_warning_node == 0) {
681 struct rlimit limits;
683 long pages, page_size;
685 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
688 ram = (int64_t) pages * (int64_t) page_size;
691 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
695 if (limits.rlim_cur != RLIM_INFINITY) {
697 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
700 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
701 "This might cause Ardour to run out of memory before your system "
702 "runs out of memory. \n\n"
703 "You can view the memory limit with 'ulimit -l', "
704 "and it is normally controlled by /etc/security/limits.conf"));
706 VBox* vbox = msg.get_vbox();
708 CheckButton cb (_("Do not show this window again"));
710 cb.signal_toggled().connect (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);
734 if (session->transport_rolling()) {
735 session->request_stop ();
739 if (session->dirty()) {
740 switch (ask_about_saving_session(_("quit"))) {
745 /* use the default name */
746 if (save_state_canfail ("")) {
747 /* failed - don't quit */
748 MessageDialog msg (*editor,
750 Ardour was unable to save your session.\n\n\
751 If you still wish to quit, please use the\n\n\
752 \"Just quit\" option."));
763 session->set_deletion_in_progress ();
766 ArdourDialog::close_all_dialogs ();
768 save_ardour_state ();
773 ARDOUR_UI::ask_about_saving_session (const string & what)
775 ArdourDialog window (_("ardour: save session?"));
776 Gtk::HBox dhbox; // the hbox for the image and text
777 Gtk::Label prompt_label;
778 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
782 msg = string_compose(_("Don't %1"), what);
783 window.add_button (msg, RESPONSE_REJECT);
784 msg = string_compose(_("Just %1"), what);
785 window.add_button (msg, RESPONSE_APPLY);
786 msg = string_compose(_("Save and %1"), what);
787 window.add_button (msg, RESPONSE_ACCEPT);
789 window.set_default_response (RESPONSE_ACCEPT);
791 Gtk::Button noquit_button (msg);
792 noquit_button.set_name ("EditorGTKButton");
797 if (session->snap_name() == session->name()) {
800 type = _("snapshot");
802 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?"),
803 type, session->snap_name());
805 prompt_label.set_text (prompt);
806 prompt_label.set_name (X_("PrompterLabel"));
807 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
809 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
810 dhbox.set_homogeneous (false);
811 dhbox.pack_start (*dimage, false, false, 5);
812 dhbox.pack_start (prompt_label, true, false, 5);
813 window.get_vbox()->pack_start (dhbox);
815 window.set_name (_("Prompter"));
816 window.set_position (Gtk::WIN_POS_MOUSE);
817 window.set_modal (true);
818 window.set_resizable (false);
824 window.set_keep_above (true);
827 ResponseType r = (ResponseType) window.run();
832 case RESPONSE_ACCEPT: // save and get out of here
834 case RESPONSE_APPLY: // get out of here
844 ARDOUR_UI::every_second ()
847 update_buffer_load ();
848 update_disk_space ();
853 ARDOUR_UI::every_point_one_seconds ()
855 update_speed_display ();
856 RapidScreenUpdate(); /* EMIT_SIGNAL */
861 ARDOUR_UI::every_point_zero_one_seconds ()
863 // august 2007: actual update frequency: 40Hz, not 100Hz
865 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
870 ARDOUR_UI::update_sample_rate (nframes_t ignored)
874 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
876 if (!engine->connected()) {
878 snprintf (buf, sizeof (buf), _("disconnected"));
882 nframes_t rate = engine->frame_rate();
884 if (fmod (rate, 1000.0) != 0.0) {
885 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
886 (float) rate/1000.0f,
887 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
889 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
891 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
895 sample_rate_label.set_text (buf);
899 ARDOUR_UI::update_cpu_load ()
902 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
903 cpu_load_label.set_text (buf);
907 ARDOUR_UI::update_buffer_load ()
913 c = session->capture_load ();
914 p = session->playback_load ();
916 push_buffer_stats (c, p);
918 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
919 session->playback_load(), session->capture_load());
920 buffer_load_label.set_text (buf);
922 buffer_load_label.set_text ("");
927 ARDOUR_UI::count_recenabled_streams (Route& route)
929 Track* track = dynamic_cast<Track*>(&route);
930 if (track && track->diskstream()->record_enabled()) {
931 rec_enabled_streams += track->n_inputs().n_total();
936 ARDOUR_UI::update_disk_space()
942 nframes_t frames = session->available_capture_duration();
944 nframes_t fr = session->frame_rate();
946 if (frames == max_frames) {
947 strcpy (buf, _("Disk: 24hrs+"));
949 rec_enabled_streams = 0;
950 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
952 if (rec_enabled_streams) {
953 frames /= rec_enabled_streams;
960 hrs = frames / (fr * 3600);
961 frames -= hrs * fr * 3600;
962 mins = frames / (fr * 60);
963 frames -= mins * fr * 60;
966 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
969 disk_space_label.set_text (buf);
971 // An attempt to make the disk space label flash red when space has run out.
973 if (frames < fr * 60 * 5) {
974 /* disk_space_box.style ("disk_space_label_empty"); */
976 /* disk_space_box.style ("disk_space_label"); */
982 ARDOUR_UI::update_wall_clock ()
989 tm_now = localtime (&now);
991 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
992 wall_clock_label.set_text (buf);
998 ARDOUR_UI::session_menu (GdkEventButton *ev)
1000 session_popup_menu->popup (0, 0);
1005 ARDOUR_UI::redisplay_recent_sessions ()
1007 std::vector<sys::path> session_directories;
1008 RecentSessionsSorter cmp;
1010 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1011 recent_session_model->clear ();
1013 ARDOUR::RecentSessions rs;
1014 ARDOUR::read_recent_sessions (rs);
1017 recent_session_display.set_model (recent_session_model);
1021 // sort them alphabetically
1022 sort (rs.begin(), rs.end(), cmp);
1024 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1025 session_directories.push_back ((*i).second);
1028 for (vector<sys::path>::const_iterator i = session_directories.begin();
1029 i != session_directories.end(); ++i)
1031 std::vector<sys::path> state_file_paths;
1033 // now get available states for this session
1035 get_state_files_in_directory (*i, state_file_paths);
1037 vector<string*>* states;
1038 vector<const gchar*> item;
1039 string fullpath = (*i).to_string();
1041 /* remove any trailing / */
1043 if (fullpath[fullpath.length()-1] == '/') {
1044 fullpath = fullpath.substr (0, fullpath.length()-1);
1047 /* check whether session still exists */
1048 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1049 /* session doesn't exist */
1050 cerr << "skipping non-existent session " << fullpath << endl;
1054 /* now get available states for this session */
1056 if ((states = Session::possible_states (fullpath)) == 0) {
1057 /* no state file? */
1061 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1063 Gtk::TreeModel::Row row = *(recent_session_model->append());
1065 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1066 row[recent_session_columns.fullpath] = fullpath;
1068 if (state_file_names.size() > 1) {
1072 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1073 i2 != state_file_names.end(); ++i2)
1076 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1078 child_row[recent_session_columns.visible_name] = *i2;
1079 child_row[recent_session_columns.fullpath] = fullpath;
1084 recent_session_display.set_model (recent_session_model);
1088 ARDOUR_UI::build_session_selector ()
1090 session_selector_window = new ArdourDialog ("session selector");
1092 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1094 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1095 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1096 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1097 recent_session_model = TreeStore::create (recent_session_columns);
1098 recent_session_display.set_model (recent_session_model);
1099 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1100 recent_session_display.set_headers_visible (false);
1101 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1102 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1104 scroller->add (recent_session_display);
1105 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1107 session_selector_window->set_name ("SessionSelectorWindow");
1108 session_selector_window->set_size_request (200, 400);
1109 session_selector_window->get_vbox()->pack_start (*scroller);
1111 recent_session_display.show();
1113 //session_selector_window->get_vbox()->show();
1117 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1119 session_selector_window->response (RESPONSE_ACCEPT);
1123 ARDOUR_UI::open_recent_session ()
1125 bool can_return = (session != 0);
1127 if (session_selector_window == 0) {
1128 build_session_selector ();
1131 redisplay_recent_sessions ();
1135 session_selector_window->set_position (WIN_POS_MOUSE);
1137 ResponseType r = (ResponseType) session_selector_window->run ();
1140 case RESPONSE_ACCEPT:
1144 session_selector_window->hide();
1151 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1155 session_selector_window->hide();
1157 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1159 if (i == recent_session_model->children().end()) {
1163 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1164 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1166 _session_is_new = false;
1168 if (load_session (path, state) == 0) {
1177 ARDOUR_UI::check_audioengine ()
1180 if (!engine->connected()) {
1181 MessageDialog msg (_("Ardour is not connected to JACK\n"
1182 "You cannot open or close sessions in this condition"));
1194 ARDOUR_UI::open_session ()
1196 if (!check_audioengine()) {
1201 /* popup selector window */
1203 if (open_session_selector == 0) {
1205 /* ardour sessions are folders */
1207 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1208 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1209 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1210 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1212 FileFilter session_filter;
1213 session_filter.add_pattern ("*.ardour");
1214 session_filter.set_name (_("Ardour sessions"));
1215 open_session_selector->add_filter (session_filter);
1216 open_session_selector->set_filter (session_filter);
1219 int response = open_session_selector->run();
1220 open_session_selector->hide ();
1223 case RESPONSE_ACCEPT:
1226 open_session_selector->hide();
1230 open_session_selector->hide();
1231 string session_path = open_session_selector->get_filename();
1235 if (session_path.length() > 0) {
1236 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1237 _session_is_new = isnew;
1238 load_session (path, name);
1245 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1247 list<boost::shared_ptr<MidiTrack> > tracks;
1250 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1257 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1259 if (tracks.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new midi track") << endmsg;
1263 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1267 if ((route = session->new_midi_route ()) == 0) {
1268 error << _("could not create new midi bus") << endmsg;
1274 MessageDialog msg (*editor,
1275 _("There are insufficient JACK ports available\n\
1276 to create a new track or bus.\n\
1277 You should save Ardour, exit and\n\
1278 restart JACK with more ports."));
1285 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1287 list<boost::shared_ptr<AudioTrack> > tracks;
1291 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1297 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1299 if (tracks.size() != how_many) {
1300 if (how_many == 1) {
1301 error << _("could not create a new audio track") << endmsg;
1303 error << string_compose (_("could only create %1 of %2 new audio %3"),
1304 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1310 routes = session->new_audio_route (input_channels, output_channels, how_many);
1312 if (routes.size() != how_many) {
1313 if (how_many == 1) {
1314 error << _("could not create a new audio track") << endmsg;
1316 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1322 if (need_control_room_outs) {
1328 route->set_stereo_control_outs (control_lr_channels);
1329 route->control_outs()->set_stereo_pan (pans, this);
1331 #endif /* CONTROLOUTS */
1335 MessageDialog msg (*editor,
1336 _("There are insufficient JACK ports available\n\
1337 to create a new track or bus.\n\
1338 You should save Ardour, exit and\n\
1339 restart JACK with more ports."));
1346 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1348 nframes_t _preroll = 0;
1351 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1352 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1354 if (new_position > _preroll) {
1355 new_position -= _preroll;
1360 session->request_locate (new_position);
1365 ARDOUR_UI::transport_goto_start ()
1368 session->goto_start();
1371 /* force displayed area in editor to start no matter
1372 what "follow playhead" setting is.
1376 editor->reset_x_origin (session->current_start_frame());
1382 ARDOUR_UI::transport_goto_zero ()
1385 session->request_locate (0);
1388 /* force displayed area in editor to start no matter
1389 what "follow playhead" setting is.
1393 editor->reset_x_origin (0);
1399 ARDOUR_UI::transport_goto_wallclock ()
1401 if (session && editor) {
1408 localtime_r (&now, &tmnow);
1410 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1411 frames += tmnow.tm_min * (60 * session->frame_rate());
1412 frames += tmnow.tm_sec * session->frame_rate();
1414 session->request_locate (frames);
1416 /* force displayed area in editor to start no matter
1417 what "follow playhead" setting is.
1421 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1427 ARDOUR_UI::transport_goto_end ()
1430 nframes_t frame = session->current_end_frame();
1431 session->request_locate (frame);
1433 /* force displayed area in editor to start no matter
1434 what "follow playhead" setting is.
1438 editor->reset_x_origin (frame);
1444 ARDOUR_UI::transport_stop ()
1450 if (session->is_auditioning()) {
1451 session->cancel_audition ();
1455 if (session->get_play_loop ()) {
1456 session->request_play_loop (false);
1459 session->request_stop ();
1463 ARDOUR_UI::transport_stop_and_forget_capture ()
1466 session->request_stop (true);
1471 ARDOUR_UI::remove_last_capture()
1474 editor->remove_last_capture();
1479 ARDOUR_UI::transport_record (bool roll)
1483 switch (session->record_status()) {
1484 case Session::Disabled:
1485 if (session->ntracks() == 0) {
1486 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1490 session->maybe_enable_record ();
1495 case Session::Recording:
1497 session->request_stop();
1499 session->disable_record (false, true);
1503 case Session::Enabled:
1504 session->disable_record (false, true);
1507 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1511 ARDOUR_UI::transport_roll ()
1519 rolling = session->transport_rolling ();
1521 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1523 if (session->get_play_loop()) {
1524 session->request_play_loop (false);
1525 auto_loop_button.set_visual_state (1);
1526 roll_button.set_visual_state (1);
1527 } else if (session->get_play_range ()) {
1528 session->request_play_range (false);
1529 play_selection_button.set_visual_state (0);
1530 } else if (rolling) {
1531 session->request_locate (session->last_transport_start(), true);
1534 session->request_transport_speed (1.0f);
1538 ARDOUR_UI::transport_loop()
1541 if (session->get_play_loop()) {
1542 if (session->transport_rolling()) {
1543 Location * looploc = session->locations()->auto_loop_location();
1545 session->request_locate (looploc->start(), true);
1550 session->request_play_loop (true);
1556 ARDOUR_UI::transport_play_selection ()
1562 if (!session->get_play_range()) {
1563 session->request_stop ();
1566 editor->play_selection ();
1570 ARDOUR_UI::transport_rewind (int option)
1572 float current_transport_speed;
1575 current_transport_speed = session->transport_speed();
1577 if (current_transport_speed >= 0.0f) {
1580 session->request_transport_speed (-1.0f);
1583 session->request_transport_speed (-4.0f);
1586 session->request_transport_speed (-0.5f);
1591 session->request_transport_speed (current_transport_speed * 1.5f);
1597 ARDOUR_UI::transport_forward (int option)
1599 float current_transport_speed;
1602 current_transport_speed = session->transport_speed();
1604 if (current_transport_speed <= 0.0f) {
1607 session->request_transport_speed (1.0f);
1610 session->request_transport_speed (4.0f);
1613 session->request_transport_speed (0.5f);
1618 session->request_transport_speed (current_transport_speed * 1.5f);
1624 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1630 boost::shared_ptr<Route> r;
1632 if ((r = session->route_by_remote_id (dstream)) != 0) {
1636 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1637 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1646 ARDOUR_UI::queue_transport_change ()
1648 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1652 ARDOUR_UI::map_transport_state ()
1654 float sp = session->transport_speed();
1657 transport_rolling ();
1658 } else if (sp < 0.0f) {
1659 transport_rewinding ();
1660 } else if (sp > 0.0f) {
1661 transport_forwarding ();
1663 transport_stopped ();
1668 ARDOUR_UI::engine_stopped ()
1670 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1671 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1672 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1676 ARDOUR_UI::engine_running ()
1678 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1679 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1680 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1682 Glib::RefPtr<Action> action;
1683 const char* action_name = 0;
1685 switch (engine->frames_per_cycle()) {
1687 action_name = X_("JACKLatency32");
1690 action_name = X_("JACKLatency64");
1693 action_name = X_("JACKLatency128");
1696 action_name = X_("JACKLatency512");
1699 action_name = X_("JACKLatency1024");
1702 action_name = X_("JACKLatency2048");
1705 action_name = X_("JACKLatency4096");
1708 action_name = X_("JACKLatency8192");
1711 /* XXX can we do anything useful ? */
1717 action = ActionManager::get_action (X_("JACK"), action_name);
1720 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1721 ract->set_active ();
1727 ARDOUR_UI::engine_halted ()
1729 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1731 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1732 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1734 update_sample_rate (0);
1736 MessageDialog msg (*editor,
1738 JACK has either been shutdown or it\n\
1739 disconnected Ardour because Ardour\n\
1740 was not fast enough. Try to restart\n\
1741 JACK, reconnect and save the session."));
1747 ARDOUR_UI::do_engine_start ()
1755 error << _("Unable to start the session running")
1765 ARDOUR_UI::setup_theme ()
1767 theme_manager->setup_theme();
1771 ARDOUR_UI::update_clocks ()
1773 if (!editor || !editor->dragging_playhead()) {
1774 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1779 ARDOUR_UI::start_clocking ()
1781 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1785 ARDOUR_UI::stop_clocking ()
1787 clock_signal_connection.disconnect ();
1791 ARDOUR_UI::toggle_clocking ()
1794 if (clock_button.get_active()) {
1803 ARDOUR_UI::_blink (void *arg)
1806 ((ARDOUR_UI *) arg)->blink ();
1813 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1817 ARDOUR_UI::start_blinking ()
1819 /* Start the blink signal. Everybody with a blinking widget
1820 uses Blink to drive the widget's state.
1823 if (blink_timeout_tag < 0) {
1825 blink_timeout_tag = g_timeout_add (240, _blink, this);
1830 ARDOUR_UI::stop_blinking ()
1832 if (blink_timeout_tag >= 0) {
1833 g_source_remove (blink_timeout_tag);
1834 blink_timeout_tag = -1;
1839 /** Ask the user for the name of a new shapshot and then take it.
1842 ARDOUR_UI::snapshot_session ()
1844 ArdourPrompter prompter (true);
1848 struct tm local_time;
1851 localtime_r (&n, &local_time);
1852 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1854 prompter.set_name ("Prompter");
1855 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1856 prompter.set_prompt (_("Name of New Snapshot"));
1857 prompter.set_initial_text (timebuf);
1859 switch (prompter.run()) {
1860 case RESPONSE_ACCEPT:
1862 prompter.get_result (snapname);
1864 bool do_save = (snapname.length() != 0);
1866 vector<sys::path> p;
1867 get_state_files_in_directory (session->session_directory().root_path(), p);
1868 vector<string> n = get_file_names_no_extension (p);
1869 if (find (n.begin(), n.end(), snapname) != n.end()) {
1871 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1872 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1873 confirm.get_vbox()->pack_start (m, true, true);
1874 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1875 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1876 confirm.show_all ();
1877 switch (confirm.run()) {
1878 case RESPONSE_CANCEL:
1884 save_state (snapname);
1895 ARDOUR_UI::save_state (const string & name)
1897 (void) save_state_canfail (name);
1901 ARDOUR_UI::save_state_canfail (string name)
1906 if (name.length() == 0) {
1907 name = session->snap_name();
1910 if ((ret = session->save_state (name)) != 0) {
1914 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1919 ARDOUR_UI::primary_clock_value_changed ()
1922 session->request_locate (primary_clock.current_time ());
1927 ARDOUR_UI::big_clock_value_changed ()
1930 session->request_locate (big_clock.current_time ());
1935 ARDOUR_UI::secondary_clock_value_changed ()
1938 session->request_locate (secondary_clock.current_time ());
1943 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1949 Session::RecordState const r = session->record_status ();
1950 bool const h = session->have_rec_enabled_diskstream ();
1952 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1954 rec_button.set_visual_state (2);
1956 rec_button.set_visual_state (0);
1958 } else if (r == Session::Recording && h) {
1959 rec_button.set_visual_state (1);
1961 rec_button.set_visual_state (0);
1966 ARDOUR_UI::save_template ()
1969 ArdourPrompter prompter (true);
1972 if (!check_audioengine()) {
1976 prompter.set_name (X_("Prompter"));
1977 prompter.set_prompt (_("Name for mix template:"));
1978 prompter.set_initial_text(session->name() + _("-template"));
1979 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1981 switch (prompter.run()) {
1982 case RESPONSE_ACCEPT:
1983 prompter.get_result (name);
1985 if (name.length()) {
1986 session->save_template (name);
1996 ARDOUR_UI::edit_metadata ()
1998 SessionMetadataEditor dialog;
1999 dialog.set_session (session);
2000 editor->ensure_float (dialog);
2005 ARDOUR_UI::import_metadata ()
2007 SessionMetadataImporter dialog;
2008 dialog.set_session (session);
2009 editor->ensure_float (dialog);
2014 ARDOUR_UI::fontconfig_dialog ()
2017 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2018 may not and it can take a while to build it. Warn them.
2021 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2023 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2024 MessageDialog msg (*_startup,
2025 _("Welcome to Ardour.\n\n"
2026 "The program will take a bit longer to start up\n"
2027 "while the system fonts are checked.\n\n"
2028 "This will only be done once, and you will\n"
2029 "not see this message again\n"),
2042 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2044 existing_session = false;
2046 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2047 session_path = cmdline_path;
2048 existing_session = true;
2049 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2050 session_path = Glib::path_get_dirname (string (cmdline_path));
2051 existing_session = true;
2053 /* it doesn't exist, assume the best */
2054 session_path = Glib::path_get_dirname (string (cmdline_path));
2057 session_name = basename_nosuffix (string (cmdline_path));
2061 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2063 /* when this is called, the backend audio system must be running */
2065 /* the main idea here is to deal with the fact that a cmdline argument for the session
2066 can be interpreted in different ways - it could be a directory or a file, and before
2067 we load, we need to know both the session directory and the snapshot (statefile) within it
2068 that we are supposed to use.
2071 if (session_name.length() == 0 || session_path.length() == 0) {
2075 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2077 Glib::ustring predicted_session_file;
2079 predicted_session_file = session_path;
2080 predicted_session_file += '/';
2081 predicted_session_file += session_name;
2082 predicted_session_file += ARDOUR::statefile_suffix;
2084 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2085 existing_session = true;
2088 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2090 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2091 /* existing .ardour file */
2092 existing_session = true;
2096 existing_session = false;
2099 /* lets just try to load it */
2101 if (create_engine ()) {
2102 backend_audio_error (false, _startup);
2106 return load_session (session_path, session_name);
2110 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2112 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2114 MessageDialog msg (str,
2116 Gtk::MESSAGE_WARNING,
2117 Gtk::BUTTONS_YES_NO,
2121 msg.set_name (X_("CleanupDialog"));
2122 msg.set_wmclass (X_("existing_session"), "Ardour");
2123 msg.set_position (Gtk::WIN_POS_MOUSE);
2126 switch (msg.run()) {
2135 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2140 AutoConnectOption iconnect;
2141 AutoConnectOption oconnect;
2145 if (Profile->get_sae()) {
2149 iconnect = AutoConnectPhysical;
2150 oconnect = AutoConnectMaster;
2151 nphysin = 0; // use all available
2152 nphysout = 0; // use all available
2156 /* get settings from advanced section of NSD */
2158 if (_startup->create_control_bus()) {
2159 cchns = (uint32_t) _startup->control_channel_count();
2164 if (_startup->create_master_bus()) {
2165 mchns = (uint32_t) _startup->master_channel_count();
2170 if (_startup->connect_inputs()) {
2171 iconnect = AutoConnectPhysical;
2173 iconnect = AutoConnectOption (0);
2176 /// @todo some minor tweaks.
2178 if (_startup->connect_outs_to_master()) {
2179 oconnect = AutoConnectMaster;
2180 } else if (_startup->connect_outs_to_physical()) {
2181 oconnect = AutoConnectPhysical;
2183 oconnect = AutoConnectOption (0);
2186 nphysin = (uint32_t) _startup->input_limit_count();
2187 nphysout = (uint32_t) _startup->output_limit_count();
2190 if (build_session (session_path,
2198 engine->frame_rate() * 60 * 5)) {
2207 ARDOUR_UI::end_loading_messages ()
2213 ARDOUR_UI::loading_message (const std::string& msg)
2216 // splash->message (msg);
2221 ARDOUR_UI::get_session_parameters (bool should_be_new)
2223 Glib::ustring session_name;
2224 Glib::ustring session_path;
2225 Glib::ustring template_name;
2227 bool likely_new = false;
2231 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2233 /* if they named a specific statefile, use it, otherwise they are
2234 just giving a session folder, and we want to use it as is
2235 to find the session.
2238 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2239 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2241 session_path = ARDOUR_COMMAND_LINE::session_name;
2244 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2248 run_startup (should_be_new);
2250 /* if we run the startup dialog again, offer more than just "new session" */
2252 should_be_new = false;
2254 session_name = _startup->session_name (likely_new);
2256 /* this shouldn't happen, but we catch it just in case it does */
2258 if (session_name.empty()) {
2261 if (_startup->use_session_template()) {
2262 template_name = _startup->session_template_name();
2263 _session_is_new = true;
2267 if (session_name[0] == '/' ||
2268 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2269 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2271 session_path = Glib::path_get_dirname (session_name);
2272 session_name = Glib::path_get_basename (session_name);
2276 session_path = _startup->session_folder();
2280 if (create_engine ()) {
2284 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2288 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2290 if (!ask_about_loading_existing_session (existing)) {
2291 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2296 _session_is_new = false;
2301 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2303 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2307 _session_is_new = true;
2310 if (likely_new && template_name.empty()) {
2312 ret = build_session_from_nsd (session_path, session_name);
2316 ret = load_session (session_path, session_name, template_name);
2324 ARDOUR_UI::close_session()
2326 if (!check_audioengine()) {
2330 unload_session (true);
2332 get_session_parameters (false);
2336 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2338 Session *new_session;
2342 session_loaded = false;
2344 if (!check_audioengine()) {
2348 unload_status = unload_session ();
2350 if (unload_status < 0) {
2352 } else if (unload_status > 0) {
2357 /* if it already exists, we must have write access */
2359 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2360 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2361 "This prevents the session from being loaded."));
2367 loading_message (_("Please wait while Ardour loads your session"));
2370 new_session = new Session (*engine, path, snap_name, mix_template);
2373 /* this one is special */
2375 catch (AudioEngine::PortRegistrationFailure& err) {
2377 MessageDialog msg (err.what(),
2380 Gtk::BUTTONS_CLOSE);
2382 msg.set_title (_("Port Registration Error"));
2383 msg.set_secondary_text (_("Click the Close button to try again."));
2384 msg.set_position (Gtk::WIN_POS_CENTER);
2388 int response = msg.run ();
2393 case RESPONSE_CANCEL:
2403 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2406 Gtk::BUTTONS_CLOSE);
2408 msg.set_title (_("Loading Error"));
2409 msg.set_secondary_text (_("Click the Close button to try again."));
2410 msg.set_position (Gtk::WIN_POS_CENTER);
2414 int response = msg.run ();
2419 case RESPONSE_CANCEL:
2427 connect_to_session (new_session);
2429 session_loaded = true;
2431 goto_editor_window ();
2434 session->set_clean ();
2445 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2446 uint32_t control_channels,
2447 uint32_t master_channels,
2448 AutoConnectOption input_connect,
2449 AutoConnectOption output_connect,
2452 nframes_t initial_length)
2454 Session *new_session;
2457 if (!check_audioengine()) {
2461 session_loaded = false;
2463 x = unload_session ();
2471 _session_is_new = true;
2474 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2475 control_channels, master_channels, nphysin, nphysout, initial_length);
2480 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2486 connect_to_session (new_session);
2488 session_loaded = true;
2490 new_session->save_state(new_session->name());
2499 editor->show_window ();
2510 ARDOUR_UI::show_about ()
2514 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2521 ARDOUR_UI::hide_about ()
2524 about->get_window()->set_cursor ();
2530 ARDOUR_UI::about_signal_response(int response)
2536 ARDOUR_UI::show_splash ()
2540 splash = new Splash;
2548 splash->queue_draw ();
2549 splash->get_window()->process_updates (true);
2554 ARDOUR_UI::hide_splash ()
2562 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2566 removed = rep.paths.size();
2569 MessageDialog msgd (*editor,
2570 _("No audio files were ready for cleanup"),
2573 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2574 msgd.set_secondary_text (_("If this seems suprising, \n\
2575 check for any existing snapshots.\n\
2576 These may still include regions that\n\
2577 require some unused files to continue to exist."));
2583 ArdourDialog results (_("ardour: cleanup"), true, false);
2585 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2586 CleanupResultsModelColumns() {
2590 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2591 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2595 CleanupResultsModelColumns results_columns;
2596 Glib::RefPtr<Gtk::ListStore> results_model;
2597 Gtk::TreeView results_display;
2599 results_model = ListStore::create (results_columns);
2600 results_display.set_model (results_model);
2601 results_display.append_column (list_title, results_columns.visible_name);
2603 results_display.set_name ("CleanupResultsList");
2604 results_display.set_headers_visible (true);
2605 results_display.set_headers_clickable (false);
2606 results_display.set_reorderable (false);
2608 Gtk::ScrolledWindow list_scroller;
2611 Gtk::HBox dhbox; // the hbox for the image and text
2612 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2613 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2615 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2617 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2619 if (rep.space < 1048576.0f) {
2621 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2623 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2627 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2629 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2633 dhbox.pack_start (*dimage, true, false, 5);
2634 dhbox.pack_start (txt, true, false, 5);
2636 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2637 TreeModel::Row row = *(results_model->append());
2638 row[results_columns.visible_name] = *i;
2639 row[results_columns.fullpath] = *i;
2642 list_scroller.add (results_display);
2643 list_scroller.set_size_request (-1, 150);
2644 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2646 dvbox.pack_start (dhbox, true, false, 5);
2647 dvbox.pack_start (list_scroller, true, false, 5);
2648 ddhbox.pack_start (dvbox, true, false, 5);
2650 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2651 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2652 results.set_default_response (RESPONSE_CLOSE);
2653 results.set_position (Gtk::WIN_POS_MOUSE);
2655 results_display.show();
2656 list_scroller.show();
2663 //results.get_vbox()->show();
2664 results.set_resizable (false);
2671 ARDOUR_UI::cleanup ()
2674 /* shouldn't happen: menu item is insensitive */
2679 MessageDialog checker (_("Are you sure you want to cleanup?"),
2681 Gtk::MESSAGE_QUESTION,
2682 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2684 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2685 ALL undo/redo information will be lost if you cleanup.\n\
2686 After cleanup, unused audio files will be moved to a \
2687 \"dead sounds\" location."));
2689 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2690 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2691 checker.set_default_response (RESPONSE_CANCEL);
2693 checker.set_name (_("CleanupDialog"));
2694 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2695 checker.set_position (Gtk::WIN_POS_MOUSE);
2697 switch (checker.run()) {
2698 case RESPONSE_ACCEPT:
2704 Session::cleanup_report rep;
2706 editor->prepare_for_cleanup ();
2708 /* do not allow flush until a session is reloaded */
2710 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2712 act->set_sensitive (false);
2715 if (session->cleanup_sources (rep)) {
2716 editor->finish_cleanup ();
2720 editor->finish_cleanup ();
2723 display_cleanup_results (rep,
2726 The following %1 %2 not in use and \n\
2727 have been moved to:\n\
2729 Flushing the wastebasket will \n\
2730 release an additional\n\
2731 %4 %5bytes of disk space.\n"
2737 ARDOUR_UI::flush_trash ()
2740 /* shouldn't happen: menu item is insensitive */
2744 Session::cleanup_report rep;
2746 if (session->cleanup_trash_sources (rep)) {
2750 display_cleanup_results (rep,
2752 _("The following %1 %2 deleted from\n\
2754 releasing %4 %5bytes of disk space"));
2758 ARDOUR_UI::add_route (Gtk::Window* float_window)
2766 if (add_route_dialog == 0) {
2767 add_route_dialog = new AddRouteDialog;
2769 add_route_dialog->set_transient_for (*float_window);
2773 if (add_route_dialog->is_visible()) {
2774 /* we're already doing this */
2778 ResponseType r = (ResponseType) add_route_dialog->run ();
2780 add_route_dialog->hide();
2783 case RESPONSE_ACCEPT:
2790 if ((count = add_route_dialog->count()) <= 0) {
2794 string template_path = add_route_dialog->track_template();
2796 if (!template_path.empty()) {
2797 session->new_route_from_template (count, template_path);
2801 uint32_t input_chan = add_route_dialog->channels ();
2802 uint32_t output_chan;
2803 string name_template = add_route_dialog->name_template ();
2804 bool track = add_route_dialog->track ();
2806 AutoConnectOption oac = Config->get_output_auto_connect();
2808 if (oac & AutoConnectMaster) {
2809 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2811 output_chan = input_chan;
2814 /* XXX do something with name template */
2816 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2818 session_add_midi_track(count);
2820 MessageDialog msg (*editor,
2821 _("Sorry, MIDI Busses are not supported at this time."));
2823 //session_add_midi_bus();
2827 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2829 session_add_audio_bus (input_chan, output_chan, count);
2835 ARDOUR_UI::mixer_settings () const
2840 node = session->instant_xml(X_("Mixer"));
2842 node = Config->instant_xml(X_("Mixer"));
2846 node = new XMLNode (X_("Mixer"));
2853 ARDOUR_UI::editor_settings () const
2858 node = session->instant_xml(X_("Editor"));
2860 node = Config->instant_xml(X_("Editor"));
2864 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2865 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2870 node = new XMLNode (X_("Editor"));
2877 ARDOUR_UI::keyboard_settings () const
2881 node = Config->extra_xml(X_("Keyboard"));
2884 node = new XMLNode (X_("Keyboard"));
2890 ARDOUR_UI::create_xrun_marker(nframes_t where)
2892 editor->mouse_add_new_marker (where, false, true);
2896 ARDOUR_UI::halt_on_xrun_message ()
2898 MessageDialog msg (*editor,
2899 _("Recording was stopped because your system could not keep up."));
2904 ARDOUR_UI::xrun_handler(nframes_t where)
2910 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2912 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2913 create_xrun_marker(where);
2916 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2917 halt_on_xrun_message ();
2922 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2927 while (disk_buffer_stats.size() > 60) {
2928 disk_buffer_stats.pop_front ();
2931 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2935 ARDOUR_UI::write_buffer_stats ()
2941 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2942 int fd = mkstemp (tmplt);
2944 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2948 FILE* fout = fdopen (fd, "w");
2950 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2954 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2955 std::ostringstream ss;
2956 localtime_r (&(*i).when, &tm);
2957 strftime (buf, sizeof (buf), "%T", &tm);
2958 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
2961 disk_buffer_stats.clear ();
2966 cerr << "Ardour buffering statistics can be found in: " << path << endl;
2972 ARDOUR_UI::disk_overrun_handler ()
2974 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2976 write_buffer_stats ();
2978 if (!have_disk_speed_dialog_displayed) {
2979 have_disk_speed_dialog_displayed = true;
2980 MessageDialog* msg = new MessageDialog (*editor, _("\
2981 The disk system on your computer\n\
2982 was not able to keep up with Ardour.\n\
2984 Specifically, it failed to write data to disk\n\
2985 quickly enough to keep up with recording.\n"));
2986 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2992 ARDOUR_UI::disk_underrun_handler ()
2994 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2996 write_buffer_stats ();
2998 if (!have_disk_speed_dialog_displayed) {
2999 have_disk_speed_dialog_displayed = true;
3000 MessageDialog* msg = new MessageDialog (*editor,
3001 _("The disk system on your computer\n\
3002 was not able to keep up with Ardour.\n\
3004 Specifically, it failed to read data from disk\n\
3005 quickly enough to keep up with playback.\n"));
3006 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3012 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3014 have_disk_speed_dialog_displayed = false;
3019 ARDOUR_UI::session_dialog (std::string msg)
3021 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3026 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3028 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3037 ARDOUR_UI::pending_state_dialog ()
3039 HBox* hbox = new HBox();
3040 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3041 ArdourDialog dialog (_("Crash Recovery"), true);
3043 This session appears to have been in\n\
3044 middle of recording when ardour or\n\
3045 the computer was shutdown.\n\
3047 Ardour can recover any captured audio for\n\
3048 you, or it can ignore it. Please decide\n\
3049 what you would like to do.\n"));
3050 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3051 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3052 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3053 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3054 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3055 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3056 dialog.set_default_response (RESPONSE_ACCEPT);
3057 dialog.set_position (WIN_POS_CENTER);
3062 switch (dialog.run ()) {
3063 case RESPONSE_ACCEPT:
3071 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3073 HBox* hbox = new HBox();
3074 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3075 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3076 Label message (string_compose (_("\
3077 This session was created with a sample rate of %1 Hz\n\
3079 The audioengine is currently running at %2 Hz\n"), desired, actual));
3081 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3082 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3083 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3084 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3085 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3086 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3087 dialog.set_default_response (RESPONSE_ACCEPT);
3088 dialog.set_position (WIN_POS_CENTER);
3093 switch (dialog.run ()) {
3094 case RESPONSE_ACCEPT:
3103 ARDOUR_UI::disconnect_from_jack ()
3106 if( engine->disconnect_from_jack ()) {
3107 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3111 update_sample_rate (0);
3116 ARDOUR_UI::reconnect_to_jack ()
3119 if (engine->reconnect_to_jack ()) {
3120 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3124 update_sample_rate (0);
3129 ARDOUR_UI::use_config ()
3132 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3134 set_transport_controllable_state (*node);
3139 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3141 if (Config->get_primary_clock_delta_edit_cursor()) {
3142 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3144 primary_clock.set (pos, 0, true);
3147 if (Config->get_secondary_clock_delta_edit_cursor()) {
3148 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3150 secondary_clock.set (pos);
3153 if (big_clock_window) {
3154 big_clock.set (pos);
3159 ARDOUR_UI::record_state_changed ()
3161 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3163 if (!session || !big_clock_window) {
3164 /* why bother - the clock isn't visible */
3168 Session::RecordState const r = session->record_status ();
3169 bool const h = session->have_rec_enabled_diskstream ();
3171 if (r == Session::Recording && h) {
3172 big_clock.set_widget_name ("BigClockRecording");
3174 big_clock.set_widget_name ("BigClockNonRecording");
3179 ARDOUR_UI::first_idle ()
3182 session->allow_auto_play (true);
3186 editor->first_idle();
3189 Keyboard::set_can_save_keybindings (true);
3194 ARDOUR_UI::store_clock_modes ()
3196 XMLNode* node = new XMLNode(X_("ClockModes"));
3198 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3199 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3202 session->add_extra_xml (*node);
3203 session->set_dirty ();
3208 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3209 : Controllable (name), ui (u), type(tp)
3215 ARDOUR_UI::TransportControllable::set_value (float val)
3217 if (type == ShuttleControl) {
3224 fract = -((0.5f - val)/0.5f);
3226 fract = ((val - 0.5f)/0.5f);
3230 ui.set_shuttle_fract (fract);
3235 /* do nothing: these are radio-style actions */
3239 const char *action = 0;
3243 action = X_("Roll");
3246 action = X_("Stop");
3249 action = X_("Goto Start");
3252 action = X_("Goto End");
3255 action = X_("Loop");
3258 action = X_("Play Selection");
3261 action = X_("Record");
3271 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3279 ARDOUR_UI::TransportControllable::get_value (void) const
3298 case ShuttleControl:
3308 ARDOUR_UI::TransportControllable::set_id (const string& str)
3314 ARDOUR_UI::setup_profile ()
3316 if (gdk_screen_width() < 1200) {
3317 Profile->set_small_screen ();
3321 if (getenv ("ARDOUR_SAE")) {
3322 Profile->set_sae ();
3323 Profile->set_single_package ();