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.
31 #include <sys/resource.h>
33 #include <gtkmm/messagedialog.h>
34 #include <gtkmm/accelmap.h>
36 #include <pbd/error.h>
37 #include <pbd/basename.h>
38 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/audiofilesource.h>
63 #include <ardour/recent_sessions.h>
64 #include <ardour/port.h>
65 #include <ardour/audio_track.h>
67 typedef uint64_t microseconds_t;
70 #include "ardour_ui.h"
71 #include "public_editor.h"
72 #include "audio_clock.h"
77 #include "add_route_dialog.h"
78 #include "new_session_dialog.h"
82 #include "gui_thread.h"
83 #include "theme_manager.h"
84 #include "engine_dialog.h"
85 #include "gain_meter.h"
86 #include "route_time_axis.h"
90 using namespace ARDOUR;
92 using namespace Gtkmm2ext;
96 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
97 UIConfiguration *ARDOUR_UI::ui_config = 0;
99 sigc::signal<void,bool> ARDOUR_UI::Blink;
100 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
101 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
102 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
104 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
106 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
108 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
109 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
110 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
111 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
115 preroll_button (_("pre\nroll")),
116 postroll_button (_("post\nroll")),
120 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
124 roll_controllable ("transport roll", *this, TransportControllable::Roll),
125 stop_controllable ("transport stop", *this, TransportControllable::Stop),
126 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
127 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
128 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
129 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
130 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
131 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
132 shuttle_controller_binding_proxy (shuttle_controllable),
134 roll_button (&roll_controllable),
135 stop_button (&stop_controllable),
136 goto_start_button (&goto_start_controllable),
137 goto_end_button (&goto_end_controllable),
138 auto_loop_button (&auto_loop_controllable),
139 play_selection_button (&play_selection_controllable),
140 rec_button (&rec_controllable),
142 shuttle_units_button (_("% ")),
144 punch_in_button (_("Punch In")),
145 punch_out_button (_("Punch Out")),
146 auto_return_button (_("Auto Return")),
147 auto_play_button (_("Auto Play")),
148 auto_input_button (_("Auto Input")),
149 click_button (_("Click")),
150 time_master_button (_("time\nmaster")),
152 auditioning_alert_button (_("AUDITION")),
153 solo_alert_button (_("SOLO")),
155 error_log_button (_("Errors"))
157 using namespace Gtk::Menu_Helpers;
162 _auto_display_errors = false;
168 if (ARDOUR_COMMAND_LINE::session_name.length()) {
169 /* only show this if we're not going to post the new session dialog */
173 if (theArdourUI == 0) {
177 ui_config = new UIConfiguration();
178 theme_manager = new ThemeManager();
184 _session_is_new = false;
185 big_clock_window = 0;
186 session_selector_window = 0;
187 new_session_dialog = 0;
188 last_key_press_time = 0;
189 connection_editor = 0;
190 add_route_dialog = 0;
195 open_session_selector = 0;
196 have_configure_timeout = false;
197 have_disk_speed_dialog_displayed = false;
198 _will_create_new_session_automatically = false;
199 session_loaded = false;
200 last_speed_displayed = -1.0f;
201 ignore_dual_punch = false;
202 _mixer_on_top = false;
204 roll_button.unset_flags (Gtk::CAN_FOCUS);
205 stop_button.unset_flags (Gtk::CAN_FOCUS);
206 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
207 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
208 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
209 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
210 rec_button.unset_flags (Gtk::CAN_FOCUS);
212 last_configure_time= 0;
214 shuttle_grabbed = false;
216 shuttle_max_speed = 8.0f;
218 shuttle_style_menu = 0;
219 shuttle_unit_menu = 0;
221 // We do not have jack linked in yet so;
223 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
225 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
226 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
228 /* handle dialog requests */
230 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
232 /* handle pending state with a dialog */
234 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
236 /* handle sr mismatch with a dialog */
238 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
240 /* lets get this party started */
243 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
244 throw failed_constructor ();
247 setup_gtk_ardour_enums ();
248 Config->set_current_owner (ConfigVariableBase::Interface);
251 GainMeter::setup_slider_pix ();
252 RouteTimeAxisView::setup_slider_pix ();
254 } catch (failed_constructor& err) {
255 error << _("could not initialize Ardour.") << endmsg;
260 /* we like keyboards */
262 keyboard = new Keyboard;
266 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
267 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
273 ARDOUR_UI::create_engine ()
275 // this gets called every time by new_session()
281 loading_message (_("Starting audio engine"));
284 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
291 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
292 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
293 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
294 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
302 ARDOUR_UI::post_engine ()
304 /* Things to be done once we create the AudioEngine
307 check_memory_locking();
309 ActionManager::init ();
312 if (setup_windows ()) {
313 throw failed_constructor ();
316 /* this is the first point at which all the keybindings are available */
318 if (ARDOUR_COMMAND_LINE::show_key_actions) {
319 vector<string> names;
320 vector<string> paths;
322 vector<AccelKey> bindings;
324 ActionManager::get_all_actions (names, paths, keys, bindings);
326 vector<string>::iterator n;
327 vector<string>::iterator k;
328 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
329 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
335 blink_timeout_tag = -1;
337 /* the global configuration object is now valid */
341 /* this being a GUI and all, we want peakfiles */
343 AudioFileSource::set_build_peakfiles (true);
344 AudioFileSource::set_build_missing_peakfiles (true);
346 /* set default clock modes */
348 if (Profile->get_sae()) {
349 primary_clock.set_mode (AudioClock::BBT);
350 secondary_clock.set_mode (AudioClock::MinSec);
352 primary_clock.set_mode (AudioClock::SMPTE);
353 secondary_clock.set_mode (AudioClock::BBT);
356 /* start the time-of-day-clock */
359 /* OS X provides an always visible wallclock, so don't be stupid */
360 update_wall_clock ();
361 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
364 update_disk_space ();
366 update_sample_rate (engine->frame_rate());
368 platform_specific ();
370 /* now start and maybe save state */
372 if (do_engine_start () == 0) {
373 if (session && _session_is_new) {
374 /* we need to retain initial visual
375 settings for a new session
377 session->save_state ("");
382 ARDOUR_UI::~ARDOUR_UI ()
384 save_ardour_state ();
398 if (add_route_dialog) {
399 delete add_route_dialog;
402 if (new_session_dialog) {
403 delete new_session_dialog;
408 ARDOUR_UI::pop_back_splash ()
410 if (Splash::instance()) {
411 // Splash::instance()->pop_back();
412 Splash::instance()->hide ();
417 ARDOUR_UI::configure_timeout ()
419 if (last_configure_time == 0) {
420 /* no configure events yet */
424 /* force a gap of 0.5 seconds since the last configure event
427 if (get_microseconds() - last_configure_time < 500000) {
430 have_configure_timeout = false;
431 save_ardour_state ();
437 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
439 if (have_configure_timeout) {
440 last_configure_time = get_microseconds();
442 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
443 have_configure_timeout = true;
450 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
452 const XMLProperty* prop;
454 if ((prop = node.property ("roll")) != 0) {
455 roll_controllable.set_id (prop->value());
457 if ((prop = node.property ("stop")) != 0) {
458 stop_controllable.set_id (prop->value());
460 if ((prop = node.property ("goto_start")) != 0) {
461 goto_start_controllable.set_id (prop->value());
463 if ((prop = node.property ("goto_end")) != 0) {
464 goto_end_controllable.set_id (prop->value());
466 if ((prop = node.property ("auto_loop")) != 0) {
467 auto_loop_controllable.set_id (prop->value());
469 if ((prop = node.property ("play_selection")) != 0) {
470 play_selection_controllable.set_id (prop->value());
472 if ((prop = node.property ("rec")) != 0) {
473 rec_controllable.set_id (prop->value());
475 if ((prop = node.property ("shuttle")) != 0) {
476 shuttle_controllable.set_id (prop->value());
481 ARDOUR_UI::get_transport_controllable_state ()
483 XMLNode* node = new XMLNode(X_("TransportControllables"));
486 roll_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("roll"), buf);
488 stop_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("stop"), buf);
490 goto_start_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("goto_start"), buf);
492 goto_end_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("goto_end"), buf);
494 auto_loop_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("auto_loop"), buf);
496 play_selection_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("play_selection"), buf);
498 rec_controllable.id().print (buf, sizeof (buf));
499 node->add_property (X_("rec"), buf);
500 shuttle_controllable.id().print (buf, sizeof (buf));
501 node->add_property (X_("shuttle"), buf);
507 ARDOUR_UI::save_ardour_state ()
509 if (!keyboard || !mixer || !editor) {
513 /* XXX this is all a bit dubious. add_extra_xml() uses
514 a different lifetime model from add_instant_xml().
517 XMLNode* node = new XMLNode (keyboard->get_state());
518 Config->add_extra_xml (*node);
519 Config->add_extra_xml (get_transport_controllable_state());
520 if (new_session_dialog) {
521 if (new_session_dialog->engine_control.was_used()) {
522 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
525 Config->save_state();
526 ui_config->save_state ();
528 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
529 XMLNode mnode(mixer->get_state());
532 session->add_instant_xml (enode, session->path());
533 session->add_instant_xml (mnode, session->path());
535 Config->add_instant_xml (enode, get_user_ardour_path());
536 Config->add_instant_xml (mnode, get_user_ardour_path());
539 Keyboard::save_keybindings ();
543 ARDOUR_UI::autosave_session ()
545 if (g_main_depth() > 1) {
546 /* inside a recursive main loop,
547 give up because we may not be able to
553 if (!Config->get_periodic_safety_backups())
557 session->maybe_write_autosave();
564 ARDOUR_UI::update_autosave ()
566 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
568 if (session->dirty()) {
569 if (_autosave_connection.connected()) {
570 _autosave_connection.disconnect();
573 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
574 Config->get_periodic_safety_backup_interval() * 1000);
577 if (_autosave_connection.connected()) {
578 _autosave_connection.disconnect();
584 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
588 title = _("Ardour could not start JACK");
590 title = _("Ardour could not connect to JACK.");
593 MessageDialog win (title,
599 win.set_secondary_text(_("There are several possible reasons:\n\
601 1) You requested audio parameters that are not supported..\n\
602 2) JACK is running as another user.\n\
604 Please consider the possibilities, and perhaps try different parameters."));
606 win.set_secondary_text(_("There are several possible reasons:\n\
608 1) JACK is not running.\n\
609 2) JACK is running as another user, perhaps root.\n\
610 3) There is already another client called \"ardour\".\n\
612 Please consider the possibilities, and perhaps (re)start JACK."));
616 win.set_transient_for (*toplevel);
620 win.add_button (Stock::OK, RESPONSE_CLOSE);
622 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
625 win.set_default_response (RESPONSE_CLOSE);
628 win.set_position (Gtk::WIN_POS_CENTER);
631 /* we just don't care about the result, but we want to block */
637 ARDOUR_UI::startup ()
641 new_session_dialog = new NewSessionDialog();
643 bool backend_audio_is_running = EngineControl::engine_running();
644 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
647 new_session_dialog->engine_control.set_state (*audio_setup);
650 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
654 BootMessage (_("Ardour is ready for use"));
659 ARDOUR_UI::no_memory_warning ()
661 XMLNode node (X_("no-memory-warning"));
662 Config->add_instant_xml (node, get_user_ardour_path());
666 ARDOUR_UI::check_memory_locking ()
669 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
673 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
675 if (engine->is_realtime() && memory_warning_node == 0) {
677 struct rlimit limits;
679 long pages, page_size;
681 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
684 ram = (int64_t) pages * (int64_t) page_size;
687 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
691 if (limits.rlim_cur != RLIM_INFINITY) {
693 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
696 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
697 "This might cause Ardour to run out of memory before your system "
698 "runs out of memory. \n\n"
699 "You can view the memory limit with 'ulimit -l', "
700 "and it is normally controlled by /etc/security/limits.conf"));
702 VBox* vbox = msg.get_vbox();
704 CheckButton cb (_("Do not show this window again"));
706 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
708 hbox.pack_start (cb, true, false);
709 vbox->pack_start (hbox);
727 if (session->transport_rolling()) {
728 session->request_stop ();
732 if (session->dirty()) {
733 switch (ask_about_saving_session(_("quit"))) {
738 /* use the default name */
739 if (save_state_canfail ("")) {
740 /* failed - don't quit */
741 MessageDialog msg (*editor,
743 Ardour was unable to save your session.\n\n\
744 If you still wish to quit, please use the\n\n\
745 \"Just quit\" option."));
756 session->set_deletion_in_progress ();
759 ArdourDialog::close_all_dialogs ();
761 save_ardour_state ();
766 ARDOUR_UI::ask_about_saving_session (const string & what)
768 ArdourDialog window (_("ardour: save session?"));
769 Gtk::HBox dhbox; // the hbox for the image and text
770 Gtk::Label prompt_label;
771 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
775 msg = string_compose(_("Don't %1"), what);
776 window.add_button (msg, RESPONSE_REJECT);
777 msg = string_compose(_("Just %1"), what);
778 window.add_button (msg, RESPONSE_APPLY);
779 msg = string_compose(_("Save and %1"), what);
780 window.add_button (msg, RESPONSE_ACCEPT);
782 window.set_default_response (RESPONSE_ACCEPT);
784 Gtk::Button noquit_button (msg);
785 noquit_button.set_name ("EditorGTKButton");
790 if (session->snap_name() == session->name()) {
793 type = _("snapshot");
795 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?"),
796 type, session->snap_name());
798 prompt_label.set_text (prompt);
799 prompt_label.set_name (X_("PrompterLabel"));
800 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
802 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
804 dhbox.set_homogeneous (false);
805 dhbox.pack_start (*dimage, false, false, 5);
806 dhbox.pack_start (prompt_label, true, false, 5);
807 window.get_vbox()->pack_start (dhbox);
809 window.set_name (_("Prompter"));
810 window.set_position (Gtk::WIN_POS_MOUSE);
811 window.set_modal (true);
812 window.set_resizable (false);
815 window.set_keep_above (true);
818 ResponseType r = (ResponseType) window.run();
823 case RESPONSE_ACCEPT: // save and get out of here
825 case RESPONSE_APPLY: // get out of here
835 ARDOUR_UI::every_second ()
838 update_buffer_load ();
839 update_disk_space ();
844 ARDOUR_UI::every_point_one_seconds ()
846 update_speed_display ();
847 RapidScreenUpdate(); /* EMIT_SIGNAL */
852 ARDOUR_UI::every_point_zero_one_seconds ()
854 // august 2007: actual update frequency: 40Hz, not 100Hz
856 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
861 ARDOUR_UI::update_sample_rate (nframes_t ignored)
865 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
867 if (!engine->connected()) {
869 snprintf (buf, sizeof (buf), _("disconnected"));
873 nframes_t rate = engine->frame_rate();
875 if (fmod (rate, 1000.0) != 0.0) {
876 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
877 (float) rate/1000.0f,
878 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
880 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
882 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
886 sample_rate_label.set_text (buf);
890 ARDOUR_UI::update_cpu_load ()
893 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
894 cpu_load_label.set_text (buf);
898 ARDOUR_UI::update_buffer_load ()
903 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
904 session->playback_load(), session->capture_load());
905 buffer_load_label.set_text (buf);
907 buffer_load_label.set_text ("");
912 ARDOUR_UI::count_recenabled_streams (Route& route)
914 Track* track = dynamic_cast<Track*>(&route);
915 if (track && track->diskstream()->record_enabled()) {
916 rec_enabled_streams += track->n_inputs();
921 ARDOUR_UI::update_disk_space()
927 nframes_t frames = session->available_capture_duration();
930 if (frames == max_frames) {
931 strcpy (buf, _("Disk: 24hrs+"));
936 nframes_t fr = session->frame_rate();
938 rec_enabled_streams = 0;
939 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
941 if (rec_enabled_streams) {
942 frames /= rec_enabled_streams;
945 hrs = frames / (fr * 3600);
946 frames -= hrs * fr * 3600;
947 mins = frames / (fr * 60);
948 frames -= mins * fr * 60;
951 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
954 disk_space_label.set_text (buf);
958 ARDOUR_UI::update_wall_clock ()
965 tm_now = localtime (&now);
967 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
968 wall_clock_label.set_text (buf);
974 ARDOUR_UI::session_menu (GdkEventButton *ev)
976 session_popup_menu->popup (0, 0);
981 ARDOUR_UI::redisplay_recent_sessions ()
983 vector<string *> *sessions;
984 vector<string *>::iterator i;
985 RecentSessionsSorter cmp;
987 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
988 recent_session_model->clear ();
991 ARDOUR::read_recent_sessions (rs);
994 recent_session_display.set_model (recent_session_model);
998 /* sort them alphabetically */
999 sort (rs.begin(), rs.end(), cmp);
1000 sessions = new vector<string*>;
1002 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1003 sessions->push_back (new string ((*i).second));
1006 for (i = sessions->begin(); i != sessions->end(); ++i) {
1008 vector<string*>* states;
1009 vector<const gchar*> item;
1010 string fullpath = *(*i);
1012 /* remove any trailing / */
1014 if (fullpath[fullpath.length()-1] == '/') {
1015 fullpath = fullpath.substr (0, fullpath.length()-1);
1018 /* check whether session still exists */
1019 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1020 /* session doesn't exist */
1021 cerr << "skipping non-existent session " << fullpath << endl;
1025 /* now get available states for this session */
1027 if ((states = Session::possible_states (fullpath)) == 0) {
1028 /* no state file? */
1032 TreeModel::Row row = *(recent_session_model->append());
1034 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1035 row[recent_session_columns.fullpath] = fullpath;
1037 if (states->size() > 1) {
1039 /* add the children */
1041 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1043 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1045 child_row[recent_session_columns.visible_name] = **i2;
1046 child_row[recent_session_columns.fullpath] = fullpath;
1055 recent_session_display.set_model (recent_session_model);
1060 ARDOUR_UI::build_session_selector ()
1062 session_selector_window = new ArdourDialog ("session selector");
1064 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1066 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1067 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1068 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1069 recent_session_model = TreeStore::create (recent_session_columns);
1070 recent_session_display.set_model (recent_session_model);
1071 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1072 recent_session_display.set_headers_visible (false);
1073 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1074 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1076 scroller->add (recent_session_display);
1077 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1079 session_selector_window->set_name ("SessionSelectorWindow");
1080 session_selector_window->set_size_request (200, 400);
1081 session_selector_window->get_vbox()->pack_start (*scroller);
1082 session_selector_window->show_all_children();
1086 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1088 session_selector_window->response (RESPONSE_ACCEPT);
1092 ARDOUR_UI::open_recent_session ()
1094 bool can_return = (session != 0);
1096 if (session_selector_window == 0) {
1097 build_session_selector ();
1100 redisplay_recent_sessions ();
1104 session_selector_window->set_position (WIN_POS_MOUSE);
1106 ResponseType r = (ResponseType) session_selector_window->run ();
1109 case RESPONSE_ACCEPT:
1113 session_selector_window->hide();
1120 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1124 session_selector_window->hide();
1126 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1128 if (i == recent_session_model->children().end()) {
1132 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1133 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1135 _session_is_new = false;
1137 if (load_session (path, state) == 0) {
1146 ARDOUR_UI::check_audioengine ()
1149 if (!engine->connected()) {
1150 MessageDialog msg (_("Ardour is not connected to JACK\n"
1151 "You cannot open or close sessions in this condition"));
1163 ARDOUR_UI::open_session ()
1165 if (!check_audioengine()) {
1169 /* popup selector window */
1171 if (open_session_selector == 0) {
1173 /* ardour sessions are folders */
1175 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1176 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1177 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1178 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1180 FileFilter session_filter;
1181 session_filter.add_pattern ("*.ardour");
1182 session_filter.set_name (_("Ardour sessions"));
1183 open_session_selector->add_filter (session_filter);
1184 open_session_selector->set_filter (session_filter);
1187 int response = open_session_selector->run();
1188 open_session_selector->hide ();
1191 case RESPONSE_ACCEPT:
1194 open_session_selector->hide();
1198 open_session_selector->hide();
1199 string session_path = open_session_selector->get_filename();
1203 if (session_path.length() > 0) {
1204 if (Session::find_session (session_path, path, name, isnew) == 0) {
1205 _session_is_new = isnew;
1206 load_session (path, name);
1213 ARDOUR_UI::session_add_midi_track ()
1215 cerr << _("Patience is a virtue.\n");
1219 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1221 list<boost::shared_ptr<AudioTrack> > tracks;
1222 Session::RouteList routes;
1225 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1231 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1233 if (tracks.size() != how_many) {
1234 if (how_many == 1) {
1235 error << _("could not create a new audio track") << endmsg;
1237 error << string_compose (_("could only create %1 of %2 new audio %3"),
1238 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1244 routes = session->new_audio_route (input_channels, output_channels, how_many);
1246 if (routes.size() != how_many) {
1247 if (how_many == 1) {
1248 error << _("could not create a new audio track") << endmsg;
1250 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1256 if (need_control_room_outs) {
1262 route->set_stereo_control_outs (control_lr_channels);
1263 route->control_outs()->set_stereo_pan (pans, this);
1265 #endif /* CONTROLOUTS */
1269 MessageDialog msg (*editor,
1270 _("There are insufficient JACK ports available\n\
1271 to create a new track or bus.\n\
1272 You should save Ardour, exit and\n\
1273 restart JACK with more ports."));
1280 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1282 nframes_t _preroll = 0;
1285 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1286 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1288 if (new_position > _preroll) {
1289 new_position -= _preroll;
1294 session->request_locate (new_position);
1299 ARDOUR_UI::transport_goto_start ()
1302 session->goto_start();
1305 /* force displayed area in editor to start no matter
1306 what "follow playhead" setting is.
1310 editor->reset_x_origin (session->current_start_frame());
1316 ARDOUR_UI::transport_goto_zero ()
1319 session->request_locate (0);
1322 /* force displayed area in editor to start no matter
1323 what "follow playhead" setting is.
1327 editor->reset_x_origin (0);
1333 ARDOUR_UI::transport_goto_wallclock ()
1335 if (session && editor) {
1342 localtime_r (&now, &tmnow);
1344 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1345 frames += tmnow.tm_min * (60 * session->frame_rate());
1346 frames += tmnow.tm_sec * session->frame_rate();
1348 session->request_locate (frames);
1350 /* force displayed area in editor to start no matter
1351 what "follow playhead" setting is.
1355 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1361 ARDOUR_UI::transport_goto_end ()
1364 nframes_t frame = session->current_end_frame();
1365 session->request_locate (frame);
1367 /* force displayed area in editor to start no matter
1368 what "follow playhead" setting is.
1372 editor->reset_x_origin (frame);
1378 ARDOUR_UI::transport_stop ()
1384 if (session->is_auditioning()) {
1385 session->cancel_audition ();
1389 if (session->get_play_loop ()) {
1390 session->request_play_loop (false);
1393 session->request_stop ();
1397 ARDOUR_UI::transport_stop_and_forget_capture ()
1400 session->request_stop (true);
1405 ARDOUR_UI::remove_last_capture()
1408 editor->remove_last_capture();
1413 ARDOUR_UI::transport_record (bool roll)
1417 switch (session->record_status()) {
1418 case Session::Disabled:
1419 if (session->ntracks() == 0) {
1420 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1424 session->maybe_enable_record ();
1429 case Session::Recording:
1431 session->request_stop();
1433 session->disable_record (false, true);
1437 case Session::Enabled:
1438 session->disable_record (false, true);
1441 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1445 ARDOUR_UI::transport_roll ()
1453 rolling = session->transport_rolling ();
1455 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1457 if (session->get_play_loop()) {
1458 session->request_play_loop (false);
1459 auto_loop_button.set_visual_state (1);
1460 roll_button.set_visual_state (1);
1461 } else if (session->get_play_range ()) {
1462 session->request_play_range (false);
1463 play_selection_button.set_visual_state (0);
1464 } else if (rolling) {
1465 session->request_locate (session->last_transport_start(), true);
1468 session->request_transport_speed (1.0f);
1472 ARDOUR_UI::transport_loop()
1475 if (session->get_play_loop()) {
1476 if (session->transport_rolling()) {
1477 Location * looploc = session->locations()->auto_loop_location();
1479 session->request_locate (looploc->start(), true);
1484 session->request_play_loop (true);
1490 ARDOUR_UI::transport_play_selection ()
1496 if (!session->get_play_range()) {
1497 session->request_stop ();
1500 editor->play_selection ();
1504 ARDOUR_UI::transport_rewind (int option)
1506 float current_transport_speed;
1509 current_transport_speed = session->transport_speed();
1511 if (current_transport_speed >= 0.0f) {
1514 session->request_transport_speed (-1.0f);
1517 session->request_transport_speed (-4.0f);
1520 session->request_transport_speed (-0.5f);
1525 session->request_transport_speed (current_transport_speed * 1.5f);
1531 ARDOUR_UI::transport_forward (int option)
1533 float current_transport_speed;
1536 current_transport_speed = session->transport_speed();
1538 if (current_transport_speed <= 0.0f) {
1541 session->request_transport_speed (1.0f);
1544 session->request_transport_speed (4.0f);
1547 session->request_transport_speed (0.5f);
1552 session->request_transport_speed (current_transport_speed * 1.5f);
1558 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1564 boost::shared_ptr<Route> r;
1566 if ((r = session->route_by_remote_id (dstream)) != 0) {
1570 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1571 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1580 ARDOUR_UI::queue_transport_change ()
1582 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1586 ARDOUR_UI::map_transport_state ()
1588 float sp = session->transport_speed();
1591 transport_rolling ();
1592 } else if (sp < 0.0f) {
1593 transport_rewinding ();
1594 } else if (sp > 0.0f) {
1595 transport_forwarding ();
1597 transport_stopped ();
1602 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1604 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1605 (int) adj.get_value()].c_str());
1609 ARDOUR_UI::engine_stopped ()
1611 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1612 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1613 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1617 ARDOUR_UI::engine_running ()
1619 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1620 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1621 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1623 Glib::RefPtr<Action> action;
1624 const char* action_name = 0;
1626 switch (engine->frames_per_cycle()) {
1628 action_name = X_("JACKLatency32");
1631 action_name = X_("JACKLatency64");
1634 action_name = X_("JACKLatency128");
1637 action_name = X_("JACKLatency512");
1640 action_name = X_("JACKLatency1024");
1643 action_name = X_("JACKLatency2048");
1646 action_name = X_("JACKLatency4096");
1649 action_name = X_("JACKLatency8192");
1652 /* XXX can we do anything useful ? */
1658 action = ActionManager::get_action (X_("JACK"), action_name);
1661 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1662 ract->set_active ();
1668 ARDOUR_UI::engine_halted ()
1670 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1672 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1673 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1675 update_sample_rate (0);
1677 MessageDialog msg (*editor,
1679 JACK has either been shutdown or it\n\
1680 disconnected Ardour because Ardour\n\
1681 was not fast enough. Try to restart\n\
1682 JACK, reconnect and save the session."));
1688 ARDOUR_UI::do_engine_start ()
1696 error << _("Unable to start the session running")
1706 ARDOUR_UI::setup_theme ()
1708 theme_manager->setup_theme();
1712 ARDOUR_UI::update_clocks ()
1714 if (!editor || !editor->dragging_playhead()) {
1715 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1720 ARDOUR_UI::start_clocking ()
1722 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1726 ARDOUR_UI::stop_clocking ()
1728 clock_signal_connection.disconnect ();
1732 ARDOUR_UI::toggle_clocking ()
1735 if (clock_button.get_active()) {
1744 ARDOUR_UI::_blink (void *arg)
1747 ((ARDOUR_UI *) arg)->blink ();
1754 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1758 ARDOUR_UI::start_blinking ()
1760 /* Start the blink signal. Everybody with a blinking widget
1761 uses Blink to drive the widget's state.
1764 if (blink_timeout_tag < 0) {
1766 blink_timeout_tag = g_timeout_add (240, _blink, this);
1771 ARDOUR_UI::stop_blinking ()
1773 if (blink_timeout_tag >= 0) {
1774 g_source_remove (blink_timeout_tag);
1775 blink_timeout_tag = -1;
1780 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1786 if (io.n_inputs() == 0) {
1791 /* XXX we're not handling multiple ports yet. */
1793 const char **connections = io.input(0)->get_connections();
1795 if (connections == 0 || connections[0] == '\0') {
1798 buf = connections[0];
1805 if (io.n_outputs() == 0) {
1810 /* XXX we're not handling multiple ports yet. */
1812 const char **connections = io.output(0)->get_connections();
1814 if (connections == 0 || connections[0] == '\0') {
1817 buf = connections[0];
1824 /** Ask the user for the name of a new shapshot and then take it.
1827 ARDOUR_UI::snapshot_session ()
1829 ArdourPrompter prompter (true);
1833 struct tm local_time;
1836 localtime_r (&n, &local_time);
1837 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1839 prompter.set_name ("Prompter");
1840 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1841 prompter.set_prompt (_("Name of New Snapshot"));
1842 prompter.set_initial_text (timebuf);
1844 switch (prompter.run()) {
1845 case RESPONSE_ACCEPT:
1846 prompter.get_result (snapname);
1847 if (snapname.length()){
1848 save_state (snapname);
1858 ARDOUR_UI::save_state (const string & name)
1860 (void) save_state_canfail (name);
1864 ARDOUR_UI::save_state_canfail (string name)
1869 if (name.length() == 0) {
1870 name = session->snap_name();
1873 if ((ret = session->save_state (name)) != 0) {
1877 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1882 ARDOUR_UI::primary_clock_value_changed ()
1885 session->request_locate (primary_clock.current_time ());
1890 ARDOUR_UI::big_clock_value_changed ()
1893 session->request_locate (big_clock.current_time ());
1898 ARDOUR_UI::secondary_clock_value_changed ()
1901 session->request_locate (secondary_clock.current_time ());
1906 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1912 switch (session->record_status()) {
1913 case Session::Enabled:
1915 rec_button.set_visual_state (2);
1917 rec_button.set_visual_state (0);
1921 case Session::Recording:
1922 rec_button.set_visual_state (1);
1926 rec_button.set_visual_state (0);
1932 ARDOUR_UI::save_template ()
1935 ArdourPrompter prompter (true);
1938 if (!check_audioengine()) {
1942 prompter.set_name (X_("Prompter"));
1943 prompter.set_prompt (_("Name for mix template:"));
1944 prompter.set_initial_text(session->name() + _("-template"));
1945 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1947 switch (prompter.run()) {
1948 case RESPONSE_ACCEPT:
1949 prompter.get_result (name);
1951 if (name.length()) {
1952 session->save_template (name);
1962 ARDOUR_UI::fontconfig_dialog ()
1965 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1966 may not and it can take a while to build it. Warn them.
1969 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1971 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1972 MessageDialog msg (*new_session_dialog,
1973 _("Welcome to Ardour.\n\n"
1974 "The program will take a bit longer to start up\n"
1975 "while the system fonts are checked.\n\n"
1976 "This will only be done once, and you will\n"
1977 "not see this message again\n"),
1990 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1992 existing_session = false;
1994 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
1995 session_path = cmdline_path;
1996 existing_session = true;
1997 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
1998 session_path = Glib::path_get_dirname (string (cmdline_path));
1999 existing_session = true;
2001 /* it doesn't exist, assume the best */
2002 session_path = Glib::path_get_dirname (string (cmdline_path));
2005 session_name = basename_nosuffix (string (cmdline_path));
2009 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2011 /* when this is called, the backend audio system must be running */
2013 /* the main idea here is to deal with the fact that a cmdline argument for the session
2014 can be interpreted in different ways - it could be a directory or a file, and before
2015 we load, we need to know both the session directory and the snapshot (statefile) within it
2016 that we are supposed to use.
2019 if (session_name.length() == 0 || session_path.length() == 0) {
2023 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2025 Glib::ustring predicted_session_file;
2027 predicted_session_file = session_path;
2028 predicted_session_file += '/';
2029 predicted_session_file += session_name;
2030 predicted_session_file += Session::statefile_suffix();
2032 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2033 existing_session = true;
2036 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2038 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2039 /* existing .ardour file */
2040 existing_session = true;
2044 existing_session = false;
2047 /* lets just try to load it */
2049 if (create_engine ()) {
2050 backend_audio_error (false, new_session_dialog);
2054 return load_session (session_path, session_name);
2058 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2060 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2062 MessageDialog msg (str,
2064 Gtk::MESSAGE_WARNING,
2065 Gtk::BUTTONS_YES_NO,
2069 msg.set_name (X_("CleanupDialog"));
2070 msg.set_wmclass (X_("existing_session"), "Ardour");
2071 msg.set_position (Gtk::WIN_POS_MOUSE);
2074 switch (msg.run()) {
2083 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2088 AutoConnectOption iconnect;
2089 AutoConnectOption oconnect;
2093 if (Profile->get_sae()) {
2097 iconnect = AutoConnectPhysical;
2098 oconnect = AutoConnectMaster;
2099 nphysin = 0; // use all available
2100 nphysout = 0; // use all available
2104 /* get settings from advanced section of NSD */
2106 if (new_session_dialog->create_control_bus()) {
2107 cchns = (uint32_t) new_session_dialog->control_channel_count();
2112 if (new_session_dialog->create_master_bus()) {
2113 mchns = (uint32_t) new_session_dialog->master_channel_count();
2118 if (new_session_dialog->connect_inputs()) {
2119 iconnect = AutoConnectPhysical;
2121 iconnect = AutoConnectOption (0);
2124 /// @todo some minor tweaks.
2126 if (new_session_dialog->connect_outs_to_master()) {
2127 oconnect = AutoConnectMaster;
2128 } else if (new_session_dialog->connect_outs_to_physical()) {
2129 oconnect = AutoConnectPhysical;
2131 oconnect = AutoConnectOption (0);
2134 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2135 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2138 if (build_session (session_path,
2146 engine->frame_rate() * 60 * 5)) {
2155 ARDOUR_UI::end_loading_messages ()
2161 ARDOUR_UI::loading_message (const std::string& msg)
2164 splash->message (msg);
2169 ARDOUR_UI::idle_load (const Glib::ustring& path)
2172 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2173 /* /path/to/foo => /path/to/foo, foo */
2174 load_session (path, basename_nosuffix (path));
2176 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2177 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2181 ARDOUR_COMMAND_LINE::session_name = path;
2183 if (new_session_dialog) {
2186 /* make it break out of Dialog::run() and
2190 new_session_dialog->response (1);
2196 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2198 bool existing_session = false;
2199 Glib::ustring session_name;
2200 Glib::ustring session_path;
2201 Glib::ustring template_name;
2205 response = Gtk::RESPONSE_NONE;
2207 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2209 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2211 /* don't ever reuse this */
2213 ARDOUR_COMMAND_LINE::session_name = string();
2215 if (existing_session && backend_audio_is_running) {
2217 /* just load the thing already */
2219 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2224 /* make the NSD use whatever information we have */
2226 new_session_dialog->set_session_name (session_name);
2227 new_session_dialog->set_session_folder (session_path);
2230 /* loading failed, or we need the NSD for something */
2232 new_session_dialog->set_modal (false);
2233 new_session_dialog->set_position (WIN_POS_CENTER);
2234 new_session_dialog->set_current_page (0);
2235 new_session_dialog->set_existing_session (existing_session);
2236 new_session_dialog->reset_recent();
2239 new_session_dialog->set_have_engine (backend_audio_is_running);
2240 new_session_dialog->present ();
2241 response = new_session_dialog->run ();
2243 _session_is_new = false;
2245 /* handle possible negative responses */
2249 /* sent by idle_load, meaning restart the whole process again */
2250 new_session_dialog->hide();
2251 new_session_dialog->reset();
2255 case Gtk::RESPONSE_CANCEL:
2256 case Gtk::RESPONSE_DELETE_EVENT:
2258 if (engine && engine->running()) {
2259 engine->stop (true);
2263 new_session_dialog->hide ();
2266 case Gtk::RESPONSE_NONE:
2267 /* "Clear" was pressed */
2271 fontconfig_dialog();
2273 if (!backend_audio_is_running) {
2274 int ret = new_session_dialog->engine_control.setup_engine ();
2277 } else if (ret > 0) {
2278 response = Gtk::RESPONSE_REJECT;
2283 if (create_engine ()) {
2285 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2288 new_session_dialog->set_existing_session (false);
2289 new_session_dialog->set_current_page (2);
2291 response = Gtk::RESPONSE_NONE;
2295 backend_audio_is_running = true;
2297 if (response == Gtk::RESPONSE_OK) {
2299 session_name = new_session_dialog->session_name();
2301 if (session_name.empty()) {
2302 response = Gtk::RESPONSE_NONE;
2306 /* if the user mistakenly typed path information into the session filename entry,
2307 convert what they typed into a path & a name
2310 if (session_name[0] == '/' ||
2311 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2312 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2314 session_path = Glib::path_get_dirname (session_name);
2315 session_name = Glib::path_get_basename (session_name);
2319 session_path = new_session_dialog->session_folder();
2322 template_name = Glib::ustring();
2323 switch (new_session_dialog->which_page()) {
2325 case NewSessionDialog::OpenPage:
2326 case NewSessionDialog::EnginePage:
2330 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2332 should_be_new = true;
2334 //XXX This is needed because session constructor wants a
2335 //non-existant path. hopefully this will be fixed at some point.
2337 session_path = Glib::build_filename (session_path, session_name);
2339 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2341 if (ask_about_loading_existing_session (session_path)) {
2344 response = RESPONSE_NONE;
2349 _session_is_new = true;
2351 if (new_session_dialog->use_session_template()) {
2353 template_name = new_session_dialog->session_template_name();
2357 if (build_session_from_nsd (session_path, session_name)) {
2358 response = RESPONSE_NONE;
2370 new_session_dialog->hide ();
2372 if (load_session (session_path, session_name, template_name)) {
2374 response = Gtk::RESPONSE_NONE;
2378 if (response == Gtk::RESPONSE_NONE) {
2379 new_session_dialog->set_existing_session (false);
2380 new_session_dialog->reset ();
2384 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2388 new_session_dialog->hide();
2389 new_session_dialog->reset();
2390 goto_editor_window ();
2395 ARDOUR_UI::close_session ()
2397 if (!check_audioengine()) {
2401 unload_session (true);
2403 get_session_parameters (true, false);
2407 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2409 Session *new_session;
2413 session_loaded = false;
2415 if (!check_audioengine()) {
2419 unload_status = unload_session ();
2421 if (unload_status < 0) {
2423 } else if (unload_status > 0) {
2428 /* if it already exists, we must have write access */
2430 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2431 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2432 "This prevents the session from being loaded."));
2438 loading_message (_("Please wait while Ardour loads your session"));
2441 new_session = new Session (*engine, path, snap_name, mix_template);
2444 /* this one is special */
2446 catch (AudioEngine::PortRegistrationFailure& err) {
2448 MessageDialog msg (err.what(),
2451 Gtk::BUTTONS_CLOSE);
2453 msg.set_title (_("Port Registration Error"));
2454 msg.set_secondary_text (_("Click the Close button to try again."));
2455 msg.set_position (Gtk::WIN_POS_CENTER);
2459 int response = msg.run ();
2464 case RESPONSE_CANCEL:
2474 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2477 Gtk::BUTTONS_CLOSE);
2479 msg.set_title (_("Loading Error"));
2480 msg.set_secondary_text (_("Click the Close button to try again."));
2481 msg.set_position (Gtk::WIN_POS_CENTER);
2485 int response = msg.run ();
2490 case RESPONSE_CANCEL:
2498 connect_to_session (new_session);
2500 Config->set_current_owner (ConfigVariableBase::Interface);
2502 session_loaded = true;
2504 goto_editor_window ();
2507 session->set_clean ();
2518 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2519 uint32_t control_channels,
2520 uint32_t master_channels,
2521 AutoConnectOption input_connect,
2522 AutoConnectOption output_connect,
2525 nframes_t initial_length)
2527 Session *new_session;
2530 if (!check_audioengine()) {
2534 session_loaded = false;
2536 x = unload_session ();
2544 _session_is_new = true;
2547 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2548 control_channels, master_channels, nphysin, nphysout, initial_length);
2553 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2559 connect_to_session (new_session);
2561 session_loaded = true;
2563 new_session->save_state(new_session->name());
2572 editor->show_window ();
2583 ARDOUR_UI::show_about ()
2587 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2594 ARDOUR_UI::hide_about ()
2597 about->get_window()->set_cursor ();
2603 ARDOUR_UI::about_signal_response(int response)
2609 ARDOUR_UI::show_splash ()
2613 splash = new Splash;
2621 splash->queue_draw ();
2622 splash->get_window()->process_updates (true);
2627 ARDOUR_UI::hide_splash ()
2635 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2639 removed = rep.paths.size();
2642 MessageDialog msgd (*editor,
2643 _("No audio files were ready for cleanup"),
2646 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2647 msgd.set_secondary_text (_("If this seems suprising, \n\
2648 check for any existing snapshots.\n\
2649 These may still include regions that\n\
2650 require some unused files to continue to exist."));
2656 ArdourDialog results (_("ardour: cleanup"), true, false);
2658 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2659 CleanupResultsModelColumns() {
2663 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2664 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2668 CleanupResultsModelColumns results_columns;
2669 Glib::RefPtr<Gtk::ListStore> results_model;
2670 Gtk::TreeView results_display;
2672 results_model = ListStore::create (results_columns);
2673 results_display.set_model (results_model);
2674 results_display.append_column (list_title, results_columns.visible_name);
2676 results_display.set_name ("CleanupResultsList");
2677 results_display.set_headers_visible (true);
2678 results_display.set_headers_clickable (false);
2679 results_display.set_reorderable (false);
2681 Gtk::ScrolledWindow list_scroller;
2684 Gtk::HBox dhbox; // the hbox for the image and text
2685 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2686 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2688 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2690 if (rep.space < 1048576.0f) {
2692 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2694 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2698 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2700 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2704 dhbox.pack_start (*dimage, true, false, 5);
2705 dhbox.pack_start (txt, true, false, 5);
2707 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2708 TreeModel::Row row = *(results_model->append());
2709 row[results_columns.visible_name] = *i;
2710 row[results_columns.fullpath] = *i;
2713 list_scroller.add (results_display);
2714 list_scroller.set_size_request (-1, 150);
2715 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2717 dvbox.pack_start (dhbox, true, false, 5);
2718 dvbox.pack_start (list_scroller, true, false, 5);
2719 ddhbox.pack_start (dvbox, true, false, 5);
2721 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2722 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2723 results.set_default_response (RESPONSE_CLOSE);
2724 results.set_position (Gtk::WIN_POS_MOUSE);
2725 results.show_all_children ();
2726 results.set_resizable (false);
2733 ARDOUR_UI::cleanup ()
2736 /* shouldn't happen: menu item is insensitive */
2741 MessageDialog checker (_("Are you sure you want to cleanup?"),
2743 Gtk::MESSAGE_QUESTION,
2744 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2746 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2747 ALL undo/redo information will be lost if you cleanup.\n\
2748 After cleanup, unused audio files will be moved to a \
2749 \"dead sounds\" location."));
2751 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2752 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2753 checker.set_default_response (RESPONSE_CANCEL);
2755 checker.set_name (_("CleanupDialog"));
2756 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2757 checker.set_position (Gtk::WIN_POS_MOUSE);
2759 switch (checker.run()) {
2760 case RESPONSE_ACCEPT:
2766 Session::cleanup_report rep;
2768 editor->prepare_for_cleanup ();
2770 /* do not allow flush until a session is reloaded */
2772 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2774 act->set_sensitive (false);
2777 if (session->cleanup_sources (rep)) {
2778 editor->finish_cleanup ();
2782 editor->finish_cleanup ();
2785 display_cleanup_results (rep,
2788 The following %1 %2 not in use and \n\
2789 have been moved to:\n\
2791 Flushing the wastebasket will \n\
2792 release an additional\n\
2793 %4 %5bytes of disk space.\n"
2799 ARDOUR_UI::flush_trash ()
2802 /* shouldn't happen: menu item is insensitive */
2806 Session::cleanup_report rep;
2808 if (session->cleanup_trash_sources (rep)) {
2812 display_cleanup_results (rep,
2814 _("The following %1 %2 deleted from\n\
2816 releasing %4 %5bytes of disk space"));
2820 ARDOUR_UI::add_route (Gtk::Window* float_window)
2828 if (add_route_dialog == 0) {
2829 add_route_dialog = new AddRouteDialog;
2831 add_route_dialog->set_transient_for (*float_window);
2835 if (add_route_dialog->is_visible()) {
2836 /* we're already doing this */
2840 ResponseType r = (ResponseType) add_route_dialog->run ();
2842 add_route_dialog->hide();
2845 case RESPONSE_ACCEPT:
2852 if ((count = add_route_dialog->count()) <= 0) {
2856 uint32_t input_chan = add_route_dialog->channels ();
2857 uint32_t output_chan;
2858 string name_template = add_route_dialog->name_template ();
2859 bool track = add_route_dialog->track ();
2861 AutoConnectOption oac = Config->get_output_auto_connect();
2863 if (oac & AutoConnectMaster) {
2864 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2866 output_chan = input_chan;
2869 /* XXX do something with name template */
2872 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2874 session_add_audio_bus (input_chan, output_chan, count);
2879 ARDOUR_UI::mixer_settings () const
2884 node = session->instant_xml(X_("Mixer"), session->path());
2886 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2890 node = new XMLNode (X_("Mixer"));
2897 ARDOUR_UI::editor_settings () const
2902 node = session->instant_xml(X_("Editor"), session->path());
2904 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2908 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2909 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2914 node = new XMLNode (X_("Editor"));
2920 ARDOUR_UI::keyboard_settings () const
2924 node = Config->extra_xml(X_("Keyboard"));
2927 node = new XMLNode (X_("Keyboard"));
2933 ARDOUR_UI::create_xrun_marker(nframes_t where)
2935 editor->mouse_add_new_marker (where, false, true);
2939 ARDOUR_UI::halt_on_xrun_message ()
2941 MessageDialog msg (*editor,
2942 _("Recording was stopped because your system could not keep up."));
2947 ARDOUR_UI::xrun_handler(nframes_t where)
2953 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2955 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2956 create_xrun_marker(where);
2959 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2960 halt_on_xrun_message ();
2965 ARDOUR_UI::disk_overrun_handler ()
2967 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2969 if (!have_disk_speed_dialog_displayed) {
2970 have_disk_speed_dialog_displayed = true;
2971 MessageDialog* msg = new MessageDialog (*editor, _("\
2972 The disk system on your computer\n\
2973 was not able to keep up with Ardour.\n\
2975 Specifically, it failed to write data to disk\n\
2976 quickly enough to keep up with recording.\n"));
2977 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2983 ARDOUR_UI::disk_underrun_handler ()
2985 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2987 if (!have_disk_speed_dialog_displayed) {
2988 have_disk_speed_dialog_displayed = true;
2989 MessageDialog* msg = new MessageDialog (*editor,
2990 _("The disk system on your computer\n\
2991 was not able to keep up with Ardour.\n\
2993 Specifically, it failed to read data from disk\n\
2994 quickly enough to keep up with playback.\n"));
2995 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3001 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3003 have_disk_speed_dialog_displayed = false;
3008 ARDOUR_UI::session_dialog (std::string msg)
3010 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3015 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3017 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3026 ARDOUR_UI::pending_state_dialog ()
3028 HBox* hbox = new HBox();
3029 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3030 ArdourDialog dialog (_("Crash Recovery"), true);
3032 This session appears to have been in\n\
3033 middle of recording when ardour or\n\
3034 the computer was shutdown.\n\
3036 Ardour can recover any captured audio for\n\
3037 you, or it can ignore it. Please decide\n\
3038 what you would like to do.\n"));
3039 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3040 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3041 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3042 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3043 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3044 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3045 dialog.set_default_response (RESPONSE_ACCEPT);
3046 dialog.set_position (WIN_POS_CENTER);
3051 switch (dialog.run ()) {
3052 case RESPONSE_ACCEPT:
3060 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3062 HBox* hbox = new HBox();
3063 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3064 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3065 Label message (string_compose (_("\
3066 This session was created with a sample rate of %1 Hz\n\
3068 The audioengine is currently running at %2 Hz\n"), desired, actual));
3070 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3071 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3072 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3073 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3074 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3075 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3076 dialog.set_default_response (RESPONSE_ACCEPT);
3077 dialog.set_position (WIN_POS_CENTER);
3082 switch (dialog.run ()) {
3083 case RESPONSE_ACCEPT:
3092 ARDOUR_UI::disconnect_from_jack ()
3095 if( engine->disconnect_from_jack ()) {
3096 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3100 update_sample_rate (0);
3105 ARDOUR_UI::reconnect_to_jack ()
3108 if (engine->reconnect_to_jack ()) {
3109 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3113 update_sample_rate (0);
3118 ARDOUR_UI::use_config ()
3120 Glib::RefPtr<Action> act;
3122 switch (Config->get_native_file_data_format ()) {
3124 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3127 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3130 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3135 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3136 ract->set_active ();
3139 switch (Config->get_native_file_header_format ()) {
3141 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3144 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3147 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3150 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3153 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3156 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3159 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3164 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3165 ract->set_active ();
3168 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3170 set_transport_controllable_state (*node);
3175 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3177 if (Config->get_primary_clock_delta_edit_cursor()) {
3178 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3180 primary_clock.set (pos, 0, true);
3183 if (Config->get_secondary_clock_delta_edit_cursor()) {
3184 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3186 secondary_clock.set (pos);
3189 if (big_clock_window) {
3190 big_clock.set (pos);
3195 ARDOUR_UI::record_state_changed ()
3197 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3199 if (!session || !big_clock_window) {
3200 /* why bother - the clock isn't visible */
3204 switch (session->record_status()) {
3205 case Session::Recording:
3206 big_clock.set_widget_name ("BigClockRecording");
3209 big_clock.set_widget_name ("BigClockNonRecording");
3215 ARDOUR_UI::first_idle ()
3218 session->allow_auto_play (true);
3222 editor->first_idle();
3225 Keyboard::set_can_save_keybindings (true);
3230 ARDOUR_UI::store_clock_modes ()
3232 XMLNode* node = new XMLNode(X_("ClockModes"));
3234 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3235 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3238 session->add_extra_xml (*node);
3239 session->set_dirty ();
3244 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3245 : Controllable (name), ui (u), type(tp)
3251 ARDOUR_UI::TransportControllable::set_value (float val)
3253 if (type == ShuttleControl) {
3260 fract = -((0.5f - val)/0.5f);
3262 fract = ((val - 0.5f)/0.5f);
3266 ui.set_shuttle_fract (fract);
3271 /* do nothing: these are radio-style actions */
3275 const char *action = 0;
3279 action = X_("Roll");
3282 action = X_("Stop");
3285 action = X_("Goto Start");
3288 action = X_("Goto End");
3291 action = X_("Loop");
3294 action = X_("Play Selection");
3297 action = X_("Record");
3307 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3315 ARDOUR_UI::TransportControllable::get_value (void) const
3334 case ShuttleControl:
3344 ARDOUR_UI::TransportControllable::set_id (const string& str)
3350 ARDOUR_UI::setup_profile ()
3352 if (gdk_screen_width() < 1200) {
3353 Profile->set_small_screen ();
3356 if (getenv ("ARDOUR_SAE")) {
3357 Profile->set_sae ();
3358 Profile->set_single_package ();