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 cerr << "\n\n\nNEW SESSION DIALOG\n\n\n";
643 new_session_dialog = new NewSessionDialog();
645 bool backend_audio_is_running = EngineControl::engine_running();
646 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
649 new_session_dialog->engine_control.set_state (*audio_setup);
652 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
656 BootMessage (_("Ardour is ready for use"));
661 ARDOUR_UI::no_memory_warning ()
663 XMLNode node (X_("no-memory-warning"));
664 Config->add_instant_xml (node, get_user_ardour_path());
668 ARDOUR_UI::check_memory_locking ()
671 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
675 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
677 if (engine->is_realtime() && memory_warning_node == 0) {
679 struct rlimit limits;
681 long pages, page_size;
683 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
686 ram = (int64_t) pages * (int64_t) page_size;
689 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
693 if (limits.rlim_cur != RLIM_INFINITY) {
695 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
698 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
699 "This might cause Ardour to run out of memory before your system "
700 "runs out of memory. \n\n"
701 "You can view the memory limit with 'ulimit -l', "
702 "and it is normally controlled by /etc/security/limits.conf"));
704 VBox* vbox = msg.get_vbox();
706 CheckButton cb (_("Do not show this window again"));
708 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
710 hbox.pack_start (cb, true, false);
711 vbox->pack_start (hbox);
729 if (session->transport_rolling()) {
730 session->request_stop ();
734 if (session->dirty()) {
735 switch (ask_about_saving_session(_("quit"))) {
740 /* use the default name */
741 if (save_state_canfail ("")) {
742 /* failed - don't quit */
743 MessageDialog msg (*editor,
745 Ardour was unable to save your session.\n\n\
746 If you still wish to quit, please use the\n\n\
747 \"Just quit\" option."));
758 session->set_deletion_in_progress ();
761 ArdourDialog::close_all_dialogs ();
763 save_ardour_state ();
768 ARDOUR_UI::ask_about_saving_session (const string & what)
770 ArdourDialog window (_("ardour: save session?"));
771 Gtk::HBox dhbox; // the hbox for the image and text
772 Gtk::Label prompt_label;
773 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
777 msg = string_compose(_("Don't %1"), what);
778 window.add_button (msg, RESPONSE_REJECT);
779 msg = string_compose(_("Just %1"), what);
780 window.add_button (msg, RESPONSE_APPLY);
781 msg = string_compose(_("Save and %1"), what);
782 window.add_button (msg, RESPONSE_ACCEPT);
784 window.set_default_response (RESPONSE_ACCEPT);
786 Gtk::Button noquit_button (msg);
787 noquit_button.set_name ("EditorGTKButton");
792 if (session->snap_name() == session->name()) {
795 type = _("snapshot");
797 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?"),
798 type, session->snap_name());
800 prompt_label.set_text (prompt);
801 prompt_label.set_name (X_("PrompterLabel"));
802 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
804 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
806 dhbox.set_homogeneous (false);
807 dhbox.pack_start (*dimage, false, false, 5);
808 dhbox.pack_start (prompt_label, true, false, 5);
809 window.get_vbox()->pack_start (dhbox);
811 window.set_name (_("Prompter"));
812 window.set_position (Gtk::WIN_POS_MOUSE);
813 window.set_modal (true);
814 window.set_resizable (false);
817 window.set_keep_above (true);
820 ResponseType r = (ResponseType) window.run();
825 case RESPONSE_ACCEPT: // save and get out of here
827 case RESPONSE_APPLY: // get out of here
837 ARDOUR_UI::every_second ()
840 update_buffer_load ();
841 update_disk_space ();
846 ARDOUR_UI::every_point_one_seconds ()
848 update_speed_display ();
849 RapidScreenUpdate(); /* EMIT_SIGNAL */
854 ARDOUR_UI::every_point_zero_one_seconds ()
856 // august 2007: actual update frequency: 40Hz, not 100Hz
858 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
863 ARDOUR_UI::update_sample_rate (nframes_t ignored)
867 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
869 if (!engine->connected()) {
871 snprintf (buf, sizeof (buf), _("disconnected"));
875 nframes_t rate = engine->frame_rate();
877 if (fmod (rate, 1000.0) != 0.0) {
878 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
879 (float) rate/1000.0f,
880 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
882 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
884 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
888 sample_rate_label.set_text (buf);
892 ARDOUR_UI::update_cpu_load ()
895 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
896 cpu_load_label.set_text (buf);
900 ARDOUR_UI::update_buffer_load ()
905 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
906 session->playback_load(), session->capture_load());
907 buffer_load_label.set_text (buf);
909 buffer_load_label.set_text ("");
914 ARDOUR_UI::count_recenabled_streams (Route& route)
916 Track* track = dynamic_cast<Track*>(&route);
917 if (track && track->diskstream()->record_enabled()) {
918 rec_enabled_streams += track->n_inputs();
923 ARDOUR_UI::update_disk_space()
929 nframes_t frames = session->available_capture_duration();
932 if (frames == max_frames) {
933 strcpy (buf, _("Disk: 24hrs+"));
938 nframes_t fr = session->frame_rate();
940 rec_enabled_streams = 0;
941 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
943 if (rec_enabled_streams) {
944 frames /= rec_enabled_streams;
947 hrs = frames / (fr * 3600);
948 frames -= hrs * fr * 3600;
949 mins = frames / (fr * 60);
950 frames -= mins * fr * 60;
953 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
956 disk_space_label.set_text (buf);
960 ARDOUR_UI::update_wall_clock ()
967 tm_now = localtime (&now);
969 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
970 wall_clock_label.set_text (buf);
976 ARDOUR_UI::session_menu (GdkEventButton *ev)
978 session_popup_menu->popup (0, 0);
983 ARDOUR_UI::redisplay_recent_sessions ()
985 vector<string *> *sessions;
986 vector<string *>::iterator i;
987 RecentSessionsSorter cmp;
989 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
990 recent_session_model->clear ();
993 ARDOUR::read_recent_sessions (rs);
996 recent_session_display.set_model (recent_session_model);
1000 /* sort them alphabetically */
1001 sort (rs.begin(), rs.end(), cmp);
1002 sessions = new vector<string*>;
1004 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1005 sessions->push_back (new string ((*i).second));
1008 for (i = sessions->begin(); i != sessions->end(); ++i) {
1010 vector<string*>* states;
1011 vector<const gchar*> item;
1012 string fullpath = *(*i);
1014 /* remove any trailing / */
1016 if (fullpath[fullpath.length()-1] == '/') {
1017 fullpath = fullpath.substr (0, fullpath.length()-1);
1020 /* check whether session still exists */
1021 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1022 /* session doesn't exist */
1023 cerr << "skipping non-existent session " << fullpath << endl;
1027 /* now get available states for this session */
1029 if ((states = Session::possible_states (fullpath)) == 0) {
1030 /* no state file? */
1034 TreeModel::Row row = *(recent_session_model->append());
1036 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1037 row[recent_session_columns.fullpath] = fullpath;
1039 if (states->size() > 1) {
1041 /* add the children */
1043 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1045 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1047 child_row[recent_session_columns.visible_name] = **i2;
1048 child_row[recent_session_columns.fullpath] = fullpath;
1057 recent_session_display.set_model (recent_session_model);
1062 ARDOUR_UI::build_session_selector ()
1064 session_selector_window = new ArdourDialog ("session selector");
1066 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1068 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1069 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1070 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1071 recent_session_model = TreeStore::create (recent_session_columns);
1072 recent_session_display.set_model (recent_session_model);
1073 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1074 recent_session_display.set_headers_visible (false);
1075 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1076 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1078 scroller->add (recent_session_display);
1079 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1081 session_selector_window->set_name ("SessionSelectorWindow");
1082 session_selector_window->set_size_request (200, 400);
1083 session_selector_window->get_vbox()->pack_start (*scroller);
1084 session_selector_window->show_all_children();
1088 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1090 session_selector_window->response (RESPONSE_ACCEPT);
1094 ARDOUR_UI::open_recent_session ()
1096 bool can_return = (session != 0);
1098 if (session_selector_window == 0) {
1099 build_session_selector ();
1102 redisplay_recent_sessions ();
1106 session_selector_window->set_position (WIN_POS_MOUSE);
1108 ResponseType r = (ResponseType) session_selector_window->run ();
1111 case RESPONSE_ACCEPT:
1115 session_selector_window->hide();
1122 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1126 session_selector_window->hide();
1128 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1130 if (i == recent_session_model->children().end()) {
1134 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1135 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1137 _session_is_new = false;
1139 if (load_session (path, state) == 0) {
1148 ARDOUR_UI::check_audioengine ()
1151 if (!engine->connected()) {
1152 MessageDialog msg (_("Ardour is not connected to JACK\n"
1153 "You cannot open or close sessions in this condition"));
1165 ARDOUR_UI::open_session ()
1167 if (!check_audioengine()) {
1171 /* popup selector window */
1173 if (open_session_selector == 0) {
1175 /* ardour sessions are folders */
1177 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1178 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1179 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1180 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1182 FileFilter session_filter;
1183 session_filter.add_pattern ("*.ardour");
1184 session_filter.set_name (_("Ardour sessions"));
1185 open_session_selector->add_filter (session_filter);
1186 open_session_selector->set_filter (session_filter);
1189 int response = open_session_selector->run();
1190 open_session_selector->hide ();
1193 case RESPONSE_ACCEPT:
1196 open_session_selector->hide();
1200 open_session_selector->hide();
1201 string session_path = open_session_selector->get_filename();
1205 if (session_path.length() > 0) {
1206 if (Session::find_session (session_path, path, name, isnew) == 0) {
1207 _session_is_new = isnew;
1208 load_session (path, name);
1215 ARDOUR_UI::session_add_midi_track ()
1217 cerr << _("Patience is a virtue.\n");
1221 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1223 list<boost::shared_ptr<AudioTrack> > tracks;
1224 Session::RouteList routes;
1227 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1233 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1235 if (tracks.size() != how_many) {
1236 if (how_many == 1) {
1237 error << _("could not create a new audio track") << endmsg;
1239 error << string_compose (_("could only create %1 of %2 new audio %3"),
1240 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1246 routes = session->new_audio_route (input_channels, output_channels, how_many);
1248 if (routes.size() != how_many) {
1249 if (how_many == 1) {
1250 error << _("could not create a new audio track") << endmsg;
1252 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1258 if (need_control_room_outs) {
1264 route->set_stereo_control_outs (control_lr_channels);
1265 route->control_outs()->set_stereo_pan (pans, this);
1267 #endif /* CONTROLOUTS */
1271 MessageDialog msg (*editor,
1272 _("There are insufficient JACK ports available\n\
1273 to create a new track or bus.\n\
1274 You should save Ardour, exit and\n\
1275 restart JACK with more ports."));
1282 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1284 nframes_t _preroll = 0;
1287 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1288 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1290 if (new_position > _preroll) {
1291 new_position -= _preroll;
1296 session->request_locate (new_position);
1301 ARDOUR_UI::transport_goto_start ()
1304 session->goto_start();
1307 /* force displayed area in editor to start no matter
1308 what "follow playhead" setting is.
1312 editor->reset_x_origin (session->current_start_frame());
1318 ARDOUR_UI::transport_goto_zero ()
1321 session->request_locate (0);
1324 /* force displayed area in editor to start no matter
1325 what "follow playhead" setting is.
1329 editor->reset_x_origin (0);
1335 ARDOUR_UI::transport_goto_wallclock ()
1337 if (session && editor) {
1344 localtime_r (&now, &tmnow);
1346 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1347 frames += tmnow.tm_min * (60 * session->frame_rate());
1348 frames += tmnow.tm_sec * session->frame_rate();
1350 session->request_locate (frames);
1352 /* force displayed area in editor to start no matter
1353 what "follow playhead" setting is.
1357 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1363 ARDOUR_UI::transport_goto_end ()
1366 nframes_t frame = session->current_end_frame();
1367 session->request_locate (frame);
1369 /* force displayed area in editor to start no matter
1370 what "follow playhead" setting is.
1374 editor->reset_x_origin (frame);
1380 ARDOUR_UI::transport_stop ()
1386 if (session->is_auditioning()) {
1387 session->cancel_audition ();
1391 if (session->get_play_loop ()) {
1392 session->request_play_loop (false);
1395 session->request_stop ();
1399 ARDOUR_UI::transport_stop_and_forget_capture ()
1402 session->request_stop (true);
1407 ARDOUR_UI::remove_last_capture()
1410 editor->remove_last_capture();
1415 ARDOUR_UI::transport_record (bool roll)
1419 switch (session->record_status()) {
1420 case Session::Disabled:
1421 if (session->ntracks() == 0) {
1422 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1426 session->maybe_enable_record ();
1431 case Session::Recording:
1433 session->request_stop();
1435 session->disable_record (false, true);
1439 case Session::Enabled:
1440 session->disable_record (false, true);
1443 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1447 ARDOUR_UI::transport_roll ()
1455 rolling = session->transport_rolling ();
1457 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1459 if (session->get_play_loop()) {
1460 session->request_play_loop (false);
1461 auto_loop_button.set_visual_state (1);
1462 roll_button.set_visual_state (1);
1463 } else if (session->get_play_range ()) {
1464 session->request_play_range (false);
1465 play_selection_button.set_visual_state (0);
1466 } else if (rolling) {
1467 session->request_locate (session->last_transport_start(), true);
1470 session->request_transport_speed (1.0f);
1474 ARDOUR_UI::transport_loop()
1477 if (session->get_play_loop()) {
1478 if (session->transport_rolling()) {
1479 Location * looploc = session->locations()->auto_loop_location();
1481 session->request_locate (looploc->start(), true);
1486 session->request_play_loop (true);
1492 ARDOUR_UI::transport_play_selection ()
1498 if (!session->get_play_range()) {
1499 session->request_stop ();
1502 editor->play_selection ();
1506 ARDOUR_UI::transport_rewind (int option)
1508 float current_transport_speed;
1511 current_transport_speed = session->transport_speed();
1513 if (current_transport_speed >= 0.0f) {
1516 session->request_transport_speed (-1.0f);
1519 session->request_transport_speed (-4.0f);
1522 session->request_transport_speed (-0.5f);
1527 session->request_transport_speed (current_transport_speed * 1.5f);
1533 ARDOUR_UI::transport_forward (int option)
1535 float current_transport_speed;
1538 current_transport_speed = session->transport_speed();
1540 if (current_transport_speed <= 0.0f) {
1543 session->request_transport_speed (1.0f);
1546 session->request_transport_speed (4.0f);
1549 session->request_transport_speed (0.5f);
1554 session->request_transport_speed (current_transport_speed * 1.5f);
1560 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1566 boost::shared_ptr<Route> r;
1568 if ((r = session->route_by_remote_id (dstream)) != 0) {
1572 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1573 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1582 ARDOUR_UI::queue_transport_change ()
1584 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1588 ARDOUR_UI::map_transport_state ()
1590 float sp = session->transport_speed();
1593 transport_rolling ();
1594 } else if (sp < 0.0f) {
1595 transport_rewinding ();
1596 } else if (sp > 0.0f) {
1597 transport_forwarding ();
1599 transport_stopped ();
1604 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1606 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1607 (int) adj.get_value()].c_str());
1611 ARDOUR_UI::engine_stopped ()
1613 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1614 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1615 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1619 ARDOUR_UI::engine_running ()
1621 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1622 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1623 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1625 Glib::RefPtr<Action> action;
1626 const char* action_name = 0;
1628 switch (engine->frames_per_cycle()) {
1630 action_name = X_("JACKLatency32");
1633 action_name = X_("JACKLatency64");
1636 action_name = X_("JACKLatency128");
1639 action_name = X_("JACKLatency512");
1642 action_name = X_("JACKLatency1024");
1645 action_name = X_("JACKLatency2048");
1648 action_name = X_("JACKLatency4096");
1651 action_name = X_("JACKLatency8192");
1654 /* XXX can we do anything useful ? */
1660 action = ActionManager::get_action (X_("JACK"), action_name);
1663 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1664 ract->set_active ();
1670 ARDOUR_UI::engine_halted ()
1672 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1674 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1675 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1677 update_sample_rate (0);
1679 MessageDialog msg (*editor,
1681 JACK has either been shutdown or it\n\
1682 disconnected Ardour because Ardour\n\
1683 was not fast enough. Try to restart\n\
1684 JACK, reconnect and save the session."));
1690 ARDOUR_UI::do_engine_start ()
1698 error << _("Unable to start the session running")
1708 ARDOUR_UI::setup_theme ()
1710 theme_manager->setup_theme();
1714 ARDOUR_UI::update_clocks ()
1716 if (!editor || !editor->dragging_playhead()) {
1717 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1722 ARDOUR_UI::start_clocking ()
1724 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1728 ARDOUR_UI::stop_clocking ()
1730 clock_signal_connection.disconnect ();
1734 ARDOUR_UI::toggle_clocking ()
1737 if (clock_button.get_active()) {
1746 ARDOUR_UI::_blink (void *arg)
1749 ((ARDOUR_UI *) arg)->blink ();
1756 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1760 ARDOUR_UI::start_blinking ()
1762 /* Start the blink signal. Everybody with a blinking widget
1763 uses Blink to drive the widget's state.
1766 if (blink_timeout_tag < 0) {
1768 blink_timeout_tag = g_timeout_add (240, _blink, this);
1773 ARDOUR_UI::stop_blinking ()
1775 if (blink_timeout_tag >= 0) {
1776 g_source_remove (blink_timeout_tag);
1777 blink_timeout_tag = -1;
1782 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1788 if (io.n_inputs() == 0) {
1793 /* XXX we're not handling multiple ports yet. */
1795 const char **connections = io.input(0)->get_connections();
1797 if (connections == 0 || connections[0] == '\0') {
1800 buf = connections[0];
1807 if (io.n_outputs() == 0) {
1812 /* XXX we're not handling multiple ports yet. */
1814 const char **connections = io.output(0)->get_connections();
1816 if (connections == 0 || connections[0] == '\0') {
1819 buf = connections[0];
1826 /** Ask the user for the name of a new shapshot and then take it.
1829 ARDOUR_UI::snapshot_session ()
1831 ArdourPrompter prompter (true);
1835 struct tm local_time;
1838 localtime_r (&n, &local_time);
1839 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1841 prompter.set_name ("Prompter");
1842 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1843 prompter.set_prompt (_("Name of New Snapshot"));
1844 prompter.set_initial_text (timebuf);
1846 switch (prompter.run()) {
1847 case RESPONSE_ACCEPT:
1848 prompter.get_result (snapname);
1849 if (snapname.length()){
1850 save_state (snapname);
1860 ARDOUR_UI::save_state (const string & name)
1862 (void) save_state_canfail (name);
1866 ARDOUR_UI::save_state_canfail (string name)
1871 if (name.length() == 0) {
1872 name = session->snap_name();
1875 if ((ret = session->save_state (name)) != 0) {
1879 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1884 ARDOUR_UI::primary_clock_value_changed ()
1887 session->request_locate (primary_clock.current_time ());
1892 ARDOUR_UI::big_clock_value_changed ()
1895 session->request_locate (big_clock.current_time ());
1900 ARDOUR_UI::secondary_clock_value_changed ()
1903 session->request_locate (secondary_clock.current_time ());
1908 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1914 switch (session->record_status()) {
1915 case Session::Enabled:
1917 rec_button.set_visual_state (2);
1919 rec_button.set_visual_state (0);
1923 case Session::Recording:
1924 rec_button.set_visual_state (1);
1928 rec_button.set_visual_state (0);
1934 ARDOUR_UI::save_template ()
1937 ArdourPrompter prompter (true);
1940 if (!check_audioengine()) {
1944 prompter.set_name (X_("Prompter"));
1945 prompter.set_prompt (_("Name for mix template:"));
1946 prompter.set_initial_text(session->name() + _("-template"));
1947 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1949 switch (prompter.run()) {
1950 case RESPONSE_ACCEPT:
1951 prompter.get_result (name);
1953 if (name.length()) {
1954 session->save_template (name);
1964 ARDOUR_UI::fontconfig_dialog ()
1967 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1968 may not and it can take a while to build it. Warn them.
1971 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1973 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1974 MessageDialog msg (*new_session_dialog,
1975 _("Welcome to Ardour.\n\n"
1976 "The program will take a bit longer to start up\n"
1977 "while the system fonts are checked.\n\n"
1978 "This will only be done once, and you will\n"
1979 "not see this message again\n"),
1992 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1994 existing_session = false;
1996 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
1997 session_path = cmdline_path;
1998 existing_session = true;
1999 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2000 session_path = Glib::path_get_dirname (string (cmdline_path));
2001 existing_session = true;
2003 /* it doesn't exist, assume the best */
2004 session_path = Glib::path_get_dirname (string (cmdline_path));
2007 session_name = basename_nosuffix (string (cmdline_path));
2011 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2013 /* when this is called, the backend audio system must be running */
2015 /* the main idea here is to deal with the fact that a cmdline argument for the session
2016 can be interpreted in different ways - it could be a directory or a file, and before
2017 we load, we need to know both the session directory and the snapshot (statefile) within it
2018 that we are supposed to use.
2021 if (session_name.length() == 0 || session_path.length() == 0) {
2025 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2027 Glib::ustring predicted_session_file;
2029 predicted_session_file = session_path;
2030 predicted_session_file += '/';
2031 predicted_session_file += session_name;
2032 predicted_session_file += Session::statefile_suffix();
2034 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2035 existing_session = true;
2038 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2040 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2041 /* existing .ardour file */
2042 existing_session = true;
2046 existing_session = false;
2049 /* lets just try to load it */
2051 if (create_engine ()) {
2052 backend_audio_error (false, new_session_dialog);
2056 return load_session (session_path, session_name);
2060 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2062 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2064 MessageDialog msg (str,
2066 Gtk::MESSAGE_WARNING,
2067 Gtk::BUTTONS_YES_NO,
2071 msg.set_name (X_("CleanupDialog"));
2072 msg.set_wmclass (X_("existing_session"), "Ardour");
2073 msg.set_position (Gtk::WIN_POS_MOUSE);
2076 switch (msg.run()) {
2085 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2090 AutoConnectOption iconnect;
2091 AutoConnectOption oconnect;
2095 if (Profile->get_sae()) {
2099 iconnect = AutoConnectPhysical;
2100 oconnect = AutoConnectMaster;
2101 nphysin = 0; // use all available
2102 nphysout = 0; // use all available
2106 /* get settings from advanced section of NSD */
2108 if (new_session_dialog->create_control_bus()) {
2109 cchns = (uint32_t) new_session_dialog->control_channel_count();
2114 if (new_session_dialog->create_master_bus()) {
2115 mchns = (uint32_t) new_session_dialog->master_channel_count();
2120 if (new_session_dialog->connect_inputs()) {
2121 iconnect = AutoConnectPhysical;
2123 iconnect = AutoConnectOption (0);
2126 /// @todo some minor tweaks.
2128 if (new_session_dialog->connect_outs_to_master()) {
2129 oconnect = AutoConnectMaster;
2130 } else if (new_session_dialog->connect_outs_to_physical()) {
2131 oconnect = AutoConnectPhysical;
2133 oconnect = AutoConnectOption (0);
2136 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2137 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2140 if (build_session (session_path,
2148 engine->frame_rate() * 60 * 5)) {
2157 ARDOUR_UI::end_loading_messages ()
2163 ARDOUR_UI::loading_message (const std::string& msg)
2166 splash->message (msg);
2171 ARDOUR_UI::idle_load (const Glib::ustring& path)
2174 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2175 /* /path/to/foo => /path/to/foo, foo */
2176 load_session (path, basename_nosuffix (path));
2178 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2179 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2183 ARDOUR_COMMAND_LINE::session_name = path;
2185 if (new_session_dialog) {
2188 /* make it break out of Dialog::run() and
2192 new_session_dialog->response (1);
2198 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2200 bool existing_session = false;
2201 Glib::ustring session_name;
2202 Glib::ustring session_path;
2203 Glib::ustring template_name;
2207 response = Gtk::RESPONSE_NONE;
2209 cerr << "\n\n\n CONSIDER CLSN = " << ARDOUR_COMMAND_LINE::session_name << "\n\n\n";
2211 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2213 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2215 cerr << "from command line got name = "
2217 << " path = " << session_path
2218 << " existing ? " << existing_session
2221 /* don't ever reuse this */
2223 ARDOUR_COMMAND_LINE::session_name = string();
2225 if (existing_session && backend_audio_is_running) {
2227 /* just load the thing already */
2229 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2234 /* make the NSD use whatever information we have */
2236 new_session_dialog->set_session_name (session_name);
2237 new_session_dialog->set_session_folder (session_path);
2240 /* loading failed, or we need the NSD for something */
2242 new_session_dialog->set_modal (false);
2243 new_session_dialog->set_position (WIN_POS_CENTER);
2244 new_session_dialog->set_current_page (0);
2245 new_session_dialog->set_existing_session (existing_session);
2246 new_session_dialog->reset_recent();
2249 new_session_dialog->set_have_engine (backend_audio_is_running);
2250 new_session_dialog->present ();
2251 response = new_session_dialog->run ();
2253 _session_is_new = false;
2255 /* handle possible negative responses */
2259 /* sent by idle_load, meaning restart the whole process again */
2260 new_session_dialog->hide();
2261 new_session_dialog->reset();
2265 case Gtk::RESPONSE_CANCEL:
2266 case Gtk::RESPONSE_DELETE_EVENT:
2268 if (engine && engine->running()) {
2269 engine->stop (true);
2273 new_session_dialog->hide ();
2276 case Gtk::RESPONSE_NONE:
2277 /* "Clear" was pressed */
2281 fontconfig_dialog();
2283 if (!backend_audio_is_running) {
2284 int ret = new_session_dialog->engine_control.setup_engine ();
2287 } else if (ret > 0) {
2288 response = Gtk::RESPONSE_REJECT;
2293 if (create_engine ()) {
2295 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2298 new_session_dialog->set_existing_session (false);
2299 new_session_dialog->set_current_page (2);
2301 response = Gtk::RESPONSE_NONE;
2305 backend_audio_is_running = true;
2307 if (response == Gtk::RESPONSE_OK) {
2309 session_name = new_session_dialog->session_name();
2311 if (session_name.empty()) {
2312 response = Gtk::RESPONSE_NONE;
2316 /* if the user mistakenly typed path information into the session filename entry,
2317 convert what they typed into a path & a name
2320 if (session_name[0] == '/' ||
2321 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2322 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2324 session_path = Glib::path_get_dirname (session_name);
2325 session_name = Glib::path_get_basename (session_name);
2329 session_path = new_session_dialog->session_folder();
2332 template_name = Glib::ustring();
2333 switch (new_session_dialog->which_page()) {
2335 case NewSessionDialog::OpenPage:
2336 case NewSessionDialog::EnginePage:
2340 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2342 should_be_new = true;
2344 //XXX This is needed because session constructor wants a
2345 //non-existant path. hopefully this will be fixed at some point.
2347 session_path = Glib::build_filename (session_path, session_name);
2349 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2351 if (ask_about_loading_existing_session (session_path)) {
2354 response = RESPONSE_NONE;
2359 _session_is_new = true;
2361 if (new_session_dialog->use_session_template()) {
2363 template_name = new_session_dialog->session_template_name();
2367 if (build_session_from_nsd (session_path, session_name)) {
2368 response = RESPONSE_NONE;
2380 new_session_dialog->hide ();
2382 cerr << "trying to load " << session_path << " as " << session_name << endl;
2384 if (load_session (session_path, session_name, template_name)) {
2386 response = Gtk::RESPONSE_NONE;
2390 if (response == Gtk::RESPONSE_NONE) {
2391 new_session_dialog->set_existing_session (false);
2392 new_session_dialog->reset ();
2396 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2400 new_session_dialog->hide();
2401 new_session_dialog->reset();
2402 goto_editor_window ();
2407 ARDOUR_UI::close_session ()
2409 if (!check_audioengine()) {
2413 unload_session (true);
2415 get_session_parameters (true, false);
2419 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2421 Session *new_session;
2425 session_loaded = false;
2427 if (!check_audioengine()) {
2431 unload_status = unload_session ();
2433 if (unload_status < 0) {
2435 } else if (unload_status > 0) {
2440 /* if it already exists, we must have write access */
2442 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2443 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2444 "This prevents the session from being loaded."));
2450 loading_message (_("Please wait while Ardour loads your session"));
2453 new_session = new Session (*engine, path, snap_name, mix_template);
2456 /* this one is special */
2458 catch (AudioEngine::PortRegistrationFailure& err) {
2460 MessageDialog msg (err.what(),
2463 Gtk::BUTTONS_CLOSE);
2465 msg.set_title (_("Port Registration Error"));
2466 msg.set_secondary_text (_("Click the Close button to try again."));
2467 msg.set_position (Gtk::WIN_POS_CENTER);
2471 int response = msg.run ();
2476 case RESPONSE_CANCEL:
2486 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2489 Gtk::BUTTONS_CLOSE);
2491 msg.set_title (_("Loading Error"));
2492 msg.set_secondary_text (_("Click the Close button to try again."));
2493 msg.set_position (Gtk::WIN_POS_CENTER);
2497 int response = msg.run ();
2502 case RESPONSE_CANCEL:
2510 connect_to_session (new_session);
2512 Config->set_current_owner (ConfigVariableBase::Interface);
2514 session_loaded = true;
2516 goto_editor_window ();
2519 session->set_clean ();
2530 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2531 uint32_t control_channels,
2532 uint32_t master_channels,
2533 AutoConnectOption input_connect,
2534 AutoConnectOption output_connect,
2537 nframes_t initial_length)
2539 Session *new_session;
2542 if (!check_audioengine()) {
2546 session_loaded = false;
2548 x = unload_session ();
2556 _session_is_new = true;
2559 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2560 control_channels, master_channels, nphysin, nphysout, initial_length);
2565 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2571 connect_to_session (new_session);
2573 session_loaded = true;
2575 new_session->save_state(new_session->name());
2584 editor->show_window ();
2595 ARDOUR_UI::show_about ()
2599 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2606 ARDOUR_UI::hide_about ()
2609 about->get_window()->set_cursor ();
2615 ARDOUR_UI::about_signal_response(int response)
2621 ARDOUR_UI::show_splash ()
2625 splash = new Splash;
2633 splash->queue_draw ();
2634 splash->get_window()->process_updates (true);
2639 ARDOUR_UI::hide_splash ()
2647 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2651 removed = rep.paths.size();
2654 MessageDialog msgd (*editor,
2655 _("No audio files were ready for cleanup"),
2658 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2659 msgd.set_secondary_text (_("If this seems suprising, \n\
2660 check for any existing snapshots.\n\
2661 These may still include regions that\n\
2662 require some unused files to continue to exist."));
2668 ArdourDialog results (_("ardour: cleanup"), true, false);
2670 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2671 CleanupResultsModelColumns() {
2675 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2676 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2680 CleanupResultsModelColumns results_columns;
2681 Glib::RefPtr<Gtk::ListStore> results_model;
2682 Gtk::TreeView results_display;
2684 results_model = ListStore::create (results_columns);
2685 results_display.set_model (results_model);
2686 results_display.append_column (list_title, results_columns.visible_name);
2688 results_display.set_name ("CleanupResultsList");
2689 results_display.set_headers_visible (true);
2690 results_display.set_headers_clickable (false);
2691 results_display.set_reorderable (false);
2693 Gtk::ScrolledWindow list_scroller;
2696 Gtk::HBox dhbox; // the hbox for the image and text
2697 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2698 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2700 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2702 if (rep.space < 1048576.0f) {
2704 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2706 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2710 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2712 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2716 dhbox.pack_start (*dimage, true, false, 5);
2717 dhbox.pack_start (txt, true, false, 5);
2719 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2720 TreeModel::Row row = *(results_model->append());
2721 row[results_columns.visible_name] = *i;
2722 row[results_columns.fullpath] = *i;
2725 list_scroller.add (results_display);
2726 list_scroller.set_size_request (-1, 150);
2727 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2729 dvbox.pack_start (dhbox, true, false, 5);
2730 dvbox.pack_start (list_scroller, true, false, 5);
2731 ddhbox.pack_start (dvbox, true, false, 5);
2733 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2734 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2735 results.set_default_response (RESPONSE_CLOSE);
2736 results.set_position (Gtk::WIN_POS_MOUSE);
2737 results.show_all_children ();
2738 results.set_resizable (false);
2745 ARDOUR_UI::cleanup ()
2748 /* shouldn't happen: menu item is insensitive */
2753 MessageDialog checker (_("Are you sure you want to cleanup?"),
2755 Gtk::MESSAGE_QUESTION,
2756 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2758 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2759 ALL undo/redo information will be lost if you cleanup.\n\
2760 After cleanup, unused audio files will be moved to a \
2761 \"dead sounds\" location."));
2763 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2764 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2765 checker.set_default_response (RESPONSE_CANCEL);
2767 checker.set_name (_("CleanupDialog"));
2768 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2769 checker.set_position (Gtk::WIN_POS_MOUSE);
2771 switch (checker.run()) {
2772 case RESPONSE_ACCEPT:
2778 Session::cleanup_report rep;
2780 editor->prepare_for_cleanup ();
2782 /* do not allow flush until a session is reloaded */
2784 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2786 act->set_sensitive (false);
2789 if (session->cleanup_sources (rep)) {
2790 editor->finish_cleanup ();
2794 editor->finish_cleanup ();
2797 display_cleanup_results (rep,
2800 The following %1 %2 not in use and \n\
2801 have been moved to:\n\
2803 Flushing the wastebasket will \n\
2804 release an additional\n\
2805 %4 %5bytes of disk space.\n"
2811 ARDOUR_UI::flush_trash ()
2814 /* shouldn't happen: menu item is insensitive */
2818 Session::cleanup_report rep;
2820 if (session->cleanup_trash_sources (rep)) {
2824 display_cleanup_results (rep,
2826 _("The following %1 %2 deleted from\n\
2828 releasing %4 %5bytes of disk space"));
2832 ARDOUR_UI::add_route (Gtk::Window* float_window)
2840 if (add_route_dialog == 0) {
2841 add_route_dialog = new AddRouteDialog;
2843 add_route_dialog->set_transient_for (*float_window);
2847 if (add_route_dialog->is_visible()) {
2848 /* we're already doing this */
2852 ResponseType r = (ResponseType) add_route_dialog->run ();
2854 add_route_dialog->hide();
2857 case RESPONSE_ACCEPT:
2864 if ((count = add_route_dialog->count()) <= 0) {
2868 uint32_t input_chan = add_route_dialog->channels ();
2869 uint32_t output_chan;
2870 string name_template = add_route_dialog->name_template ();
2871 bool track = add_route_dialog->track ();
2873 AutoConnectOption oac = Config->get_output_auto_connect();
2875 if (oac & AutoConnectMaster) {
2876 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2878 output_chan = input_chan;
2881 /* XXX do something with name template */
2883 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2886 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2888 session_add_audio_bus (input_chan, output_chan, count);
2893 ARDOUR_UI::mixer_settings () const
2898 node = session->instant_xml(X_("Mixer"), session->path());
2900 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2904 node = new XMLNode (X_("Mixer"));
2911 ARDOUR_UI::editor_settings () const
2916 node = session->instant_xml(X_("Editor"), session->path());
2918 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2922 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2923 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2928 node = new XMLNode (X_("Editor"));
2934 ARDOUR_UI::keyboard_settings () const
2938 node = Config->extra_xml(X_("Keyboard"));
2941 node = new XMLNode (X_("Keyboard"));
2947 ARDOUR_UI::create_xrun_marker(nframes_t where)
2949 editor->mouse_add_new_marker (where, false, true);
2953 ARDOUR_UI::halt_on_xrun_message ()
2955 MessageDialog msg (*editor,
2956 _("Recording was stopped because your system could not keep up."));
2961 ARDOUR_UI::xrun_handler(nframes_t where)
2963 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), 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 ();