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
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #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>
77 #include "ardour_ui.h"
78 #include "public_editor.h"
79 #include "audio_clock.h"
84 #include "add_route_dialog.h"
85 #include "new_session_dialog.h"
88 #include "gui_thread.h"
89 #include "theme_manager.h"
90 #include "bundle_manager.h"
94 using namespace ARDOUR;
96 using namespace Gtkmm2ext;
100 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
101 UIConfiguration *ARDOUR_UI::ui_config = 0;
103 sigc::signal<void,bool> ARDOUR_UI::Blink;
104 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
105 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
106 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
108 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
110 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
112 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
113 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
114 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
115 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
119 adjuster_table (3, 3),
123 preroll_button (_("pre\nroll")),
124 postroll_button (_("post\nroll")),
128 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
132 roll_controllable ("transport roll", *this, TransportControllable::Roll),
133 stop_controllable ("transport stop", *this, TransportControllable::Stop),
134 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
135 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
136 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
137 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
138 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
139 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
140 shuttle_controller_binding_proxy (shuttle_controllable),
142 roll_button (roll_controllable),
143 stop_button (stop_controllable),
144 goto_start_button (goto_start_controllable),
145 goto_end_button (goto_end_controllable),
146 auto_loop_button (auto_loop_controllable),
147 play_selection_button (play_selection_controllable),
148 rec_button (rec_controllable),
150 shuttle_units_button (_("% ")),
152 punch_in_button (_("Punch In")),
153 punch_out_button (_("Punch Out")),
154 auto_return_button (_("Auto Return")),
155 auto_play_button (_("Auto Play")),
156 auto_input_button (_("Auto Input")),
157 click_button (_("Click")),
158 time_master_button (_("time\nmaster")),
160 auditioning_alert_button (_("AUDITION")),
161 solo_alert_button (_("SOLO")),
163 error_log_button (_("Errors"))
166 using namespace Gtk::Menu_Helpers;
172 _auto_display_errors = false;
176 if (theArdourUI == 0) {
180 ui_config = new UIConfiguration();
181 theme_manager = new ThemeManager();
187 _session_is_new = false;
188 big_clock_window = 0;
189 session_selector_window = 0;
190 last_key_press_time = 0;
191 connection_editor = 0;
192 _will_create_new_session_automatically = false;
193 new_session_dialog = 0;
195 add_route_dialog = 0;
199 open_session_selector = 0;
200 have_configure_timeout = false;
201 have_disk_speed_dialog_displayed = false;
202 session_loaded = false;
203 last_speed_displayed = -1.0f;
205 sys::path key_bindings_file;
207 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
208 "ardour.bindings", key_bindings_file);
210 keybindings_path = key_bindings_file.to_string();
212 /* store all bindings changes in per-user file, no matter where they were loaded from */
213 user_keybindings_path = user_config_directory().to_string ();
214 user_keybindings_path += '/';
215 user_keybindings_path += "ardour.bindings";
217 can_save_keybindings = false;
219 last_configure_time.tv_sec = 0;
220 last_configure_time.tv_usec = 0;
222 shuttle_grabbed = false;
224 shuttle_max_speed = 8.0f;
226 shuttle_style_menu = 0;
227 shuttle_unit_menu = 0;
229 gettimeofday (&last_peak_grab, 0);
230 gettimeofday (&last_shuttle_request, 0);
232 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
233 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
235 /* handle pending state with a dialog */
237 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
239 /* lets get this party started */
242 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
243 setup_gtk_ardour_enums ();
244 Config->set_current_owner (ConfigVariableBase::Interface);
247 } catch (failed_constructor& err) {
248 error << _("could not initialize Ardour.") << endmsg;
253 /* we like keyboards */
255 keyboard = new Keyboard;
257 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
258 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
264 ARDOUR_UI::create_engine ()
266 // this gets called every time by new_session()
273 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
280 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
281 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
282 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
283 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
291 ARDOUR_UI::post_engine ()
293 extern int setup_midi ();
295 /* Things to be done once we create the AudioEngine
298 MIDI::Manager::instance()->set_api_data (engine->jack());
301 ActionManager::init ();
304 if (setup_windows ()) {
305 throw failed_constructor ();
308 check_memory_locking();
310 /* this is the first point at which all the keybindings are available */
312 if (ARDOUR_COMMAND_LINE::show_key_actions) {
313 vector<string> names;
314 vector<string> paths;
316 vector<AccelKey> bindings;
318 ActionManager::get_all_actions (names, paths, keys, bindings);
320 vector<string>::iterator n;
321 vector<string>::iterator k;
322 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
323 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
329 blink_timeout_tag = -1;
331 /* the global configuration object is now valid */
335 /* this being a GUI and all, we want peakfiles */
337 AudioFileSource::set_build_peakfiles (true);
338 AudioFileSource::set_build_missing_peakfiles (true);
340 /* set default clock modes */
342 primary_clock.set_mode (AudioClock::SMPTE);
343 secondary_clock.set_mode (AudioClock::BBT);
345 /* start the time-of-day-clock */
348 /* OS X provides an always visible wallclock, so don't be stupid */
349 update_wall_clock ();
350 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
353 update_disk_space ();
355 update_sample_rate (engine->frame_rate());
357 /* now start and maybe save state */
359 if (do_engine_start () == 0) {
360 if (session && _session_is_new) {
361 /* we need to retain initial visual
362 settings for a new session
364 session->save_state ("");
369 ARDOUR_UI::~ARDOUR_UI ()
371 save_ardour_state ();
385 if (add_route_dialog) {
386 delete add_route_dialog;
390 if (new_session_dialog) {
391 delete new_session_dialog;
396 ARDOUR_UI::configure_timeout ()
401 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
402 /* no configure events yet */
406 gettimeofday (&now, 0);
407 timersub (&now, &last_configure_time, &diff);
409 /* force a gap of 0.5 seconds since the last configure event
412 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
415 have_configure_timeout = false;
416 save_ardour_state ();
422 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
424 if (have_configure_timeout) {
425 gettimeofday (&last_configure_time, 0);
427 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
428 have_configure_timeout = true;
435 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
437 const XMLProperty* prop;
439 if ((prop = node.property ("roll")) != 0) {
440 roll_controllable.set_id (prop->value());
442 if ((prop = node.property ("stop")) != 0) {
443 stop_controllable.set_id (prop->value());
445 if ((prop = node.property ("goto_start")) != 0) {
446 goto_start_controllable.set_id (prop->value());
448 if ((prop = node.property ("goto_end")) != 0) {
449 goto_end_controllable.set_id (prop->value());
451 if ((prop = node.property ("auto_loop")) != 0) {
452 auto_loop_controllable.set_id (prop->value());
454 if ((prop = node.property ("play_selection")) != 0) {
455 play_selection_controllable.set_id (prop->value());
457 if ((prop = node.property ("rec")) != 0) {
458 rec_controllable.set_id (prop->value());
460 if ((prop = node.property ("shuttle")) != 0) {
461 shuttle_controllable.set_id (prop->value());
466 ARDOUR_UI::get_transport_controllable_state ()
468 XMLNode* node = new XMLNode(X_("TransportControllables"));
471 roll_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("roll"), buf);
473 stop_controllable.id().print (buf, sizeof (buf));
474 node->add_property (X_("stop"), buf);
475 goto_start_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("goto_start"), buf);
477 goto_end_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("goto_end"), buf);
479 auto_loop_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("auto_loop"), buf);
481 play_selection_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("play_selection"), buf);
483 rec_controllable.id().print (buf, sizeof (buf));
484 node->add_property (X_("rec"), buf);
485 shuttle_controllable.id().print (buf, sizeof (buf));
486 node->add_property (X_("shuttle"), buf);
492 ARDOUR_UI::save_ardour_state ()
494 if (!keyboard || !mixer || !editor) {
498 /* XXX this is all a bit dubious. add_extra_xml() uses
499 a different lifetime model from add_instant_xml().
502 XMLNode* node = new XMLNode (keyboard->get_state());
503 Config->add_extra_xml (*node);
504 Config->add_extra_xml (get_transport_controllable_state());
505 Config->save_state();
506 ui_config->save_state ();
508 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
509 XMLNode mnode(mixer->get_state());
512 session->add_instant_xml (enode);
513 session->add_instant_xml (mnode);
515 Config->add_instant_xml (enode);
516 Config->add_instant_xml (mnode);
523 ARDOUR_UI::autosave_session ()
525 if (!Config->get_periodic_safety_backups())
529 session->maybe_write_autosave();
536 ARDOUR_UI::update_autosave ()
538 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
540 if (session->dirty()) {
541 if (_autosave_connection.connected()) {
542 _autosave_connection.disconnect();
545 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
546 Config->get_periodic_safety_backup_interval() * 1000);
549 if (_autosave_connection.connected()) {
550 _autosave_connection.disconnect();
556 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
560 title = _("Ardour could not start JACK");
562 title = _("Ardour could not connect to JACK.");
565 MessageDialog win (title,
571 win.set_secondary_text(_("There are several possible reasons:\n\
573 1) You requested audio parameters that are not supported..\n\
574 2) JACK is running as another user.\n\
576 Please consider the possibilities, and perhaps try different parameters."));
578 win.set_secondary_text(_("There are several possible reasons:\n\
580 1) JACK is not running.\n\
581 2) JACK is running as another user, perhaps root.\n\
582 3) There is already another client called \"ardour\".\n\
584 Please consider the possibilities, and perhaps (re)start JACK."));
588 win.set_transient_for (*toplevel);
592 win.add_button (Stock::OK, RESPONSE_CLOSE);
594 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
597 win.set_default_response (RESPONSE_CLOSE);
600 win.set_position (Gtk::WIN_POS_CENTER);
602 if (!ARDOUR_COMMAND_LINE::no_splash) {
606 /* we just don't care about the result, but we want to block */
612 ARDOUR_UI::startup ()
617 new_session_dialog = new NewSessionDialog();
619 /* If no session name is given: we're not loading a session yet, nor creating a new one */
621 if (ARDOUR_COMMAND_LINE::session_name.length()) {
623 /* Load session or start the new session dialog */
625 if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
627 MessageDialog msg (string_compose(_("Could not find command line session \"%1\""),
628 ARDOUR_COMMAND_LINE::session_name),
633 msg.set_position (Gtk::WIN_POS_MOUSE);
640 if (!ARDOUR_COMMAND_LINE::new_session) {
642 /* Supposed to be loading an existing session, but the session doesn't exist */
645 MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
646 "To create it from the command line, start ardour as:\n ardour --new %1"), path),
651 msg.set_position (Gtk::WIN_POS_MOUSE);
662 bool have_backend = EngineControl::engine_running();
663 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
666 new_session_dialog->engine_control.set_state (*audio_setup);
669 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
677 ARDOUR_UI::no_memory_warning ()
679 XMLNode node (X_("no-memory-warning"));
680 Config->add_instant_xml (node);
684 ARDOUR_UI::check_memory_locking ()
687 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
691 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
693 if (engine->is_realtime() && memory_warning_node == 0) {
695 struct rlimit limits;
697 long pages, page_size;
699 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
702 ram = (int64_t) pages * (int64_t) page_size;
705 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
709 if (limits.rlim_cur != RLIM_INFINITY) {
711 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
714 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
715 "This might cause Ardour to run out of memory before your system "
716 "runs out of memory. \n\n"
717 "You can view the memory limit with 'ulimit -l', "
718 "and it is normally controlled by /etc/security/limits.conf"));
720 VBox* vbox = msg.get_vbox();
722 CheckButton cb (_("Do not show this window again"));
724 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
726 hbox.pack_start (cb, true, false);
727 vbox->pack_start (hbox);
732 editor->ensure_float (msg);
746 if (session->transport_rolling()) {
747 session->request_stop ();
751 if (session->dirty()) {
752 switch (ask_about_saving_session(_("quit"))) {
757 /* use the default name */
758 if (save_state_canfail ("")) {
759 /* failed - don't quit */
760 MessageDialog msg (*editor,
762 Ardour was unable to save your session.\n\n\
763 If you still wish to quit, please use the\n\n\
764 \"Just quit\" option."));
774 session->set_deletion_in_progress ();
778 Config->save_state();
779 ARDOUR_UI::config()->save_state();
784 ARDOUR_UI::ask_about_saving_session (const string & what)
786 ArdourDialog window (_("ardour: save session?"));
787 Gtk::HBox dhbox; // the hbox for the image and text
788 Gtk::Label prompt_label;
789 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
793 msg = string_compose(_("Don't %1"), what);
794 window.add_button (msg, RESPONSE_REJECT);
795 msg = string_compose(_("Just %1"), what);
796 window.add_button (msg, RESPONSE_APPLY);
797 msg = string_compose(_("Save and %1"), what);
798 window.add_button (msg, RESPONSE_ACCEPT);
800 window.set_default_response (RESPONSE_ACCEPT);
802 Gtk::Button noquit_button (msg);
803 noquit_button.set_name ("EditorGTKButton");
808 if (session->snap_name() == session->name()) {
811 type = _("snapshot");
813 prompt = string_compose(_("The %1\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
814 type, session->snap_name());
816 prompt_label.set_text (prompt);
817 prompt_label.set_name (X_("PrompterLabel"));
818 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
820 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
822 dhbox.set_homogeneous (false);
823 dhbox.pack_start (*dimage, false, false, 5);
824 dhbox.pack_start (prompt_label, true, false, 5);
825 window.get_vbox()->pack_start (dhbox);
827 window.set_name (_("Prompter"));
828 window.set_position (Gtk::WIN_POS_MOUSE);
829 window.set_modal (true);
830 window.set_resizable (false);
837 save_the_session = 0;
839 window.set_keep_above (true);
842 ResponseType r = (ResponseType) window.run();
847 case RESPONSE_ACCEPT: // save and get out of here
849 case RESPONSE_APPLY: // get out of here
859 ARDOUR_UI::every_second ()
862 update_buffer_load ();
863 update_disk_space ();
868 ARDOUR_UI::every_point_one_seconds ()
870 update_speed_display ();
871 RapidScreenUpdate(); /* EMIT_SIGNAL */
876 ARDOUR_UI::every_point_zero_one_seconds ()
878 // august 2007: actual update frequency: 40Hz, not 100Hz
880 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
885 ARDOUR_UI::update_sample_rate (nframes_t ignored)
889 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
891 if (!engine->connected()) {
893 snprintf (buf, sizeof (buf), _("disconnected"));
897 nframes_t rate = engine->frame_rate();
899 if (fmod (rate, 1000.0) != 0.0) {
900 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
901 (float) rate/1000.0f,
902 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
904 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
906 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
910 sample_rate_label.set_text (buf);
914 ARDOUR_UI::update_cpu_load ()
917 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
918 cpu_load_label.set_text (buf);
922 ARDOUR_UI::update_buffer_load ()
927 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
928 session->playback_load(), session->capture_load());
929 buffer_load_label.set_text (buf);
931 buffer_load_label.set_text ("");
936 ARDOUR_UI::count_recenabled_streams (Route& route)
938 Track* track = dynamic_cast<Track*>(&route);
939 if (track && track->diskstream()->record_enabled()) {
940 rec_enabled_streams += track->n_inputs().n_total();
945 ARDOUR_UI::update_disk_space()
951 nframes_t frames = session->available_capture_duration();
954 if (frames == max_frames) {
955 strcpy (buf, _("Disk: 24hrs+"));
960 nframes_t fr = session->frame_rate();
962 rec_enabled_streams = 0;
963 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
965 if (rec_enabled_streams) {
966 frames /= rec_enabled_streams;
969 hrs = frames / (fr * 3600);
970 frames -= hrs * fr * 3600;
971 mins = frames / (fr * 60);
972 frames -= mins * fr * 60;
975 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
978 disk_space_label.set_text (buf);
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 if (state_file_paths.empty()) {
1042 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1044 Gtk::TreeModel::Row row = *(recent_session_model->append());
1046 const string fullpath = (*i).to_string();
1048 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1049 row[recent_session_columns.fullpath] = fullpath;
1051 if (state_file_names.size() > 1) {
1055 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1056 i2 != state_file_names.end(); ++i2)
1059 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1061 child_row[recent_session_columns.visible_name] = *i2;
1062 child_row[recent_session_columns.fullpath] = fullpath;
1067 recent_session_display.set_model (recent_session_model);
1071 ARDOUR_UI::build_session_selector ()
1073 session_selector_window = new ArdourDialog ("session selector");
1075 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1077 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1078 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1079 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1080 recent_session_model = TreeStore::create (recent_session_columns);
1081 recent_session_display.set_model (recent_session_model);
1082 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1083 recent_session_display.set_headers_visible (false);
1084 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1085 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1087 scroller->add (recent_session_display);
1088 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1090 session_selector_window->set_name ("SessionSelectorWindow");
1091 session_selector_window->set_size_request (200, 400);
1092 session_selector_window->get_vbox()->pack_start (*scroller);
1094 recent_session_display.show();
1096 //session_selector_window->get_vbox()->show();
1100 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1102 session_selector_window->response (RESPONSE_ACCEPT);
1106 ARDOUR_UI::open_recent_session ()
1108 bool can_return = (session != 0);
1110 if (session_selector_window == 0) {
1111 build_session_selector ();
1114 redisplay_recent_sessions ();
1118 session_selector_window->set_position (WIN_POS_MOUSE);
1120 ResponseType r = (ResponseType) session_selector_window->run ();
1123 case RESPONSE_ACCEPT:
1127 session_selector_window->hide();
1134 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1138 session_selector_window->hide();
1140 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1142 if (i == recent_session_model->children().end()) {
1146 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1147 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1149 _session_is_new = false;
1151 if (load_session (path, state) == 0) {
1160 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1162 struct stat statbuf;
1164 if (stat (info.filename.c_str(), &statbuf) != 0) {
1168 if (!S_ISDIR(statbuf.st_mode)) {
1174 string session_file = info.filename;
1175 session_file += '/';
1176 session_file += Glib::path_get_basename (info.filename);
1177 session_file += ".ardour";
1179 if (stat (session_file.c_str(), &statbuf) != 0) {
1183 return S_ISREG (statbuf.st_mode);
1187 ARDOUR_UI::check_audioengine ()
1190 if (!engine->connected()) {
1191 MessageDialog msg (_("Ardour is not connected to JACK\n"
1192 "You cannot open or close sessions in this condition"));
1203 ARDOUR_UI::open_session ()
1205 if (!check_audioengine()) {
1210 /* popup selector window */
1212 if (open_session_selector == 0) {
1214 /* ardour sessions are folders */
1216 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1217 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1218 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1219 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1221 FileFilter session_filter;
1222 session_filter.add_pattern ("*.ardour");
1223 session_filter.set_name (_("Ardour sessions"));
1224 open_session_selector->add_filter (session_filter);
1225 open_session_selector->set_filter (session_filter);
1228 int response = open_session_selector->run();
1229 open_session_selector->hide ();
1232 case RESPONSE_ACCEPT:
1235 open_session_selector->hide();
1239 open_session_selector->hide();
1240 string session_path = open_session_selector->get_filename();
1244 if (session_path.length() > 0) {
1245 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1246 _session_is_new = isnew;
1247 load_session (path, name);
1254 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1256 list<boost::shared_ptr<MidiTrack> > tracks;
1259 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1266 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1268 if (tracks.size() != how_many) {
1269 if (how_many == 1) {
1270 error << _("could not create a new midi track") << endmsg;
1272 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1276 if ((route = session->new_midi_route ()) == 0) {
1277 error << _("could not create new midi bus") << endmsg;
1283 MessageDialog msg (*editor,
1284 _("There are insufficient JACK ports available\n\
1285 to create a new track or bus.\n\
1286 You should save Ardour, exit and\n\
1287 restart JACK with more ports."));
1294 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1296 list<boost::shared_ptr<AudioTrack> > tracks;
1297 Session::RouteList routes;
1300 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1306 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1308 if (tracks.size() != how_many) {
1309 if (how_many == 1) {
1310 error << _("could not create a new audio track") << endmsg;
1312 error << string_compose (_("could only create %1 of %2 new audio %3"),
1313 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1319 routes = session->new_audio_route (input_channels, output_channels, how_many);
1321 if (routes.size() != how_many) {
1322 if (how_many == 1) {
1323 error << _("could not create a new audio track") << endmsg;
1325 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1331 if (need_control_room_outs) {
1337 route->set_stereo_control_outs (control_lr_channels);
1338 route->control_outs()->set_stereo_pan (pans, this);
1340 #endif /* CONTROLOUTS */
1344 MessageDialog msg (*editor,
1345 _("There are insufficient JACK ports available\n\
1346 to create a new track or bus.\n\
1347 You should save Ardour, exit and\n\
1348 restart JACK with more ports."));
1354 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1356 nframes_t _preroll = 0;
1359 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1360 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1362 if (new_position > _preroll) {
1363 new_position -= _preroll;
1368 session->request_locate (new_position);
1373 ARDOUR_UI::transport_goto_start ()
1376 session->goto_start();
1379 /* force displayed area in editor to start no matter
1380 what "follow playhead" setting is.
1384 editor->reset_x_origin (session->current_start_frame());
1390 ARDOUR_UI::transport_goto_zero ()
1393 session->request_locate (0);
1396 /* force displayed area in editor to start no matter
1397 what "follow playhead" setting is.
1401 editor->reset_x_origin (0);
1407 ARDOUR_UI::transport_goto_end ()
1410 nframes_t frame = session->current_end_frame();
1411 session->request_locate (frame);
1413 /* force displayed area in editor to start no matter
1414 what "follow playhead" setting is.
1418 editor->reset_x_origin (frame);
1424 ARDOUR_UI::transport_stop ()
1430 if (session->is_auditioning()) {
1431 session->cancel_audition ();
1435 if (session->get_play_loop ()) {
1436 session->request_play_loop (false);
1439 session->request_stop ();
1443 ARDOUR_UI::transport_stop_and_forget_capture ()
1446 session->request_stop (true);
1451 ARDOUR_UI::remove_last_capture()
1454 editor->remove_last_capture();
1459 ARDOUR_UI::transport_record (bool roll)
1462 switch (session->record_status()) {
1463 case Session::Disabled:
1464 if (session->ntracks() == 0) {
1465 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1469 session->maybe_enable_record ();
1474 case Session::Recording:
1476 session->request_stop();
1478 session->disable_record (false, true);
1482 case Session::Enabled:
1483 session->disable_record (false, true);
1489 ARDOUR_UI::transport_roll ()
1497 rolling = session->transport_rolling ();
1499 if (session->get_play_loop()) {
1500 session->request_play_loop (false);
1501 auto_loop_button.set_visual_state (1);
1502 roll_button.set_visual_state (1);
1503 } else if (session->get_play_range ()) {
1504 session->request_play_range (false);
1505 play_selection_button.set_visual_state (0);
1506 } else if (rolling) {
1507 session->request_locate (session->last_transport_start(), true);
1510 session->request_transport_speed (1.0f);
1514 ARDOUR_UI::transport_loop()
1517 if (session->get_play_loop()) {
1518 if (session->transport_rolling()) {
1519 Location * looploc = session->locations()->auto_loop_location();
1521 session->request_locate (looploc->start(), true);
1526 session->request_play_loop (true);
1532 ARDOUR_UI::transport_play_selection ()
1538 if (!session->get_play_range()) {
1539 session->request_stop ();
1542 editor->play_selection ();
1546 ARDOUR_UI::transport_rewind (int option)
1548 float current_transport_speed;
1551 current_transport_speed = session->transport_speed();
1553 if (current_transport_speed >= 0.0f) {
1556 session->request_transport_speed (-1.0f);
1559 session->request_transport_speed (-4.0f);
1562 session->request_transport_speed (-0.5f);
1567 session->request_transport_speed (current_transport_speed * 1.5f);
1573 ARDOUR_UI::transport_forward (int option)
1575 float current_transport_speed;
1578 current_transport_speed = session->transport_speed();
1580 if (current_transport_speed <= 0.0f) {
1583 session->request_transport_speed (1.0f);
1586 session->request_transport_speed (4.0f);
1589 session->request_transport_speed (0.5f);
1594 session->request_transport_speed (current_transport_speed * 1.5f);
1600 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1606 boost::shared_ptr<Route> r;
1608 if ((r = session->route_by_remote_id (dstream)) != 0) {
1612 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1613 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1622 ARDOUR_UI::queue_transport_change ()
1624 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1628 ARDOUR_UI::map_transport_state ()
1630 float sp = session->transport_speed();
1633 transport_rolling ();
1634 } else if (sp < 0.0f) {
1635 transport_rewinding ();
1636 } else if (sp > 0.0f) {
1637 transport_forwarding ();
1639 transport_stopped ();
1644 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1646 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1647 (int) adj.get_value()].c_str());
1651 ARDOUR_UI::engine_stopped ()
1653 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1654 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1655 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1659 ARDOUR_UI::engine_running ()
1661 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1662 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1663 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1665 Glib::RefPtr<Action> action;
1666 const char* action_name = 0;
1668 switch (engine->frames_per_cycle()) {
1670 action_name = X_("JACKLatency32");
1673 action_name = X_("JACKLatency64");
1676 action_name = X_("JACKLatency128");
1679 action_name = X_("JACKLatency512");
1682 action_name = X_("JACKLatency1024");
1685 action_name = X_("JACKLatency2048");
1688 action_name = X_("JACKLatency4096");
1691 action_name = X_("JACKLatency8192");
1694 /* XXX can we do anything useful ? */
1700 action = ActionManager::get_action (X_("JACK"), action_name);
1703 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1704 ract->set_active ();
1710 ARDOUR_UI::engine_halted ()
1712 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1714 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1715 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1717 update_sample_rate (0);
1719 MessageDialog msg (*editor,
1721 JACK has either been shutdown or it\n\
1722 disconnected Ardour because Ardour\n\
1723 was not fast enough. You can save the\n\
1724 session and/or try to reconnect to JACK ."));
1729 ARDOUR_UI::do_engine_start ()
1737 error << _("Unable to start the session running")
1747 ARDOUR_UI::setup_theme ()
1749 theme_manager->setup_theme();
1753 ARDOUR_UI::update_clocks ()
1755 if (!editor || !editor->dragging_playhead()) {
1756 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1761 ARDOUR_UI::start_clocking ()
1763 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1767 ARDOUR_UI::stop_clocking ()
1769 clock_signal_connection.disconnect ();
1773 ARDOUR_UI::toggle_clocking ()
1776 if (clock_button.get_active()) {
1785 ARDOUR_UI::_blink (void *arg)
1788 ((ARDOUR_UI *) arg)->blink ();
1795 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1799 ARDOUR_UI::start_blinking ()
1801 /* Start the blink signal. Everybody with a blinking widget
1802 uses Blink to drive the widget's state.
1805 if (blink_timeout_tag < 0) {
1807 blink_timeout_tag = g_timeout_add (240, _blink, this);
1812 ARDOUR_UI::stop_blinking ()
1814 if (blink_timeout_tag >= 0) {
1815 g_source_remove (blink_timeout_tag);
1816 blink_timeout_tag = -1;
1821 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1826 vector<string> connections;
1829 if (io.n_inputs().n_total() == 0) {
1834 /* XXX we're not handling multiple ports yet. */
1836 if (io.input(0)->get_connections(connections) == 0) {
1839 buf = connections.front();
1844 if (io.n_outputs().n_total() == 0) {
1849 /* XXX we're not handling multiple ports yet. */
1851 if (io.output(0)->get_connections(connections) == 0) {
1854 buf = connections.front();
1859 /** Ask the user for the name of a new shapshot and then take it.
1862 ARDOUR_UI::snapshot_session ()
1864 ArdourPrompter prompter (true);
1868 struct tm local_time;
1871 localtime_r (&n, &local_time);
1872 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1874 prompter.set_name ("Prompter");
1875 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1876 prompter.set_prompt (_("Name of New Snapshot"));
1877 prompter.set_initial_text (timebuf);
1879 switch (prompter.run()) {
1880 case RESPONSE_ACCEPT:
1881 prompter.get_result (snapname);
1882 if (snapname.length()){
1883 save_state (snapname);
1893 ARDOUR_UI::save_state (const string & name)
1895 (void) save_state_canfail (name);
1899 ARDOUR_UI::save_state_canfail (string name)
1904 if (name.length() == 0) {
1905 name = session->snap_name();
1908 if ((ret = session->save_state (name)) != 0) {
1912 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1917 ARDOUR_UI::restore_state (string name)
1920 if (name.length() == 0) {
1921 name = session->name();
1923 session->restore_state (name);
1928 ARDOUR_UI::primary_clock_value_changed ()
1931 session->request_locate (primary_clock.current_time ());
1936 ARDOUR_UI::big_clock_value_changed ()
1939 session->request_locate (big_clock.current_time ());
1944 ARDOUR_UI::secondary_clock_value_changed ()
1947 session->request_locate (secondary_clock.current_time ());
1952 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1954 if (session && dstream && dstream->record_enabled()) {
1956 Session::RecordState rs;
1958 rs = session->record_status ();
1961 case Session::Disabled:
1962 case Session::Enabled:
1963 if (w->get_state() != STATE_SELECTED) {
1964 w->set_state (STATE_SELECTED);
1968 case Session::Recording:
1969 if (w->get_state() != STATE_ACTIVE) {
1970 w->set_state (STATE_ACTIVE);
1976 if (w->get_state() != STATE_NORMAL) {
1977 w->set_state (STATE_NORMAL);
1983 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1989 switch (session->record_status()) {
1990 case Session::Enabled:
1992 rec_button.set_visual_state (2);
1994 rec_button.set_visual_state (0);
1998 case Session::Recording:
1999 rec_button.set_visual_state (1);
2003 rec_button.set_visual_state (0);
2009 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2017 ARDOUR_UI::save_template ()
2020 ArdourPrompter prompter (true);
2023 if (!check_audioengine()) {
2027 prompter.set_name (X_("Prompter"));
2028 prompter.set_prompt (_("Name for mix template:"));
2029 prompter.set_initial_text(session->name() + _("-template"));
2030 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2032 switch (prompter.run()) {
2033 case RESPONSE_ACCEPT:
2034 prompter.get_result (name);
2036 if (name.length()) {
2037 session->save_template (name);
2047 ARDOUR_UI::fontconfig_dialog ()
2050 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2051 may not and it can take a while to build it. Warn them.
2054 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2056 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2057 MessageDialog msg (*new_session_dialog,
2058 _("Welcome to Ardour.\n\n"
2059 "The program will take a bit longer to start up\n"
2060 "while the system fonts are checked.\n\n"
2061 "This will only be done once, and you will\n"
2062 "not see this message again\n"),
2074 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2076 bool existing_session = false;
2077 Glib::ustring session_name;
2078 Glib::ustring session_path;
2079 Glib::ustring template_name;
2081 if (!loading_dialog) {
2082 loading_dialog = new MessageDialog (*new_session_dialog,
2090 int response = Gtk::RESPONSE_NONE;
2092 if (predetermined_path.length()) {
2094 /* before we start, lets see if the given path looks like
2095 an existing ardour session. if it does, skip the
2096 tabs that we don't need
2099 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2100 session_path = predetermined_path;
2101 existing_session = true;
2102 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_REGULAR)) {
2103 session_path = Glib::path_get_dirname (string (predetermined_path));
2104 existing_session = true;
2106 /* it doesn't exist, assume the best */
2107 session_path = Glib::path_get_dirname (string (predetermined_path));
2110 session_name = basename_nosuffix (string (predetermined_path));
2112 new_session_dialog->set_session_name (session_name);
2113 new_session_dialog->set_session_folder (session_path);
2114 new_session_dialog->set_modal (true);
2116 if (existing_session) {
2118 if (session_name.length() == 0 || session_path.length() == 0) {
2119 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2123 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2124 Glib::ustring predicted_session_file;
2126 predicted_session_file = predetermined_path;
2127 predicted_session_file += '/';
2128 predicted_session_file += session_name;
2129 predicted_session_file += ARDOUR::statefile_suffix;
2131 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2132 existing_session = true;
2135 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2137 if (predetermined_path.find (ARDOUR::statefile_suffix) == predetermined_path.length() - 7) {
2138 /* existing .ardour file */
2139 existing_session = true;
2142 existing_session = false;
2145 if (existing_session && have_engine) {
2146 /* lets just try to load it */
2148 loading_dialog->set_message (_("Starting audio engine"));
2149 loading_dialog->show_all ();
2152 if (create_engine ()) {
2153 backend_audio_error (!have_engine, new_session_dialog);
2154 loading_dialog->hide ();
2158 if (load_session (session_path, session_name) == 0) {
2165 /* loading failed, or we need the NSD for something */
2167 new_session_dialog->set_position (WIN_POS_CENTER);
2168 new_session_dialog->set_current_page (0);
2169 new_session_dialog->set_existing_session (existing_session);
2170 new_session_dialog->reset_recent();
2173 new_session_dialog->set_have_engine (have_engine);
2174 new_session_dialog->present ();
2175 response = new_session_dialog->run ();
2176 loading_dialog->hide ();
2178 _session_is_new = false;
2180 /* handle possible negative responses */
2182 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2187 new_session_dialog->hide ();
2190 } else if (response == Gtk::RESPONSE_NONE) {
2191 /* "Clear" was pressed */
2196 fontconfig_dialog();
2198 /* if we're here to help set up audio parameters this is where want to do that.
2202 if (new_session_dialog->engine_control.setup_engine ()) {
2203 new_session_dialog->hide ();
2207 loading_dialog->set_message (_("Starting audio engine"));
2208 loading_dialog->show_all ();
2212 if (create_engine ()) {
2213 backend_audio_error (!have_engine, new_session_dialog);
2214 loading_dialog->hide ();
2216 /* audio setup page */
2217 new_session_dialog->set_existing_session (false);
2218 new_session_dialog->set_current_page (2);
2219 response = Gtk::RESPONSE_NONE;
2223 loading_dialog->hide ();
2226 /* now handle possible affirmative responses */
2228 if (response == Gtk::RESPONSE_YES) {
2230 /* YES == OPEN from the session selector */
2232 session_name = new_session_dialog->session_name();
2234 if (session_name.empty()) {
2235 response = Gtk::RESPONSE_NONE;
2239 if (session_name[0] == '/' ||
2240 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2241 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2242 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2243 response = Gtk::RESPONSE_NONE;
2247 session_path = new_session_dialog->session_folder();
2248 if (load_session (session_path, session_name)) {
2249 response = Gtk::RESPONSE_NONE;
2254 } else if (response == Gtk::RESPONSE_OK) {
2256 /* OK == OPEN button */
2258 session_name = new_session_dialog->session_name();
2260 if (session_name.empty()) {
2261 response = Gtk::RESPONSE_NONE;
2265 switch (new_session_dialog->which_page()) {
2266 case NewSessionDialog::OpenPage:
2267 case NewSessionDialog::EnginePage:
2269 if (session_name[0] == '/' ||
2270 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2271 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2273 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2274 response = Gtk::RESPONSE_NONE;
2279 session_path = new_session_dialog->session_folder();
2281 if (load_session (session_path, session_name)) {
2282 response = Gtk::RESPONSE_NONE;
2288 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2290 cerr << "on page zero\n";
2292 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2293 should_be_new = true;
2296 /* handle what appear to be paths rather than just a name */
2298 if (session_name[0] == '/' ||
2299 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2300 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2302 session_path = Glib::path_get_dirname (session_name);
2303 session_name = Glib::path_get_basename (session_name);
2307 session_path = new_session_dialog->session_folder();
2311 //XXX This is needed because session constructor wants a
2312 //non-existant path. hopefully this will be fixed at some point.
2314 session_path = Glib::build_filename (session_path, session_name);
2316 if (!should_be_new) {
2318 if (load_session (session_path, session_name)) {
2319 response = Gtk::RESPONSE_NONE;
2323 continue; /* leaves while() loop because response != NONE */
2325 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2327 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2329 MessageDialog msg (str,
2331 Gtk::MESSAGE_WARNING,
2332 Gtk::BUTTONS_YES_NO,
2336 msg.set_name (X_("CleanupDialog"));
2337 msg.set_wmclass (X_("existing_session"), "Ardour");
2338 msg.set_position (Gtk::WIN_POS_MOUSE);
2340 switch (msg.run()) {
2342 new_session_dialog->hide ();
2343 goto_editor_window ();
2345 if (load_session (session_path, session_name)) {
2346 response = Gtk::RESPONSE_NONE;
2352 response = RESPONSE_NONE;
2353 new_session_dialog->reset ();
2354 new_session_dialog->set_existing_session (false);
2355 loading_dialog->hide ();
2360 _session_is_new = true;
2362 if (new_session_dialog->use_session_template()) {
2364 template_name = new_session_dialog->session_template_name();
2366 new_session_dialog->hide ();
2367 goto_editor_window ();
2370 if (load_session (session_path, session_name, template_name)) {
2371 response = Gtk::RESPONSE_NONE;
2380 AutoConnectOption iconnect;
2381 AutoConnectOption oconnect;
2385 if (Profile->get_sae()) {
2389 iconnect = AutoConnectPhysical;
2390 oconnect = AutoConnectMaster;
2391 nphysin = 0; // use all available
2392 nphysout = 0; // use all available
2396 /* get settings from advanced section of NSD */
2398 if (new_session_dialog->create_control_bus()) {
2399 cchns = (uint32_t) new_session_dialog->control_channel_count();
2404 if (new_session_dialog->create_master_bus()) {
2405 mchns = (uint32_t) new_session_dialog->master_channel_count();
2410 if (new_session_dialog->connect_inputs()) {
2411 iconnect = AutoConnectPhysical;
2413 iconnect = AutoConnectOption (0);
2416 /// @todo some minor tweaks.
2418 if (new_session_dialog->connect_outs_to_master()) {
2419 oconnect = AutoConnectMaster;
2420 } else if (new_session_dialog->connect_outs_to_physical()) {
2421 oconnect = AutoConnectPhysical;
2423 oconnect = AutoConnectOption (0);
2426 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2427 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2430 if (build_session (session_path,
2438 engine->frame_rate() * 60 * 5)) {
2440 response = Gtk::RESPONSE_NONE;
2444 new_session_dialog->hide ();
2445 goto_editor_window ();
2456 if (response == Gtk::RESPONSE_NONE) {
2457 loading_dialog->hide ();
2458 new_session_dialog->set_existing_session (false);
2459 new_session_dialog->reset ();
2462 } while (response == Gtk::RESPONSE_NONE);
2466 loading_dialog->hide ();
2467 new_session_dialog->hide();
2472 ARDOUR_UI::close_session()
2474 if (!check_audioengine()) {
2478 unload_session (true);
2480 get_session_parameters ("", true, false);
2484 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2486 Session *new_session;
2490 session_loaded = false;
2492 if (!check_audioengine()) {
2496 unload_status = unload_session ();
2498 if (unload_status < 0) {
2500 } else if (unload_status > 0) {
2505 /* if it already exists, we must have write access */
2507 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2508 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2509 "This prevents the session from being loaded."));
2514 if (loading_dialog) {
2515 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2519 disable_screen_updates ();
2522 new_session = new Session (*engine, path, snap_name, mix_template);
2525 /* this one is special */
2527 catch (AudioEngine::PortRegistrationFailure& err) {
2529 MessageDialog msg (err.what(),
2532 Gtk::BUTTONS_OK_CANCEL);
2534 msg.set_title (_("Loading Error"));
2535 msg.set_secondary_text (_("Click the OK button to try again."));
2536 msg.set_position (Gtk::WIN_POS_CENTER);
2539 int response = msg.run ();
2544 case RESPONSE_CANCEL:
2554 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2557 Gtk::BUTTONS_OK_CANCEL);
2559 msg.set_title (_("Loading Error"));
2560 msg.set_secondary_text (_("Click the OK button to try again."));
2561 msg.set_position (Gtk::WIN_POS_CENTER);
2564 int response = msg.run ();
2569 case RESPONSE_CANCEL:
2577 connect_to_session (new_session);
2579 Config->set_current_owner (ConfigVariableBase::Interface);
2581 session_loaded = true;
2583 goto_editor_window ();
2586 session->set_clean ();
2589 enable_screen_updates ();
2598 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2599 uint32_t control_channels,
2600 uint32_t master_channels,
2601 AutoConnectOption input_connect,
2602 AutoConnectOption output_connect,
2605 nframes_t initial_length)
2607 Session *new_session;
2610 if (!check_audioengine()) {
2614 session_loaded = false;
2616 x = unload_session ();
2624 _session_is_new = true;
2627 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2628 control_channels, master_channels, nphysin, nphysout, initial_length);
2633 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2638 connect_to_session (new_session);
2640 session_loaded = true;
2648 editor->show_window ();
2659 ARDOUR_UI::show_splash ()
2662 about = new About();
2663 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2670 ARDOUR_UI::about_signal_response(int response)
2676 ARDOUR_UI::hide_splash ()
2679 about->get_window()->set_cursor ();
2685 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2689 removed = rep.paths.size();
2692 MessageDialog msgd (*editor,
2693 _("No audio files were ready for cleanup"),
2696 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2697 msgd.set_secondary_text (_("If this seems suprising, \n\
2698 check for any existing snapshots.\n\
2699 These may still include regions that\n\
2700 require some unused files to continue to exist."));
2706 ArdourDialog results (_("ardour: cleanup"), true, false);
2708 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2709 CleanupResultsModelColumns() {
2713 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2714 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2718 CleanupResultsModelColumns results_columns;
2719 Glib::RefPtr<Gtk::ListStore> results_model;
2720 Gtk::TreeView results_display;
2722 results_model = ListStore::create (results_columns);
2723 results_display.set_model (results_model);
2724 results_display.append_column (list_title, results_columns.visible_name);
2726 results_display.set_name ("CleanupResultsList");
2727 results_display.set_headers_visible (true);
2728 results_display.set_headers_clickable (false);
2729 results_display.set_reorderable (false);
2731 Gtk::ScrolledWindow list_scroller;
2734 Gtk::HBox dhbox; // the hbox for the image and text
2735 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2736 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2738 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2740 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2742 if (rep.space < 1048576.0f) {
2744 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2746 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2750 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2752 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2756 dhbox.pack_start (*dimage, true, false, 5);
2757 dhbox.pack_start (txt, true, false, 5);
2759 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2760 TreeModel::Row row = *(results_model->append());
2761 row[results_columns.visible_name] = *i;
2762 row[results_columns.fullpath] = *i;
2765 list_scroller.add (results_display);
2766 list_scroller.set_size_request (-1, 150);
2767 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2769 dvbox.pack_start (dhbox, true, false, 5);
2770 dvbox.pack_start (list_scroller, true, false, 5);
2771 ddhbox.pack_start (dvbox, true, false, 5);
2773 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2774 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2775 results.set_default_response (RESPONSE_CLOSE);
2776 results.set_position (Gtk::WIN_POS_MOUSE);
2778 results_display.show();
2779 list_scroller.show();
2786 //results.get_vbox()->show();
2787 results.set_resizable (false);
2794 ARDOUR_UI::cleanup ()
2797 /* shouldn't happen: menu item is insensitive */
2802 MessageDialog checker (_("Are you sure you want to cleanup?"),
2804 Gtk::MESSAGE_QUESTION,
2805 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2807 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2808 ALL undo/redo information will be lost if you cleanup.\n\
2809 After cleanup, unused audio files will be moved to a \
2810 \"dead sounds\" location."));
2812 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2813 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2814 checker.set_default_response (RESPONSE_CANCEL);
2816 checker.set_name (_("CleanupDialog"));
2817 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2818 checker.set_position (Gtk::WIN_POS_MOUSE);
2820 switch (checker.run()) {
2821 case RESPONSE_ACCEPT:
2827 Session::cleanup_report rep;
2829 editor->prepare_for_cleanup ();
2831 /* do not allow flush until a session is reloaded */
2833 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2835 act->set_sensitive (false);
2838 if (session->cleanup_sources (rep)) {
2843 display_cleanup_results (rep,
2846 The following %1 %2 not in use and \n\
2847 have been moved to:\n\
2849 Flushing the wastebasket will \n\
2850 release an additional\n\
2851 %4 %5bytes of disk space.\n"
2859 ARDOUR_UI::flush_trash ()
2862 /* shouldn't happen: menu item is insensitive */
2866 Session::cleanup_report rep;
2868 if (session->cleanup_trash_sources (rep)) {
2872 display_cleanup_results (rep,
2874 _("The following %1 %2 deleted from\n\
2876 releasing %4 %5bytes of disk space"));
2880 ARDOUR_UI::add_route (Gtk::Window* float_window)
2888 if (add_route_dialog == 0) {
2889 add_route_dialog = new AddRouteDialog;
2891 add_route_dialog->set_transient_for (*float_window);
2895 if (add_route_dialog->is_visible()) {
2896 /* we're already doing this */
2900 ResponseType r = (ResponseType) add_route_dialog->run ();
2902 add_route_dialog->hide();
2905 case RESPONSE_ACCEPT:
2912 if ((count = add_route_dialog->count()) <= 0) {
2916 uint32_t input_chan = add_route_dialog->channels ();
2917 uint32_t output_chan;
2918 string name_template = add_route_dialog->name_template ();
2919 bool track = add_route_dialog->track ();
2921 AutoConnectOption oac = Config->get_output_auto_connect();
2923 if (oac & AutoConnectMaster) {
2924 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2926 output_chan = input_chan;
2929 /* XXX do something with name template */
2931 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2933 session_add_midi_track(count);
2935 MessageDialog msg (*editor,
2936 _("Sorry, MIDI Busses are not supported at this time."));
2938 //session_add_midi_bus();
2942 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2944 session_add_audio_bus (input_chan, output_chan, count);
2950 ARDOUR_UI::mixer_settings () const
2955 node = session->instant_xml(X_("Mixer"));
2957 node = Config->instant_xml(X_("Mixer"));
2961 node = new XMLNode (X_("Mixer"));
2968 ARDOUR_UI::editor_settings () const
2973 node = session->instant_xml(X_("Editor"));
2975 node = Config->instant_xml(X_("Editor"));
2979 node = new XMLNode (X_("Editor"));
2985 ARDOUR_UI::keyboard_settings () const
2989 node = Config->extra_xml(X_("Keyboard"));
2992 node = new XMLNode (X_("Keyboard"));
2998 ARDOUR_UI::halt_on_xrun_message ()
3000 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3002 MessageDialog msg (*editor,
3003 _("Recording was stopped because your system could not keep up."));
3008 ARDOUR_UI::disk_overrun_handler ()
3010 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3012 if (!have_disk_speed_dialog_displayed) {
3013 have_disk_speed_dialog_displayed = true;
3014 MessageDialog* msg = new MessageDialog (*editor, _("\
3015 The disk system on your computer\n\
3016 was not able to keep up with Ardour.\n\
3018 Specifically, it failed to write data to disk\n\
3019 quickly enough to keep up with recording.\n"));
3020 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3026 ARDOUR_UI::disk_underrun_handler ()
3028 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3030 if (!have_disk_speed_dialog_displayed) {
3031 have_disk_speed_dialog_displayed = true;
3032 MessageDialog* msg = new MessageDialog (*editor,
3033 _("The disk system on your computer\n\
3034 was not able to keep up with Ardour.\n\
3036 Specifically, it failed to read data from disk\n\
3037 quickly enough to keep up with playback.\n"));
3038 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3044 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3046 have_disk_speed_dialog_displayed = false;
3051 ARDOUR_UI::pending_state_dialog ()
3053 HBox* hbox = new HBox();
3054 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3055 ArdourDialog dialog (_("Crash Recovery"), true);
3057 This session appears to have been in\n\
3058 middle of recording when ardour or\n\
3059 the computer was shutdown.\n\
3061 Ardour can recover any captured audio for\n\
3062 you, or it can ignore it. Please decide\n\
3063 what you would like to do.\n"));
3064 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3065 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3066 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3067 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3068 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3069 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3070 dialog.set_default_response (RESPONSE_ACCEPT);
3071 dialog.set_position (WIN_POS_CENTER);
3076 switch (dialog.run ()) {
3077 case RESPONSE_ACCEPT:
3085 ARDOUR_UI::disconnect_from_jack ()
3088 if( engine->disconnect_from_jack ()) {
3089 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3093 update_sample_rate (0);
3098 ARDOUR_UI::reconnect_to_jack ()
3101 if (engine->reconnect_to_jack ()) {
3102 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3106 update_sample_rate (0);
3111 ARDOUR_UI::cmdline_new_session (string path)
3113 if (path[0] != '/') {
3114 char buf[PATH_MAX+1];
3117 getcwd (buf, sizeof (buf));
3124 get_session_parameters (path, false, true);
3126 _will_create_new_session_automatically = false; /* done it */
3128 return FALSE; /* don't call it again */
3132 ARDOUR_UI::use_config ()
3134 Glib::RefPtr<Action> act;
3136 switch (Config->get_native_file_data_format ()) {
3138 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3141 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3144 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3149 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3150 ract->set_active ();
3153 switch (Config->get_native_file_header_format ()) {
3155 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3158 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3161 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3164 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3167 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3170 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3173 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3178 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3179 ract->set_active ();
3182 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3184 set_transport_controllable_state (*node);
3189 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3191 if (Config->get_primary_clock_delta_edit_cursor()) {
3192 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3194 primary_clock.set (pos, 0, true);
3197 if (Config->get_secondary_clock_delta_edit_cursor()) {
3198 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3200 secondary_clock.set (pos);
3203 if (big_clock_window) {
3204 big_clock.set (pos);
3209 ARDOUR_UI::record_state_changed ()
3211 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3213 if (!session || !big_clock_window) {
3214 /* why bother - the clock isn't visible */
3218 switch (session->record_status()) {
3219 case Session::Recording:
3220 big_clock.set_widget_name ("BigClockRecording");
3223 big_clock.set_widget_name ("BigClockNonRecording");
3229 ARDOUR_UI::set_keybindings_path (string path)
3231 keybindings_path = path;
3235 ARDOUR_UI::save_keybindings ()
3237 if (can_save_keybindings) {
3238 AccelMap::save (user_keybindings_path);
3243 ARDOUR_UI::first_idle ()
3246 session->allow_auto_play (true);
3248 can_save_keybindings = true;
3253 ARDOUR_UI::store_clock_modes ()
3255 XMLNode* node = new XMLNode(X_("ClockModes"));
3257 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3258 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3261 session->add_extra_xml (*node);
3262 session->set_dirty ();
3267 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3268 : Controllable (name), ui (u), type(tp)
3274 ARDOUR_UI::TransportControllable::set_value (float val)
3276 if (type == ShuttleControl) {
3283 fract = -((0.5f - val)/0.5f);
3285 fract = ((val - 0.5f)/0.5f);
3289 ui.set_shuttle_fract (fract);
3294 /* do nothing: these are radio-style actions */
3298 const char *action = 0;
3302 action = X_("Roll");
3305 action = X_("Stop");
3308 action = X_("Goto Start");
3311 action = X_("Goto End");
3314 action = X_("Loop");
3317 action = X_("Play Selection");
3320 action = X_("Record");
3330 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3338 ARDOUR_UI::TransportControllable::get_value (void) const
3357 case ShuttleControl:
3367 ARDOUR_UI::TransportControllable::set_id (const string& str)
3373 ARDOUR_UI::setup_profile ()
3375 if (gdk_screen_width() < 1200) {
3376 Profile->set_small_screen ();
3380 if (getenv ("ARDOUR_SAE")) {
3381 Profile->set_sae ();
3382 Profile->set_single_package ();