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 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1844 vector<string> connections;
1847 if (io.n_inputs().n_total() == 0) {
1852 /* XXX we're not handling multiple ports yet. */
1854 if (io.input(0)->get_connections(connections) == 0) {
1857 buf = connections.front();
1862 if (io.n_outputs().n_total() == 0) {
1867 /* XXX we're not handling multiple ports yet. */
1869 if (io.output(0)->get_connections(connections) == 0) {
1872 buf = connections.front();
1877 /** Ask the user for the name of a new shapshot and then take it.
1880 ARDOUR_UI::snapshot_session ()
1882 ArdourPrompter prompter (true);
1886 struct tm local_time;
1889 localtime_r (&n, &local_time);
1890 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1892 prompter.set_name ("Prompter");
1893 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1894 prompter.set_prompt (_("Name of New Snapshot"));
1895 prompter.set_initial_text (timebuf);
1897 switch (prompter.run()) {
1898 case RESPONSE_ACCEPT:
1900 prompter.get_result (snapname);
1902 bool do_save = (snapname.length() != 0);
1904 vector<sys::path> p;
1905 get_state_files_in_directory (session->session_directory().root_path(), p);
1906 vector<string> n = get_file_names_no_extension (p);
1907 if (find (n.begin(), n.end(), snapname) != n.end()) {
1909 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1910 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1911 confirm.get_vbox()->pack_start (m, true, true);
1912 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1913 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1914 confirm.show_all ();
1915 switch (confirm.run()) {
1916 case RESPONSE_CANCEL:
1922 save_state (snapname);
1933 ARDOUR_UI::save_state (const string & name)
1935 (void) save_state_canfail (name);
1939 ARDOUR_UI::save_state_canfail (string name)
1944 if (name.length() == 0) {
1945 name = session->snap_name();
1948 if ((ret = session->save_state (name)) != 0) {
1952 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1957 ARDOUR_UI::primary_clock_value_changed ()
1960 session->request_locate (primary_clock.current_time ());
1965 ARDOUR_UI::big_clock_value_changed ()
1968 session->request_locate (big_clock.current_time ());
1973 ARDOUR_UI::secondary_clock_value_changed ()
1976 session->request_locate (secondary_clock.current_time ());
1981 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1987 Session::RecordState const r = session->record_status ();
1988 bool const h = session->have_rec_enabled_diskstream ();
1990 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1992 rec_button.set_visual_state (2);
1994 rec_button.set_visual_state (0);
1996 } else if (r == Session::Recording && h) {
1997 rec_button.set_visual_state (1);
1999 rec_button.set_visual_state (0);
2004 ARDOUR_UI::save_template ()
2007 ArdourPrompter prompter (true);
2010 if (!check_audioengine()) {
2014 prompter.set_name (X_("Prompter"));
2015 prompter.set_prompt (_("Name for mix template:"));
2016 prompter.set_initial_text(session->name() + _("-template"));
2017 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2019 switch (prompter.run()) {
2020 case RESPONSE_ACCEPT:
2021 prompter.get_result (name);
2023 if (name.length()) {
2024 session->save_template (name);
2034 ARDOUR_UI::edit_metadata ()
2036 SessionMetadataEditor dialog;
2037 dialog.set_session (session);
2038 editor->ensure_float (dialog);
2043 ARDOUR_UI::import_metadata ()
2045 SessionMetadataImporter dialog;
2046 dialog.set_session (session);
2047 editor->ensure_float (dialog);
2052 ARDOUR_UI::fontconfig_dialog ()
2055 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2056 may not and it can take a while to build it. Warn them.
2059 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2061 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2062 MessageDialog msg (*_startup,
2063 _("Welcome to Ardour.\n\n"
2064 "The program will take a bit longer to start up\n"
2065 "while the system fonts are checked.\n\n"
2066 "This will only be done once, and you will\n"
2067 "not see this message again\n"),
2080 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2082 existing_session = false;
2084 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2085 session_path = cmdline_path;
2086 existing_session = true;
2087 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2088 session_path = Glib::path_get_dirname (string (cmdline_path));
2089 existing_session = true;
2091 /* it doesn't exist, assume the best */
2092 session_path = Glib::path_get_dirname (string (cmdline_path));
2095 session_name = basename_nosuffix (string (cmdline_path));
2099 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2101 /* when this is called, the backend audio system must be running */
2103 /* the main idea here is to deal with the fact that a cmdline argument for the session
2104 can be interpreted in different ways - it could be a directory or a file, and before
2105 we load, we need to know both the session directory and the snapshot (statefile) within it
2106 that we are supposed to use.
2109 if (session_name.length() == 0 || session_path.length() == 0) {
2113 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2115 Glib::ustring predicted_session_file;
2117 predicted_session_file = session_path;
2118 predicted_session_file += '/';
2119 predicted_session_file += session_name;
2120 predicted_session_file += ARDOUR::statefile_suffix;
2122 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2123 existing_session = true;
2126 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2128 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2129 /* existing .ardour file */
2130 existing_session = true;
2134 existing_session = false;
2137 /* lets just try to load it */
2139 if (create_engine ()) {
2140 backend_audio_error (false, _startup);
2144 return load_session (session_path, session_name);
2148 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2150 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2152 MessageDialog msg (str,
2154 Gtk::MESSAGE_WARNING,
2155 Gtk::BUTTONS_YES_NO,
2159 msg.set_name (X_("CleanupDialog"));
2160 msg.set_wmclass (X_("existing_session"), "Ardour");
2161 msg.set_position (Gtk::WIN_POS_MOUSE);
2164 switch (msg.run()) {
2173 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2178 AutoConnectOption iconnect;
2179 AutoConnectOption oconnect;
2183 if (Profile->get_sae()) {
2187 iconnect = AutoConnectPhysical;
2188 oconnect = AutoConnectMaster;
2189 nphysin = 0; // use all available
2190 nphysout = 0; // use all available
2194 /* get settings from advanced section of NSD */
2196 if (_startup->create_control_bus()) {
2197 cchns = (uint32_t) _startup->control_channel_count();
2202 if (_startup->create_master_bus()) {
2203 mchns = (uint32_t) _startup->master_channel_count();
2208 if (_startup->connect_inputs()) {
2209 iconnect = AutoConnectPhysical;
2211 iconnect = AutoConnectOption (0);
2214 /// @todo some minor tweaks.
2216 if (_startup->connect_outs_to_master()) {
2217 oconnect = AutoConnectMaster;
2218 } else if (_startup->connect_outs_to_physical()) {
2219 oconnect = AutoConnectPhysical;
2221 oconnect = AutoConnectOption (0);
2224 nphysin = (uint32_t) _startup->input_limit_count();
2225 nphysout = (uint32_t) _startup->output_limit_count();
2228 if (build_session (session_path,
2236 engine->frame_rate() * 60 * 5)) {
2245 ARDOUR_UI::end_loading_messages ()
2251 ARDOUR_UI::loading_message (const std::string& msg)
2254 // splash->message (msg);
2259 ARDOUR_UI::get_session_parameters (bool should_be_new)
2261 Glib::ustring session_name;
2262 Glib::ustring session_path;
2263 Glib::ustring template_name;
2265 bool likely_new = false;
2269 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2271 /* if they named a specific statefile, use it, otherwise they are
2272 just giving a session folder, and we want to use it as is
2273 to find the session.
2276 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2277 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2279 session_path = ARDOUR_COMMAND_LINE::session_name;
2282 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2286 run_startup (should_be_new);
2288 /* if we run the startup dialog again, offer more than just "new session" */
2290 should_be_new = false;
2292 session_name = _startup->session_name (likely_new);
2294 /* this shouldn't happen, but we catch it just in case it does */
2296 if (session_name.empty()) {
2299 if (_startup->use_session_template()) {
2300 template_name = _startup->session_template_name();
2301 _session_is_new = true;
2305 if (session_name[0] == '/' ||
2306 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2307 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2309 session_path = Glib::path_get_dirname (session_name);
2310 session_name = Glib::path_get_basename (session_name);
2314 session_path = _startup->session_folder();
2318 if (create_engine ()) {
2322 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2326 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2328 if (!ask_about_loading_existing_session (existing)) {
2329 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2334 _session_is_new = false;
2339 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2341 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2345 _session_is_new = true;
2348 if (likely_new && template_name.empty()) {
2350 ret = build_session_from_nsd (session_path, session_name);
2354 ret = load_session (session_path, session_name, template_name);
2362 ARDOUR_UI::close_session()
2364 if (!check_audioengine()) {
2368 unload_session (true);
2370 get_session_parameters (false);
2374 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2376 Session *new_session;
2380 session_loaded = false;
2382 if (!check_audioengine()) {
2386 unload_status = unload_session ();
2388 if (unload_status < 0) {
2390 } else if (unload_status > 0) {
2395 /* if it already exists, we must have write access */
2397 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2398 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2399 "This prevents the session from being loaded."));
2405 loading_message (_("Please wait while Ardour loads your session"));
2408 new_session = new Session (*engine, path, snap_name, mix_template);
2411 /* this one is special */
2413 catch (AudioEngine::PortRegistrationFailure& err) {
2415 MessageDialog msg (err.what(),
2418 Gtk::BUTTONS_CLOSE);
2420 msg.set_title (_("Port Registration Error"));
2421 msg.set_secondary_text (_("Click the Close button to try again."));
2422 msg.set_position (Gtk::WIN_POS_CENTER);
2426 int response = msg.run ();
2431 case RESPONSE_CANCEL:
2441 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2444 Gtk::BUTTONS_CLOSE);
2446 msg.set_title (_("Loading Error"));
2447 msg.set_secondary_text (_("Click the Close button to try again."));
2448 msg.set_position (Gtk::WIN_POS_CENTER);
2452 int response = msg.run ();
2457 case RESPONSE_CANCEL:
2465 connect_to_session (new_session);
2467 session_loaded = true;
2469 goto_editor_window ();
2472 session->set_clean ();
2483 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2484 uint32_t control_channels,
2485 uint32_t master_channels,
2486 AutoConnectOption input_connect,
2487 AutoConnectOption output_connect,
2490 nframes_t initial_length)
2492 Session *new_session;
2495 if (!check_audioengine()) {
2499 session_loaded = false;
2501 x = unload_session ();
2509 _session_is_new = true;
2512 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2513 control_channels, master_channels, nphysin, nphysout, initial_length);
2518 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2524 connect_to_session (new_session);
2526 session_loaded = true;
2528 new_session->save_state(new_session->name());
2537 editor->show_window ();
2548 ARDOUR_UI::show_about ()
2552 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2559 ARDOUR_UI::hide_about ()
2562 about->get_window()->set_cursor ();
2568 ARDOUR_UI::about_signal_response(int response)
2574 ARDOUR_UI::show_splash ()
2578 splash = new Splash;
2586 splash->queue_draw ();
2587 splash->get_window()->process_updates (true);
2592 ARDOUR_UI::hide_splash ()
2600 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2604 removed = rep.paths.size();
2607 MessageDialog msgd (*editor,
2608 _("No audio files were ready for cleanup"),
2611 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2612 msgd.set_secondary_text (_("If this seems suprising, \n\
2613 check for any existing snapshots.\n\
2614 These may still include regions that\n\
2615 require some unused files to continue to exist."));
2621 ArdourDialog results (_("ardour: cleanup"), true, false);
2623 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2624 CleanupResultsModelColumns() {
2628 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2629 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2633 CleanupResultsModelColumns results_columns;
2634 Glib::RefPtr<Gtk::ListStore> results_model;
2635 Gtk::TreeView results_display;
2637 results_model = ListStore::create (results_columns);
2638 results_display.set_model (results_model);
2639 results_display.append_column (list_title, results_columns.visible_name);
2641 results_display.set_name ("CleanupResultsList");
2642 results_display.set_headers_visible (true);
2643 results_display.set_headers_clickable (false);
2644 results_display.set_reorderable (false);
2646 Gtk::ScrolledWindow list_scroller;
2649 Gtk::HBox dhbox; // the hbox for the image and text
2650 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2651 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2653 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2655 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2657 if (rep.space < 1048576.0f) {
2659 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2661 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2665 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2667 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2671 dhbox.pack_start (*dimage, true, false, 5);
2672 dhbox.pack_start (txt, true, false, 5);
2674 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2675 TreeModel::Row row = *(results_model->append());
2676 row[results_columns.visible_name] = *i;
2677 row[results_columns.fullpath] = *i;
2680 list_scroller.add (results_display);
2681 list_scroller.set_size_request (-1, 150);
2682 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2684 dvbox.pack_start (dhbox, true, false, 5);
2685 dvbox.pack_start (list_scroller, true, false, 5);
2686 ddhbox.pack_start (dvbox, true, false, 5);
2688 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2689 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2690 results.set_default_response (RESPONSE_CLOSE);
2691 results.set_position (Gtk::WIN_POS_MOUSE);
2693 results_display.show();
2694 list_scroller.show();
2701 //results.get_vbox()->show();
2702 results.set_resizable (false);
2709 ARDOUR_UI::cleanup ()
2712 /* shouldn't happen: menu item is insensitive */
2717 MessageDialog checker (_("Are you sure you want to cleanup?"),
2719 Gtk::MESSAGE_QUESTION,
2720 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2722 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2723 ALL undo/redo information will be lost if you cleanup.\n\
2724 After cleanup, unused audio files will be moved to a \
2725 \"dead sounds\" location."));
2727 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2728 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2729 checker.set_default_response (RESPONSE_CANCEL);
2731 checker.set_name (_("CleanupDialog"));
2732 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2733 checker.set_position (Gtk::WIN_POS_MOUSE);
2735 switch (checker.run()) {
2736 case RESPONSE_ACCEPT:
2742 Session::cleanup_report rep;
2744 editor->prepare_for_cleanup ();
2746 /* do not allow flush until a session is reloaded */
2748 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2750 act->set_sensitive (false);
2753 if (session->cleanup_sources (rep)) {
2754 editor->finish_cleanup ();
2758 editor->finish_cleanup ();
2761 display_cleanup_results (rep,
2764 The following %1 %2 not in use and \n\
2765 have been moved to:\n\
2767 Flushing the wastebasket will \n\
2768 release an additional\n\
2769 %4 %5bytes of disk space.\n"
2775 ARDOUR_UI::flush_trash ()
2778 /* shouldn't happen: menu item is insensitive */
2782 Session::cleanup_report rep;
2784 if (session->cleanup_trash_sources (rep)) {
2788 display_cleanup_results (rep,
2790 _("The following %1 %2 deleted from\n\
2792 releasing %4 %5bytes of disk space"));
2796 ARDOUR_UI::add_route (Gtk::Window* float_window)
2804 if (add_route_dialog == 0) {
2805 add_route_dialog = new AddRouteDialog;
2807 add_route_dialog->set_transient_for (*float_window);
2811 if (add_route_dialog->is_visible()) {
2812 /* we're already doing this */
2816 ResponseType r = (ResponseType) add_route_dialog->run ();
2818 add_route_dialog->hide();
2821 case RESPONSE_ACCEPT:
2828 if ((count = add_route_dialog->count()) <= 0) {
2832 string template_path = add_route_dialog->track_template();
2834 if (!template_path.empty()) {
2835 session->new_route_from_template (count, template_path);
2839 uint32_t input_chan = add_route_dialog->channels ();
2840 uint32_t output_chan;
2841 string name_template = add_route_dialog->name_template ();
2842 bool track = add_route_dialog->track ();
2844 AutoConnectOption oac = Config->get_output_auto_connect();
2846 if (oac & AutoConnectMaster) {
2847 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2849 output_chan = input_chan;
2852 /* XXX do something with name template */
2854 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2856 session_add_midi_track(count);
2858 MessageDialog msg (*editor,
2859 _("Sorry, MIDI Busses are not supported at this time."));
2861 //session_add_midi_bus();
2865 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2867 session_add_audio_bus (input_chan, output_chan, count);
2873 ARDOUR_UI::mixer_settings () const
2878 node = session->instant_xml(X_("Mixer"));
2880 node = Config->instant_xml(X_("Mixer"));
2884 node = new XMLNode (X_("Mixer"));
2891 ARDOUR_UI::editor_settings () const
2896 node = session->instant_xml(X_("Editor"));
2898 node = Config->instant_xml(X_("Editor"));
2902 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2903 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2908 node = new XMLNode (X_("Editor"));
2915 ARDOUR_UI::keyboard_settings () const
2919 node = Config->extra_xml(X_("Keyboard"));
2922 node = new XMLNode (X_("Keyboard"));
2928 ARDOUR_UI::create_xrun_marker(nframes_t where)
2930 editor->mouse_add_new_marker (where, false, true);
2934 ARDOUR_UI::halt_on_xrun_message ()
2936 MessageDialog msg (*editor,
2937 _("Recording was stopped because your system could not keep up."));
2942 ARDOUR_UI::xrun_handler(nframes_t where)
2948 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2950 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2951 create_xrun_marker(where);
2954 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2955 halt_on_xrun_message ();
2960 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2965 while (disk_buffer_stats.size() > 60) {
2966 disk_buffer_stats.pop_front ();
2969 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2973 ARDOUR_UI::write_buffer_stats ()
2979 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2980 int fd = mkstemp (tmplt);
2982 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2986 FILE* fout = fdopen (fd, "w");
2988 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2992 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2993 std::ostringstream ss;
2994 localtime_r (&(*i).when, &tm);
2995 strftime (buf, sizeof (buf), "%T", &tm);
2996 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
2999 disk_buffer_stats.clear ();
3004 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3010 ARDOUR_UI::disk_overrun_handler ()
3012 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3014 write_buffer_stats ();
3016 if (!have_disk_speed_dialog_displayed) {
3017 have_disk_speed_dialog_displayed = true;
3018 MessageDialog* msg = new MessageDialog (*editor, _("\
3019 The disk system on your computer\n\
3020 was not able to keep up with Ardour.\n\
3022 Specifically, it failed to write data to disk\n\
3023 quickly enough to keep up with recording.\n"));
3024 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3030 ARDOUR_UI::disk_underrun_handler ()
3032 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3034 write_buffer_stats ();
3036 if (!have_disk_speed_dialog_displayed) {
3037 have_disk_speed_dialog_displayed = true;
3038 MessageDialog* msg = new MessageDialog (*editor,
3039 _("The disk system on your computer\n\
3040 was not able to keep up with Ardour.\n\
3042 Specifically, it failed to read data from disk\n\
3043 quickly enough to keep up with playback.\n"));
3044 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3050 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3052 have_disk_speed_dialog_displayed = false;
3057 ARDOUR_UI::session_dialog (std::string msg)
3059 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3064 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3066 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3075 ARDOUR_UI::pending_state_dialog ()
3077 HBox* hbox = new HBox();
3078 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3079 ArdourDialog dialog (_("Crash Recovery"), true);
3081 This session appears to have been in\n\
3082 middle of recording when ardour or\n\
3083 the computer was shutdown.\n\
3085 Ardour can recover any captured audio for\n\
3086 you, or it can ignore it. Please decide\n\
3087 what you would like to do.\n"));
3088 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3089 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3090 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3091 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3092 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3093 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3094 dialog.set_default_response (RESPONSE_ACCEPT);
3095 dialog.set_position (WIN_POS_CENTER);
3100 switch (dialog.run ()) {
3101 case RESPONSE_ACCEPT:
3109 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3111 HBox* hbox = new HBox();
3112 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3113 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3114 Label message (string_compose (_("\
3115 This session was created with a sample rate of %1 Hz\n\
3117 The audioengine is currently running at %2 Hz\n"), desired, actual));
3119 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3120 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3121 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3122 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3123 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3124 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3125 dialog.set_default_response (RESPONSE_ACCEPT);
3126 dialog.set_position (WIN_POS_CENTER);
3131 switch (dialog.run ()) {
3132 case RESPONSE_ACCEPT:
3141 ARDOUR_UI::disconnect_from_jack ()
3144 if( engine->disconnect_from_jack ()) {
3145 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3149 update_sample_rate (0);
3154 ARDOUR_UI::reconnect_to_jack ()
3157 if (engine->reconnect_to_jack ()) {
3158 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3162 update_sample_rate (0);
3167 ARDOUR_UI::use_config ()
3170 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3172 set_transport_controllable_state (*node);
3177 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3179 if (Config->get_primary_clock_delta_edit_cursor()) {
3180 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3182 primary_clock.set (pos, 0, true);
3185 if (Config->get_secondary_clock_delta_edit_cursor()) {
3186 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3188 secondary_clock.set (pos);
3191 if (big_clock_window) {
3192 big_clock.set (pos);
3197 ARDOUR_UI::record_state_changed ()
3199 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3201 if (!session || !big_clock_window) {
3202 /* why bother - the clock isn't visible */
3206 Session::RecordState const r = session->record_status ();
3207 bool const h = session->have_rec_enabled_diskstream ();
3209 if (r == Session::Recording && h) {
3210 big_clock.set_widget_name ("BigClockRecording");
3212 big_clock.set_widget_name ("BigClockNonRecording");
3217 ARDOUR_UI::first_idle ()
3220 session->allow_auto_play (true);
3224 editor->first_idle();
3227 Keyboard::set_can_save_keybindings (true);
3232 ARDOUR_UI::store_clock_modes ()
3234 XMLNode* node = new XMLNode(X_("ClockModes"));
3236 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3237 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3240 session->add_extra_xml (*node);
3241 session->set_dirty ();
3246 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3247 : Controllable (name), ui (u), type(tp)
3253 ARDOUR_UI::TransportControllable::set_value (float val)
3255 if (type == ShuttleControl) {
3262 fract = -((0.5f - val)/0.5f);
3264 fract = ((val - 0.5f)/0.5f);
3268 ui.set_shuttle_fract (fract);
3273 /* do nothing: these are radio-style actions */
3277 const char *action = 0;
3281 action = X_("Roll");
3284 action = X_("Stop");
3287 action = X_("Goto Start");
3290 action = X_("Goto End");
3293 action = X_("Loop");
3296 action = X_("Play Selection");
3299 action = X_("Record");
3309 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3317 ARDOUR_UI::TransportControllable::get_value (void) const
3336 case ShuttleControl:
3346 ARDOUR_UI::TransportControllable::set_id (const string& str)
3352 ARDOUR_UI::setup_profile ()
3354 if (gdk_screen_width() < 1200) {
3355 Profile->set_small_screen ();
3359 if (getenv ("ARDOUR_SAE")) {
3360 Profile->set_sae ();
3361 Profile->set_single_package ();