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/plugin.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/audiofilesource.h>
64 #include <ardour/recent_sessions.h>
65 #include <ardour/port.h>
66 #include <ardour/audio_track.h>
68 typedef uint64_t microseconds_t;
71 #include "ardour_ui.h"
72 #include "public_editor.h"
73 #include "audio_clock.h"
78 #include "add_route_dialog.h"
79 #include "new_session_dialog.h"
83 #include "gui_thread.h"
84 #include "theme_manager.h"
85 #include "engine_dialog.h"
86 #include "gain_meter.h"
87 #include "route_time_axis.h"
91 using namespace ARDOUR;
93 using namespace Gtkmm2ext;
97 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
98 UIConfiguration *ARDOUR_UI::ui_config = 0;
100 sigc::signal<void,bool> ARDOUR_UI::Blink;
101 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
102 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
103 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
105 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
107 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
109 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
110 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
111 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
112 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
116 preroll_button (_("pre\nroll")),
117 postroll_button (_("post\nroll")),
121 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
125 roll_controllable ("transport roll", *this, TransportControllable::Roll),
126 stop_controllable ("transport stop", *this, TransportControllable::Stop),
127 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
128 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
129 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
130 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
131 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
132 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
133 shuttle_controller_binding_proxy (shuttle_controllable),
135 roll_button (&roll_controllable),
136 stop_button (&stop_controllable),
137 goto_start_button (&goto_start_controllable),
138 goto_end_button (&goto_end_controllable),
139 auto_loop_button (&auto_loop_controllable),
140 play_selection_button (&play_selection_controllable),
141 rec_button (&rec_controllable),
143 shuttle_units_button (_("% ")),
145 punch_in_button (_("Punch In")),
146 punch_out_button (_("Punch Out")),
147 auto_return_button (_("Auto Return")),
148 auto_play_button (_("Auto Play")),
149 auto_input_button (_("Auto Input")),
150 click_button (_("Click")),
151 time_master_button (_("time\nmaster")),
153 auditioning_alert_button (_("AUDITION")),
154 solo_alert_button (_("SOLO")),
156 error_log_button (_("Errors"))
158 using namespace Gtk::Menu_Helpers;
163 _auto_display_errors = false;
169 if (ARDOUR_COMMAND_LINE::session_name.length()) {
170 /* only show this if we're not going to post the new session dialog */
174 if (theArdourUI == 0) {
178 ui_config = new UIConfiguration();
179 theme_manager = new ThemeManager();
185 _session_is_new = false;
186 big_clock_window = 0;
187 session_selector_window = 0;
188 new_session_dialog = 0;
189 last_key_press_time = 0;
190 connection_editor = 0;
191 add_route_dialog = 0;
196 open_session_selector = 0;
197 have_configure_timeout = false;
198 have_disk_speed_dialog_displayed = false;
199 _will_create_new_session_automatically = false;
200 session_loaded = false;
201 last_speed_displayed = -1.0f;
202 ignore_dual_punch = false;
203 _mixer_on_top = false;
205 roll_button.unset_flags (Gtk::CAN_FOCUS);
206 stop_button.unset_flags (Gtk::CAN_FOCUS);
207 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
208 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
209 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
210 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
211 rec_button.unset_flags (Gtk::CAN_FOCUS);
213 last_configure_time= 0;
215 shuttle_grabbed = false;
217 shuttle_max_speed = 8.0f;
219 shuttle_style_menu = 0;
220 shuttle_unit_menu = 0;
222 // We do not have jack linked in yet so;
224 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
226 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
227 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
229 ARDOUR::Plugin::PresetFileExists.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler));
231 /* handle dialog requests */
233 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
235 /* handle pending state with a dialog */
237 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
239 /* handle sr mismatch with a dialog */
241 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
243 /* lets get this party started */
246 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
247 throw failed_constructor ();
250 setup_gtk_ardour_enums ();
251 Config->set_current_owner (ConfigVariableBase::Interface);
254 GainMeter::setup_slider_pix ();
255 RouteTimeAxisView::setup_slider_pix ();
257 } catch (failed_constructor& err) {
258 error << _("could not initialize Ardour.") << endmsg;
263 /* we like keyboards */
265 keyboard = new Keyboard;
269 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
270 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
276 ARDOUR_UI::create_engine ()
278 // this gets called every time by new_session()
284 loading_message (_("Starting audio engine"));
287 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
294 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
295 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
296 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
297 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
305 ARDOUR_UI::post_engine ()
307 /* Things to be done once we create the AudioEngine
310 check_memory_locking();
312 ActionManager::init ();
315 if (setup_windows ()) {
316 throw failed_constructor ();
319 /* this is the first point at which all the keybindings are available */
321 if (ARDOUR_COMMAND_LINE::show_key_actions) {
322 vector<string> names;
323 vector<string> paths;
325 vector<AccelKey> bindings;
327 ActionManager::get_all_actions (names, paths, keys, bindings);
329 vector<string>::iterator n;
330 vector<string>::iterator k;
331 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
332 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
338 blink_timeout_tag = -1;
340 /* the global configuration object is now valid */
344 /* this being a GUI and all, we want peakfiles */
346 AudioFileSource::set_build_peakfiles (true);
347 AudioFileSource::set_build_missing_peakfiles (true);
349 /* set default clock modes */
351 if (Profile->get_sae()) {
352 primary_clock.set_mode (AudioClock::BBT);
353 secondary_clock.set_mode (AudioClock::MinSec);
355 primary_clock.set_mode (AudioClock::SMPTE);
356 secondary_clock.set_mode (AudioClock::BBT);
359 /* start the time-of-day-clock */
362 /* OS X provides an always visible wallclock, so don't be stupid */
363 update_wall_clock ();
364 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
367 update_disk_space ();
369 update_sample_rate (engine->frame_rate());
371 platform_specific ();
373 /* now start and maybe save state */
375 if (do_engine_start () == 0) {
376 if (session && _session_is_new) {
377 /* we need to retain initial visual
378 settings for a new session
380 session->save_state ("");
385 ARDOUR_UI::~ARDOUR_UI ()
387 save_ardour_state ();
401 if (add_route_dialog) {
402 delete add_route_dialog;
405 if (new_session_dialog) {
406 delete new_session_dialog;
411 ARDOUR_UI::pop_back_splash ()
413 if (Splash::instance()) {
414 // Splash::instance()->pop_back();
415 Splash::instance()->hide ();
420 ARDOUR_UI::configure_timeout ()
422 if (last_configure_time == 0) {
423 /* no configure events yet */
427 /* force a gap of 0.5 seconds since the last configure event
430 if (get_microseconds() - last_configure_time < 500000) {
433 have_configure_timeout = false;
434 save_ardour_state ();
440 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
442 if (have_configure_timeout) {
443 last_configure_time = get_microseconds();
445 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
446 have_configure_timeout = true;
453 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
455 const XMLProperty* prop;
457 if ((prop = node.property ("roll")) != 0) {
458 roll_controllable.set_id (prop->value());
460 if ((prop = node.property ("stop")) != 0) {
461 stop_controllable.set_id (prop->value());
463 if ((prop = node.property ("goto_start")) != 0) {
464 goto_start_controllable.set_id (prop->value());
466 if ((prop = node.property ("goto_end")) != 0) {
467 goto_end_controllable.set_id (prop->value());
469 if ((prop = node.property ("auto_loop")) != 0) {
470 auto_loop_controllable.set_id (prop->value());
472 if ((prop = node.property ("play_selection")) != 0) {
473 play_selection_controllable.set_id (prop->value());
475 if ((prop = node.property ("rec")) != 0) {
476 rec_controllable.set_id (prop->value());
478 if ((prop = node.property ("shuttle")) != 0) {
479 shuttle_controllable.set_id (prop->value());
484 ARDOUR_UI::get_transport_controllable_state ()
486 XMLNode* node = new XMLNode(X_("TransportControllables"));
489 roll_controllable.id().print (buf, sizeof (buf));
490 node->add_property (X_("roll"), buf);
491 stop_controllable.id().print (buf, sizeof (buf));
492 node->add_property (X_("stop"), buf);
493 goto_start_controllable.id().print (buf, sizeof (buf));
494 node->add_property (X_("goto_start"), buf);
495 goto_end_controllable.id().print (buf, sizeof (buf));
496 node->add_property (X_("goto_end"), buf);
497 auto_loop_controllable.id().print (buf, sizeof (buf));
498 node->add_property (X_("auto_loop"), buf);
499 play_selection_controllable.id().print (buf, sizeof (buf));
500 node->add_property (X_("play_selection"), buf);
501 rec_controllable.id().print (buf, sizeof (buf));
502 node->add_property (X_("rec"), buf);
503 shuttle_controllable.id().print (buf, sizeof (buf));
504 node->add_property (X_("shuttle"), buf);
510 ARDOUR_UI::save_ardour_state ()
512 if (!keyboard || !mixer || !editor) {
516 /* XXX this is all a bit dubious. add_extra_xml() uses
517 a different lifetime model from add_instant_xml().
520 XMLNode* node = new XMLNode (keyboard->get_state());
521 Config->add_extra_xml (*node);
522 Config->add_extra_xml (get_transport_controllable_state());
523 if (new_session_dialog) {
524 if (new_session_dialog->engine_control.was_used()) {
525 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
528 Config->save_state();
529 ui_config->save_state ();
531 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
532 XMLNode mnode(mixer->get_state());
535 session->add_instant_xml (enode, session->path());
536 session->add_instant_xml (mnode, session->path());
538 Config->add_instant_xml (enode, get_user_ardour_path());
539 Config->add_instant_xml (mnode, get_user_ardour_path());
542 Keyboard::save_keybindings ();
546 ARDOUR_UI::autosave_session ()
548 if (g_main_depth() > 1) {
549 /* inside a recursive main loop,
550 give up because we may not be able to
556 if (!Config->get_periodic_safety_backups())
560 session->maybe_write_autosave();
567 ARDOUR_UI::update_autosave ()
569 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
571 if (session->dirty()) {
572 if (_autosave_connection.connected()) {
573 _autosave_connection.disconnect();
576 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
577 Config->get_periodic_safety_backup_interval() * 1000);
580 if (_autosave_connection.connected()) {
581 _autosave_connection.disconnect();
587 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
591 title = _("Ardour could not start JACK");
593 title = _("Ardour could not connect to JACK.");
596 MessageDialog win (title,
602 win.set_secondary_text(_("There are several possible reasons:\n\
604 1) You requested audio parameters that are not supported..\n\
605 2) JACK is running as another user.\n\
607 Please consider the possibilities, and perhaps try different parameters."));
609 win.set_secondary_text(_("There are several possible reasons:\n\
611 1) JACK is not running.\n\
612 2) JACK is running as another user, perhaps root.\n\
613 3) There is already another client called \"ardour\".\n\
615 Please consider the possibilities, and perhaps (re)start JACK."));
619 win.set_transient_for (*toplevel);
623 win.add_button (Stock::OK, RESPONSE_CLOSE);
625 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
628 win.set_default_response (RESPONSE_CLOSE);
631 win.set_position (Gtk::WIN_POS_CENTER);
634 /* we just don't care about the result, but we want to block */
640 ARDOUR_UI::startup ()
644 new_session_dialog = new NewSessionDialog();
646 bool backend_audio_is_running = EngineControl::engine_running();
647 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
650 new_session_dialog->engine_control.set_state (*audio_setup);
653 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
657 BootMessage (_("Ardour is ready for use"));
662 ARDOUR_UI::no_memory_warning ()
664 XMLNode node (X_("no-memory-warning"));
665 Config->add_instant_xml (node, get_user_ardour_path());
669 ARDOUR_UI::check_memory_locking ()
672 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
676 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
678 if (engine->is_realtime() && memory_warning_node == 0) {
680 struct rlimit limits;
682 long pages, page_size;
684 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
687 ram = (int64_t) pages * (int64_t) page_size;
690 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
694 if (limits.rlim_cur != RLIM_INFINITY) {
696 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
699 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
700 "This might cause Ardour to run out of memory before your system "
701 "runs out of memory. \n\n"
702 "You can view the memory limit with 'ulimit -l', "
703 "and it is normally controlled by /etc/security/limits.conf"));
705 VBox* vbox = msg.get_vbox();
707 CheckButton cb (_("Do not show this window again"));
709 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
711 hbox.pack_start (cb, true, false);
712 vbox->pack_start (hbox);
730 if (session->transport_rolling()) {
731 session->request_stop ();
735 if (session->dirty()) {
736 switch (ask_about_saving_session(_("quit"))) {
741 /* use the default name */
742 if (save_state_canfail ("")) {
743 /* failed - don't quit */
744 MessageDialog msg (*editor,
746 Ardour was unable to save your session.\n\n\
747 If you still wish to quit, please use the\n\n\
748 \"Just quit\" option."));
759 session->set_deletion_in_progress ();
762 ArdourDialog::close_all_dialogs ();
764 save_ardour_state ();
769 ARDOUR_UI::ask_about_saving_session (const string & what)
771 ArdourDialog window (_("ardour: save session?"));
772 Gtk::HBox dhbox; // the hbox for the image and text
773 Gtk::Label prompt_label;
774 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
778 msg = string_compose(_("Don't %1"), what);
779 window.add_button (msg, RESPONSE_REJECT);
780 msg = string_compose(_("Just %1"), what);
781 window.add_button (msg, RESPONSE_APPLY);
782 msg = string_compose(_("Save and %1"), what);
783 window.add_button (msg, RESPONSE_ACCEPT);
785 window.set_default_response (RESPONSE_ACCEPT);
787 Gtk::Button noquit_button (msg);
788 noquit_button.set_name ("EditorGTKButton");
793 if (session->snap_name() == session->name()) {
796 type = _("snapshot");
798 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?"),
799 type, session->snap_name());
801 prompt_label.set_text (prompt);
802 prompt_label.set_name (X_("PrompterLabel"));
803 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
805 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
807 dhbox.set_homogeneous (false);
808 dhbox.pack_start (*dimage, false, false, 5);
809 dhbox.pack_start (prompt_label, true, false, 5);
810 window.get_vbox()->pack_start (dhbox);
812 window.set_name (_("Prompter"));
813 window.set_position (Gtk::WIN_POS_MOUSE);
814 window.set_modal (true);
815 window.set_resizable (false);
818 window.set_keep_above (true);
821 ResponseType r = (ResponseType) window.run();
826 case RESPONSE_ACCEPT: // save and get out of here
828 case RESPONSE_APPLY: // get out of here
838 ARDOUR_UI::every_second ()
841 update_buffer_load ();
842 update_disk_space ();
847 ARDOUR_UI::every_point_one_seconds ()
849 update_speed_display ();
850 RapidScreenUpdate(); /* EMIT_SIGNAL */
855 ARDOUR_UI::every_point_zero_one_seconds ()
857 // august 2007: actual update frequency: 40Hz, not 100Hz
859 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
864 ARDOUR_UI::update_sample_rate (nframes_t ignored)
868 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
870 if (!engine->connected()) {
872 snprintf (buf, sizeof (buf), _("disconnected"));
876 nframes_t rate = engine->frame_rate();
878 if (fmod (rate, 1000.0) != 0.0) {
879 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
880 (float) rate/1000.0f,
881 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
883 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
889 sample_rate_label.set_text (buf);
893 ARDOUR_UI::update_cpu_load ()
896 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
897 cpu_load_label.set_text (buf);
901 ARDOUR_UI::update_buffer_load ()
906 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
907 session->playback_load(), session->capture_load());
908 buffer_load_label.set_text (buf);
910 buffer_load_label.set_text ("");
915 ARDOUR_UI::count_recenabled_streams (Route& route)
917 Track* track = dynamic_cast<Track*>(&route);
918 if (track && track->diskstream()->record_enabled()) {
919 rec_enabled_streams += track->n_inputs();
924 ARDOUR_UI::update_disk_space()
930 nframes_t frames = session->available_capture_duration();
933 if (frames == max_frames) {
934 strcpy (buf, _("Disk: 24hrs+"));
939 nframes_t fr = session->frame_rate();
941 rec_enabled_streams = 0;
942 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
944 if (rec_enabled_streams) {
945 frames /= rec_enabled_streams;
948 hrs = frames / (fr * 3600);
949 frames -= hrs * fr * 3600;
950 mins = frames / (fr * 60);
951 frames -= mins * fr * 60;
954 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
957 disk_space_label.set_text (buf);
961 ARDOUR_UI::update_wall_clock ()
968 tm_now = localtime (&now);
970 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
971 wall_clock_label.set_text (buf);
977 ARDOUR_UI::session_menu (GdkEventButton *ev)
979 session_popup_menu->popup (0, 0);
984 ARDOUR_UI::redisplay_recent_sessions ()
986 vector<string *> *sessions;
987 vector<string *>::iterator i;
988 RecentSessionsSorter cmp;
990 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
991 recent_session_model->clear ();
994 ARDOUR::read_recent_sessions (rs);
997 recent_session_display.set_model (recent_session_model);
1001 /* sort them alphabetically */
1002 sort (rs.begin(), rs.end(), cmp);
1003 sessions = new vector<string*>;
1005 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1006 sessions->push_back (new string ((*i).second));
1009 for (i = sessions->begin(); i != sessions->end(); ++i) {
1011 vector<string*>* states;
1012 vector<const gchar*> item;
1013 string fullpath = *(*i);
1015 /* remove any trailing / */
1017 if (fullpath[fullpath.length()-1] == '/') {
1018 fullpath = fullpath.substr (0, fullpath.length()-1);
1021 /* check whether session still exists */
1022 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1023 /* session doesn't exist */
1024 cerr << "skipping non-existent session " << fullpath << endl;
1028 /* now get available states for this session */
1030 if ((states = Session::possible_states (fullpath)) == 0) {
1031 /* no state file? */
1035 TreeModel::Row row = *(recent_session_model->append());
1037 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1038 row[recent_session_columns.fullpath] = fullpath;
1040 if (states->size() > 1) {
1042 /* add the children */
1044 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1046 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1048 child_row[recent_session_columns.visible_name] = **i2;
1049 child_row[recent_session_columns.fullpath] = fullpath;
1058 recent_session_display.set_model (recent_session_model);
1063 ARDOUR_UI::build_session_selector ()
1065 session_selector_window = new ArdourDialog ("session selector");
1067 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1069 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1070 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1071 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1072 recent_session_model = TreeStore::create (recent_session_columns);
1073 recent_session_display.set_model (recent_session_model);
1074 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1075 recent_session_display.set_headers_visible (false);
1076 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1077 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1079 scroller->add (recent_session_display);
1080 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1082 session_selector_window->set_name ("SessionSelectorWindow");
1083 session_selector_window->set_size_request (200, 400);
1084 session_selector_window->get_vbox()->pack_start (*scroller);
1085 session_selector_window->show_all_children();
1089 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1091 session_selector_window->response (RESPONSE_ACCEPT);
1095 ARDOUR_UI::open_recent_session ()
1097 bool can_return = (session != 0);
1099 if (session_selector_window == 0) {
1100 build_session_selector ();
1103 redisplay_recent_sessions ();
1107 session_selector_window->set_position (WIN_POS_MOUSE);
1109 ResponseType r = (ResponseType) session_selector_window->run ();
1112 case RESPONSE_ACCEPT:
1116 session_selector_window->hide();
1123 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1127 session_selector_window->hide();
1129 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1131 if (i == recent_session_model->children().end()) {
1135 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1136 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1138 _session_is_new = false;
1140 if (load_session (path, state) == 0) {
1149 ARDOUR_UI::check_audioengine ()
1152 if (!engine->connected()) {
1153 MessageDialog msg (_("Ardour is not connected to JACK\n"
1154 "You cannot open or close sessions in this condition"));
1166 ARDOUR_UI::open_session ()
1168 if (!check_audioengine()) {
1172 /* popup selector window */
1174 if (open_session_selector == 0) {
1176 /* ardour sessions are folders */
1178 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1179 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1180 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1181 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1183 FileFilter session_filter;
1184 session_filter.add_pattern ("*.ardour");
1185 session_filter.set_name (_("Ardour sessions"));
1186 open_session_selector->add_filter (session_filter);
1187 open_session_selector->set_filter (session_filter);
1190 int response = open_session_selector->run();
1191 open_session_selector->hide ();
1194 case RESPONSE_ACCEPT:
1197 open_session_selector->hide();
1201 open_session_selector->hide();
1202 string session_path = open_session_selector->get_filename();
1206 if (session_path.length() > 0) {
1207 if (Session::find_session (session_path, path, name, isnew) == 0) {
1208 _session_is_new = isnew;
1209 load_session (path, name);
1216 ARDOUR_UI::session_add_midi_track ()
1218 cerr << _("Patience is a virtue.\n");
1222 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1224 list<boost::shared_ptr<AudioTrack> > tracks;
1225 Session::RouteList routes;
1228 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1234 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1236 if (tracks.size() != how_many) {
1237 if (how_many == 1) {
1238 error << _("could not create a new audio track") << endmsg;
1240 error << string_compose (_("could only create %1 of %2 new audio %3"),
1241 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1247 routes = session->new_audio_route (input_channels, output_channels, how_many);
1249 if (routes.size() != how_many) {
1250 if (how_many == 1) {
1251 error << _("could not create a new audio track") << endmsg;
1253 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1259 if (need_control_room_outs) {
1265 route->set_stereo_control_outs (control_lr_channels);
1266 route->control_outs()->set_stereo_pan (pans, this);
1268 #endif /* CONTROLOUTS */
1272 MessageDialog msg (*editor,
1273 _("There are insufficient JACK ports available\n\
1274 to create a new track or bus.\n\
1275 You should save Ardour, exit and\n\
1276 restart JACK with more ports."));
1283 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1285 nframes_t _preroll = 0;
1288 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1289 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1291 if (new_position > _preroll) {
1292 new_position -= _preroll;
1297 session->request_locate (new_position);
1302 ARDOUR_UI::transport_goto_start ()
1305 session->goto_start();
1308 /* force displayed area in editor to start no matter
1309 what "follow playhead" setting is.
1313 editor->reset_x_origin (session->current_start_frame());
1319 ARDOUR_UI::transport_goto_zero ()
1322 session->request_locate (0);
1325 /* force displayed area in editor to start no matter
1326 what "follow playhead" setting is.
1330 editor->reset_x_origin (0);
1336 ARDOUR_UI::transport_goto_wallclock ()
1338 if (session && editor) {
1345 localtime_r (&now, &tmnow);
1347 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1348 frames += tmnow.tm_min * (60 * session->frame_rate());
1349 frames += tmnow.tm_sec * session->frame_rate();
1351 session->request_locate (frames);
1353 /* force displayed area in editor to start no matter
1354 what "follow playhead" setting is.
1358 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1364 ARDOUR_UI::transport_goto_end ()
1367 nframes_t frame = session->current_end_frame();
1368 session->request_locate (frame);
1370 /* force displayed area in editor to start no matter
1371 what "follow playhead" setting is.
1375 editor->reset_x_origin (frame);
1381 ARDOUR_UI::transport_stop ()
1387 if (session->is_auditioning()) {
1388 session->cancel_audition ();
1392 if (session->get_play_loop ()) {
1393 session->request_play_loop (false);
1396 session->request_stop ();
1400 ARDOUR_UI::transport_stop_and_forget_capture ()
1403 session->request_stop (true);
1408 ARDOUR_UI::remove_last_capture()
1411 editor->remove_last_capture();
1416 ARDOUR_UI::transport_record (bool roll)
1420 switch (session->record_status()) {
1421 case Session::Disabled:
1422 if (session->ntracks() == 0) {
1423 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1427 session->maybe_enable_record ();
1432 case Session::Recording:
1434 session->request_stop();
1436 session->disable_record (false, true);
1440 case Session::Enabled:
1441 session->disable_record (false, true);
1444 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1448 ARDOUR_UI::transport_roll ()
1456 rolling = session->transport_rolling ();
1458 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1460 if (session->get_play_loop()) {
1461 session->request_play_loop (false);
1462 auto_loop_button.set_visual_state (1);
1463 roll_button.set_visual_state (1);
1464 } else if (session->get_play_range ()) {
1465 session->request_play_range (false);
1466 play_selection_button.set_visual_state (0);
1467 } else if (rolling) {
1468 session->request_locate (session->last_transport_start(), true);
1471 session->request_transport_speed (1.0f);
1475 ARDOUR_UI::transport_loop()
1478 if (session->get_play_loop()) {
1479 if (session->transport_rolling()) {
1480 Location * looploc = session->locations()->auto_loop_location();
1482 session->request_locate (looploc->start(), true);
1487 session->request_play_loop (true);
1493 ARDOUR_UI::transport_play_selection ()
1499 if (!session->get_play_range()) {
1500 session->request_stop ();
1503 editor->play_selection ();
1507 ARDOUR_UI::transport_rewind (int option)
1509 float current_transport_speed;
1512 current_transport_speed = session->transport_speed();
1514 if (current_transport_speed >= 0.0f) {
1517 session->request_transport_speed (-1.0f);
1520 session->request_transport_speed (-4.0f);
1523 session->request_transport_speed (-0.5f);
1528 session->request_transport_speed (current_transport_speed * 1.5f);
1534 ARDOUR_UI::transport_forward (int option)
1536 float current_transport_speed;
1539 current_transport_speed = session->transport_speed();
1541 if (current_transport_speed <= 0.0f) {
1544 session->request_transport_speed (1.0f);
1547 session->request_transport_speed (4.0f);
1550 session->request_transport_speed (0.5f);
1555 session->request_transport_speed (current_transport_speed * 1.5f);
1561 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1567 boost::shared_ptr<Route> r;
1569 if ((r = session->route_by_remote_id (dstream)) != 0) {
1573 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1574 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1583 ARDOUR_UI::queue_transport_change ()
1585 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1589 ARDOUR_UI::map_transport_state ()
1591 float sp = session->transport_speed();
1594 transport_rolling ();
1595 } else if (sp < 0.0f) {
1596 transport_rewinding ();
1597 } else if (sp > 0.0f) {
1598 transport_forwarding ();
1600 transport_stopped ();
1605 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1607 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1608 (int) adj.get_value()].c_str());
1612 ARDOUR_UI::engine_stopped ()
1614 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1615 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1616 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1620 ARDOUR_UI::engine_running ()
1622 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1623 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1624 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1626 Glib::RefPtr<Action> action;
1627 const char* action_name = 0;
1629 switch (engine->frames_per_cycle()) {
1631 action_name = X_("JACKLatency32");
1634 action_name = X_("JACKLatency64");
1637 action_name = X_("JACKLatency128");
1640 action_name = X_("JACKLatency512");
1643 action_name = X_("JACKLatency1024");
1646 action_name = X_("JACKLatency2048");
1649 action_name = X_("JACKLatency4096");
1652 action_name = X_("JACKLatency8192");
1655 /* XXX can we do anything useful ? */
1661 action = ActionManager::get_action (X_("JACK"), action_name);
1664 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1665 ract->set_active ();
1671 ARDOUR_UI::engine_halted ()
1673 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1675 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1676 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1678 update_sample_rate (0);
1680 MessageDialog msg (*editor,
1682 JACK has either been shutdown or it\n\
1683 disconnected Ardour because Ardour\n\
1684 was not fast enough. Try to restart\n\
1685 JACK, reconnect and save the session."));
1691 ARDOUR_UI::do_engine_start ()
1699 error << _("Unable to start the session running")
1709 ARDOUR_UI::setup_theme ()
1711 theme_manager->setup_theme();
1715 ARDOUR_UI::update_clocks ()
1717 if (!editor || !editor->dragging_playhead()) {
1718 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1723 ARDOUR_UI::start_clocking ()
1725 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1729 ARDOUR_UI::stop_clocking ()
1731 clock_signal_connection.disconnect ();
1735 ARDOUR_UI::toggle_clocking ()
1738 if (clock_button.get_active()) {
1747 ARDOUR_UI::_blink (void *arg)
1750 ((ARDOUR_UI *) arg)->blink ();
1757 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1761 ARDOUR_UI::start_blinking ()
1763 /* Start the blink signal. Everybody with a blinking widget
1764 uses Blink to drive the widget's state.
1767 if (blink_timeout_tag < 0) {
1769 blink_timeout_tag = g_timeout_add (240, _blink, this);
1774 ARDOUR_UI::stop_blinking ()
1776 if (blink_timeout_tag >= 0) {
1777 g_source_remove (blink_timeout_tag);
1778 blink_timeout_tag = -1;
1783 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1789 if (io.n_inputs() == 0) {
1794 /* XXX we're not handling multiple ports yet. */
1796 const char **connections = io.input(0)->get_connections();
1798 if (connections == 0 || connections[0] == '\0') {
1801 buf = connections[0];
1808 if (io.n_outputs() == 0) {
1813 /* XXX we're not handling multiple ports yet. */
1815 const char **connections = io.output(0)->get_connections();
1817 if (connections == 0 || connections[0] == '\0') {
1820 buf = connections[0];
1827 /** Ask the user for the name of a new shapshot and then take it.
1830 ARDOUR_UI::snapshot_session ()
1832 ArdourPrompter prompter (true);
1836 struct tm local_time;
1839 localtime_r (&n, &local_time);
1840 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1842 prompter.set_name ("Prompter");
1843 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1844 prompter.set_prompt (_("Name of New Snapshot"));
1845 prompter.set_initial_text (timebuf);
1847 switch (prompter.run()) {
1848 case RESPONSE_ACCEPT:
1849 prompter.get_result (snapname);
1850 if (snapname.length()){
1851 save_state (snapname);
1861 ARDOUR_UI::save_state (const string & name)
1863 (void) save_state_canfail (name);
1867 ARDOUR_UI::save_state_canfail (string name)
1872 if (name.length() == 0) {
1873 name = session->snap_name();
1876 if ((ret = session->save_state (name)) != 0) {
1880 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1885 ARDOUR_UI::primary_clock_value_changed ()
1888 session->request_locate (primary_clock.current_time ());
1893 ARDOUR_UI::big_clock_value_changed ()
1896 session->request_locate (big_clock.current_time ());
1901 ARDOUR_UI::secondary_clock_value_changed ()
1904 session->request_locate (secondary_clock.current_time ());
1909 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1915 switch (session->record_status()) {
1916 case Session::Enabled:
1918 rec_button.set_visual_state (2);
1920 rec_button.set_visual_state (0);
1924 case Session::Recording:
1925 rec_button.set_visual_state (1);
1929 rec_button.set_visual_state (0);
1935 ARDOUR_UI::save_template ()
1938 ArdourPrompter prompter (true);
1941 if (!check_audioengine()) {
1945 prompter.set_name (X_("Prompter"));
1946 prompter.set_prompt (_("Name for mix template:"));
1947 prompter.set_initial_text(session->name() + _("-template"));
1948 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1950 switch (prompter.run()) {
1951 case RESPONSE_ACCEPT:
1952 prompter.get_result (name);
1954 if (name.length()) {
1955 session->save_template (name);
1965 ARDOUR_UI::fontconfig_dialog ()
1968 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1969 may not and it can take a while to build it. Warn them.
1972 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1974 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1975 MessageDialog msg (*new_session_dialog,
1976 _("Welcome to Ardour.\n\n"
1977 "The program will take a bit longer to start up\n"
1978 "while the system fonts are checked.\n\n"
1979 "This will only be done once, and you will\n"
1980 "not see this message again\n"),
1993 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1995 existing_session = false;
1997 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
1998 session_path = cmdline_path;
1999 existing_session = true;
2000 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2001 session_path = Glib::path_get_dirname (string (cmdline_path));
2002 existing_session = true;
2004 /* it doesn't exist, assume the best */
2005 session_path = Glib::path_get_dirname (string (cmdline_path));
2008 session_name = basename_nosuffix (string (cmdline_path));
2012 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2014 /* when this is called, the backend audio system must be running */
2016 /* the main idea here is to deal with the fact that a cmdline argument for the session
2017 can be interpreted in different ways - it could be a directory or a file, and before
2018 we load, we need to know both the session directory and the snapshot (statefile) within it
2019 that we are supposed to use.
2022 if (session_name.length() == 0 || session_path.length() == 0) {
2026 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2028 Glib::ustring predicted_session_file;
2030 predicted_session_file = session_path;
2031 predicted_session_file += '/';
2032 predicted_session_file += session_name;
2033 predicted_session_file += Session::statefile_suffix();
2035 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2036 existing_session = true;
2039 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2041 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2042 /* existing .ardour file */
2043 existing_session = true;
2047 existing_session = false;
2050 /* lets just try to load it */
2052 if (create_engine ()) {
2053 backend_audio_error (false, new_session_dialog);
2057 return load_session (session_path, session_name);
2061 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2063 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2065 MessageDialog msg (str,
2067 Gtk::MESSAGE_WARNING,
2068 Gtk::BUTTONS_YES_NO,
2072 msg.set_name (X_("CleanupDialog"));
2073 msg.set_wmclass (X_("existing_session"), "Ardour");
2074 msg.set_position (Gtk::WIN_POS_MOUSE);
2077 switch (msg.run()) {
2086 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2091 AutoConnectOption iconnect;
2092 AutoConnectOption oconnect;
2096 if (Profile->get_sae()) {
2100 iconnect = AutoConnectPhysical;
2101 oconnect = AutoConnectMaster;
2102 nphysin = 0; // use all available
2103 nphysout = 0; // use all available
2107 /* get settings from advanced section of NSD */
2109 if (new_session_dialog->create_control_bus()) {
2110 cchns = (uint32_t) new_session_dialog->control_channel_count();
2115 if (new_session_dialog->create_master_bus()) {
2116 mchns = (uint32_t) new_session_dialog->master_channel_count();
2121 if (new_session_dialog->connect_inputs()) {
2122 iconnect = AutoConnectPhysical;
2124 iconnect = AutoConnectOption (0);
2127 /// @todo some minor tweaks.
2129 if (new_session_dialog->connect_outs_to_master()) {
2130 oconnect = AutoConnectMaster;
2131 } else if (new_session_dialog->connect_outs_to_physical()) {
2132 oconnect = AutoConnectPhysical;
2134 oconnect = AutoConnectOption (0);
2137 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2138 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2141 if (build_session (session_path,
2149 engine->frame_rate() * 60 * 5)) {
2158 ARDOUR_UI::end_loading_messages ()
2164 ARDOUR_UI::loading_message (const std::string& msg)
2167 splash->message (msg);
2172 ARDOUR_UI::idle_load (const Glib::ustring& path)
2175 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2176 /* /path/to/foo => /path/to/foo, foo */
2177 load_session (path, basename_nosuffix (path));
2179 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2180 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2184 ARDOUR_COMMAND_LINE::session_name = path;
2186 if (new_session_dialog) {
2189 /* make it break out of Dialog::run() and
2193 new_session_dialog->response (1);
2199 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2201 bool existing_session = false;
2202 Glib::ustring session_name;
2203 Glib::ustring session_path;
2204 Glib::ustring template_name;
2208 response = Gtk::RESPONSE_NONE;
2210 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2212 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2214 /* don't ever reuse this */
2216 ARDOUR_COMMAND_LINE::session_name = string();
2218 if (existing_session && backend_audio_is_running) {
2220 /* just load the thing already */
2222 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2227 /* make the NSD use whatever information we have */
2229 new_session_dialog->set_session_name (session_name);
2230 new_session_dialog->set_session_folder (session_path);
2233 /* loading failed, or we need the NSD for something */
2235 new_session_dialog->set_modal (false);
2236 new_session_dialog->set_position (WIN_POS_CENTER);
2237 new_session_dialog->set_current_page (0);
2238 new_session_dialog->set_existing_session (existing_session);
2239 new_session_dialog->reset_recent();
2242 new_session_dialog->set_have_engine (backend_audio_is_running);
2243 new_session_dialog->present ();
2244 response = new_session_dialog->run ();
2246 _session_is_new = false;
2248 /* handle possible negative responses */
2252 /* sent by idle_load, meaning restart the whole process again */
2253 new_session_dialog->hide();
2254 new_session_dialog->reset();
2258 case Gtk::RESPONSE_CANCEL:
2259 case Gtk::RESPONSE_DELETE_EVENT:
2261 if (engine && engine->running()) {
2262 engine->stop (true);
2266 new_session_dialog->hide ();
2269 case Gtk::RESPONSE_NONE:
2270 /* "Clear" was pressed */
2274 fontconfig_dialog();
2276 if (!backend_audio_is_running) {
2277 int ret = new_session_dialog->engine_control.setup_engine ();
2280 } else if (ret > 0) {
2281 response = Gtk::RESPONSE_REJECT;
2286 if (create_engine ()) {
2288 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2291 new_session_dialog->set_existing_session (false);
2292 new_session_dialog->set_current_page (2);
2294 response = Gtk::RESPONSE_NONE;
2298 backend_audio_is_running = true;
2300 if (response == Gtk::RESPONSE_OK) {
2302 session_name = new_session_dialog->session_name();
2304 if (session_name.empty()) {
2305 response = Gtk::RESPONSE_NONE;
2309 /* if the user mistakenly typed path information into the session filename entry,
2310 convert what they typed into a path & a name
2313 if (session_name[0] == '/' ||
2314 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2315 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2317 session_path = Glib::path_get_dirname (session_name);
2318 session_name = Glib::path_get_basename (session_name);
2322 session_path = new_session_dialog->session_folder();
2325 template_name = Glib::ustring();
2326 switch (new_session_dialog->which_page()) {
2328 case NewSessionDialog::OpenPage:
2329 case NewSessionDialog::EnginePage:
2333 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2335 should_be_new = true;
2337 //XXX This is needed because session constructor wants a
2338 //non-existant path. hopefully this will be fixed at some point.
2340 session_path = Glib::build_filename (session_path, session_name);
2342 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2344 if (ask_about_loading_existing_session (session_path)) {
2347 response = RESPONSE_NONE;
2352 _session_is_new = true;
2354 if (new_session_dialog->use_session_template()) {
2356 template_name = new_session_dialog->session_template_name();
2360 if (build_session_from_nsd (session_path, session_name)) {
2361 response = RESPONSE_NONE;
2373 new_session_dialog->hide ();
2375 if (load_session (session_path, session_name, template_name)) {
2377 response = Gtk::RESPONSE_NONE;
2381 if (response == Gtk::RESPONSE_NONE) {
2382 new_session_dialog->set_existing_session (false);
2383 new_session_dialog->reset ();
2387 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2391 new_session_dialog->hide();
2392 new_session_dialog->reset();
2393 goto_editor_window ();
2398 ARDOUR_UI::close_session ()
2400 if (!check_audioengine()) {
2404 unload_session (true);
2406 get_session_parameters (true, false);
2410 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2412 Session *new_session;
2416 session_loaded = false;
2418 if (!check_audioengine()) {
2422 unload_status = unload_session ();
2424 if (unload_status < 0) {
2426 } else if (unload_status > 0) {
2431 /* if it already exists, we must have write access */
2433 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2434 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2435 "This prevents the session from being loaded."));
2441 loading_message (_("Please wait while Ardour loads your session"));
2444 new_session = new Session (*engine, path, snap_name, mix_template);
2447 /* this one is special */
2449 catch (AudioEngine::PortRegistrationFailure& err) {
2451 MessageDialog msg (err.what(),
2454 Gtk::BUTTONS_CLOSE);
2456 msg.set_title (_("Port Registration Error"));
2457 msg.set_secondary_text (_("Click the Close button to try again."));
2458 msg.set_position (Gtk::WIN_POS_CENTER);
2462 int response = msg.run ();
2467 case RESPONSE_CANCEL:
2477 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2480 Gtk::BUTTONS_CLOSE);
2482 msg.set_title (_("Loading Error"));
2483 msg.set_secondary_text (_("Click the Close button to try again."));
2484 msg.set_position (Gtk::WIN_POS_CENTER);
2488 int response = msg.run ();
2493 case RESPONSE_CANCEL:
2501 connect_to_session (new_session);
2503 Config->set_current_owner (ConfigVariableBase::Interface);
2505 session_loaded = true;
2507 goto_editor_window ();
2510 session->set_clean ();
2521 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2522 uint32_t control_channels,
2523 uint32_t master_channels,
2524 AutoConnectOption input_connect,
2525 AutoConnectOption output_connect,
2528 nframes_t initial_length)
2530 Session *new_session;
2533 if (!check_audioengine()) {
2537 session_loaded = false;
2539 x = unload_session ();
2547 _session_is_new = true;
2550 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2551 control_channels, master_channels, nphysin, nphysout, initial_length);
2556 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2562 connect_to_session (new_session);
2564 session_loaded = true;
2566 new_session->save_state(new_session->name());
2575 editor->show_window ();
2586 ARDOUR_UI::show_about ()
2590 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2597 ARDOUR_UI::hide_about ()
2600 about->get_window()->set_cursor ();
2606 ARDOUR_UI::about_signal_response(int response)
2612 ARDOUR_UI::show_splash ()
2616 splash = new Splash;
2624 splash->queue_draw ();
2625 splash->get_window()->process_updates (true);
2630 ARDOUR_UI::hide_splash ()
2638 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2642 removed = rep.paths.size();
2645 MessageDialog msgd (*editor,
2646 _("No audio files were ready for cleanup"),
2649 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2650 msgd.set_secondary_text (_("If this seems suprising, \n\
2651 check for any existing snapshots.\n\
2652 These may still include regions that\n\
2653 require some unused files to continue to exist."));
2659 ArdourDialog results (_("ardour: cleanup"), true, false);
2661 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2662 CleanupResultsModelColumns() {
2666 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2667 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2671 CleanupResultsModelColumns results_columns;
2672 Glib::RefPtr<Gtk::ListStore> results_model;
2673 Gtk::TreeView results_display;
2675 results_model = ListStore::create (results_columns);
2676 results_display.set_model (results_model);
2677 results_display.append_column (list_title, results_columns.visible_name);
2679 results_display.set_name ("CleanupResultsList");
2680 results_display.set_headers_visible (true);
2681 results_display.set_headers_clickable (false);
2682 results_display.set_reorderable (false);
2684 Gtk::ScrolledWindow list_scroller;
2687 Gtk::HBox dhbox; // the hbox for the image and text
2688 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2689 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2691 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2693 if (rep.space < 1048576.0f) {
2695 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2697 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2701 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2703 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2707 dhbox.pack_start (*dimage, true, false, 5);
2708 dhbox.pack_start (txt, true, false, 5);
2710 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2711 TreeModel::Row row = *(results_model->append());
2712 row[results_columns.visible_name] = *i;
2713 row[results_columns.fullpath] = *i;
2716 list_scroller.add (results_display);
2717 list_scroller.set_size_request (-1, 150);
2718 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2720 dvbox.pack_start (dhbox, true, false, 5);
2721 dvbox.pack_start (list_scroller, true, false, 5);
2722 ddhbox.pack_start (dvbox, true, false, 5);
2724 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2725 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2726 results.set_default_response (RESPONSE_CLOSE);
2727 results.set_position (Gtk::WIN_POS_MOUSE);
2728 results.show_all_children ();
2729 results.set_resizable (false);
2736 ARDOUR_UI::cleanup ()
2739 /* shouldn't happen: menu item is insensitive */
2744 MessageDialog checker (_("Are you sure you want to cleanup?"),
2746 Gtk::MESSAGE_QUESTION,
2747 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2749 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2750 ALL undo/redo information will be lost if you cleanup.\n\
2751 After cleanup, unused audio files will be moved to a \
2752 \"dead sounds\" location."));
2754 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2755 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2756 checker.set_default_response (RESPONSE_CANCEL);
2758 checker.set_name (_("CleanupDialog"));
2759 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2760 checker.set_position (Gtk::WIN_POS_MOUSE);
2762 switch (checker.run()) {
2763 case RESPONSE_ACCEPT:
2769 Session::cleanup_report rep;
2771 editor->prepare_for_cleanup ();
2773 /* do not allow flush until a session is reloaded */
2775 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2777 act->set_sensitive (false);
2780 if (session->cleanup_sources (rep)) {
2781 editor->finish_cleanup ();
2785 editor->finish_cleanup ();
2788 display_cleanup_results (rep,
2791 The following %1 %2 not in use and \n\
2792 have been moved to:\n\
2794 Flushing the wastebasket will \n\
2795 release an additional\n\
2796 %4 %5bytes of disk space.\n"
2802 ARDOUR_UI::flush_trash ()
2805 /* shouldn't happen: menu item is insensitive */
2809 Session::cleanup_report rep;
2811 if (session->cleanup_trash_sources (rep)) {
2815 display_cleanup_results (rep,
2817 _("The following %1 %2 deleted from\n\
2819 releasing %4 %5bytes of disk space"));
2823 ARDOUR_UI::add_route (Gtk::Window* float_window)
2831 if (add_route_dialog == 0) {
2832 add_route_dialog = new AddRouteDialog;
2834 add_route_dialog->set_transient_for (*float_window);
2838 if (add_route_dialog->is_visible()) {
2839 /* we're already doing this */
2843 ResponseType r = (ResponseType) add_route_dialog->run ();
2845 add_route_dialog->hide();
2848 case RESPONSE_ACCEPT:
2855 if ((count = add_route_dialog->count()) <= 0) {
2859 string template_path = add_route_dialog->track_template();
2861 if (!template_path.empty()) {
2862 session->new_route_from_template (count, template_path);
2866 uint32_t input_chan = add_route_dialog->channels ();
2867 uint32_t output_chan;
2868 string name_template = add_route_dialog->name_template ();
2869 bool track = add_route_dialog->track ();
2871 AutoConnectOption oac = Config->get_output_auto_connect();
2873 if (oac & AutoConnectMaster) {
2874 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2876 output_chan = input_chan;
2879 /* XXX do something with name template */
2882 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2884 session_add_audio_bus (input_chan, output_chan, count);
2889 ARDOUR_UI::mixer_settings () const
2894 node = session->instant_xml(X_("Mixer"), session->path());
2896 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2900 node = new XMLNode (X_("Mixer"));
2907 ARDOUR_UI::editor_settings () const
2912 node = session->instant_xml(X_("Editor"), session->path());
2914 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2918 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2919 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2924 node = new XMLNode (X_("Editor"));
2930 ARDOUR_UI::keyboard_settings () const
2934 node = Config->extra_xml(X_("Keyboard"));
2937 node = new XMLNode (X_("Keyboard"));
2943 ARDOUR_UI::create_xrun_marker(nframes_t where)
2945 editor->mouse_add_new_marker (where, false, true);
2949 ARDOUR_UI::halt_on_xrun_message ()
2951 MessageDialog msg (*editor,
2952 _("Recording was stopped because your system could not keep up."));
2957 ARDOUR_UI::xrun_handler(nframes_t where)
2963 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2965 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2966 create_xrun_marker(where);
2969 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2970 halt_on_xrun_message ();
2975 ARDOUR_UI::preset_file_exists_handler ()
2977 /* if driven from another thread, say "do not overwrite" and show the user nothing.
2980 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
2984 HBox* hbox = new HBox();
2985 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2986 Gtk::Dialog dialog (_("Preset Exists"), true, false);
2988 A preset with this name already exists for this plugin.\n\
2990 What you would like to do?\n"));
2991 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2992 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2993 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2994 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2995 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
2996 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
2997 dialog.set_default_response (RESPONSE_ACCEPT);
2998 dialog.set_position (WIN_POS_MOUSE);
2999 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3005 switch (dialog.run ()) {
3006 case RESPONSE_ACCEPT:
3014 ARDOUR_UI::disk_overrun_handler ()
3016 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3018 if (!have_disk_speed_dialog_displayed) {
3019 have_disk_speed_dialog_displayed = true;
3020 MessageDialog* msg = new MessageDialog (*editor, _("\
3021 The disk system on your computer\n\
3022 was not able to keep up with Ardour.\n\
3024 Specifically, it failed to write data to disk\n\
3025 quickly enough to keep up with recording.\n"));
3026 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3032 ARDOUR_UI::disk_underrun_handler ()
3034 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3036 if (!have_disk_speed_dialog_displayed) {
3037 have_disk_speed_dialog_displayed = true;
3038 MessageDialog* msg = new MessageDialog (*editor,
3039 _("The disk system on your computer\n\
3040 was not able to keep up with Ardour.\n\
3042 Specifically, it failed to read data from disk\n\
3043 quickly enough to keep up with playback.\n"));
3044 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3050 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3052 have_disk_speed_dialog_displayed = false;
3057 ARDOUR_UI::session_dialog (std::string msg)
3059 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3064 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3066 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3075 ARDOUR_UI::pending_state_dialog ()
3077 HBox* hbox = new HBox();
3078 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3079 ArdourDialog dialog (_("Crash Recovery"), true);
3081 This session appears to have been in\n\
3082 middle of recording when ardour or\n\
3083 the computer was shutdown.\n\
3085 Ardour can recover any captured audio for\n\
3086 you, or it can ignore it. Please decide\n\
3087 what you would like to do.\n"));
3088 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3089 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3090 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3091 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3092 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3093 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3094 dialog.set_default_response (RESPONSE_ACCEPT);
3095 dialog.set_position (WIN_POS_CENTER);
3100 switch (dialog.run ()) {
3101 case RESPONSE_ACCEPT:
3109 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3111 HBox* hbox = new HBox();
3112 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3113 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3114 Label message (string_compose (_("\
3115 This session was created with a sample rate of %1 Hz\n\
3117 The audioengine is currently running at %2 Hz\n"), desired, actual));
3119 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3120 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3121 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3122 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3123 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3124 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3125 dialog.set_default_response (RESPONSE_ACCEPT);
3126 dialog.set_position (WIN_POS_CENTER);
3131 switch (dialog.run ()) {
3132 case RESPONSE_ACCEPT:
3141 ARDOUR_UI::disconnect_from_jack ()
3144 if( engine->disconnect_from_jack ()) {
3145 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3149 update_sample_rate (0);
3154 ARDOUR_UI::reconnect_to_jack ()
3157 if (engine->reconnect_to_jack ()) {
3158 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3162 update_sample_rate (0);
3167 ARDOUR_UI::use_config ()
3169 Glib::RefPtr<Action> act;
3171 switch (Config->get_native_file_data_format ()) {
3173 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3176 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3179 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3184 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3185 ract->set_active ();
3188 switch (Config->get_native_file_header_format ()) {
3190 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3193 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3196 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3199 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3202 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3205 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3208 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3213 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3214 ract->set_active ();
3217 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3219 set_transport_controllable_state (*node);
3224 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3226 if (Config->get_primary_clock_delta_edit_cursor()) {
3227 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3229 primary_clock.set (pos, 0, true);
3232 if (Config->get_secondary_clock_delta_edit_cursor()) {
3233 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3235 secondary_clock.set (pos);
3238 if (big_clock_window) {
3239 big_clock.set (pos);
3244 ARDOUR_UI::record_state_changed ()
3246 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3248 if (!session || !big_clock_window) {
3249 /* why bother - the clock isn't visible */
3253 switch (session->record_status()) {
3254 case Session::Recording:
3255 big_clock.set_widget_name ("BigClockRecording");
3258 big_clock.set_widget_name ("BigClockNonRecording");
3264 ARDOUR_UI::first_idle ()
3267 session->allow_auto_play (true);
3271 editor->first_idle();
3274 Keyboard::set_can_save_keybindings (true);
3279 ARDOUR_UI::store_clock_modes ()
3281 XMLNode* node = new XMLNode(X_("ClockModes"));
3283 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3284 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3287 session->add_extra_xml (*node);
3288 session->set_dirty ();
3293 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3294 : Controllable (name), ui (u), type(tp)
3300 ARDOUR_UI::TransportControllable::set_value (float val)
3302 if (type == ShuttleControl) {
3309 fract = -((0.5f - val)/0.5f);
3311 fract = ((val - 0.5f)/0.5f);
3315 ui.set_shuttle_fract (fract);
3320 /* do nothing: these are radio-style actions */
3324 const char *action = 0;
3328 action = X_("Roll");
3331 action = X_("Stop");
3334 action = X_("Goto Start");
3337 action = X_("Goto End");
3340 action = X_("Loop");
3343 action = X_("Play Selection");
3346 action = X_("Record");
3356 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3364 ARDOUR_UI::TransportControllable::get_value (void) const
3383 case ShuttleControl:
3393 ARDOUR_UI::TransportControllable::set_id (const string& str)
3399 ARDOUR_UI::setup_profile ()
3401 if (gdk_screen_width() < 1200) {
3402 Profile->set_small_screen ();
3405 if (getenv ("ARDOUR_SAE")) {
3406 Profile->set_sae ();
3407 Profile->set_single_package ();