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.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/basename.h>
37 #include <pbd/compose.h>
38 #include <pbd/pathscanner.h>
39 #include <pbd/failed_constructor.h>
40 #include <pbd/enumwriter.h>
41 #include <pbd/stacktrace.h>
42 #include <gtkmm2ext/gtk_ui.h>
43 #include <gtkmm2ext/utils.h>
44 #include <gtkmm2ext/click_box.h>
45 #include <gtkmm2ext/fastmeter.h>
46 #include <gtkmm2ext/stop_signal.h>
47 #include <gtkmm2ext/popup.h>
48 #include <gtkmm2ext/window_title.h>
50 #include <midi++/port.h>
51 #include <midi++/mmc.h>
53 #include <ardour/ardour.h>
54 #include <ardour/profile.h>
55 #include <ardour/session_route.h>
56 #include <ardour/port.h>
57 #include <ardour/audioengine.h>
58 #include <ardour/playlist.h>
59 #include <ardour/utils.h>
60 #include <ardour/audio_diskstream.h>
61 #include <ardour/audiofilesource.h>
62 #include <ardour/recent_sessions.h>
63 #include <ardour/port.h>
64 #include <ardour/audio_track.h>
67 #include "ardour_ui.h"
68 #include "public_editor.h"
69 #include "audio_clock.h"
74 #include "add_route_dialog.h"
75 #include "new_session_dialog.h"
79 #include "gui_thread.h"
80 #include "theme_manager.h"
81 #include "engine_dialog.h"
85 using namespace ARDOUR;
87 using namespace Gtkmm2ext;
91 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
92 UIConfiguration *ARDOUR_UI::ui_config = 0;
94 sigc::signal<void,bool> ARDOUR_UI::Blink;
95 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
96 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
97 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
99 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
101 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
103 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
104 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
105 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
106 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
110 adjuster_table (3, 3),
114 preroll_button (_("pre\nroll")),
115 postroll_button (_("post\nroll")),
119 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
123 roll_controllable ("transport roll", *this, TransportControllable::Roll),
124 stop_controllable ("transport stop", *this, TransportControllable::Stop),
125 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
126 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
127 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
128 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
129 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
130 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
131 shuttle_controller_binding_proxy (shuttle_controllable),
133 roll_button (roll_controllable),
134 stop_button (stop_controllable),
135 goto_start_button (goto_start_controllable),
136 goto_end_button (goto_end_controllable),
137 auto_loop_button (auto_loop_controllable),
138 play_selection_button (play_selection_controllable),
139 rec_button (rec_controllable),
141 shuttle_units_button (_("% ")),
143 punch_in_button (_("Punch In")),
144 punch_out_button (_("Punch Out")),
145 auto_return_button (_("Auto Return")),
146 auto_play_button (_("Auto Play")),
147 auto_input_button (_("Auto Input")),
148 click_button (_("Click")),
149 time_master_button (_("time\nmaster")),
151 auditioning_alert_button (_("AUDITION")),
152 solo_alert_button (_("SOLO")),
154 error_log_button (_("Errors"))
156 using namespace Gtk::Menu_Helpers;
161 _auto_display_errors = false;
167 if (ARDOUR_COMMAND_LINE::session_name.length()) {
168 /* only show this if we're not going to post the new session dialog */
172 if (theArdourUI == 0) {
176 ui_config = new UIConfiguration();
177 theme_manager = new ThemeManager();
183 _session_is_new = false;
184 big_clock_window = 0;
185 session_selector_window = 0;
186 new_session_dialog = 0;
187 last_key_press_time = 0;
188 connection_editor = 0;
189 add_route_dialog = 0;
194 open_session_selector = 0;
195 have_configure_timeout = false;
196 have_disk_speed_dialog_displayed = false;
197 _will_create_new_session_automatically = false;
198 session_loaded = false;
199 last_speed_displayed = -1.0f;
200 ignore_dual_punch = false;
202 last_configure_time.tv_sec = 0;
203 last_configure_time.tv_usec = 0;
205 shuttle_grabbed = false;
207 shuttle_max_speed = 8.0f;
209 shuttle_style_menu = 0;
210 shuttle_unit_menu = 0;
212 gettimeofday (&last_peak_grab, 0);
213 gettimeofday (&last_shuttle_request, 0);
215 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
216 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
218 /* handle dialog requests */
220 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
222 /* handle pending state with a dialog */
224 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
226 /* handle sr mismatch with a dialog */
228 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
230 /* lets get this party started */
233 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
234 throw failed_constructor ();
237 setup_gtk_ardour_enums ();
238 Config->set_current_owner (ConfigVariableBase::Interface);
241 } catch (failed_constructor& err) {
242 error << _("could not initialize Ardour.") << endmsg;
247 /* we like keyboards */
249 keyboard = new Keyboard;
253 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
254 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
260 ARDOUR_UI::create_engine ()
262 // this gets called every time by new_session()
268 loading_message (_("Starting audio engine"));
271 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
278 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
279 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
280 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
281 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
289 ARDOUR_UI::post_engine ()
291 /* Things to be done once we create the AudioEngine
294 check_memory_locking();
296 ActionManager::init ();
299 if (setup_windows ()) {
300 throw failed_constructor ();
303 /* this is the first point at which all the keybindings are available */
305 if (ARDOUR_COMMAND_LINE::show_key_actions) {
306 vector<string> names;
307 vector<string> paths;
309 vector<AccelKey> bindings;
311 ActionManager::get_all_actions (names, paths, keys, bindings);
313 vector<string>::iterator n;
314 vector<string>::iterator k;
315 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
316 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
322 blink_timeout_tag = -1;
324 /* the global configuration object is now valid */
328 /* this being a GUI and all, we want peakfiles */
330 AudioFileSource::set_build_peakfiles (true);
331 AudioFileSource::set_build_missing_peakfiles (true);
333 /* set default clock modes */
335 if (Profile->get_sae()) {
336 primary_clock.set_mode (AudioClock::MinSec);
338 primary_clock.set_mode (AudioClock::SMPTE);
340 secondary_clock.set_mode (AudioClock::BBT);
342 /* start the time-of-day-clock */
345 /* OS X provides an always visible wallclock, so don't be stupid */
346 update_wall_clock ();
347 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
350 update_disk_space ();
352 update_sample_rate (engine->frame_rate());
354 platform_specific ();
356 /* now start and maybe save state */
358 if (do_engine_start () == 0) {
359 if (session && _session_is_new) {
360 /* we need to retain initial visual
361 settings for a new session
363 session->save_state ("");
368 ARDOUR_UI::~ARDOUR_UI ()
370 save_ardour_state ();
384 if (add_route_dialog) {
385 delete add_route_dialog;
388 if (new_session_dialog) {
389 delete new_session_dialog;
394 ARDOUR_UI::pop_back_splash ()
396 if (Splash::instance()) {
397 // Splash::instance()->pop_back();
398 Splash::instance()->hide ();
403 ARDOUR_UI::configure_timeout ()
408 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
409 /* no configure events yet */
413 gettimeofday (&now, 0);
414 timersub (&now, &last_configure_time, &diff);
416 /* force a gap of 0.5 seconds since the last configure event
419 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
422 have_configure_timeout = false;
423 save_ardour_state ();
429 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
431 if (have_configure_timeout) {
432 gettimeofday (&last_configure_time, 0);
434 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
435 have_configure_timeout = true;
442 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
444 const XMLProperty* prop;
446 if ((prop = node.property ("roll")) != 0) {
447 roll_controllable.set_id (prop->value());
449 if ((prop = node.property ("stop")) != 0) {
450 stop_controllable.set_id (prop->value());
452 if ((prop = node.property ("goto_start")) != 0) {
453 goto_start_controllable.set_id (prop->value());
455 if ((prop = node.property ("goto_end")) != 0) {
456 goto_end_controllable.set_id (prop->value());
458 if ((prop = node.property ("auto_loop")) != 0) {
459 auto_loop_controllable.set_id (prop->value());
461 if ((prop = node.property ("play_selection")) != 0) {
462 play_selection_controllable.set_id (prop->value());
464 if ((prop = node.property ("rec")) != 0) {
465 rec_controllable.set_id (prop->value());
467 if ((prop = node.property ("shuttle")) != 0) {
468 shuttle_controllable.set_id (prop->value());
473 ARDOUR_UI::get_transport_controllable_state ()
475 XMLNode* node = new XMLNode(X_("TransportControllables"));
478 roll_controllable.id().print (buf, sizeof (buf));
479 node->add_property (X_("roll"), buf);
480 stop_controllable.id().print (buf, sizeof (buf));
481 node->add_property (X_("stop"), buf);
482 goto_start_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("goto_start"), buf);
484 goto_end_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("goto_end"), buf);
486 auto_loop_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("auto_loop"), buf);
488 play_selection_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("play_selection"), buf);
490 rec_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("rec"), buf);
492 shuttle_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("shuttle"), buf);
499 ARDOUR_UI::save_ardour_state ()
501 if (!keyboard || !mixer || !editor) {
505 /* XXX this is all a bit dubious. add_extra_xml() uses
506 a different lifetime model from add_instant_xml().
509 XMLNode* node = new XMLNode (keyboard->get_state());
510 Config->add_extra_xml (*node);
511 Config->add_extra_xml (get_transport_controllable_state());
512 if (new_session_dialog) {
513 if (new_session_dialog->engine_control.was_used()) {
514 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
517 Config->save_state();
518 ui_config->save_state ();
520 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
521 XMLNode mnode(mixer->get_state());
524 session->add_instant_xml (enode, session->path());
525 session->add_instant_xml (mnode, session->path());
527 Config->add_instant_xml (enode, get_user_ardour_path());
528 Config->add_instant_xml (mnode, get_user_ardour_path());
531 Keyboard::save_keybindings ();
535 ARDOUR_UI::autosave_session ()
537 if (!Config->get_periodic_safety_backups())
541 session->maybe_write_autosave();
548 ARDOUR_UI::update_autosave ()
550 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
552 if (session->dirty()) {
553 if (_autosave_connection.connected()) {
554 _autosave_connection.disconnect();
557 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
558 Config->get_periodic_safety_backup_interval() * 1000);
561 if (_autosave_connection.connected()) {
562 _autosave_connection.disconnect();
568 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
572 title = _("Ardour could not start JACK");
574 title = _("Ardour could not connect to JACK.");
577 MessageDialog win (title,
583 win.set_secondary_text(_("There are several possible reasons:\n\
585 1) You requested audio parameters that are not supported..\n\
586 2) JACK is running as another user.\n\
588 Please consider the possibilities, and perhaps try different parameters."));
590 win.set_secondary_text(_("There are several possible reasons:\n\
592 1) JACK is not running.\n\
593 2) JACK is running as another user, perhaps root.\n\
594 3) There is already another client called \"ardour\".\n\
596 Please consider the possibilities, and perhaps (re)start JACK."));
600 win.set_transient_for (*toplevel);
604 win.add_button (Stock::OK, RESPONSE_CLOSE);
606 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
609 win.set_default_response (RESPONSE_CLOSE);
612 win.set_position (Gtk::WIN_POS_CENTER);
615 /* we just don't care about the result, but we want to block */
621 ARDOUR_UI::startup ()
625 new_session_dialog = new NewSessionDialog();
627 bool backend_audio_is_running = EngineControl::engine_running();
628 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
631 new_session_dialog->engine_control.set_state (*audio_setup);
634 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
638 BootMessage (_("Ardour is ready for use"));
643 ARDOUR_UI::no_memory_warning ()
645 XMLNode node (X_("no-memory-warning"));
646 Config->add_instant_xml (node, get_user_ardour_path());
650 ARDOUR_UI::check_memory_locking ()
653 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
657 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
659 if (engine->is_realtime() && memory_warning_node == 0) {
661 struct rlimit limits;
663 long pages, page_size;
665 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
668 ram = (int64_t) pages * (int64_t) page_size;
671 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
675 if (limits.rlim_cur != RLIM_INFINITY) {
677 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
680 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
681 "This might cause Ardour to run out of memory before your system "
682 "runs out of memory. \n\n"
683 "You can view the memory limit with 'ulimit -l', "
684 "and it is normally controlled by /etc/security/limits.conf"));
686 VBox* vbox = msg.get_vbox();
688 CheckButton cb (_("Do not show this window again"));
690 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
692 hbox.pack_start (cb, true, false);
693 vbox->pack_start (hbox);
711 if (session->transport_rolling()) {
712 session->request_stop ();
716 if (session->dirty()) {
717 switch (ask_about_saving_session(_("quit"))) {
722 /* use the default name */
723 if (save_state_canfail ("")) {
724 /* failed - don't quit */
725 MessageDialog msg (*editor,
727 Ardour was unable to save your session.\n\n\
728 If you still wish to quit, please use the\n\n\
729 \"Just quit\" option."));
740 session->set_deletion_in_progress ();
744 save_ardour_state ();
749 ARDOUR_UI::ask_about_saving_session (const string & what)
751 ArdourDialog window (_("ardour: save session?"));
752 Gtk::HBox dhbox; // the hbox for the image and text
753 Gtk::Label prompt_label;
754 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
758 msg = string_compose(_("Don't %1"), what);
759 window.add_button (msg, RESPONSE_REJECT);
760 msg = string_compose(_("Just %1"), what);
761 window.add_button (msg, RESPONSE_APPLY);
762 msg = string_compose(_("Save and %1"), what);
763 window.add_button (msg, RESPONSE_ACCEPT);
765 window.set_default_response (RESPONSE_ACCEPT);
767 Gtk::Button noquit_button (msg);
768 noquit_button.set_name ("EditorGTKButton");
773 if (session->snap_name() == session->name()) {
776 type = _("snapshot");
778 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?"),
779 type, session->snap_name());
781 prompt_label.set_text (prompt);
782 prompt_label.set_name (X_("PrompterLabel"));
783 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
785 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
787 dhbox.set_homogeneous (false);
788 dhbox.pack_start (*dimage, false, false, 5);
789 dhbox.pack_start (prompt_label, true, false, 5);
790 window.get_vbox()->pack_start (dhbox);
792 window.set_name (_("Prompter"));
793 window.set_position (Gtk::WIN_POS_MOUSE);
794 window.set_modal (true);
795 window.set_resizable (false);
798 save_the_session = 0;
800 window.set_keep_above (true);
803 ResponseType r = (ResponseType) window.run();
808 case RESPONSE_ACCEPT: // save and get out of here
810 case RESPONSE_APPLY: // get out of here
820 ARDOUR_UI::every_second ()
823 update_buffer_load ();
824 update_disk_space ();
829 ARDOUR_UI::every_point_one_seconds ()
831 update_speed_display ();
832 RapidScreenUpdate(); /* EMIT_SIGNAL */
837 ARDOUR_UI::every_point_zero_one_seconds ()
839 // august 2007: actual update frequency: 40Hz, not 100Hz
841 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
846 ARDOUR_UI::update_sample_rate (nframes_t ignored)
850 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
852 if (!engine->connected()) {
854 snprintf (buf, sizeof (buf), _("disconnected"));
858 nframes_t rate = engine->frame_rate();
860 if (fmod (rate, 1000.0) != 0.0) {
861 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
862 (float) rate/1000.0f,
863 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
865 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
867 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
871 sample_rate_label.set_text (buf);
875 ARDOUR_UI::update_cpu_load ()
878 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
879 cpu_load_label.set_text (buf);
883 ARDOUR_UI::update_buffer_load ()
888 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
889 session->playback_load(), session->capture_load());
890 buffer_load_label.set_text (buf);
892 buffer_load_label.set_text ("");
897 ARDOUR_UI::count_recenabled_streams (Route& route)
899 Track* track = dynamic_cast<Track*>(&route);
900 if (track && track->diskstream()->record_enabled()) {
901 rec_enabled_streams += track->n_inputs();
906 ARDOUR_UI::update_disk_space()
912 nframes_t frames = session->available_capture_duration();
915 if (frames == max_frames) {
916 strcpy (buf, _("Disk: 24hrs+"));
921 nframes_t fr = session->frame_rate();
923 rec_enabled_streams = 0;
924 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
926 if (rec_enabled_streams) {
927 frames /= rec_enabled_streams;
930 hrs = frames / (fr * 3600);
931 frames -= hrs * fr * 3600;
932 mins = frames / (fr * 60);
933 frames -= mins * fr * 60;
936 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
939 disk_space_label.set_text (buf);
943 ARDOUR_UI::update_wall_clock ()
950 tm_now = localtime (&now);
952 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
953 wall_clock_label.set_text (buf);
959 ARDOUR_UI::session_menu (GdkEventButton *ev)
961 session_popup_menu->popup (0, 0);
966 ARDOUR_UI::redisplay_recent_sessions ()
968 vector<string *> *sessions;
969 vector<string *>::iterator i;
970 RecentSessionsSorter cmp;
972 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
973 recent_session_model->clear ();
976 ARDOUR::read_recent_sessions (rs);
979 recent_session_display.set_model (recent_session_model);
983 /* sort them alphabetically */
984 sort (rs.begin(), rs.end(), cmp);
985 sessions = new vector<string*>;
987 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
988 sessions->push_back (new string ((*i).second));
991 for (i = sessions->begin(); i != sessions->end(); ++i) {
993 vector<string*>* states;
994 vector<const gchar*> item;
995 string fullpath = *(*i);
997 /* remove any trailing / */
999 if (fullpath[fullpath.length()-1] == '/') {
1000 fullpath = fullpath.substr (0, fullpath.length()-1);
1003 /* check whether session still exists */
1004 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1005 /* session doesn't exist */
1006 cerr << "skipping non-existent session " << fullpath << endl;
1010 /* now get available states for this session */
1012 if ((states = Session::possible_states (fullpath)) == 0) {
1013 /* no state file? */
1017 TreeModel::Row row = *(recent_session_model->append());
1019 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1020 row[recent_session_columns.fullpath] = fullpath;
1022 if (states->size() > 1) {
1024 /* add the children */
1026 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1028 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1030 child_row[recent_session_columns.visible_name] = **i2;
1031 child_row[recent_session_columns.fullpath] = fullpath;
1040 recent_session_display.set_model (recent_session_model);
1045 ARDOUR_UI::build_session_selector ()
1047 session_selector_window = new ArdourDialog ("session selector");
1049 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1051 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1052 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1053 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1054 recent_session_model = TreeStore::create (recent_session_columns);
1055 recent_session_display.set_model (recent_session_model);
1056 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1057 recent_session_display.set_headers_visible (false);
1058 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1059 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1061 scroller->add (recent_session_display);
1062 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1064 session_selector_window->set_name ("SessionSelectorWindow");
1065 session_selector_window->set_size_request (200, 400);
1066 session_selector_window->get_vbox()->pack_start (*scroller);
1067 session_selector_window->show_all_children();
1071 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1073 session_selector_window->response (RESPONSE_ACCEPT);
1077 ARDOUR_UI::open_recent_session ()
1079 bool can_return = (session != 0);
1081 if (session_selector_window == 0) {
1082 build_session_selector ();
1085 redisplay_recent_sessions ();
1089 session_selector_window->set_position (WIN_POS_MOUSE);
1091 ResponseType r = (ResponseType) session_selector_window->run ();
1094 case RESPONSE_ACCEPT:
1098 session_selector_window->hide();
1105 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1109 session_selector_window->hide();
1111 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1113 if (i == recent_session_model->children().end()) {
1117 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1118 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1120 _session_is_new = false;
1122 if (load_session (path, state) == 0) {
1131 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1133 struct stat statbuf;
1135 if (stat (info.filename.c_str(), &statbuf) != 0) {
1139 if (!S_ISDIR(statbuf.st_mode)) {
1145 string session_file = info.filename;
1146 session_file += '/';
1147 session_file += Glib::path_get_basename (info.filename);
1148 session_file += ".ardour";
1150 if (stat (session_file.c_str(), &statbuf) != 0) {
1154 return S_ISREG (statbuf.st_mode);
1158 ARDOUR_UI::check_audioengine ()
1161 if (!engine->connected()) {
1162 MessageDialog msg (_("Ardour is not connected to JACK\n"
1163 "You cannot open or close sessions in this condition"));
1175 ARDOUR_UI::open_session ()
1177 if (!check_audioengine()) {
1181 /* popup selector window */
1183 if (open_session_selector == 0) {
1185 /* ardour sessions are folders */
1187 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1188 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1189 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1190 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1192 FileFilter session_filter;
1193 session_filter.add_pattern ("*.ardour");
1194 session_filter.set_name (_("Ardour sessions"));
1195 open_session_selector->add_filter (session_filter);
1196 open_session_selector->set_filter (session_filter);
1199 int response = open_session_selector->run();
1200 open_session_selector->hide ();
1203 case RESPONSE_ACCEPT:
1206 open_session_selector->hide();
1210 open_session_selector->hide();
1211 string session_path = open_session_selector->get_filename();
1215 if (session_path.length() > 0) {
1216 if (Session::find_session (session_path, path, name, isnew) == 0) {
1217 _session_is_new = isnew;
1218 load_session (path, name);
1225 ARDOUR_UI::session_add_midi_track ()
1227 cerr << _("Patience is a virtue.\n");
1231 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1233 list<boost::shared_ptr<AudioTrack> > tracks;
1234 Session::RouteList routes;
1237 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1243 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1245 if (tracks.size() != how_many) {
1246 if (how_many == 1) {
1247 error << _("could not create a new audio track") << endmsg;
1249 error << string_compose (_("could only create %1 of %2 new audio %3"),
1250 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1256 routes = session->new_audio_route (input_channels, output_channels, how_many);
1258 if (routes.size() != how_many) {
1259 if (how_many == 1) {
1260 error << _("could not create a new audio track") << endmsg;
1262 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1268 if (need_control_room_outs) {
1274 route->set_stereo_control_outs (control_lr_channels);
1275 route->control_outs()->set_stereo_pan (pans, this);
1277 #endif /* CONTROLOUTS */
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::do_transport_locate (nframes_t new_position)
1294 nframes_t _preroll = 0;
1297 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1298 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1300 if (new_position > _preroll) {
1301 new_position -= _preroll;
1306 session->request_locate (new_position);
1311 ARDOUR_UI::transport_goto_start ()
1314 session->goto_start();
1317 /* force displayed area in editor to start no matter
1318 what "follow playhead" setting is.
1322 editor->reset_x_origin (session->current_start_frame());
1328 ARDOUR_UI::transport_goto_zero ()
1331 session->request_locate (0);
1334 /* force displayed area in editor to start no matter
1335 what "follow playhead" setting is.
1339 editor->reset_x_origin (0);
1345 ARDOUR_UI::transport_goto_end ()
1348 nframes_t frame = session->current_end_frame();
1349 session->request_locate (frame);
1351 /* force displayed area in editor to start no matter
1352 what "follow playhead" setting is.
1356 editor->reset_x_origin (frame);
1362 ARDOUR_UI::transport_stop ()
1368 if (session->is_auditioning()) {
1369 session->cancel_audition ();
1373 if (session->get_play_loop ()) {
1374 session->request_play_loop (false);
1377 session->request_stop ();
1381 ARDOUR_UI::transport_stop_and_forget_capture ()
1384 session->request_stop (true);
1389 ARDOUR_UI::remove_last_capture()
1392 editor->remove_last_capture();
1397 ARDOUR_UI::transport_record (bool roll)
1401 switch (session->record_status()) {
1402 case Session::Disabled:
1403 if (session->ntracks() == 0) {
1404 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1408 session->maybe_enable_record ();
1413 case Session::Recording:
1415 session->request_stop();
1417 session->disable_record (false, true);
1421 case Session::Enabled:
1422 session->disable_record (false, true);
1425 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1429 ARDOUR_UI::transport_roll ()
1437 rolling = session->transport_rolling ();
1439 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1441 if (session->get_play_loop()) {
1442 session->request_play_loop (false);
1443 auto_loop_button.set_visual_state (1);
1444 roll_button.set_visual_state (1);
1445 } else if (session->get_play_range ()) {
1446 session->request_play_range (false);
1447 play_selection_button.set_visual_state (0);
1448 } else if (rolling) {
1449 session->request_locate (session->last_transport_start(), true);
1452 session->request_transport_speed (1.0f);
1456 ARDOUR_UI::transport_loop()
1459 if (session->get_play_loop()) {
1460 if (session->transport_rolling()) {
1461 Location * looploc = session->locations()->auto_loop_location();
1463 session->request_locate (looploc->start(), true);
1468 session->request_play_loop (true);
1474 ARDOUR_UI::transport_play_selection ()
1480 if (!session->get_play_range()) {
1481 session->request_stop ();
1484 editor->play_selection ();
1488 ARDOUR_UI::transport_rewind (int option)
1490 float current_transport_speed;
1493 current_transport_speed = session->transport_speed();
1495 if (current_transport_speed >= 0.0f) {
1498 session->request_transport_speed (-1.0f);
1501 session->request_transport_speed (-4.0f);
1504 session->request_transport_speed (-0.5f);
1509 session->request_transport_speed (current_transport_speed * 1.5f);
1515 ARDOUR_UI::transport_forward (int option)
1517 float current_transport_speed;
1520 current_transport_speed = session->transport_speed();
1522 if (current_transport_speed <= 0.0f) {
1525 session->request_transport_speed (1.0f);
1528 session->request_transport_speed (4.0f);
1531 session->request_transport_speed (0.5f);
1536 session->request_transport_speed (current_transport_speed * 1.5f);
1542 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1548 boost::shared_ptr<Route> r;
1550 if ((r = session->route_by_remote_id (dstream)) != 0) {
1554 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1555 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1564 ARDOUR_UI::queue_transport_change ()
1566 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1570 ARDOUR_UI::map_transport_state ()
1572 float sp = session->transport_speed();
1575 transport_rolling ();
1576 } else if (sp < 0.0f) {
1577 transport_rewinding ();
1578 } else if (sp > 0.0f) {
1579 transport_forwarding ();
1581 transport_stopped ();
1586 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1588 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1589 (int) adj.get_value()].c_str());
1593 ARDOUR_UI::engine_stopped ()
1595 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1596 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1597 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1601 ARDOUR_UI::engine_running ()
1603 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1604 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1605 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1607 Glib::RefPtr<Action> action;
1608 const char* action_name = 0;
1610 switch (engine->frames_per_cycle()) {
1612 action_name = X_("JACKLatency32");
1615 action_name = X_("JACKLatency64");
1618 action_name = X_("JACKLatency128");
1621 action_name = X_("JACKLatency512");
1624 action_name = X_("JACKLatency1024");
1627 action_name = X_("JACKLatency2048");
1630 action_name = X_("JACKLatency4096");
1633 action_name = X_("JACKLatency8192");
1636 /* XXX can we do anything useful ? */
1642 action = ActionManager::get_action (X_("JACK"), action_name);
1645 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1646 ract->set_active ();
1652 ARDOUR_UI::engine_halted ()
1654 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1656 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1657 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1659 update_sample_rate (0);
1661 MessageDialog msg (*editor,
1663 JACK has either been shutdown or it\n\
1664 disconnected Ardour because Ardour\n\
1665 was not fast enough. You can save the\n\
1666 session and/or try to reconnect to JACK ."));
1672 ARDOUR_UI::do_engine_start ()
1680 error << _("Unable to start the session running")
1690 ARDOUR_UI::setup_theme ()
1692 theme_manager->setup_theme();
1696 ARDOUR_UI::update_clocks ()
1698 if (!editor || !editor->dragging_playhead()) {
1699 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1704 ARDOUR_UI::start_clocking ()
1706 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1710 ARDOUR_UI::stop_clocking ()
1712 clock_signal_connection.disconnect ();
1716 ARDOUR_UI::toggle_clocking ()
1719 if (clock_button.get_active()) {
1728 ARDOUR_UI::_blink (void *arg)
1731 ((ARDOUR_UI *) arg)->blink ();
1738 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1742 ARDOUR_UI::start_blinking ()
1744 /* Start the blink signal. Everybody with a blinking widget
1745 uses Blink to drive the widget's state.
1748 if (blink_timeout_tag < 0) {
1750 blink_timeout_tag = g_timeout_add (240, _blink, this);
1755 ARDOUR_UI::stop_blinking ()
1757 if (blink_timeout_tag >= 0) {
1758 g_source_remove (blink_timeout_tag);
1759 blink_timeout_tag = -1;
1764 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1770 if (io.n_inputs() == 0) {
1775 /* XXX we're not handling multiple ports yet. */
1777 const char **connections = io.input(0)->get_connections();
1779 if (connections == 0 || connections[0] == '\0') {
1782 buf = connections[0];
1789 if (io.n_outputs() == 0) {
1794 /* XXX we're not handling multiple ports yet. */
1796 const char **connections = io.output(0)->get_connections();
1798 if (connections == 0 || connections[0] == '\0') {
1801 buf = connections[0];
1808 /** Ask the user for the name of a new shapshot and then take it.
1811 ARDOUR_UI::snapshot_session ()
1813 ArdourPrompter prompter (true);
1817 struct tm local_time;
1820 localtime_r (&n, &local_time);
1821 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1823 prompter.set_name ("Prompter");
1824 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1825 prompter.set_prompt (_("Name of New Snapshot"));
1826 prompter.set_initial_text (timebuf);
1828 switch (prompter.run()) {
1829 case RESPONSE_ACCEPT:
1830 prompter.get_result (snapname);
1831 if (snapname.length()){
1832 save_state (snapname);
1842 ARDOUR_UI::save_state (const string & name)
1844 (void) save_state_canfail (name);
1848 ARDOUR_UI::save_state_canfail (string name)
1853 if (name.length() == 0) {
1854 name = session->snap_name();
1857 if ((ret = session->save_state (name)) != 0) {
1861 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1866 ARDOUR_UI::restore_state (string name)
1869 if (name.length() == 0) {
1870 name = session->name();
1872 session->restore_state (name);
1877 ARDOUR_UI::primary_clock_value_changed ()
1880 session->request_locate (primary_clock.current_time ());
1885 ARDOUR_UI::big_clock_value_changed ()
1888 session->request_locate (big_clock.current_time ());
1893 ARDOUR_UI::secondary_clock_value_changed ()
1896 session->request_locate (secondary_clock.current_time ());
1901 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1903 if (session && dstream && dstream->record_enabled()) {
1905 Session::RecordState rs;
1907 rs = session->record_status ();
1910 case Session::Disabled:
1911 case Session::Enabled:
1912 if (w->get_state() != STATE_SELECTED) {
1913 w->set_state (STATE_SELECTED);
1917 case Session::Recording:
1918 if (w->get_state() != STATE_ACTIVE) {
1919 w->set_state (STATE_ACTIVE);
1925 if (w->get_state() != STATE_NORMAL) {
1926 w->set_state (STATE_NORMAL);
1932 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1938 switch (session->record_status()) {
1939 case Session::Enabled:
1941 rec_button.set_visual_state (2);
1943 rec_button.set_visual_state (0);
1947 case Session::Recording:
1948 rec_button.set_visual_state (1);
1952 rec_button.set_visual_state (0);
1958 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1966 ARDOUR_UI::save_template ()
1969 ArdourPrompter prompter (true);
1972 if (!check_audioengine()) {
1976 prompter.set_name (X_("Prompter"));
1977 prompter.set_prompt (_("Name for mix template:"));
1978 prompter.set_initial_text(session->name() + _("-template"));
1979 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1981 switch (prompter.run()) {
1982 case RESPONSE_ACCEPT:
1983 prompter.get_result (name);
1985 if (name.length()) {
1986 session->save_template (name);
1996 ARDOUR_UI::fontconfig_dialog ()
1999 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2000 may not and it can take a while to build it. Warn them.
2003 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2005 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2006 MessageDialog msg (*new_session_dialog,
2007 _("Welcome to Ardour.\n\n"
2008 "The program will take a bit longer to start up\n"
2009 "while the system fonts are checked.\n\n"
2010 "This will only be done once, and you will\n"
2011 "not see this message again\n"),
2024 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2026 existing_session = false;
2028 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2029 session_path = cmdline_path;
2030 existing_session = true;
2031 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2032 session_path = Glib::path_get_dirname (string (cmdline_path));
2033 existing_session = true;
2035 /* it doesn't exist, assume the best */
2036 session_path = Glib::path_get_dirname (string (cmdline_path));
2039 session_name = basename_nosuffix (string (cmdline_path));
2043 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2045 /* when this is called, the backend audio system must be running */
2047 /* the main idea here is to deal with the fact that a cmdline argument for the session
2048 can be interpreted in different ways - it could be a directory or a file, and before
2049 we load, we need to know both the session directory and the snapshot (statefile) within it
2050 that we are supposed to use.
2053 if (session_name.length() == 0 || session_path.length() == 0) {
2057 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2059 Glib::ustring predicted_session_file;
2061 predicted_session_file = session_path;
2062 predicted_session_file += '/';
2063 predicted_session_file += session_name;
2064 predicted_session_file += Session::statefile_suffix();
2066 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2067 existing_session = true;
2070 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2072 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2073 /* existing .ardour file */
2074 existing_session = true;
2078 existing_session = false;
2081 /* lets just try to load it */
2083 if (create_engine ()) {
2084 backend_audio_error (false, new_session_dialog);
2088 return load_session (session_path, session_name);
2092 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2094 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2096 MessageDialog msg (str,
2098 Gtk::MESSAGE_WARNING,
2099 Gtk::BUTTONS_YES_NO,
2103 msg.set_name (X_("CleanupDialog"));
2104 msg.set_wmclass (X_("existing_session"), "Ardour");
2105 msg.set_position (Gtk::WIN_POS_MOUSE);
2108 switch (msg.run()) {
2117 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2122 AutoConnectOption iconnect;
2123 AutoConnectOption oconnect;
2127 if (Profile->get_sae()) {
2131 iconnect = AutoConnectPhysical;
2132 oconnect = AutoConnectMaster;
2133 nphysin = 0; // use all available
2134 nphysout = 0; // use all available
2138 /* get settings from advanced section of NSD */
2140 if (new_session_dialog->create_control_bus()) {
2141 cchns = (uint32_t) new_session_dialog->control_channel_count();
2146 if (new_session_dialog->create_master_bus()) {
2147 mchns = (uint32_t) new_session_dialog->master_channel_count();
2152 if (new_session_dialog->connect_inputs()) {
2153 iconnect = AutoConnectPhysical;
2155 iconnect = AutoConnectOption (0);
2158 /// @todo some minor tweaks.
2160 if (new_session_dialog->connect_outs_to_master()) {
2161 oconnect = AutoConnectMaster;
2162 } else if (new_session_dialog->connect_outs_to_physical()) {
2163 oconnect = AutoConnectPhysical;
2165 oconnect = AutoConnectOption (0);
2168 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2169 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2172 if (build_session (session_path,
2180 engine->frame_rate() * 60 * 5)) {
2189 ARDOUR_UI::end_loading_messages ()
2195 ARDOUR_UI::loading_message (const std::string& msg)
2198 splash->message (msg);
2203 ARDOUR_UI::idle_load (const Glib::ustring& path)
2206 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2207 /* /path/to/foo => /path/to/foo, foo */
2208 load_session (path, basename_nosuffix (path));
2210 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2211 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2214 ARDOUR_COMMAND_LINE::session_name = path;
2215 if (new_session_dialog) {
2216 /* make it break out of Dialog::run() and
2219 new_session_dialog->response (1);
2225 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2227 bool existing_session = false;
2228 Glib::ustring session_name;
2229 Glib::ustring session_path;
2230 Glib::ustring template_name;
2234 response = Gtk::RESPONSE_NONE;
2236 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2238 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2240 /* don't ever reuse this */
2242 ARDOUR_COMMAND_LINE::session_name = string();
2244 if (existing_session && backend_audio_is_running) {
2246 /* just load the thing already */
2248 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2253 /* make the NSD use whatever information we have */
2255 new_session_dialog->set_session_name (session_name);
2256 new_session_dialog->set_session_folder (session_path);
2259 /* loading failed, or we need the NSD for something */
2261 new_session_dialog->set_modal (false);
2262 new_session_dialog->set_position (WIN_POS_CENTER);
2263 new_session_dialog->set_current_page (0);
2264 new_session_dialog->set_existing_session (existing_session);
2265 new_session_dialog->reset_recent();
2268 new_session_dialog->set_have_engine (backend_audio_is_running);
2269 new_session_dialog->present ();
2270 response = new_session_dialog->run ();
2272 _session_is_new = false;
2274 /* handle possible negative responses */
2278 /* sent by idle_load, meaning restart the whole process again */
2279 new_session_dialog->hide();
2280 new_session_dialog->reset();
2284 case Gtk::RESPONSE_CANCEL:
2285 case Gtk::RESPONSE_DELETE_EVENT:
2289 new_session_dialog->hide ();
2292 case Gtk::RESPONSE_NONE:
2293 /* "Clear" was pressed */
2297 fontconfig_dialog();
2299 if (!backend_audio_is_running) {
2300 if (new_session_dialog->engine_control.setup_engine ()) {
2301 new_session_dialog->hide ();
2306 if (create_engine ()) {
2308 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2311 new_session_dialog->set_existing_session (false);
2312 new_session_dialog->set_current_page (2);
2314 response = Gtk::RESPONSE_NONE;
2318 backend_audio_is_running = true;
2320 if (response == Gtk::RESPONSE_OK) {
2322 session_name = new_session_dialog->session_name();
2324 if (session_name.empty()) {
2325 response = Gtk::RESPONSE_NONE;
2329 /* if the user mistakenly typed path information into the session filename entry,
2330 convert what they typed into a path & a name
2333 if (session_name[0] == '/' ||
2334 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2335 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2337 session_path = Glib::path_get_dirname (session_name);
2338 session_name = Glib::path_get_basename (session_name);
2342 session_path = new_session_dialog->session_folder();
2345 template_name = Glib::ustring();
2346 switch (new_session_dialog->which_page()) {
2348 case NewSessionDialog::OpenPage:
2349 case NewSessionDialog::EnginePage:
2353 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2355 should_be_new = true;
2357 //XXX This is needed because session constructor wants a
2358 //non-existant path. hopefully this will be fixed at some point.
2360 session_path = Glib::build_filename (session_path, session_name);
2362 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2364 if (ask_about_loading_existing_session (session_path)) {
2367 response = RESPONSE_NONE;
2372 _session_is_new = true;
2374 if (new_session_dialog->use_session_template()) {
2376 template_name = new_session_dialog->session_template_name();
2380 if (build_session_from_nsd (session_path, session_name)) {
2381 response = RESPONSE_NONE;
2393 new_session_dialog->hide ();
2395 if (load_session (session_path, session_name, template_name)) {
2397 response = Gtk::RESPONSE_NONE;
2401 if (response == Gtk::RESPONSE_NONE) {
2402 new_session_dialog->set_existing_session (false);
2403 new_session_dialog->reset ();
2407 } while (response == Gtk::RESPONSE_NONE);
2411 new_session_dialog->hide();
2412 new_session_dialog->reset();
2413 goto_editor_window ();
2418 ARDOUR_UI::close_session ()
2420 if (!check_audioengine()) {
2424 unload_session (true);
2426 get_session_parameters (true, false);
2430 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2432 Session *new_session;
2436 session_loaded = false;
2438 if (!check_audioengine()) {
2442 unload_status = unload_session ();
2444 if (unload_status < 0) {
2446 } else if (unload_status > 0) {
2451 /* if it already exists, we must have write access */
2453 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2454 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2455 "This prevents the session from being loaded."));
2461 loading_message (_("Please wait while Ardour loads your session"));
2464 new_session = new Session (*engine, path, snap_name, mix_template);
2467 /* this one is special */
2469 catch (AudioEngine::PortRegistrationFailure& err) {
2471 MessageDialog msg (err.what(),
2474 Gtk::BUTTONS_OK_CANCEL);
2476 msg.set_title (_("Loading Error"));
2477 msg.set_secondary_text (_("Click the OK button to try again."));
2478 msg.set_position (Gtk::WIN_POS_CENTER);
2482 int response = msg.run ();
2487 case RESPONSE_CANCEL:
2497 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2500 Gtk::BUTTONS_OK_CANCEL);
2502 msg.set_title (_("Loading Error"));
2503 msg.set_secondary_text (_("Click the OK button to try again."));
2504 msg.set_position (Gtk::WIN_POS_CENTER);
2508 int response = msg.run ();
2513 case RESPONSE_CANCEL:
2521 connect_to_session (new_session);
2523 Config->set_current_owner (ConfigVariableBase::Interface);
2525 session_loaded = true;
2527 goto_editor_window ();
2530 session->set_clean ();
2541 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2542 uint32_t control_channels,
2543 uint32_t master_channels,
2544 AutoConnectOption input_connect,
2545 AutoConnectOption output_connect,
2548 nframes_t initial_length)
2550 Session *new_session;
2553 if (!check_audioengine()) {
2557 session_loaded = false;
2559 x = unload_session ();
2567 _session_is_new = true;
2570 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2571 control_channels, master_channels, nphysin, nphysout, initial_length);
2576 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2582 connect_to_session (new_session);
2584 session_loaded = true;
2592 editor->show_window ();
2603 ARDOUR_UI::show_about ()
2607 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2614 ARDOUR_UI::hide_about ()
2617 about->get_window()->set_cursor ();
2623 ARDOUR_UI::about_signal_response(int response)
2629 ARDOUR_UI::show_splash ()
2633 splash = new Splash;
2641 splash->queue_draw ();
2642 splash->get_window()->process_updates (true);
2647 ARDOUR_UI::hide_splash ()
2655 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2659 removed = rep.paths.size();
2662 MessageDialog msgd (*editor,
2663 _("No audio files were ready for cleanup"),
2666 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2667 msgd.set_secondary_text (_("If this seems suprising, \n\
2668 check for any existing snapshots.\n\
2669 These may still include regions that\n\
2670 require some unused files to continue to exist."));
2676 ArdourDialog results (_("ardour: cleanup"), true, false);
2678 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2679 CleanupResultsModelColumns() {
2683 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2684 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2688 CleanupResultsModelColumns results_columns;
2689 Glib::RefPtr<Gtk::ListStore> results_model;
2690 Gtk::TreeView results_display;
2692 results_model = ListStore::create (results_columns);
2693 results_display.set_model (results_model);
2694 results_display.append_column (list_title, results_columns.visible_name);
2696 results_display.set_name ("CleanupResultsList");
2697 results_display.set_headers_visible (true);
2698 results_display.set_headers_clickable (false);
2699 results_display.set_reorderable (false);
2701 Gtk::ScrolledWindow list_scroller;
2704 Gtk::HBox dhbox; // the hbox for the image and text
2705 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2706 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2708 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2710 if (rep.space < 1048576.0f) {
2712 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2714 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2718 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2720 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2724 dhbox.pack_start (*dimage, true, false, 5);
2725 dhbox.pack_start (txt, true, false, 5);
2727 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2728 TreeModel::Row row = *(results_model->append());
2729 row[results_columns.visible_name] = *i;
2730 row[results_columns.fullpath] = *i;
2733 list_scroller.add (results_display);
2734 list_scroller.set_size_request (-1, 150);
2735 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2737 dvbox.pack_start (dhbox, true, false, 5);
2738 dvbox.pack_start (list_scroller, true, false, 5);
2739 ddhbox.pack_start (dvbox, true, false, 5);
2741 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2742 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2743 results.set_default_response (RESPONSE_CLOSE);
2744 results.set_position (Gtk::WIN_POS_MOUSE);
2745 results.show_all_children ();
2746 results.set_resizable (false);
2753 ARDOUR_UI::cleanup ()
2756 /* shouldn't happen: menu item is insensitive */
2761 MessageDialog checker (_("Are you sure you want to cleanup?"),
2763 Gtk::MESSAGE_QUESTION,
2764 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2766 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2767 ALL undo/redo information will be lost if you cleanup.\n\
2768 After cleanup, unused audio files will be moved to a \
2769 \"dead sounds\" location."));
2771 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2772 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2773 checker.set_default_response (RESPONSE_CANCEL);
2775 checker.set_name (_("CleanupDialog"));
2776 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2777 checker.set_position (Gtk::WIN_POS_MOUSE);
2779 switch (checker.run()) {
2780 case RESPONSE_ACCEPT:
2786 Session::cleanup_report rep;
2788 editor->prepare_for_cleanup ();
2790 /* do not allow flush until a session is reloaded */
2792 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2794 act->set_sensitive (false);
2797 if (session->cleanup_sources (rep)) {
2802 display_cleanup_results (rep,
2805 The following %1 %2 not in use and \n\
2806 have been moved to:\n\
2808 Flushing the wastebasket will \n\
2809 release an additional\n\
2810 %4 %5bytes of disk space.\n"
2818 ARDOUR_UI::flush_trash ()
2821 /* shouldn't happen: menu item is insensitive */
2825 Session::cleanup_report rep;
2827 if (session->cleanup_trash_sources (rep)) {
2831 display_cleanup_results (rep,
2833 _("The following %1 %2 deleted from\n\
2835 releasing %4 %5bytes of disk space"));
2839 ARDOUR_UI::add_route (Gtk::Window* float_window)
2847 if (add_route_dialog == 0) {
2848 add_route_dialog = new AddRouteDialog;
2850 add_route_dialog->set_transient_for (*float_window);
2854 if (add_route_dialog->is_visible()) {
2855 /* we're already doing this */
2859 ResponseType r = (ResponseType) add_route_dialog->run ();
2861 add_route_dialog->hide();
2864 case RESPONSE_ACCEPT:
2871 if ((count = add_route_dialog->count()) <= 0) {
2875 uint32_t input_chan = add_route_dialog->channels ();
2876 uint32_t output_chan;
2877 string name_template = add_route_dialog->name_template ();
2878 bool track = add_route_dialog->track ();
2880 AutoConnectOption oac = Config->get_output_auto_connect();
2882 if (oac & AutoConnectMaster) {
2883 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2885 output_chan = input_chan;
2888 /* XXX do something with name template */
2890 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2893 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2895 session_add_audio_bus (input_chan, output_chan, count);
2900 ARDOUR_UI::mixer_settings () const
2905 node = session->instant_xml(X_("Mixer"), session->path());
2907 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2911 node = new XMLNode (X_("Mixer"));
2918 ARDOUR_UI::editor_settings () const
2923 node = session->instant_xml(X_("Editor"), session->path());
2925 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2929 node = new XMLNode (X_("Editor"));
2935 ARDOUR_UI::keyboard_settings () const
2939 node = Config->extra_xml(X_("Keyboard"));
2942 node = new XMLNode (X_("Keyboard"));
2948 ARDOUR_UI::create_xrun_marker(nframes_t where)
2950 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
2951 editor->mouse_add_new_marker (where, false, true);
2955 ARDOUR_UI::halt_on_xrun_message ()
2957 MessageDialog msg (*editor,
2958 _("Recording was stopped because your system could not keep up."));
2963 ARDOUR_UI::xrun_handler(nframes_t where)
2965 if (Config->get_create_xrun_marker() && session->actively_recording()) {
2966 create_xrun_marker(where);
2969 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2970 halt_on_xrun_message ();
2975 ARDOUR_UI::disk_overrun_handler ()
2977 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2979 if (!have_disk_speed_dialog_displayed) {
2980 have_disk_speed_dialog_displayed = true;
2981 MessageDialog* msg = new MessageDialog (*editor, _("\
2982 The disk system on your computer\n\
2983 was not able to keep up with Ardour.\n\
2985 Specifically, it failed to write data to disk\n\
2986 quickly enough to keep up with recording.\n"));
2987 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2993 ARDOUR_UI::disk_underrun_handler ()
2995 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2997 if (!have_disk_speed_dialog_displayed) {
2998 have_disk_speed_dialog_displayed = true;
2999 MessageDialog* msg = new MessageDialog (*editor,
3000 _("The disk system on your computer\n\
3001 was not able to keep up with Ardour.\n\
3003 Specifically, it failed to read data from disk\n\
3004 quickly enough to keep up with playback.\n"));
3005 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3011 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3013 have_disk_speed_dialog_displayed = false;
3018 ARDOUR_UI::session_dialog (std::string msg)
3020 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3025 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3027 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3036 ARDOUR_UI::pending_state_dialog ()
3038 HBox* hbox = new HBox();
3039 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3040 ArdourDialog dialog (_("Crash Recovery"), true);
3042 This session appears to have been in\n\
3043 middle of recording when ardour or\n\
3044 the computer was shutdown.\n\
3046 Ardour can recover any captured audio for\n\
3047 you, or it can ignore it. Please decide\n\
3048 what you would like to do.\n"));
3049 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3050 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3051 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3052 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3053 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3054 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3055 dialog.set_default_response (RESPONSE_ACCEPT);
3056 dialog.set_position (WIN_POS_CENTER);
3061 switch (dialog.run ()) {
3062 case RESPONSE_ACCEPT:
3070 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3072 HBox* hbox = new HBox();
3073 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3074 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3075 Label message (string_compose (_("\
3076 This session was created with a sample rate of %1 Hz\n\
3078 The audioengine is currently running at %2 Hz\n"), desired, actual));
3080 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3081 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3082 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3083 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3084 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3085 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3086 dialog.set_default_response (RESPONSE_ACCEPT);
3087 dialog.set_position (WIN_POS_CENTER);
3092 switch (dialog.run ()) {
3093 case RESPONSE_ACCEPT:
3102 ARDOUR_UI::disconnect_from_jack ()
3105 if( engine->disconnect_from_jack ()) {
3106 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3110 update_sample_rate (0);
3115 ARDOUR_UI::reconnect_to_jack ()
3118 if (engine->reconnect_to_jack ()) {
3119 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3123 update_sample_rate (0);
3128 ARDOUR_UI::use_config ()
3130 Glib::RefPtr<Action> act;
3132 switch (Config->get_native_file_data_format ()) {
3134 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3137 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3140 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3145 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3146 ract->set_active ();
3149 switch (Config->get_native_file_header_format ()) {
3151 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3154 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3157 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3160 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3163 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3166 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3169 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3174 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3175 ract->set_active ();
3178 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3180 set_transport_controllable_state (*node);
3185 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3187 if (Config->get_primary_clock_delta_edit_cursor()) {
3188 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3190 primary_clock.set (pos, 0, true);
3193 if (Config->get_secondary_clock_delta_edit_cursor()) {
3194 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3196 secondary_clock.set (pos);
3199 if (big_clock_window) {
3200 big_clock.set (pos);
3205 ARDOUR_UI::record_state_changed ()
3207 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3209 if (!session || !big_clock_window) {
3210 /* why bother - the clock isn't visible */
3214 switch (session->record_status()) {
3215 case Session::Recording:
3216 big_clock.set_widget_name ("BigClockRecording");
3219 big_clock.set_widget_name ("BigClockNonRecording");
3225 ARDOUR_UI::first_idle ()
3228 session->allow_auto_play (true);
3232 editor->first_idle();
3235 Keyboard::set_can_save_keybindings (true);
3240 ARDOUR_UI::store_clock_modes ()
3242 XMLNode* node = new XMLNode(X_("ClockModes"));
3244 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3245 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3248 session->add_extra_xml (*node);
3249 session->set_dirty ();
3254 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3255 : Controllable (name), ui (u), type(tp)
3261 ARDOUR_UI::TransportControllable::set_value (float val)
3263 if (type == ShuttleControl) {
3270 fract = -((0.5f - val)/0.5f);
3272 fract = ((val - 0.5f)/0.5f);
3276 ui.set_shuttle_fract (fract);
3281 /* do nothing: these are radio-style actions */
3285 const char *action = 0;
3289 action = X_("Roll");
3292 action = X_("Stop");
3295 action = X_("Goto Start");
3298 action = X_("Goto End");
3301 action = X_("Loop");
3304 action = X_("Play Selection");
3307 action = X_("Record");
3317 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3325 ARDOUR_UI::TransportControllable::get_value (void) const
3344 case ShuttleControl:
3354 ARDOUR_UI::TransportControllable::set_id (const string& str)
3360 ARDOUR_UI::setup_profile ()
3362 if (gdk_screen_width() < 1200) {
3363 Profile->set_small_screen ();
3366 if (getenv ("ARDOUR_SAE")) {
3367 Profile->set_sae ();
3368 Profile->set_single_package ();