2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
34 #include <sys/resource.h>
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include "midi++/manager.h"
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
76 typedef uint64_t microseconds_t;
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
86 #include "add_route_dialog.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
97 #include "engine_dialog.h"
101 using namespace ARDOUR;
103 using namespace Gtkmm2ext;
105 using namespace sigc;
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
117 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
119 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
120 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
121 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
122 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
126 preroll_button (_("pre\nroll")),
127 postroll_button (_("post\nroll")),
131 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
135 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143 shuttle_controller_binding_proxy (shuttle_controllable),
145 roll_button (roll_controllable),
146 stop_button (stop_controllable),
147 goto_start_button (goto_start_controllable),
148 goto_end_button (goto_end_controllable),
149 auto_loop_button (auto_loop_controllable),
150 play_selection_button (play_selection_controllable),
151 rec_button (rec_controllable),
153 shuttle_units_button (_("% ")),
155 punch_in_button (_("Punch In")),
156 punch_out_button (_("Punch Out")),
157 auto_return_button (_("Auto Return")),
158 auto_play_button (_("Auto Play")),
159 auto_input_button (_("Auto Input")),
160 click_button (_("Click")),
161 time_master_button (_("time\nmaster")),
163 auditioning_alert_button (_("AUDITION")),
164 solo_alert_button (_("SOLO")),
166 error_log_button (_("Errors"))
169 using namespace Gtk::Menu_Helpers;
175 _auto_display_errors = false;
182 if (theArdourUI == 0) {
186 ui_config = new UIConfiguration();
187 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 _will_create_new_session_automatically = false;
199 add_route_dialog = 0;
203 open_session_selector = 0;
204 have_configure_timeout = false;
205 have_disk_speed_dialog_displayed = false;
206 session_loaded = false;
207 last_speed_displayed = -1.0f;
208 ignore_dual_punch = false;
209 _mixer_on_top = false;
211 roll_button.unset_flags (Gtk::CAN_FOCUS);
212 stop_button.unset_flags (Gtk::CAN_FOCUS);
213 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
215 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
216 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
217 rec_button.unset_flags (Gtk::CAN_FOCUS);
219 last_configure_time= 0;
221 shuttle_grabbed = false;
223 shuttle_max_speed = 8.0f;
225 shuttle_style_menu = 0;
226 shuttle_unit_menu = 0;
228 // We do not have jack linked in yet so;
230 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
232 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
233 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
235 /* handle dialog requests */
237 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
239 /* handle pending state with a dialog */
241 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
243 /* handle sr mismatch with a dialog */
245 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
247 /* lets get this party started */
250 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
251 throw failed_constructor ();
254 setup_gtk_ardour_enums ();
255 Config->set_current_owner (ConfigVariableBase::Interface);
258 GainMeter::setup_slider_pix ();
259 RouteTimeAxisView::setup_slider_pix ();
261 } catch (failed_constructor& err) {
262 error << _("could not initialize Ardour.") << endmsg;
267 /* we like keyboards */
269 keyboard = new Keyboard;
273 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
274 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
280 ARDOUR_UI::run_startup (bool should_be_new)
283 _startup = new ArdourStartup ();
286 _startup->set_new_only (should_be_new);
287 _startup->present ();
291 /* we don't return here until the startup assistant is finished */
297 ARDOUR_UI::create_engine ()
299 // this gets called every time by new_session()
305 loading_message (_("Starting audio engine"));
308 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
315 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
316 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
317 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
318 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
326 ARDOUR_UI::post_engine ()
328 /* Things to be done once we create the AudioEngine
331 MIDI::Manager::instance()->set_api_data (engine->jack());
334 ActionManager::init ();
337 if (setup_windows ()) {
338 throw failed_constructor ();
341 check_memory_locking();
343 /* this is the first point at which all the keybindings are available */
345 if (ARDOUR_COMMAND_LINE::show_key_actions) {
346 vector<string> names;
347 vector<string> paths;
349 vector<AccelKey> bindings;
351 ActionManager::get_all_actions (names, paths, keys, bindings);
353 vector<string>::iterator n;
354 vector<string>::iterator k;
355 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
356 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
362 blink_timeout_tag = -1;
364 /* the global configuration object is now valid */
368 /* this being a GUI and all, we want peakfiles */
370 AudioFileSource::set_build_peakfiles (true);
371 AudioFileSource::set_build_missing_peakfiles (true);
373 /* set default clock modes */
375 if (Profile->get_sae()) {
376 primary_clock.set_mode (AudioClock::BBT);
377 secondary_clock.set_mode (AudioClock::MinSec);
379 primary_clock.set_mode (AudioClock::SMPTE);
380 secondary_clock.set_mode (AudioClock::BBT);
383 /* start the time-of-day-clock */
386 /* OS X provides an always visible wallclock, so don't be stupid */
387 update_wall_clock ();
388 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
391 update_disk_space ();
393 update_sample_rate (engine->frame_rate());
395 /* now start and maybe save state */
397 if (do_engine_start () == 0) {
398 if (session && _session_is_new) {
399 /* we need to retain initial visual
400 settings for a new session
402 session->save_state ("");
407 ARDOUR_UI::~ARDOUR_UI ()
409 save_ardour_state ();
414 delete add_route_dialog;
418 ARDOUR_UI::pop_back_splash ()
420 if (Splash::instance()) {
421 // Splash::instance()->pop_back();
422 Splash::instance()->hide ();
427 ARDOUR_UI::configure_timeout ()
429 if (last_configure_time == 0) {
430 /* no configure events yet */
434 /* force a gap of 0.5 seconds since the last configure event
437 if (get_microseconds() - last_configure_time < 500000) {
440 have_configure_timeout = false;
441 save_ardour_state ();
447 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
449 if (have_configure_timeout) {
450 last_configure_time = get_microseconds();
452 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
453 have_configure_timeout = true;
460 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
462 const XMLProperty* prop;
464 if ((prop = node.property ("roll")) != 0) {
465 roll_controllable->set_id (prop->value());
467 if ((prop = node.property ("stop")) != 0) {
468 stop_controllable->set_id (prop->value());
470 if ((prop = node.property ("goto-start")) != 0) {
471 goto_start_controllable->set_id (prop->value());
473 if ((prop = node.property ("goto-end")) != 0) {
474 goto_end_controllable->set_id (prop->value());
476 if ((prop = node.property ("auto-loop")) != 0) {
477 auto_loop_controllable->set_id (prop->value());
479 if ((prop = node.property ("play-selection")) != 0) {
480 play_selection_controllable->set_id (prop->value());
482 if ((prop = node.property ("rec")) != 0) {
483 rec_controllable->set_id (prop->value());
485 if ((prop = node.property ("shuttle")) != 0) {
486 shuttle_controllable->set_id (prop->value());
491 ARDOUR_UI::get_transport_controllable_state ()
493 XMLNode* node = new XMLNode(X_("TransportControllables"));
496 roll_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("roll"), buf);
498 stop_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("stop"), buf);
500 goto_start_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("goto_start"), buf);
502 goto_end_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("goto_end"), buf);
504 auto_loop_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("auto_loop"), buf);
506 play_selection_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("play_selection"), buf);
508 rec_controllable->id().print (buf, sizeof (buf));
509 node->add_property (X_("rec"), buf);
510 shuttle_controllable->id().print (buf, sizeof (buf));
511 node->add_property (X_("shuttle"), buf);
517 ARDOUR_UI::save_ardour_state ()
519 if (!keyboard || !mixer || !editor) {
523 /* XXX this is all a bit dubious. add_extra_xml() uses
524 a different lifetime model from add_instant_xml().
527 XMLNode* node = new XMLNode (keyboard->get_state());
528 Config->add_extra_xml (*node);
529 Config->add_extra_xml (get_transport_controllable_state());
530 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
531 Config->add_extra_xml (_startup->engine_control()->get_state());
533 Config->save_state();
534 ui_config->save_state ();
536 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
537 XMLNode mnode(mixer->get_state());
540 session->add_instant_xml (enode);
541 session->add_instant_xml (mnode);
543 Config->add_instant_xml (enode);
544 Config->add_instant_xml (mnode);
547 Keyboard::save_keybindings ();
551 ARDOUR_UI::autosave_session ()
553 if (g_main_depth() > 1) {
554 /* inside a recursive main loop,
555 give up because we may not be able to
561 if (!Config->get_periodic_safety_backups()) {
566 session->maybe_write_autosave();
573 ARDOUR_UI::update_autosave ()
575 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
577 if (session->dirty()) {
578 if (_autosave_connection.connected()) {
579 _autosave_connection.disconnect();
582 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
583 Config->get_periodic_safety_backup_interval() * 1000);
586 if (_autosave_connection.connected()) {
587 _autosave_connection.disconnect();
593 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
597 title = _("Ardour could not start JACK");
599 title = _("Ardour could not connect to JACK.");
602 MessageDialog win (title,
608 win.set_secondary_text(_("There are several possible reasons:\n\
610 1) You requested audio parameters that are not supported..\n\
611 2) JACK is running as another user.\n\
613 Please consider the possibilities, and perhaps try different parameters."));
615 win.set_secondary_text(_("There are several possible reasons:\n\
617 1) JACK is not running.\n\
618 2) JACK is running as another user, perhaps root.\n\
619 3) There is already another client called \"ardour\".\n\
621 Please consider the possibilities, and perhaps (re)start JACK."));
625 win.set_transient_for (*toplevel);
629 win.add_button (Stock::OK, RESPONSE_CLOSE);
631 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
634 win.set_default_response (RESPONSE_CLOSE);
637 win.set_position (Gtk::WIN_POS_CENTER);
640 /* we just don't care about the result, but we want to block */
646 ARDOUR_UI::startup ()
648 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
650 if (audio_setup && _startup && _startup->engine_control()) {
651 _startup->engine_control()->set_state (*audio_setup);
654 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
658 goto_editor_window ();
660 BootMessage (_("Ardour is ready for use"));
665 ARDOUR_UI::no_memory_warning ()
667 XMLNode node (X_("no-memory-warning"));
668 Config->add_instant_xml (node);
672 ARDOUR_UI::check_memory_locking ()
675 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
679 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
681 if (engine->is_realtime() && memory_warning_node == 0) {
683 struct rlimit limits;
685 long pages, page_size;
687 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
690 ram = (int64_t) pages * (int64_t) page_size;
693 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
697 if (limits.rlim_cur != RLIM_INFINITY) {
699 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
702 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
703 "This might cause Ardour to run out of memory before your system "
704 "runs out of memory. \n\n"
705 "You can view the memory limit with 'ulimit -l', "
706 "and it is normally controlled by /etc/security/limits.conf"));
708 VBox* vbox = msg.get_vbox();
710 CheckButton cb (_("Do not show this window again"));
712 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
714 hbox.pack_start (cb, true, false);
715 vbox->pack_start (hbox);
722 editor->ensure_float (msg);
736 if (session->transport_rolling()) {
737 session->request_stop ();
741 if (session->dirty()) {
742 switch (ask_about_saving_session(_("quit"))) {
747 /* use the default name */
748 if (save_state_canfail ("")) {
749 /* failed - don't quit */
750 MessageDialog msg (*editor,
752 Ardour was unable to save your session.\n\n\
753 If you still wish to quit, please use the\n\n\
754 \"Just quit\" option."));
765 session->set_deletion_in_progress ();
768 ArdourDialog::close_all_dialogs ();
770 save_ardour_state ();
775 ARDOUR_UI::ask_about_saving_session (const string & what)
777 ArdourDialog window (_("ardour: save session?"));
778 Gtk::HBox dhbox; // the hbox for the image and text
779 Gtk::Label prompt_label;
780 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
784 msg = string_compose(_("Don't %1"), what);
785 window.add_button (msg, RESPONSE_REJECT);
786 msg = string_compose(_("Just %1"), what);
787 window.add_button (msg, RESPONSE_APPLY);
788 msg = string_compose(_("Save and %1"), what);
789 window.add_button (msg, RESPONSE_ACCEPT);
791 window.set_default_response (RESPONSE_ACCEPT);
793 Gtk::Button noquit_button (msg);
794 noquit_button.set_name ("EditorGTKButton");
799 if (session->snap_name() == session->name()) {
802 type = _("snapshot");
804 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?"),
805 type, session->snap_name());
807 prompt_label.set_text (prompt);
808 prompt_label.set_name (X_("PrompterLabel"));
809 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
811 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
812 dhbox.set_homogeneous (false);
813 dhbox.pack_start (*dimage, false, false, 5);
814 dhbox.pack_start (prompt_label, true, false, 5);
815 window.get_vbox()->pack_start (dhbox);
817 window.set_name (_("Prompter"));
818 window.set_position (Gtk::WIN_POS_MOUSE);
819 window.set_modal (true);
820 window.set_resizable (false);
826 window.set_keep_above (true);
829 ResponseType r = (ResponseType) window.run();
834 case RESPONSE_ACCEPT: // save and get out of here
836 case RESPONSE_APPLY: // get out of here
846 ARDOUR_UI::every_second ()
849 update_buffer_load ();
850 update_disk_space ();
855 ARDOUR_UI::every_point_one_seconds ()
857 update_speed_display ();
858 RapidScreenUpdate(); /* EMIT_SIGNAL */
863 ARDOUR_UI::every_point_zero_one_seconds ()
865 // august 2007: actual update frequency: 40Hz, not 100Hz
867 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
872 ARDOUR_UI::update_sample_rate (nframes_t ignored)
876 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
878 if (!engine->connected()) {
880 snprintf (buf, sizeof (buf), _("disconnected"));
884 nframes_t rate = engine->frame_rate();
886 if (fmod (rate, 1000.0) != 0.0) {
887 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
888 (float) rate/1000.0f,
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
891 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
893 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
897 sample_rate_label.set_text (buf);
901 ARDOUR_UI::update_cpu_load ()
904 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
905 cpu_load_label.set_text (buf);
909 ARDOUR_UI::update_buffer_load ()
915 c = session->capture_load ();
916 p = session->playback_load ();
918 push_buffer_stats (c, p);
920 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
921 session->playback_load(), session->capture_load());
922 buffer_load_label.set_text (buf);
924 buffer_load_label.set_text ("");
929 ARDOUR_UI::count_recenabled_streams (Route& route)
931 Track* track = dynamic_cast<Track*>(&route);
932 if (track && track->diskstream()->record_enabled()) {
933 rec_enabled_streams += track->n_inputs().n_total();
938 ARDOUR_UI::update_disk_space()
944 nframes_t frames = session->available_capture_duration();
946 nframes_t fr = session->frame_rate();
948 if (frames == max_frames) {
949 strcpy (buf, _("Disk: 24hrs+"));
951 rec_enabled_streams = 0;
952 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
954 if (rec_enabled_streams) {
955 frames /= rec_enabled_streams;
962 hrs = frames / (fr * 3600);
963 frames -= hrs * fr * 3600;
964 mins = frames / (fr * 60);
965 frames -= mins * fr * 60;
968 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
971 disk_space_label.set_text (buf);
973 // An attempt to make the disk space label flash red when space has run out.
975 if (frames < fr * 60 * 5) {
976 /* disk_space_box.style ("disk_space_label_empty"); */
978 /* disk_space_box.style ("disk_space_label"); */
984 ARDOUR_UI::update_wall_clock ()
991 tm_now = localtime (&now);
993 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
994 wall_clock_label.set_text (buf);
1000 ARDOUR_UI::session_menu (GdkEventButton *ev)
1002 session_popup_menu->popup (0, 0);
1007 ARDOUR_UI::redisplay_recent_sessions ()
1009 std::vector<sys::path> session_directories;
1010 RecentSessionsSorter cmp;
1012 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1013 recent_session_model->clear ();
1015 ARDOUR::RecentSessions rs;
1016 ARDOUR::read_recent_sessions (rs);
1019 recent_session_display.set_model (recent_session_model);
1023 // sort them alphabetically
1024 sort (rs.begin(), rs.end(), cmp);
1026 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1027 session_directories.push_back ((*i).second);
1030 for (vector<sys::path>::const_iterator i = session_directories.begin();
1031 i != session_directories.end(); ++i)
1033 std::vector<sys::path> state_file_paths;
1035 // now get available states for this session
1037 get_state_files_in_directory (*i, state_file_paths);
1039 vector<string*>* states;
1040 vector<const gchar*> item;
1041 string fullpath = (*i).to_string();
1043 /* remove any trailing / */
1045 if (fullpath[fullpath.length()-1] == '/') {
1046 fullpath = fullpath.substr (0, fullpath.length()-1);
1049 /* check whether session still exists */
1050 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1051 /* session doesn't exist */
1052 cerr << "skipping non-existent session " << fullpath << endl;
1056 /* now get available states for this session */
1058 if ((states = Session::possible_states (fullpath)) == 0) {
1059 /* no state file? */
1063 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1065 Gtk::TreeModel::Row row = *(recent_session_model->append());
1067 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1068 row[recent_session_columns.fullpath] = fullpath;
1070 if (state_file_names.size() > 1) {
1074 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1075 i2 != state_file_names.end(); ++i2)
1078 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1080 child_row[recent_session_columns.visible_name] = *i2;
1081 child_row[recent_session_columns.fullpath] = fullpath;
1086 recent_session_display.set_model (recent_session_model);
1090 ARDOUR_UI::build_session_selector ()
1092 session_selector_window = new ArdourDialog ("session selector");
1094 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1096 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1097 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1098 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1099 recent_session_model = TreeStore::create (recent_session_columns);
1100 recent_session_display.set_model (recent_session_model);
1101 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1102 recent_session_display.set_headers_visible (false);
1103 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1104 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1106 scroller->add (recent_session_display);
1107 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1109 session_selector_window->set_name ("SessionSelectorWindow");
1110 session_selector_window->set_size_request (200, 400);
1111 session_selector_window->get_vbox()->pack_start (*scroller);
1113 recent_session_display.show();
1115 //session_selector_window->get_vbox()->show();
1119 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1121 session_selector_window->response (RESPONSE_ACCEPT);
1125 ARDOUR_UI::open_recent_session ()
1127 bool can_return = (session != 0);
1129 if (session_selector_window == 0) {
1130 build_session_selector ();
1133 redisplay_recent_sessions ();
1137 session_selector_window->set_position (WIN_POS_MOUSE);
1139 ResponseType r = (ResponseType) session_selector_window->run ();
1142 case RESPONSE_ACCEPT:
1146 session_selector_window->hide();
1153 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1157 session_selector_window->hide();
1159 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1161 if (i == recent_session_model->children().end()) {
1165 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1166 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1168 _session_is_new = false;
1170 if (load_session (path, state) == 0) {
1179 ARDOUR_UI::check_audioengine ()
1182 if (!engine->connected()) {
1183 MessageDialog msg (_("Ardour is not connected to JACK\n"
1184 "You cannot open or close sessions in this condition"));
1196 ARDOUR_UI::open_session ()
1198 if (!check_audioengine()) {
1203 /* popup selector window */
1205 if (open_session_selector == 0) {
1207 /* ardour sessions are folders */
1209 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1210 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1211 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1212 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1214 FileFilter session_filter;
1215 session_filter.add_pattern ("*.ardour");
1216 session_filter.set_name (_("Ardour sessions"));
1217 open_session_selector->add_filter (session_filter);
1218 open_session_selector->set_filter (session_filter);
1221 int response = open_session_selector->run();
1222 open_session_selector->hide ();
1225 case RESPONSE_ACCEPT:
1228 open_session_selector->hide();
1232 open_session_selector->hide();
1233 string session_path = open_session_selector->get_filename();
1237 if (session_path.length() > 0) {
1238 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1239 _session_is_new = isnew;
1240 load_session (path, name);
1247 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1249 list<boost::shared_ptr<MidiTrack> > tracks;
1252 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1259 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1261 if (tracks.size() != how_many) {
1262 if (how_many == 1) {
1263 error << _("could not create a new midi track") << endmsg;
1265 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1269 if ((route = session->new_midi_route ()) == 0) {
1270 error << _("could not create new midi bus") << endmsg;
1276 MessageDialog msg (*editor,
1277 _("There are insufficient JACK ports available\n\
1278 to create a new track or bus.\n\
1279 You should save Ardour, exit and\n\
1280 restart JACK with more ports."));
1287 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1289 list<boost::shared_ptr<AudioTrack> > tracks;
1293 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1299 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1301 if (tracks.size() != how_many) {
1302 if (how_many == 1) {
1303 error << _("could not create a new audio track") << endmsg;
1305 error << string_compose (_("could only create %1 of %2 new audio %3"),
1306 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1312 routes = session->new_audio_route (input_channels, output_channels, how_many);
1314 if (routes.size() != how_many) {
1315 if (how_many == 1) {
1316 error << _("could not create a new audio track") << endmsg;
1318 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1324 if (need_control_room_outs) {
1330 route->set_stereo_control_outs (control_lr_channels);
1331 route->control_outs()->set_stereo_pan (pans, this);
1333 #endif /* CONTROLOUTS */
1337 MessageDialog msg (*editor,
1338 _("There are insufficient JACK ports available\n\
1339 to create a new track or bus.\n\
1340 You should save Ardour, exit and\n\
1341 restart JACK with more ports."));
1348 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1350 nframes_t _preroll = 0;
1353 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1354 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1356 if (new_position > _preroll) {
1357 new_position -= _preroll;
1362 session->request_locate (new_position);
1367 ARDOUR_UI::transport_goto_start ()
1370 session->goto_start();
1373 /* force displayed area in editor to start no matter
1374 what "follow playhead" setting is.
1378 editor->reset_x_origin (session->current_start_frame());
1384 ARDOUR_UI::transport_goto_zero ()
1387 session->request_locate (0);
1390 /* force displayed area in editor to start no matter
1391 what "follow playhead" setting is.
1395 editor->reset_x_origin (0);
1401 ARDOUR_UI::transport_goto_wallclock ()
1403 if (session && editor) {
1410 localtime_r (&now, &tmnow);
1412 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1413 frames += tmnow.tm_min * (60 * session->frame_rate());
1414 frames += tmnow.tm_sec * session->frame_rate();
1416 session->request_locate (frames);
1418 /* force displayed area in editor to start no matter
1419 what "follow playhead" setting is.
1423 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1429 ARDOUR_UI::transport_goto_end ()
1432 nframes_t frame = session->current_end_frame();
1433 session->request_locate (frame);
1435 /* force displayed area in editor to start no matter
1436 what "follow playhead" setting is.
1440 editor->reset_x_origin (frame);
1446 ARDOUR_UI::transport_stop ()
1452 if (session->is_auditioning()) {
1453 session->cancel_audition ();
1457 if (session->get_play_loop ()) {
1458 session->request_play_loop (false);
1461 session->request_stop ();
1465 ARDOUR_UI::transport_stop_and_forget_capture ()
1468 session->request_stop (true);
1473 ARDOUR_UI::remove_last_capture()
1476 editor->remove_last_capture();
1481 ARDOUR_UI::transport_record (bool roll)
1485 switch (session->record_status()) {
1486 case Session::Disabled:
1487 if (session->ntracks() == 0) {
1488 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1492 session->maybe_enable_record ();
1497 case Session::Recording:
1499 session->request_stop();
1501 session->disable_record (false, true);
1505 case Session::Enabled:
1506 session->disable_record (false, true);
1509 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1513 ARDOUR_UI::transport_roll ()
1521 rolling = session->transport_rolling ();
1523 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1525 if (session->get_play_loop()) {
1526 session->request_play_loop (false);
1527 auto_loop_button.set_visual_state (1);
1528 roll_button.set_visual_state (1);
1529 } else if (session->get_play_range ()) {
1530 session->request_play_range (false);
1531 play_selection_button.set_visual_state (0);
1532 } else if (rolling) {
1533 session->request_locate (session->last_transport_start(), true);
1536 session->request_transport_speed (1.0f);
1540 ARDOUR_UI::transport_loop()
1543 if (session->get_play_loop()) {
1544 if (session->transport_rolling()) {
1545 Location * looploc = session->locations()->auto_loop_location();
1547 session->request_locate (looploc->start(), true);
1552 session->request_play_loop (true);
1558 ARDOUR_UI::transport_play_selection ()
1564 if (!session->get_play_range()) {
1565 session->request_stop ();
1568 editor->play_selection ();
1572 ARDOUR_UI::transport_rewind (int option)
1574 float current_transport_speed;
1577 current_transport_speed = session->transport_speed();
1579 if (current_transport_speed >= 0.0f) {
1582 session->request_transport_speed (-1.0f);
1585 session->request_transport_speed (-4.0f);
1588 session->request_transport_speed (-0.5f);
1593 session->request_transport_speed (current_transport_speed * 1.5f);
1599 ARDOUR_UI::transport_forward (int option)
1601 float current_transport_speed;
1604 current_transport_speed = session->transport_speed();
1606 if (current_transport_speed <= 0.0f) {
1609 session->request_transport_speed (1.0f);
1612 session->request_transport_speed (4.0f);
1615 session->request_transport_speed (0.5f);
1620 session->request_transport_speed (current_transport_speed * 1.5f);
1626 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1632 boost::shared_ptr<Route> r;
1634 if ((r = session->route_by_remote_id (dstream)) != 0) {
1638 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1639 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1648 ARDOUR_UI::queue_transport_change ()
1650 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1654 ARDOUR_UI::map_transport_state ()
1656 float sp = session->transport_speed();
1659 transport_rolling ();
1660 } else if (sp < 0.0f) {
1661 transport_rewinding ();
1662 } else if (sp > 0.0f) {
1663 transport_forwarding ();
1665 transport_stopped ();
1670 ARDOUR_UI::engine_stopped ()
1672 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1673 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1674 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1678 ARDOUR_UI::engine_running ()
1680 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1681 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1682 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1684 Glib::RefPtr<Action> action;
1685 const char* action_name = 0;
1687 switch (engine->frames_per_cycle()) {
1689 action_name = X_("JACKLatency32");
1692 action_name = X_("JACKLatency64");
1695 action_name = X_("JACKLatency128");
1698 action_name = X_("JACKLatency512");
1701 action_name = X_("JACKLatency1024");
1704 action_name = X_("JACKLatency2048");
1707 action_name = X_("JACKLatency4096");
1710 action_name = X_("JACKLatency8192");
1713 /* XXX can we do anything useful ? */
1719 action = ActionManager::get_action (X_("JACK"), action_name);
1722 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1723 ract->set_active ();
1729 ARDOUR_UI::engine_halted ()
1731 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1733 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1734 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1736 update_sample_rate (0);
1738 MessageDialog msg (*editor,
1740 JACK has either been shutdown or it\n\
1741 disconnected Ardour because Ardour\n\
1742 was not fast enough. Try to restart\n\
1743 JACK, reconnect and save the session."));
1749 ARDOUR_UI::do_engine_start ()
1757 error << _("Unable to start the session running")
1767 ARDOUR_UI::setup_theme ()
1769 theme_manager->setup_theme();
1773 ARDOUR_UI::update_clocks ()
1775 if (!editor || !editor->dragging_playhead()) {
1776 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1781 ARDOUR_UI::start_clocking ()
1783 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1787 ARDOUR_UI::stop_clocking ()
1789 clock_signal_connection.disconnect ();
1793 ARDOUR_UI::toggle_clocking ()
1796 if (clock_button.get_active()) {
1805 ARDOUR_UI::_blink (void *arg)
1808 ((ARDOUR_UI *) arg)->blink ();
1815 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1819 ARDOUR_UI::start_blinking ()
1821 /* Start the blink signal. Everybody with a blinking widget
1822 uses Blink to drive the widget's state.
1825 if (blink_timeout_tag < 0) {
1827 blink_timeout_tag = g_timeout_add (240, _blink, this);
1832 ARDOUR_UI::stop_blinking ()
1834 if (blink_timeout_tag >= 0) {
1835 g_source_remove (blink_timeout_tag);
1836 blink_timeout_tag = -1;
1841 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1846 vector<string> connections;
1849 if (io.n_inputs().n_total() == 0) {
1854 /* XXX we're not handling multiple ports yet. */
1856 if (io.input(0)->get_connections(connections) == 0) {
1859 buf = connections.front();
1864 if (io.n_outputs().n_total() == 0) {
1869 /* XXX we're not handling multiple ports yet. */
1871 if (io.output(0)->get_connections(connections) == 0) {
1874 buf = connections.front();
1879 /** Ask the user for the name of a new shapshot and then take it.
1882 ARDOUR_UI::snapshot_session ()
1884 ArdourPrompter prompter (true);
1888 struct tm local_time;
1891 localtime_r (&n, &local_time);
1892 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1894 prompter.set_name ("Prompter");
1895 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1896 prompter.set_prompt (_("Name of New Snapshot"));
1897 prompter.set_initial_text (timebuf);
1899 switch (prompter.run()) {
1900 case RESPONSE_ACCEPT:
1901 prompter.get_result (snapname);
1902 if (snapname.length()){
1903 save_state (snapname);
1913 ARDOUR_UI::save_state (const string & name)
1915 (void) save_state_canfail (name);
1919 ARDOUR_UI::save_state_canfail (string name)
1924 if (name.length() == 0) {
1925 name = session->snap_name();
1928 if ((ret = session->save_state (name)) != 0) {
1932 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1937 ARDOUR_UI::primary_clock_value_changed ()
1940 session->request_locate (primary_clock.current_time ());
1945 ARDOUR_UI::big_clock_value_changed ()
1948 session->request_locate (big_clock.current_time ());
1953 ARDOUR_UI::secondary_clock_value_changed ()
1956 session->request_locate (secondary_clock.current_time ());
1961 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1967 Session::RecordState const r = session->record_status ();
1968 bool const h = session->have_rec_enabled_diskstream ();
1970 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1972 rec_button.set_visual_state (2);
1974 rec_button.set_visual_state (0);
1976 } else if (r == Session::Recording && h) {
1977 rec_button.set_visual_state (1);
1979 rec_button.set_visual_state (0);
1984 ARDOUR_UI::save_template ()
1987 ArdourPrompter prompter (true);
1990 if (!check_audioengine()) {
1994 prompter.set_name (X_("Prompter"));
1995 prompter.set_prompt (_("Name for mix template:"));
1996 prompter.set_initial_text(session->name() + _("-template"));
1997 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1999 switch (prompter.run()) {
2000 case RESPONSE_ACCEPT:
2001 prompter.get_result (name);
2003 if (name.length()) {
2004 session->save_template (name);
2014 ARDOUR_UI::edit_metadata ()
2016 SessionMetadataEditor dialog;
2017 dialog.set_session (session);
2018 editor->ensure_float (dialog);
2023 ARDOUR_UI::import_metadata ()
2025 SessionMetadataImporter dialog;
2026 dialog.set_session (session);
2027 editor->ensure_float (dialog);
2032 ARDOUR_UI::fontconfig_dialog ()
2035 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2036 may not and it can take a while to build it. Warn them.
2039 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2041 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2042 MessageDialog msg (*_startup,
2043 _("Welcome to Ardour.\n\n"
2044 "The program will take a bit longer to start up\n"
2045 "while the system fonts are checked.\n\n"
2046 "This will only be done once, and you will\n"
2047 "not see this message again\n"),
2060 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2062 existing_session = false;
2064 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2065 session_path = cmdline_path;
2066 existing_session = true;
2067 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2068 session_path = Glib::path_get_dirname (string (cmdline_path));
2069 existing_session = true;
2071 /* it doesn't exist, assume the best */
2072 session_path = Glib::path_get_dirname (string (cmdline_path));
2075 session_name = basename_nosuffix (string (cmdline_path));
2079 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2081 /* when this is called, the backend audio system must be running */
2083 /* the main idea here is to deal with the fact that a cmdline argument for the session
2084 can be interpreted in different ways - it could be a directory or a file, and before
2085 we load, we need to know both the session directory and the snapshot (statefile) within it
2086 that we are supposed to use.
2089 if (session_name.length() == 0 || session_path.length() == 0) {
2093 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2095 Glib::ustring predicted_session_file;
2097 predicted_session_file = session_path;
2098 predicted_session_file += '/';
2099 predicted_session_file += session_name;
2100 predicted_session_file += ARDOUR::statefile_suffix;
2102 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2103 existing_session = true;
2106 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2108 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2109 /* existing .ardour file */
2110 existing_session = true;
2114 existing_session = false;
2117 /* lets just try to load it */
2119 if (create_engine ()) {
2120 backend_audio_error (false, _startup);
2124 return load_session (session_path, session_name);
2128 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2130 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2132 MessageDialog msg (str,
2134 Gtk::MESSAGE_WARNING,
2135 Gtk::BUTTONS_YES_NO,
2139 msg.set_name (X_("CleanupDialog"));
2140 msg.set_wmclass (X_("existing_session"), "Ardour");
2141 msg.set_position (Gtk::WIN_POS_MOUSE);
2144 switch (msg.run()) {
2153 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2158 AutoConnectOption iconnect;
2159 AutoConnectOption oconnect;
2163 if (Profile->get_sae()) {
2167 iconnect = AutoConnectPhysical;
2168 oconnect = AutoConnectMaster;
2169 nphysin = 0; // use all available
2170 nphysout = 0; // use all available
2174 /* get settings from advanced section of NSD */
2176 if (_startup->create_control_bus()) {
2177 cchns = (uint32_t) _startup->control_channel_count();
2182 if (_startup->create_master_bus()) {
2183 mchns = (uint32_t) _startup->master_channel_count();
2188 if (_startup->connect_inputs()) {
2189 iconnect = AutoConnectPhysical;
2191 iconnect = AutoConnectOption (0);
2194 /// @todo some minor tweaks.
2196 if (_startup->connect_outs_to_master()) {
2197 oconnect = AutoConnectMaster;
2198 } else if (_startup->connect_outs_to_physical()) {
2199 oconnect = AutoConnectPhysical;
2201 oconnect = AutoConnectOption (0);
2204 nphysin = (uint32_t) _startup->input_limit_count();
2205 nphysout = (uint32_t) _startup->output_limit_count();
2208 if (build_session (session_path,
2216 engine->frame_rate() * 60 * 5)) {
2225 ARDOUR_UI::end_loading_messages ()
2231 ARDOUR_UI::loading_message (const std::string& msg)
2234 // splash->message (msg);
2239 ARDOUR_UI::get_session_parameters (bool should_be_new)
2241 Glib::ustring session_name;
2242 Glib::ustring session_path;
2243 Glib::ustring template_name;
2245 bool likely_new = false;
2249 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2251 /* if they named a specific statefile, use it, otherwise they are
2252 just giving a session folder, and we want to use it as is
2253 to find the session.
2256 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2257 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2259 session_path = ARDOUR_COMMAND_LINE::session_name;
2262 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2266 run_startup (should_be_new);
2268 /* if we run the startup dialog again, offer more than just "new session" */
2270 should_be_new = false;
2272 session_name = _startup->session_name (likely_new);
2274 /* this shouldn't happen, but we catch it just in case it does */
2276 if (session_name.empty()) {
2279 if (_startup->use_session_template()) {
2280 template_name = _startup->session_template_name();
2281 _session_is_new = true;
2285 if (session_name[0] == '/' ||
2286 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2287 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2289 session_path = Glib::path_get_dirname (session_name);
2290 session_name = Glib::path_get_basename (session_name);
2294 session_path = _startup->session_folder();
2298 if (create_engine ()) {
2302 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2306 ustring existing = Glib::build_filename (session_path, session_name);
2308 if (!ask_about_loading_existing_session (existing)) {
2309 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2314 _session_is_new = false;
2319 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2321 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2325 _session_is_new = true;
2328 if (likely_new && template_name.empty()) {
2330 ret = build_session_from_nsd (session_path, session_name);
2334 ret = load_session (session_path, session_name, template_name);
2342 ARDOUR_UI::close_session()
2344 if (!check_audioengine()) {
2348 unload_session (true);
2350 get_session_parameters (false);
2354 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2356 Session *new_session;
2360 session_loaded = false;
2362 if (!check_audioengine()) {
2366 unload_status = unload_session ();
2368 if (unload_status < 0) {
2370 } else if (unload_status > 0) {
2375 /* if it already exists, we must have write access */
2377 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2378 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2379 "This prevents the session from being loaded."));
2385 loading_message (_("Please wait while Ardour loads your session"));
2388 new_session = new Session (*engine, path, snap_name, mix_template);
2391 /* this one is special */
2393 catch (AudioEngine::PortRegistrationFailure& err) {
2395 MessageDialog msg (err.what(),
2398 Gtk::BUTTONS_CLOSE);
2400 msg.set_title (_("Port Registration Error"));
2401 msg.set_secondary_text (_("Click the Close button to try again."));
2402 msg.set_position (Gtk::WIN_POS_CENTER);
2406 int response = msg.run ();
2411 case RESPONSE_CANCEL:
2421 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2424 Gtk::BUTTONS_CLOSE);
2426 msg.set_title (_("Loading Error"));
2427 msg.set_secondary_text (_("Click the Close button to try again."));
2428 msg.set_position (Gtk::WIN_POS_CENTER);
2432 int response = msg.run ();
2437 case RESPONSE_CANCEL:
2445 connect_to_session (new_session);
2447 Config->set_current_owner (ConfigVariableBase::Interface);
2449 session_loaded = true;
2451 goto_editor_window ();
2454 session->set_clean ();
2465 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2466 uint32_t control_channels,
2467 uint32_t master_channels,
2468 AutoConnectOption input_connect,
2469 AutoConnectOption output_connect,
2472 nframes_t initial_length)
2474 Session *new_session;
2477 if (!check_audioengine()) {
2481 session_loaded = false;
2483 x = unload_session ();
2491 _session_is_new = true;
2494 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2495 control_channels, master_channels, nphysin, nphysout, initial_length);
2500 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2506 connect_to_session (new_session);
2508 session_loaded = true;
2510 new_session->save_state(new_session->name());
2519 editor->show_window ();
2530 ARDOUR_UI::show_about ()
2534 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2541 ARDOUR_UI::hide_about ()
2544 about->get_window()->set_cursor ();
2550 ARDOUR_UI::about_signal_response(int response)
2556 ARDOUR_UI::show_splash ()
2560 splash = new Splash;
2568 splash->queue_draw ();
2569 splash->get_window()->process_updates (true);
2574 ARDOUR_UI::hide_splash ()
2582 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2586 removed = rep.paths.size();
2589 MessageDialog msgd (*editor,
2590 _("No audio files were ready for cleanup"),
2593 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2594 msgd.set_secondary_text (_("If this seems suprising, \n\
2595 check for any existing snapshots.\n\
2596 These may still include regions that\n\
2597 require some unused files to continue to exist."));
2603 ArdourDialog results (_("ardour: cleanup"), true, false);
2605 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2606 CleanupResultsModelColumns() {
2610 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2611 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2615 CleanupResultsModelColumns results_columns;
2616 Glib::RefPtr<Gtk::ListStore> results_model;
2617 Gtk::TreeView results_display;
2619 results_model = ListStore::create (results_columns);
2620 results_display.set_model (results_model);
2621 results_display.append_column (list_title, results_columns.visible_name);
2623 results_display.set_name ("CleanupResultsList");
2624 results_display.set_headers_visible (true);
2625 results_display.set_headers_clickable (false);
2626 results_display.set_reorderable (false);
2628 Gtk::ScrolledWindow list_scroller;
2631 Gtk::HBox dhbox; // the hbox for the image and text
2632 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2633 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2635 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2637 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2639 if (rep.space < 1048576.0f) {
2641 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2643 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2647 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2649 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2653 dhbox.pack_start (*dimage, true, false, 5);
2654 dhbox.pack_start (txt, true, false, 5);
2656 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2657 TreeModel::Row row = *(results_model->append());
2658 row[results_columns.visible_name] = *i;
2659 row[results_columns.fullpath] = *i;
2662 list_scroller.add (results_display);
2663 list_scroller.set_size_request (-1, 150);
2664 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2666 dvbox.pack_start (dhbox, true, false, 5);
2667 dvbox.pack_start (list_scroller, true, false, 5);
2668 ddhbox.pack_start (dvbox, true, false, 5);
2670 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2671 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2672 results.set_default_response (RESPONSE_CLOSE);
2673 results.set_position (Gtk::WIN_POS_MOUSE);
2675 results_display.show();
2676 list_scroller.show();
2683 //results.get_vbox()->show();
2684 results.set_resizable (false);
2691 ARDOUR_UI::cleanup ()
2694 /* shouldn't happen: menu item is insensitive */
2699 MessageDialog checker (_("Are you sure you want to cleanup?"),
2701 Gtk::MESSAGE_QUESTION,
2702 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2704 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2705 ALL undo/redo information will be lost if you cleanup.\n\
2706 After cleanup, unused audio files will be moved to a \
2707 \"dead sounds\" location."));
2709 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2710 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2711 checker.set_default_response (RESPONSE_CANCEL);
2713 checker.set_name (_("CleanupDialog"));
2714 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2715 checker.set_position (Gtk::WIN_POS_MOUSE);
2717 switch (checker.run()) {
2718 case RESPONSE_ACCEPT:
2724 Session::cleanup_report rep;
2726 editor->prepare_for_cleanup ();
2728 /* do not allow flush until a session is reloaded */
2730 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2732 act->set_sensitive (false);
2735 if (session->cleanup_sources (rep)) {
2736 editor->finish_cleanup ();
2740 editor->finish_cleanup ();
2743 display_cleanup_results (rep,
2746 The following %1 %2 not in use and \n\
2747 have been moved to:\n\
2749 Flushing the wastebasket will \n\
2750 release an additional\n\
2751 %4 %5bytes of disk space.\n"
2757 ARDOUR_UI::flush_trash ()
2760 /* shouldn't happen: menu item is insensitive */
2764 Session::cleanup_report rep;
2766 if (session->cleanup_trash_sources (rep)) {
2770 display_cleanup_results (rep,
2772 _("The following %1 %2 deleted from\n\
2774 releasing %4 %5bytes of disk space"));
2778 ARDOUR_UI::add_route (Gtk::Window* float_window)
2786 if (add_route_dialog == 0) {
2787 add_route_dialog = new AddRouteDialog;
2789 add_route_dialog->set_transient_for (*float_window);
2793 if (add_route_dialog->is_visible()) {
2794 /* we're already doing this */
2798 ResponseType r = (ResponseType) add_route_dialog->run ();
2800 add_route_dialog->hide();
2803 case RESPONSE_ACCEPT:
2810 if ((count = add_route_dialog->count()) <= 0) {
2814 string template_path = add_route_dialog->track_template();
2816 if (!template_path.empty()) {
2817 session->new_route_from_template (count, template_path);
2821 uint32_t input_chan = add_route_dialog->channels ();
2822 uint32_t output_chan;
2823 string name_template = add_route_dialog->name_template ();
2824 bool track = add_route_dialog->track ();
2826 AutoConnectOption oac = Config->get_output_auto_connect();
2828 if (oac & AutoConnectMaster) {
2829 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2831 output_chan = input_chan;
2834 /* XXX do something with name template */
2836 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2838 session_add_midi_track(count);
2840 MessageDialog msg (*editor,
2841 _("Sorry, MIDI Busses are not supported at this time."));
2843 //session_add_midi_bus();
2847 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2849 session_add_audio_bus (input_chan, output_chan, count);
2855 ARDOUR_UI::mixer_settings () const
2860 node = session->instant_xml(X_("Mixer"));
2862 node = Config->instant_xml(X_("Mixer"));
2866 node = new XMLNode (X_("Mixer"));
2873 ARDOUR_UI::editor_settings () const
2878 node = session->instant_xml(X_("Editor"));
2880 node = Config->instant_xml(X_("Editor"));
2884 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2885 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2890 node = new XMLNode (X_("Editor"));
2897 ARDOUR_UI::keyboard_settings () const
2901 node = Config->extra_xml(X_("Keyboard"));
2904 node = new XMLNode (X_("Keyboard"));
2910 ARDOUR_UI::create_xrun_marker(nframes_t where)
2912 editor->mouse_add_new_marker (where, false, true);
2916 ARDOUR_UI::halt_on_xrun_message ()
2918 MessageDialog msg (*editor,
2919 _("Recording was stopped because your system could not keep up."));
2924 ARDOUR_UI::xrun_handler(nframes_t where)
2930 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2932 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2933 create_xrun_marker(where);
2936 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2937 halt_on_xrun_message ();
2942 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2947 while (disk_buffer_stats.size() > 60) {
2948 disk_buffer_stats.pop_front ();
2951 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2955 ARDOUR_UI::write_buffer_stats ()
2961 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2962 int fd = mkstemp (tmplt);
2964 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2968 FILE* fout = fdopen (fd, "w");
2970 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2974 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2975 std::ostringstream ss;
2976 localtime_r (&(*i).when, &tm);
2977 strftime (buf, sizeof (buf), "%T", &tm);
2978 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
2981 disk_buffer_stats.clear ();
2986 cerr << "Ardour buffering statistics can be found in: " << path << endl;
2992 ARDOUR_UI::disk_overrun_handler ()
2994 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2996 write_buffer_stats ();
2998 if (!have_disk_speed_dialog_displayed) {
2999 have_disk_speed_dialog_displayed = true;
3000 MessageDialog* msg = new MessageDialog (*editor, _("\
3001 The disk system on your computer\n\
3002 was not able to keep up with Ardour.\n\
3004 Specifically, it failed to write data to disk\n\
3005 quickly enough to keep up with recording.\n"));
3006 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3012 ARDOUR_UI::disk_underrun_handler ()
3014 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3016 write_buffer_stats ();
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 read data from disk\n\
3025 quickly enough to keep up with playback.\n"));
3026 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3032 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3034 have_disk_speed_dialog_displayed = false;
3039 ARDOUR_UI::session_dialog (std::string msg)
3041 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3046 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3048 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3057 ARDOUR_UI::pending_state_dialog ()
3059 HBox* hbox = new HBox();
3060 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3061 ArdourDialog dialog (_("Crash Recovery"), true);
3063 This session appears to have been in\n\
3064 middle of recording when ardour or\n\
3065 the computer was shutdown.\n\
3067 Ardour can recover any captured audio for\n\
3068 you, or it can ignore it. Please decide\n\
3069 what you would like to do.\n"));
3070 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3071 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3072 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3073 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3074 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3075 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3076 dialog.set_default_response (RESPONSE_ACCEPT);
3077 dialog.set_position (WIN_POS_CENTER);
3082 switch (dialog.run ()) {
3083 case RESPONSE_ACCEPT:
3091 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3093 HBox* hbox = new HBox();
3094 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3095 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3096 Label message (string_compose (_("\
3097 This session was created with a sample rate of %1 Hz\n\
3099 The audioengine is currently running at %2 Hz\n"), desired, actual));
3101 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3102 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3103 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3104 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3105 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3106 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3107 dialog.set_default_response (RESPONSE_ACCEPT);
3108 dialog.set_position (WIN_POS_CENTER);
3113 switch (dialog.run ()) {
3114 case RESPONSE_ACCEPT:
3123 ARDOUR_UI::disconnect_from_jack ()
3126 if( engine->disconnect_from_jack ()) {
3127 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3131 update_sample_rate (0);
3136 ARDOUR_UI::reconnect_to_jack ()
3139 if (engine->reconnect_to_jack ()) {
3140 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3144 update_sample_rate (0);
3149 ARDOUR_UI::use_config ()
3151 Glib::RefPtr<Action> act;
3153 switch (Config->get_native_file_data_format ()) {
3155 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3158 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3161 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3166 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3167 ract->set_active ();
3170 switch (Config->get_native_file_header_format ()) {
3172 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3175 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3178 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3181 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3184 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3187 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3190 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3195 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3196 ract->set_active ();
3199 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3201 set_transport_controllable_state (*node);
3206 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3208 if (Config->get_primary_clock_delta_edit_cursor()) {
3209 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3211 primary_clock.set (pos, 0, true);
3214 if (Config->get_secondary_clock_delta_edit_cursor()) {
3215 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3217 secondary_clock.set (pos);
3220 if (big_clock_window) {
3221 big_clock.set (pos);
3226 ARDOUR_UI::record_state_changed ()
3228 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3230 if (!session || !big_clock_window) {
3231 /* why bother - the clock isn't visible */
3235 Session::RecordState const r = session->record_status ();
3236 bool const h = session->have_rec_enabled_diskstream ();
3238 if (r == Session::Recording && h) {
3239 big_clock.set_widget_name ("BigClockRecording");
3241 big_clock.set_widget_name ("BigClockNonRecording");
3246 ARDOUR_UI::first_idle ()
3249 session->allow_auto_play (true);
3253 editor->first_idle();
3256 Keyboard::set_can_save_keybindings (true);
3261 ARDOUR_UI::store_clock_modes ()
3263 XMLNode* node = new XMLNode(X_("ClockModes"));
3265 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3266 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3269 session->add_extra_xml (*node);
3270 session->set_dirty ();
3275 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3276 : Controllable (name), ui (u), type(tp)
3282 ARDOUR_UI::TransportControllable::set_value (float val)
3284 if (type == ShuttleControl) {
3291 fract = -((0.5f - val)/0.5f);
3293 fract = ((val - 0.5f)/0.5f);
3297 ui.set_shuttle_fract (fract);
3302 /* do nothing: these are radio-style actions */
3306 const char *action = 0;
3310 action = X_("Roll");
3313 action = X_("Stop");
3316 action = X_("Goto Start");
3319 action = X_("Goto End");
3322 action = X_("Loop");
3325 action = X_("Play Selection");
3328 action = X_("Record");
3338 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3346 ARDOUR_UI::TransportControllable::get_value (void) const
3365 case ShuttleControl:
3375 ARDOUR_UI::TransportControllable::set_id (const string& str)
3381 ARDOUR_UI::setup_profile ()
3383 if (gdk_screen_width() < 1200) {
3384 Profile->set_small_screen ();
3388 if (getenv ("ARDOUR_SAE")) {
3389 Profile->set_sae ();
3390 Profile->set_single_package ();