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"
89 #include "gui_thread.h"
90 #include "theme_manager.h"
91 #include "bundle_manager.h"
95 using namespace ARDOUR;
97 using namespace Gtkmm2ext;
101 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
102 UIConfiguration *ARDOUR_UI::ui_config = 0;
104 sigc::signal<void,bool> ARDOUR_UI::Blink;
105 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
106 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
107 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
109 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
111 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
113 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
114 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
115 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
116 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
120 adjuster_table (3, 3),
124 preroll_button (_("pre\nroll")),
125 postroll_button (_("post\nroll")),
129 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
133 roll_controllable ("transport roll", *this, TransportControllable::Roll),
134 stop_controllable ("transport stop", *this, TransportControllable::Stop),
135 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
136 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
137 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
138 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
139 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
140 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
141 shuttle_controller_binding_proxy (shuttle_controllable),
143 roll_button (roll_controllable),
144 stop_button (stop_controllable),
145 goto_start_button (goto_start_controllable),
146 goto_end_button (goto_end_controllable),
147 auto_loop_button (auto_loop_controllable),
148 play_selection_button (play_selection_controllable),
149 rec_button (rec_controllable),
151 shuttle_units_button (_("% ")),
153 punch_in_button (_("Punch In")),
154 punch_out_button (_("Punch Out")),
155 auto_return_button (_("Auto Return")),
156 auto_play_button (_("Auto Play")),
157 auto_input_button (_("Auto Input")),
158 click_button (_("Click")),
159 time_master_button (_("time\nmaster")),
161 auditioning_alert_button (_("AUDITION")),
162 solo_alert_button (_("SOLO")),
164 error_log_button (_("Errors"))
167 using namespace Gtk::Menu_Helpers;
173 _auto_display_errors = false;
178 if (ARDOUR_COMMAND_LINE::session_name.length()) {
179 /* only show this if we're not going to post the new session dialog */
183 if (theArdourUI == 0) {
187 ui_config = new UIConfiguration();
188 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 connection_editor = 0;
199 _will_create_new_session_automatically = false;
200 new_session_dialog = 0;
201 add_route_dialog = 0;
205 open_session_selector = 0;
206 have_configure_timeout = false;
207 have_disk_speed_dialog_displayed = false;
208 session_loaded = false;
209 last_speed_displayed = -1.0f;
211 sys::path key_bindings_file;
213 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
214 "ardour.bindings", key_bindings_file);
216 keybindings_path = key_bindings_file.to_string();
218 /* store all bindings changes in per-user file, no matter where they were loaded from */
219 user_keybindings_path = user_config_directory().to_string ();
220 user_keybindings_path += '/';
221 user_keybindings_path += "ardour.bindings";
223 can_save_keybindings = false;
225 last_configure_time.tv_sec = 0;
226 last_configure_time.tv_usec = 0;
228 shuttle_grabbed = false;
230 shuttle_max_speed = 8.0f;
232 shuttle_style_menu = 0;
233 shuttle_unit_menu = 0;
235 gettimeofday (&last_peak_grab, 0);
236 gettimeofday (&last_shuttle_request, 0);
238 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle pending state with a dialog */
243 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
245 /* handle sr mismatch with a dialog */
247 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
249 /* lets get this party started */
252 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
253 throw failed_constructor ();
256 setup_gtk_ardour_enums ();
257 Config->set_current_owner (ConfigVariableBase::Interface);
260 } catch (failed_constructor& err) {
261 error << _("could not initialize Ardour.") << endmsg;
266 /* we like keyboards */
268 keyboard = new Keyboard;
270 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
271 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
277 ARDOUR_UI::create_engine ()
279 // this gets called every time by new_session()
285 loading_message (_("Starting audio engine"));
288 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
295 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
296 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
297 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
298 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
306 ARDOUR_UI::post_engine ()
308 extern int setup_midi ();
310 /* Things to be done once we create the AudioEngine
313 MIDI::Manager::instance()->set_api_data (engine->jack());
316 ActionManager::init ();
319 if (setup_windows ()) {
320 throw failed_constructor ();
323 check_memory_locking();
325 /* this is the first point at which all the keybindings are available */
327 if (ARDOUR_COMMAND_LINE::show_key_actions) {
328 vector<string> names;
329 vector<string> paths;
331 vector<AccelKey> bindings;
333 ActionManager::get_all_actions (names, paths, keys, bindings);
335 vector<string>::iterator n;
336 vector<string>::iterator k;
337 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
338 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
344 blink_timeout_tag = -1;
346 /* the global configuration object is now valid */
350 /* this being a GUI and all, we want peakfiles */
352 AudioFileSource::set_build_peakfiles (true);
353 AudioFileSource::set_build_missing_peakfiles (true);
355 /* set default clock modes */
357 primary_clock.set_mode (AudioClock::SMPTE);
358 secondary_clock.set_mode (AudioClock::BBT);
360 /* start the time-of-day-clock */
363 /* OS X provides an always visible wallclock, so don't be stupid */
364 update_wall_clock ();
365 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
368 update_disk_space ();
370 update_sample_rate (engine->frame_rate());
372 /* now start and maybe save state */
374 if (do_engine_start () == 0) {
375 if (session && _session_is_new) {
376 /* we need to retain initial visual
377 settings for a new session
379 session->save_state ("");
384 ARDOUR_UI::~ARDOUR_UI ()
386 save_ardour_state ();
400 if (add_route_dialog) {
401 delete add_route_dialog;
405 if (new_session_dialog) {
406 delete new_session_dialog;
411 ARDOUR_UI::pop_back_splash ()
413 if (Splash::instance()) {
414 // Splash::instance()->pop_back();
415 Splash::instance()->hide ();
420 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
426 /* no configure events yet */
430 gettimeofday (&now, 0);
431 timersub (&now, &last_configure_time, &diff);
433 /* force a gap of 0.5 seconds since the last configure event
436 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
439 have_configure_timeout = false;
440 save_ardour_state ();
446 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
448 if (have_configure_timeout) {
449 gettimeofday (&last_configure_time, 0);
451 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
452 have_configure_timeout = true;
459 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
461 const XMLProperty* prop;
463 if ((prop = node.property ("roll")) != 0) {
464 roll_controllable.set_id (prop->value());
466 if ((prop = node.property ("stop")) != 0) {
467 stop_controllable.set_id (prop->value());
469 if ((prop = node.property ("goto_start")) != 0) {
470 goto_start_controllable.set_id (prop->value());
472 if ((prop = node.property ("goto_end")) != 0) {
473 goto_end_controllable.set_id (prop->value());
475 if ((prop = node.property ("auto_loop")) != 0) {
476 auto_loop_controllable.set_id (prop->value());
478 if ((prop = node.property ("play_selection")) != 0) {
479 play_selection_controllable.set_id (prop->value());
481 if ((prop = node.property ("rec")) != 0) {
482 rec_controllable.set_id (prop->value());
484 if ((prop = node.property ("shuttle")) != 0) {
485 shuttle_controllable.set_id (prop->value());
490 ARDOUR_UI::get_transport_controllable_state ()
492 XMLNode* node = new XMLNode(X_("TransportControllables"));
495 roll_controllable.id().print (buf, sizeof (buf));
496 node->add_property (X_("roll"), buf);
497 stop_controllable.id().print (buf, sizeof (buf));
498 node->add_property (X_("stop"), buf);
499 goto_start_controllable.id().print (buf, sizeof (buf));
500 node->add_property (X_("goto_start"), buf);
501 goto_end_controllable.id().print (buf, sizeof (buf));
502 node->add_property (X_("goto_end"), buf);
503 auto_loop_controllable.id().print (buf, sizeof (buf));
504 node->add_property (X_("auto_loop"), buf);
505 play_selection_controllable.id().print (buf, sizeof (buf));
506 node->add_property (X_("play_selection"), buf);
507 rec_controllable.id().print (buf, sizeof (buf));
508 node->add_property (X_("rec"), buf);
509 shuttle_controllable.id().print (buf, sizeof (buf));
510 node->add_property (X_("shuttle"), buf);
516 ARDOUR_UI::save_ardour_state ()
518 if (!keyboard || !mixer || !editor) {
522 /* XXX this is all a bit dubious. add_extra_xml() uses
523 a different lifetime model from add_instant_xml().
526 XMLNode* node = new XMLNode (keyboard->get_state());
527 Config->add_extra_xml (*node);
528 Config->add_extra_xml (get_transport_controllable_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);
547 ARDOUR_UI::autosave_session ()
549 if (!Config->get_periodic_safety_backups())
553 session->maybe_write_autosave();
560 ARDOUR_UI::update_autosave ()
562 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
564 if (session->dirty()) {
565 if (_autosave_connection.connected()) {
566 _autosave_connection.disconnect();
569 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
570 Config->get_periodic_safety_backup_interval() * 1000);
573 if (_autosave_connection.connected()) {
574 _autosave_connection.disconnect();
580 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
584 title = _("Ardour could not start JACK");
586 title = _("Ardour could not connect to JACK.");
589 MessageDialog win (title,
595 win.set_secondary_text(_("There are several possible reasons:\n\
597 1) You requested audio parameters that are not supported..\n\
598 2) JACK is running as another user.\n\
600 Please consider the possibilities, and perhaps try different parameters."));
602 win.set_secondary_text(_("There are several possible reasons:\n\
604 1) JACK is not running.\n\
605 2) JACK is running as another user, perhaps root.\n\
606 3) There is already another client called \"ardour\".\n\
608 Please consider the possibilities, and perhaps (re)start JACK."));
612 win.set_transient_for (*toplevel);
616 win.add_button (Stock::OK, RESPONSE_CLOSE);
618 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
621 win.set_default_response (RESPONSE_CLOSE);
624 win.set_position (Gtk::WIN_POS_CENTER);
627 /* we just don't care about the result, but we want to block */
633 ARDOUR_UI::startup ()
637 new_session_dialog = new NewSessionDialog();
639 bool backend_audio_is_running = EngineControl::engine_running();
640 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
643 new_session_dialog->engine_control.set_state (*audio_setup);
646 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
654 ARDOUR_UI::no_memory_warning ()
656 XMLNode node (X_("no-memory-warning"));
657 Config->add_instant_xml (node);
661 ARDOUR_UI::check_memory_locking ()
664 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
668 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
670 if (engine->is_realtime() && memory_warning_node == 0) {
672 struct rlimit limits;
674 long pages, page_size;
676 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
679 ram = (int64_t) pages * (int64_t) page_size;
682 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
686 if (limits.rlim_cur != RLIM_INFINITY) {
688 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
691 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
692 "This might cause Ardour to run out of memory before your system "
693 "runs out of memory. \n\n"
694 "You can view the memory limit with 'ulimit -l', "
695 "and it is normally controlled by /etc/security/limits.conf"));
697 VBox* vbox = msg.get_vbox();
699 CheckButton cb (_("Do not show this window again"));
701 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
703 hbox.pack_start (cb, true, false);
704 vbox->pack_start (hbox);
711 editor->ensure_float (msg);
725 if (session->transport_rolling()) {
726 session->request_stop ();
730 if (session->dirty()) {
731 switch (ask_about_saving_session(_("quit"))) {
736 /* use the default name */
737 if (save_state_canfail ("")) {
738 /* failed - don't quit */
739 MessageDialog msg (*editor,
741 Ardour was unable to save your session.\n\n\
742 If you still wish to quit, please use the\n\n\
743 \"Just quit\" option."));
754 session->set_deletion_in_progress ();
758 Config->save_state();
759 ARDOUR_UI::config()->save_state();
764 ARDOUR_UI::ask_about_saving_session (const string & what)
766 ArdourDialog window (_("ardour: save session?"));
767 Gtk::HBox dhbox; // the hbox for the image and text
768 Gtk::Label prompt_label;
769 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
773 msg = string_compose(_("Don't %1"), what);
774 window.add_button (msg, RESPONSE_REJECT);
775 msg = string_compose(_("Just %1"), what);
776 window.add_button (msg, RESPONSE_APPLY);
777 msg = string_compose(_("Save and %1"), what);
778 window.add_button (msg, RESPONSE_ACCEPT);
780 window.set_default_response (RESPONSE_ACCEPT);
782 Gtk::Button noquit_button (msg);
783 noquit_button.set_name ("EditorGTKButton");
788 if (session->snap_name() == session->name()) {
791 type = _("snapshot");
793 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?"),
794 type, session->snap_name());
796 prompt_label.set_text (prompt);
797 prompt_label.set_name (X_("PrompterLabel"));
798 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
800 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
802 dhbox.set_homogeneous (false);
803 dhbox.pack_start (*dimage, false, false, 5);
804 dhbox.pack_start (prompt_label, true, false, 5);
805 window.get_vbox()->pack_start (dhbox);
807 window.set_name (_("Prompter"));
808 window.set_position (Gtk::WIN_POS_MOUSE);
809 window.set_modal (true);
810 window.set_resizable (false);
817 save_the_session = 0;
819 window.set_keep_above (true);
822 ResponseType r = (ResponseType) window.run();
827 case RESPONSE_ACCEPT: // save and get out of here
829 case RESPONSE_APPLY: // get out of here
839 ARDOUR_UI::every_second ()
842 update_buffer_load ();
843 update_disk_space ();
848 ARDOUR_UI::every_point_one_seconds ()
850 update_speed_display ();
851 RapidScreenUpdate(); /* EMIT_SIGNAL */
856 ARDOUR_UI::every_point_zero_one_seconds ()
858 // august 2007: actual update frequency: 40Hz, not 100Hz
860 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
865 ARDOUR_UI::update_sample_rate (nframes_t ignored)
869 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
871 if (!engine->connected()) {
873 snprintf (buf, sizeof (buf), _("disconnected"));
877 nframes_t rate = engine->frame_rate();
879 if (fmod (rate, 1000.0) != 0.0) {
880 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
881 (float) rate/1000.0f,
882 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
884 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
886 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
890 sample_rate_label.set_text (buf);
894 ARDOUR_UI::update_cpu_load ()
897 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
898 cpu_load_label.set_text (buf);
902 ARDOUR_UI::update_buffer_load ()
907 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
908 session->playback_load(), session->capture_load());
909 buffer_load_label.set_text (buf);
911 buffer_load_label.set_text ("");
916 ARDOUR_UI::count_recenabled_streams (Route& route)
918 Track* track = dynamic_cast<Track*>(&route);
919 if (track && track->diskstream()->record_enabled()) {
920 rec_enabled_streams += track->n_inputs().n_total();
925 ARDOUR_UI::update_disk_space()
931 nframes_t frames = session->available_capture_duration();
934 if (frames == max_frames) {
935 strcpy (buf, _("Disk: 24hrs+"));
940 nframes_t fr = session->frame_rate();
942 rec_enabled_streams = 0;
943 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
945 if (rec_enabled_streams) {
946 frames /= rec_enabled_streams;
949 hrs = frames / (fr * 3600);
950 frames -= hrs * fr * 3600;
951 mins = frames / (fr * 60);
952 frames -= mins * fr * 60;
955 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
958 disk_space_label.set_text (buf);
962 ARDOUR_UI::update_wall_clock ()
969 tm_now = localtime (&now);
971 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
972 wall_clock_label.set_text (buf);
978 ARDOUR_UI::session_menu (GdkEventButton *ev)
980 session_popup_menu->popup (0, 0);
985 ARDOUR_UI::redisplay_recent_sessions ()
987 std::vector<sys::path> session_directories;
988 RecentSessionsSorter cmp;
990 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
991 recent_session_model->clear ();
993 ARDOUR::RecentSessions rs;
994 ARDOUR::read_recent_sessions (rs);
997 recent_session_display.set_model (recent_session_model);
1001 // sort them alphabetically
1002 sort (rs.begin(), rs.end(), cmp);
1004 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1005 session_directories.push_back ((*i).second);
1008 for (vector<sys::path>::const_iterator i = session_directories.begin();
1009 i != session_directories.end(); ++i)
1011 std::vector<sys::path> state_file_paths;
1013 // now get available states for this session
1015 get_state_files_in_directory (*i, state_file_paths);
1017 vector<string*>* states;
1018 vector<const gchar*> item;
1019 string fullpath = (*i).to_string();
1021 /* remove any trailing / */
1023 if (fullpath[fullpath.length()-1] == '/') {
1024 fullpath = fullpath.substr (0, fullpath.length()-1);
1027 /* check whether session still exists */
1028 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1029 /* session doesn't exist */
1030 cerr << "skipping non-existent session " << fullpath << endl;
1034 /* now get available states for this session */
1036 if ((states = Session::possible_states (fullpath)) == 0) {
1037 /* no state file? */
1041 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1043 Gtk::TreeModel::Row row = *(recent_session_model->append());
1045 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1046 row[recent_session_columns.fullpath] = fullpath;
1048 if (state_file_names.size() > 1) {
1052 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1053 i2 != state_file_names.end(); ++i2)
1056 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1058 child_row[recent_session_columns.visible_name] = *i2;
1059 child_row[recent_session_columns.fullpath] = fullpath;
1064 recent_session_display.set_model (recent_session_model);
1068 ARDOUR_UI::build_session_selector ()
1070 session_selector_window = new ArdourDialog ("session selector");
1072 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1074 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1075 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1076 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1077 recent_session_model = TreeStore::create (recent_session_columns);
1078 recent_session_display.set_model (recent_session_model);
1079 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1080 recent_session_display.set_headers_visible (false);
1081 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1082 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1084 scroller->add (recent_session_display);
1085 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1087 session_selector_window->set_name ("SessionSelectorWindow");
1088 session_selector_window->set_size_request (200, 400);
1089 session_selector_window->get_vbox()->pack_start (*scroller);
1091 recent_session_display.show();
1093 //session_selector_window->get_vbox()->show();
1097 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1099 session_selector_window->response (RESPONSE_ACCEPT);
1103 ARDOUR_UI::open_recent_session ()
1105 bool can_return = (session != 0);
1107 if (session_selector_window == 0) {
1108 build_session_selector ();
1111 redisplay_recent_sessions ();
1115 session_selector_window->set_position (WIN_POS_MOUSE);
1117 ResponseType r = (ResponseType) session_selector_window->run ();
1120 case RESPONSE_ACCEPT:
1124 session_selector_window->hide();
1131 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1135 session_selector_window->hide();
1137 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1139 if (i == recent_session_model->children().end()) {
1143 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1144 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1146 _session_is_new = false;
1148 if (load_session (path, state) == 0) {
1157 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1159 struct stat statbuf;
1161 if (stat (info.filename.c_str(), &statbuf) != 0) {
1165 if (!S_ISDIR(statbuf.st_mode)) {
1171 string session_file = info.filename;
1172 session_file += '/';
1173 session_file += Glib::path_get_basename (info.filename);
1174 session_file += ".ardour";
1176 if (stat (session_file.c_str(), &statbuf) != 0) {
1180 return S_ISREG (statbuf.st_mode);
1184 ARDOUR_UI::check_audioengine ()
1187 if (!engine->connected()) {
1188 MessageDialog msg (_("Ardour is not connected to JACK\n"
1189 "You cannot open or close sessions in this condition"));
1201 ARDOUR_UI::open_session ()
1203 if (!check_audioengine()) {
1208 /* popup selector window */
1210 if (open_session_selector == 0) {
1212 /* ardour sessions are folders */
1214 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1215 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1216 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1217 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1219 FileFilter session_filter;
1220 session_filter.add_pattern ("*.ardour");
1221 session_filter.set_name (_("Ardour sessions"));
1222 open_session_selector->add_filter (session_filter);
1223 open_session_selector->set_filter (session_filter);
1226 int response = open_session_selector->run();
1227 open_session_selector->hide ();
1230 case RESPONSE_ACCEPT:
1233 open_session_selector->hide();
1237 open_session_selector->hide();
1238 string session_path = open_session_selector->get_filename();
1242 if (session_path.length() > 0) {
1243 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1244 _session_is_new = isnew;
1245 load_session (path, name);
1252 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1254 list<boost::shared_ptr<MidiTrack> > tracks;
1257 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1264 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1266 if (tracks.size() != how_many) {
1267 if (how_many == 1) {
1268 error << _("could not create a new midi track") << endmsg;
1270 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1274 if ((route = session->new_midi_route ()) == 0) {
1275 error << _("could not create new midi bus") << endmsg;
1281 MessageDialog msg (*editor,
1282 _("There are insufficient JACK ports available\n\
1283 to create a new track or bus.\n\
1284 You should save Ardour, exit and\n\
1285 restart JACK with more ports."));
1292 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1294 list<boost::shared_ptr<AudioTrack> > tracks;
1295 Session::RouteList routes;
1298 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1304 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1306 if (tracks.size() != how_many) {
1307 if (how_many == 1) {
1308 error << _("could not create a new audio track") << endmsg;
1310 error << string_compose (_("could only create %1 of %2 new audio %3"),
1311 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1317 routes = session->new_audio_route (input_channels, output_channels, how_many);
1319 if (routes.size() != how_many) {
1320 if (how_many == 1) {
1321 error << _("could not create a new audio track") << endmsg;
1323 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1329 if (need_control_room_outs) {
1335 route->set_stereo_control_outs (control_lr_channels);
1336 route->control_outs()->set_stereo_pan (pans, this);
1338 #endif /* CONTROLOUTS */
1342 MessageDialog msg (*editor,
1343 _("There are insufficient JACK ports available\n\
1344 to create a new track or bus.\n\
1345 You should save Ardour, exit and\n\
1346 restart JACK with more ports."));
1353 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1355 nframes_t _preroll = 0;
1358 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1359 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1361 if (new_position > _preroll) {
1362 new_position -= _preroll;
1367 session->request_locate (new_position);
1372 ARDOUR_UI::transport_goto_start ()
1375 session->goto_start();
1378 /* force displayed area in editor to start no matter
1379 what "follow playhead" setting is.
1383 editor->reset_x_origin (session->current_start_frame());
1389 ARDOUR_UI::transport_goto_zero ()
1392 session->request_locate (0);
1395 /* force displayed area in editor to start no matter
1396 what "follow playhead" setting is.
1400 editor->reset_x_origin (0);
1406 ARDOUR_UI::transport_goto_end ()
1409 nframes_t frame = session->current_end_frame();
1410 session->request_locate (frame);
1412 /* force displayed area in editor to start no matter
1413 what "follow playhead" setting is.
1417 editor->reset_x_origin (frame);
1423 ARDOUR_UI::transport_stop ()
1429 if (session->is_auditioning()) {
1430 session->cancel_audition ();
1434 if (session->get_play_loop ()) {
1435 session->request_play_loop (false);
1438 session->request_stop ();
1442 ARDOUR_UI::transport_stop_and_forget_capture ()
1445 session->request_stop (true);
1450 ARDOUR_UI::remove_last_capture()
1453 editor->remove_last_capture();
1458 ARDOUR_UI::transport_record (bool roll)
1461 switch (session->record_status()) {
1462 case Session::Disabled:
1463 if (session->ntracks() == 0) {
1464 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1468 session->maybe_enable_record ();
1473 case Session::Recording:
1475 session->request_stop();
1477 session->disable_record (false, true);
1481 case Session::Enabled:
1482 session->disable_record (false, true);
1488 ARDOUR_UI::transport_roll ()
1496 rolling = session->transport_rolling ();
1498 if (session->get_play_loop()) {
1499 session->request_play_loop (false);
1500 auto_loop_button.set_visual_state (1);
1501 roll_button.set_visual_state (1);
1502 } else if (session->get_play_range ()) {
1503 session->request_play_range (false);
1504 play_selection_button.set_visual_state (0);
1505 } else if (rolling) {
1506 session->request_locate (session->last_transport_start(), true);
1509 session->request_transport_speed (1.0f);
1513 ARDOUR_UI::transport_loop()
1516 if (session->get_play_loop()) {
1517 if (session->transport_rolling()) {
1518 Location * looploc = session->locations()->auto_loop_location();
1520 session->request_locate (looploc->start(), true);
1525 session->request_play_loop (true);
1531 ARDOUR_UI::transport_play_selection ()
1537 if (!session->get_play_range()) {
1538 session->request_stop ();
1541 editor->play_selection ();
1545 ARDOUR_UI::transport_rewind (int option)
1547 float current_transport_speed;
1550 current_transport_speed = session->transport_speed();
1552 if (current_transport_speed >= 0.0f) {
1555 session->request_transport_speed (-1.0f);
1558 session->request_transport_speed (-4.0f);
1561 session->request_transport_speed (-0.5f);
1566 session->request_transport_speed (current_transport_speed * 1.5f);
1572 ARDOUR_UI::transport_forward (int option)
1574 float current_transport_speed;
1577 current_transport_speed = session->transport_speed();
1579 if (current_transport_speed <= 0.0f) {
1582 session->request_transport_speed (1.0f);
1585 session->request_transport_speed (4.0f);
1588 session->request_transport_speed (0.5f);
1593 session->request_transport_speed (current_transport_speed * 1.5f);
1599 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1605 boost::shared_ptr<Route> r;
1607 if ((r = session->route_by_remote_id (dstream)) != 0) {
1611 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1612 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1621 ARDOUR_UI::queue_transport_change ()
1623 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1627 ARDOUR_UI::map_transport_state ()
1629 float sp = session->transport_speed();
1632 transport_rolling ();
1633 } else if (sp < 0.0f) {
1634 transport_rewinding ();
1635 } else if (sp > 0.0f) {
1636 transport_forwarding ();
1638 transport_stopped ();
1643 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1645 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1646 (int) adj.get_value()].c_str());
1650 ARDOUR_UI::engine_stopped ()
1652 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1653 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1654 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1658 ARDOUR_UI::engine_running ()
1660 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1661 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1662 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1664 Glib::RefPtr<Action> action;
1665 const char* action_name = 0;
1667 switch (engine->frames_per_cycle()) {
1669 action_name = X_("JACKLatency32");
1672 action_name = X_("JACKLatency64");
1675 action_name = X_("JACKLatency128");
1678 action_name = X_("JACKLatency512");
1681 action_name = X_("JACKLatency1024");
1684 action_name = X_("JACKLatency2048");
1687 action_name = X_("JACKLatency4096");
1690 action_name = X_("JACKLatency8192");
1693 /* XXX can we do anything useful ? */
1699 action = ActionManager::get_action (X_("JACK"), action_name);
1702 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1703 ract->set_active ();
1709 ARDOUR_UI::engine_halted ()
1711 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1713 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1714 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1716 update_sample_rate (0);
1718 MessageDialog msg (*editor,
1720 JACK has either been shutdown or it\n\
1721 disconnected Ardour because Ardour\n\
1722 was not fast enough. You can save the\n\
1723 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"),
2075 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2077 existing_session = false;
2079 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2080 session_path = cmdline_path;
2081 existing_session = true;
2082 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2083 session_path = Glib::path_get_dirname (string (cmdline_path));
2084 existing_session = true;
2086 /* it doesn't exist, assume the best */
2087 session_path = Glib::path_get_dirname (string (cmdline_path));
2090 session_name = basename_nosuffix (string (cmdline_path));
2094 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2096 /* when this is called, the backend audio system must be running */
2098 /* the main idea here is to deal with the fact that a cmdline argument for the session
2099 can be interpreted in different ways - it could be a directory or a file, and before
2100 we load, we need to know both the session directory and the snapshot (statefile) within it
2101 that we are supposed to use.
2104 if (session_name.length() == 0 || session_path.length() == 0) {
2108 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2110 Glib::ustring predicted_session_file;
2112 predicted_session_file = session_path;
2113 predicted_session_file += '/';
2114 predicted_session_file += session_name;
2115 predicted_session_file += ARDOUR::statefile_suffix;
2117 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2118 existing_session = true;
2121 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2123 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2124 /* existing .ardour file */
2125 existing_session = true;
2129 existing_session = false;
2132 /* lets just try to load it */
2134 if (create_engine ()) {
2135 backend_audio_error (false, new_session_dialog);
2139 return load_session (session_path, session_name);
2143 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2145 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2147 MessageDialog msg (str,
2149 Gtk::MESSAGE_WARNING,
2150 Gtk::BUTTONS_YES_NO,
2154 msg.set_name (X_("CleanupDialog"));
2155 msg.set_wmclass (X_("existing_session"), "Ardour");
2156 msg.set_position (Gtk::WIN_POS_MOUSE);
2159 switch (msg.run()) {
2168 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2173 AutoConnectOption iconnect;
2174 AutoConnectOption oconnect;
2178 if (Profile->get_sae()) {
2182 iconnect = AutoConnectPhysical;
2183 oconnect = AutoConnectMaster;
2184 nphysin = 0; // use all available
2185 nphysout = 0; // use all available
2189 /* get settings from advanced section of NSD */
2191 if (new_session_dialog->create_control_bus()) {
2192 cchns = (uint32_t) new_session_dialog->control_channel_count();
2197 if (new_session_dialog->create_master_bus()) {
2198 mchns = (uint32_t) new_session_dialog->master_channel_count();
2203 if (new_session_dialog->connect_inputs()) {
2204 iconnect = AutoConnectPhysical;
2206 iconnect = AutoConnectOption (0);
2209 /// @todo some minor tweaks.
2211 if (new_session_dialog->connect_outs_to_master()) {
2212 oconnect = AutoConnectMaster;
2213 } else if (new_session_dialog->connect_outs_to_physical()) {
2214 oconnect = AutoConnectPhysical;
2216 oconnect = AutoConnectOption (0);
2219 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2220 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2223 if (build_session (session_path,
2231 engine->frame_rate() * 60 * 5)) {
2240 ARDOUR_UI::end_loading_messages ()
2246 ARDOUR_UI::loading_message (const std::string& msg)
2248 cerr << "say: " << msg << endl;
2250 splash->message (msg);
2255 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2257 bool existing_session = false;
2258 Glib::ustring session_name;
2259 Glib::ustring session_path;
2260 Glib::ustring template_name;
2262 int response = Gtk::RESPONSE_NONE;
2264 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2266 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2268 /* don't ever reuse this */
2270 ARDOUR_COMMAND_LINE::session_name = string();
2272 if (existing_session && backend_audio_is_running) {
2274 /* just load the thing already */
2276 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2281 /* make the NSD use whatever information we have */
2283 new_session_dialog->set_session_name (session_name);
2284 new_session_dialog->set_session_folder (session_path);
2287 /* loading failed, or we need the NSD for something */
2289 new_session_dialog->set_modal (false);
2290 new_session_dialog->set_position (WIN_POS_CENTER);
2291 new_session_dialog->set_current_page (0);
2292 new_session_dialog->set_existing_session (existing_session);
2293 new_session_dialog->reset_recent();
2296 new_session_dialog->set_have_engine (backend_audio_is_running);
2297 new_session_dialog->present ();
2298 end_loading_messages ();
2299 response = new_session_dialog->run ();
2301 _session_is_new = false;
2303 /* handle possible negative responses */
2306 case Gtk::RESPONSE_CANCEL:
2307 case Gtk::RESPONSE_DELETE_EVENT:
2311 new_session_dialog->hide ();
2314 case Gtk::RESPONSE_NONE:
2315 /* "Clear" was pressed */
2319 fontconfig_dialog();
2321 if (!backend_audio_is_running) {
2322 if (new_session_dialog->engine_control.setup_engine ()) {
2323 new_session_dialog->hide ();
2328 if (create_engine ()) {
2330 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2333 new_session_dialog->set_existing_session (false);
2334 new_session_dialog->set_current_page (2);
2336 response = Gtk::RESPONSE_NONE;
2340 backend_audio_is_running = true;
2342 if (response == Gtk::RESPONSE_OK) {
2344 session_name = new_session_dialog->session_name();
2346 if (session_name.empty()) {
2347 response = Gtk::RESPONSE_NONE;
2351 /* if the user mistakenly typed path information into the session filename entry,
2352 convert what they typed into a path & a name
2355 if (session_name[0] == '/' ||
2356 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2357 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2359 session_path = Glib::path_get_dirname (session_name);
2360 session_name = Glib::path_get_basename (session_name);
2364 session_path = new_session_dialog->session_folder();
2367 template_name = Glib::ustring();
2368 switch (new_session_dialog->which_page()) {
2370 case NewSessionDialog::OpenPage:
2371 case NewSessionDialog::EnginePage:
2375 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2377 should_be_new = true;
2379 //XXX This is needed because session constructor wants a
2380 //non-existant path. hopefully this will be fixed at some point.
2382 session_path = Glib::build_filename (session_path, session_name);
2384 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2386 if (ask_about_loading_existing_session (session_path)) {
2389 response = RESPONSE_NONE;
2394 _session_is_new = true;
2396 if (new_session_dialog->use_session_template()) {
2398 template_name = new_session_dialog->session_template_name();
2402 if (build_session_from_nsd (session_path, session_name)) {
2403 response = RESPONSE_NONE;
2415 new_session_dialog->hide ();
2417 if (load_session (session_path, session_name, template_name)) {
2419 response = Gtk::RESPONSE_NONE;
2423 if (response == Gtk::RESPONSE_NONE) {
2424 new_session_dialog->set_existing_session (false);
2425 new_session_dialog->reset ();
2429 } while (response == Gtk::RESPONSE_NONE);
2433 new_session_dialog->hide();
2434 new_session_dialog->reset();
2435 goto_editor_window ();
2440 ARDOUR_UI::close_session()
2442 if (!check_audioengine()) {
2446 unload_session (true);
2448 get_session_parameters (true, false);
2452 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2454 Session *new_session;
2458 session_loaded = false;
2460 if (!check_audioengine()) {
2464 unload_status = unload_session ();
2466 if (unload_status < 0) {
2468 } else if (unload_status > 0) {
2473 /* if it already exists, we must have write access */
2475 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2476 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2477 "This prevents the session from being loaded."));
2483 loading_message (_("Please wait while Ardour loads your session"));
2484 disable_screen_updates ();
2487 new_session = new Session (*engine, path, snap_name, mix_template);
2490 /* this one is special */
2492 catch (AudioEngine::PortRegistrationFailure& err) {
2494 MessageDialog msg (err.what(),
2497 Gtk::BUTTONS_OK_CANCEL);
2499 msg.set_title (_("Loading Error"));
2500 msg.set_secondary_text (_("Click the OK button to try again."));
2501 msg.set_position (Gtk::WIN_POS_CENTER);
2505 int response = msg.run ();
2510 case RESPONSE_CANCEL:
2520 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2523 Gtk::BUTTONS_OK_CANCEL);
2525 msg.set_title (_("Loading Error"));
2526 msg.set_secondary_text (_("Click the OK button to try again."));
2527 msg.set_position (Gtk::WIN_POS_CENTER);
2531 int response = msg.run ();
2536 case RESPONSE_CANCEL:
2544 connect_to_session (new_session);
2546 Config->set_current_owner (ConfigVariableBase::Interface);
2548 session_loaded = true;
2550 goto_editor_window ();
2553 session->set_clean ();
2556 enable_screen_updates ();
2565 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2566 uint32_t control_channels,
2567 uint32_t master_channels,
2568 AutoConnectOption input_connect,
2569 AutoConnectOption output_connect,
2572 nframes_t initial_length)
2574 Session *new_session;
2577 if (!check_audioengine()) {
2581 session_loaded = false;
2583 x = unload_session ();
2591 _session_is_new = true;
2594 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2595 control_channels, master_channels, nphysin, nphysout, initial_length);
2600 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2606 connect_to_session (new_session);
2608 session_loaded = true;
2616 editor->show_window ();
2627 ARDOUR_UI::show_about ()
2631 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2638 ARDOUR_UI::hide_about ()
2641 about->get_window()->set_cursor ();
2647 ARDOUR_UI::about_signal_response(int response)
2653 ARDOUR_UI::show_splash ()
2657 splash = new Splash;
2665 splash->queue_draw ();
2666 splash->get_window()->process_updates (true);
2671 ARDOUR_UI::hide_splash ()
2679 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2683 removed = rep.paths.size();
2686 MessageDialog msgd (*editor,
2687 _("No audio files were ready for cleanup"),
2690 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2691 msgd.set_secondary_text (_("If this seems suprising, \n\
2692 check for any existing snapshots.\n\
2693 These may still include regions that\n\
2694 require some unused files to continue to exist."));
2700 ArdourDialog results (_("ardour: cleanup"), true, false);
2702 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2703 CleanupResultsModelColumns() {
2707 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2708 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2712 CleanupResultsModelColumns results_columns;
2713 Glib::RefPtr<Gtk::ListStore> results_model;
2714 Gtk::TreeView results_display;
2716 results_model = ListStore::create (results_columns);
2717 results_display.set_model (results_model);
2718 results_display.append_column (list_title, results_columns.visible_name);
2720 results_display.set_name ("CleanupResultsList");
2721 results_display.set_headers_visible (true);
2722 results_display.set_headers_clickable (false);
2723 results_display.set_reorderable (false);
2725 Gtk::ScrolledWindow list_scroller;
2728 Gtk::HBox dhbox; // the hbox for the image and text
2729 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2730 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2732 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2734 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2736 if (rep.space < 1048576.0f) {
2738 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2740 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2744 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2746 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2750 dhbox.pack_start (*dimage, true, false, 5);
2751 dhbox.pack_start (txt, true, false, 5);
2753 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2754 TreeModel::Row row = *(results_model->append());
2755 row[results_columns.visible_name] = *i;
2756 row[results_columns.fullpath] = *i;
2759 list_scroller.add (results_display);
2760 list_scroller.set_size_request (-1, 150);
2761 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2763 dvbox.pack_start (dhbox, true, false, 5);
2764 dvbox.pack_start (list_scroller, true, false, 5);
2765 ddhbox.pack_start (dvbox, true, false, 5);
2767 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2768 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2769 results.set_default_response (RESPONSE_CLOSE);
2770 results.set_position (Gtk::WIN_POS_MOUSE);
2772 results_display.show();
2773 list_scroller.show();
2780 //results.get_vbox()->show();
2781 results.set_resizable (false);
2788 ARDOUR_UI::cleanup ()
2791 /* shouldn't happen: menu item is insensitive */
2796 MessageDialog checker (_("Are you sure you want to cleanup?"),
2798 Gtk::MESSAGE_QUESTION,
2799 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2801 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2802 ALL undo/redo information will be lost if you cleanup.\n\
2803 After cleanup, unused audio files will be moved to a \
2804 \"dead sounds\" location."));
2806 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2807 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2808 checker.set_default_response (RESPONSE_CANCEL);
2810 checker.set_name (_("CleanupDialog"));
2811 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2812 checker.set_position (Gtk::WIN_POS_MOUSE);
2814 switch (checker.run()) {
2815 case RESPONSE_ACCEPT:
2821 Session::cleanup_report rep;
2823 editor->prepare_for_cleanup ();
2825 /* do not allow flush until a session is reloaded */
2827 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2829 act->set_sensitive (false);
2832 if (session->cleanup_sources (rep)) {
2837 display_cleanup_results (rep,
2840 The following %1 %2 not in use and \n\
2841 have been moved to:\n\
2843 Flushing the wastebasket will \n\
2844 release an additional\n\
2845 %4 %5bytes of disk space.\n"
2853 ARDOUR_UI::flush_trash ()
2856 /* shouldn't happen: menu item is insensitive */
2860 Session::cleanup_report rep;
2862 if (session->cleanup_trash_sources (rep)) {
2866 display_cleanup_results (rep,
2868 _("The following %1 %2 deleted from\n\
2870 releasing %4 %5bytes of disk space"));
2874 ARDOUR_UI::add_route (Gtk::Window* float_window)
2882 if (add_route_dialog == 0) {
2883 add_route_dialog = new AddRouteDialog;
2885 add_route_dialog->set_transient_for (*float_window);
2889 if (add_route_dialog->is_visible()) {
2890 /* we're already doing this */
2894 ResponseType r = (ResponseType) add_route_dialog->run ();
2896 add_route_dialog->hide();
2899 case RESPONSE_ACCEPT:
2906 if ((count = add_route_dialog->count()) <= 0) {
2910 uint32_t input_chan = add_route_dialog->channels ();
2911 uint32_t output_chan;
2912 string name_template = add_route_dialog->name_template ();
2913 bool track = add_route_dialog->track ();
2915 AutoConnectOption oac = Config->get_output_auto_connect();
2917 if (oac & AutoConnectMaster) {
2918 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2920 output_chan = input_chan;
2923 /* XXX do something with name template */
2925 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2927 session_add_midi_track(count);
2929 MessageDialog msg (*editor,
2930 _("Sorry, MIDI Busses are not supported at this time."));
2932 //session_add_midi_bus();
2936 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2938 session_add_audio_bus (input_chan, output_chan, count);
2944 ARDOUR_UI::mixer_settings () const
2949 node = session->instant_xml(X_("Mixer"));
2951 node = Config->instant_xml(X_("Mixer"));
2955 node = new XMLNode (X_("Mixer"));
2962 ARDOUR_UI::editor_settings () const
2967 node = session->instant_xml(X_("Editor"));
2969 node = Config->instant_xml(X_("Editor"));
2973 node = new XMLNode (X_("Editor"));
2979 ARDOUR_UI::keyboard_settings () const
2983 node = Config->extra_xml(X_("Keyboard"));
2986 node = new XMLNode (X_("Keyboard"));
2992 ARDOUR_UI::halt_on_xrun_message ()
2994 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2996 MessageDialog msg (*editor,
2997 _("Recording was stopped because your system could not keep up."));
3002 ARDOUR_UI::disk_overrun_handler ()
3004 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3006 if (!have_disk_speed_dialog_displayed) {
3007 have_disk_speed_dialog_displayed = true;
3008 MessageDialog* msg = new MessageDialog (*editor, _("\
3009 The disk system on your computer\n\
3010 was not able to keep up with Ardour.\n\
3012 Specifically, it failed to write data to disk\n\
3013 quickly enough to keep up with recording.\n"));
3014 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3020 ARDOUR_UI::disk_underrun_handler ()
3022 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3024 if (!have_disk_speed_dialog_displayed) {
3025 have_disk_speed_dialog_displayed = true;
3026 MessageDialog* msg = new MessageDialog (*editor,
3027 _("The disk system on your computer\n\
3028 was not able to keep up with Ardour.\n\
3030 Specifically, it failed to read data from disk\n\
3031 quickly enough to keep up with playback.\n"));
3032 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3038 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3040 have_disk_speed_dialog_displayed = false;
3045 ARDOUR_UI::pending_state_dialog ()
3047 HBox* hbox = new HBox();
3048 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3049 ArdourDialog dialog (_("Crash Recovery"), true);
3051 This session appears to have been in\n\
3052 middle of recording when ardour or\n\
3053 the computer was shutdown.\n\
3055 Ardour can recover any captured audio for\n\
3056 you, or it can ignore it. Please decide\n\
3057 what you would like to do.\n"));
3058 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3059 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3060 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3061 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3062 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3063 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3064 dialog.set_default_response (RESPONSE_ACCEPT);
3065 dialog.set_position (WIN_POS_CENTER);
3070 switch (dialog.run ()) {
3071 case RESPONSE_ACCEPT:
3079 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3081 HBox* hbox = new HBox();
3082 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3083 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3084 Label message (string_compose (_("\
3085 This session was created with a sample rate of %1 Hz\n\
3087 The audioengine is currently running at %2 Hz\n"), desired, actual));
3089 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3090 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3091 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3092 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3093 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3094 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3095 dialog.set_default_response (RESPONSE_ACCEPT);
3096 dialog.set_position (WIN_POS_CENTER);
3101 switch (dialog.run ()) {
3102 case RESPONSE_ACCEPT:
3111 ARDOUR_UI::disconnect_from_jack ()
3114 if( engine->disconnect_from_jack ()) {
3115 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3119 update_sample_rate (0);
3124 ARDOUR_UI::reconnect_to_jack ()
3127 if (engine->reconnect_to_jack ()) {
3128 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3132 update_sample_rate (0);
3137 ARDOUR_UI::use_config ()
3139 Glib::RefPtr<Action> act;
3141 switch (Config->get_native_file_data_format ()) {
3143 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3146 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3149 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3154 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3155 ract->set_active ();
3158 switch (Config->get_native_file_header_format ()) {
3160 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3163 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3166 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3169 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3172 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3175 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3178 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3183 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3184 ract->set_active ();
3187 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3189 set_transport_controllable_state (*node);
3194 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3196 if (Config->get_primary_clock_delta_edit_cursor()) {
3197 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3199 primary_clock.set (pos, 0, true);
3202 if (Config->get_secondary_clock_delta_edit_cursor()) {
3203 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3205 secondary_clock.set (pos);
3208 if (big_clock_window) {
3209 big_clock.set (pos);
3214 ARDOUR_UI::record_state_changed ()
3216 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3218 if (!session || !big_clock_window) {
3219 /* why bother - the clock isn't visible */
3223 switch (session->record_status()) {
3224 case Session::Recording:
3225 big_clock.set_widget_name ("BigClockRecording");
3228 big_clock.set_widget_name ("BigClockNonRecording");
3234 ARDOUR_UI::set_keybindings_path (string path)
3236 keybindings_path = path;
3240 ARDOUR_UI::save_keybindings ()
3242 if (can_save_keybindings) {
3243 AccelMap::save (user_keybindings_path);
3248 ARDOUR_UI::first_idle ()
3251 session->allow_auto_play (true);
3253 can_save_keybindings = true;
3258 ARDOUR_UI::store_clock_modes ()
3260 XMLNode* node = new XMLNode(X_("ClockModes"));
3262 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3263 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3266 session->add_extra_xml (*node);
3267 session->set_dirty ();
3272 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3273 : Controllable (name), ui (u), type(tp)
3279 ARDOUR_UI::TransportControllable::set_value (float val)
3281 if (type == ShuttleControl) {
3288 fract = -((0.5f - val)/0.5f);
3290 fract = ((val - 0.5f)/0.5f);
3294 ui.set_shuttle_fract (fract);
3299 /* do nothing: these are radio-style actions */
3303 const char *action = 0;
3307 action = X_("Roll");
3310 action = X_("Stop");
3313 action = X_("Goto Start");
3316 action = X_("Goto End");
3319 action = X_("Loop");
3322 action = X_("Play Selection");
3325 action = X_("Record");
3335 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3343 ARDOUR_UI::TransportControllable::get_value (void) const
3362 case ShuttleControl:
3372 ARDOUR_UI::TransportControllable::set_id (const string& str)
3378 ARDOUR_UI::setup_profile ()
3380 if (gdk_screen_width() < 1200) {
3381 Profile->set_small_screen ();
3385 if (getenv ("ARDOUR_SAE")) {
3386 Profile->set_sae ();
3387 Profile->set_single_package ();