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:
1902 prompter.get_result (snapname);
1904 bool do_save = (snapname.length() != 0);
1906 vector<sys::path> p;
1907 get_state_files_in_directory (session->session_directory().root_path(), p);
1908 vector<string> n = get_file_names_no_extension (p);
1909 if (find (n.begin(), n.end(), snapname) != n.end()) {
1911 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1912 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1913 confirm.get_vbox()->pack_start (m, true, true);
1914 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1915 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1916 confirm.show_all ();
1917 switch (confirm.run()) {
1918 case RESPONSE_CANCEL:
1924 save_state (snapname);
1935 ARDOUR_UI::save_state (const string & name)
1937 (void) save_state_canfail (name);
1941 ARDOUR_UI::save_state_canfail (string name)
1946 if (name.length() == 0) {
1947 name = session->snap_name();
1950 if ((ret = session->save_state (name)) != 0) {
1954 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1959 ARDOUR_UI::primary_clock_value_changed ()
1962 session->request_locate (primary_clock.current_time ());
1967 ARDOUR_UI::big_clock_value_changed ()
1970 session->request_locate (big_clock.current_time ());
1975 ARDOUR_UI::secondary_clock_value_changed ()
1978 session->request_locate (secondary_clock.current_time ());
1983 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1989 Session::RecordState const r = session->record_status ();
1990 bool const h = session->have_rec_enabled_diskstream ();
1992 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1994 rec_button.set_visual_state (2);
1996 rec_button.set_visual_state (0);
1998 } else if (r == Session::Recording && h) {
1999 rec_button.set_visual_state (1);
2001 rec_button.set_visual_state (0);
2006 ARDOUR_UI::save_template ()
2009 ArdourPrompter prompter (true);
2012 if (!check_audioengine()) {
2016 prompter.set_name (X_("Prompter"));
2017 prompter.set_prompt (_("Name for mix template:"));
2018 prompter.set_initial_text(session->name() + _("-template"));
2019 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2021 switch (prompter.run()) {
2022 case RESPONSE_ACCEPT:
2023 prompter.get_result (name);
2025 if (name.length()) {
2026 session->save_template (name);
2036 ARDOUR_UI::edit_metadata ()
2038 SessionMetadataEditor dialog;
2039 dialog.set_session (session);
2040 editor->ensure_float (dialog);
2045 ARDOUR_UI::import_metadata ()
2047 SessionMetadataImporter dialog;
2048 dialog.set_session (session);
2049 editor->ensure_float (dialog);
2054 ARDOUR_UI::fontconfig_dialog ()
2057 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2058 may not and it can take a while to build it. Warn them.
2061 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2063 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2064 MessageDialog msg (*_startup,
2065 _("Welcome to Ardour.\n\n"
2066 "The program will take a bit longer to start up\n"
2067 "while the system fonts are checked.\n\n"
2068 "This will only be done once, and you will\n"
2069 "not see this message again\n"),
2082 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2084 existing_session = false;
2086 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2087 session_path = cmdline_path;
2088 existing_session = true;
2089 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2090 session_path = Glib::path_get_dirname (string (cmdline_path));
2091 existing_session = true;
2093 /* it doesn't exist, assume the best */
2094 session_path = Glib::path_get_dirname (string (cmdline_path));
2097 session_name = basename_nosuffix (string (cmdline_path));
2101 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2103 /* when this is called, the backend audio system must be running */
2105 /* the main idea here is to deal with the fact that a cmdline argument for the session
2106 can be interpreted in different ways - it could be a directory or a file, and before
2107 we load, we need to know both the session directory and the snapshot (statefile) within it
2108 that we are supposed to use.
2111 if (session_name.length() == 0 || session_path.length() == 0) {
2115 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2117 Glib::ustring predicted_session_file;
2119 predicted_session_file = session_path;
2120 predicted_session_file += '/';
2121 predicted_session_file += session_name;
2122 predicted_session_file += ARDOUR::statefile_suffix;
2124 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2125 existing_session = true;
2128 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2130 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2131 /* existing .ardour file */
2132 existing_session = true;
2136 existing_session = false;
2139 /* lets just try to load it */
2141 if (create_engine ()) {
2142 backend_audio_error (false, _startup);
2146 return load_session (session_path, session_name);
2150 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2152 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2154 MessageDialog msg (str,
2156 Gtk::MESSAGE_WARNING,
2157 Gtk::BUTTONS_YES_NO,
2161 msg.set_name (X_("CleanupDialog"));
2162 msg.set_wmclass (X_("existing_session"), "Ardour");
2163 msg.set_position (Gtk::WIN_POS_MOUSE);
2166 switch (msg.run()) {
2175 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2180 AutoConnectOption iconnect;
2181 AutoConnectOption oconnect;
2185 if (Profile->get_sae()) {
2189 iconnect = AutoConnectPhysical;
2190 oconnect = AutoConnectMaster;
2191 nphysin = 0; // use all available
2192 nphysout = 0; // use all available
2196 /* get settings from advanced section of NSD */
2198 if (_startup->create_control_bus()) {
2199 cchns = (uint32_t) _startup->control_channel_count();
2204 if (_startup->create_master_bus()) {
2205 mchns = (uint32_t) _startup->master_channel_count();
2210 if (_startup->connect_inputs()) {
2211 iconnect = AutoConnectPhysical;
2213 iconnect = AutoConnectOption (0);
2216 /// @todo some minor tweaks.
2218 if (_startup->connect_outs_to_master()) {
2219 oconnect = AutoConnectMaster;
2220 } else if (_startup->connect_outs_to_physical()) {
2221 oconnect = AutoConnectPhysical;
2223 oconnect = AutoConnectOption (0);
2226 nphysin = (uint32_t) _startup->input_limit_count();
2227 nphysout = (uint32_t) _startup->output_limit_count();
2230 if (build_session (session_path,
2238 engine->frame_rate() * 60 * 5)) {
2247 ARDOUR_UI::end_loading_messages ()
2253 ARDOUR_UI::loading_message (const std::string& msg)
2256 // splash->message (msg);
2261 ARDOUR_UI::get_session_parameters (bool should_be_new)
2263 Glib::ustring session_name;
2264 Glib::ustring session_path;
2265 Glib::ustring template_name;
2267 bool likely_new = false;
2271 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2273 /* if they named a specific statefile, use it, otherwise they are
2274 just giving a session folder, and we want to use it as is
2275 to find the session.
2278 if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2279 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2281 session_path = ARDOUR_COMMAND_LINE::session_name;
2284 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2288 run_startup (should_be_new);
2290 /* if we run the startup dialog again, offer more than just "new session" */
2292 should_be_new = false;
2294 session_name = _startup->session_name (likely_new);
2296 /* this shouldn't happen, but we catch it just in case it does */
2298 if (session_name.empty()) {
2301 if (_startup->use_session_template()) {
2302 template_name = _startup->session_template_name();
2303 _session_is_new = true;
2307 if (session_name[0] == '/' ||
2308 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2309 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2311 session_path = Glib::path_get_dirname (session_name);
2312 session_name = Glib::path_get_basename (session_name);
2316 session_path = _startup->session_folder();
2320 if (create_engine ()) {
2324 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2328 ustring existing = Glib::build_filename (session_path, session_name);
2330 if (!ask_about_loading_existing_session (existing)) {
2331 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2336 _session_is_new = false;
2341 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2343 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2347 _session_is_new = true;
2350 if (likely_new && template_name.empty()) {
2352 ret = build_session_from_nsd (session_path, session_name);
2356 ret = load_session (session_path, session_name, template_name);
2364 ARDOUR_UI::close_session()
2366 if (!check_audioengine()) {
2370 unload_session (true);
2372 get_session_parameters (false);
2376 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2378 Session *new_session;
2382 session_loaded = false;
2384 if (!check_audioengine()) {
2388 unload_status = unload_session ();
2390 if (unload_status < 0) {
2392 } else if (unload_status > 0) {
2397 /* if it already exists, we must have write access */
2399 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2400 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2401 "This prevents the session from being loaded."));
2407 loading_message (_("Please wait while Ardour loads your session"));
2410 new_session = new Session (*engine, path, snap_name, mix_template);
2413 /* this one is special */
2415 catch (AudioEngine::PortRegistrationFailure& err) {
2417 MessageDialog msg (err.what(),
2420 Gtk::BUTTONS_CLOSE);
2422 msg.set_title (_("Port Registration Error"));
2423 msg.set_secondary_text (_("Click the Close button to try again."));
2424 msg.set_position (Gtk::WIN_POS_CENTER);
2428 int response = msg.run ();
2433 case RESPONSE_CANCEL:
2443 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2446 Gtk::BUTTONS_CLOSE);
2448 msg.set_title (_("Loading Error"));
2449 msg.set_secondary_text (_("Click the Close button to try again."));
2450 msg.set_position (Gtk::WIN_POS_CENTER);
2454 int response = msg.run ();
2459 case RESPONSE_CANCEL:
2467 connect_to_session (new_session);
2469 Config->set_current_owner (ConfigVariableBase::Interface);
2471 session_loaded = true;
2473 goto_editor_window ();
2476 session->set_clean ();
2487 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2488 uint32_t control_channels,
2489 uint32_t master_channels,
2490 AutoConnectOption input_connect,
2491 AutoConnectOption output_connect,
2494 nframes_t initial_length)
2496 Session *new_session;
2499 if (!check_audioengine()) {
2503 session_loaded = false;
2505 x = unload_session ();
2513 _session_is_new = true;
2516 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2517 control_channels, master_channels, nphysin, nphysout, initial_length);
2522 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2528 connect_to_session (new_session);
2530 session_loaded = true;
2532 new_session->save_state(new_session->name());
2541 editor->show_window ();
2552 ARDOUR_UI::show_about ()
2556 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2563 ARDOUR_UI::hide_about ()
2566 about->get_window()->set_cursor ();
2572 ARDOUR_UI::about_signal_response(int response)
2578 ARDOUR_UI::show_splash ()
2582 splash = new Splash;
2590 splash->queue_draw ();
2591 splash->get_window()->process_updates (true);
2596 ARDOUR_UI::hide_splash ()
2604 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2608 removed = rep.paths.size();
2611 MessageDialog msgd (*editor,
2612 _("No audio files were ready for cleanup"),
2615 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2616 msgd.set_secondary_text (_("If this seems suprising, \n\
2617 check for any existing snapshots.\n\
2618 These may still include regions that\n\
2619 require some unused files to continue to exist."));
2625 ArdourDialog results (_("ardour: cleanup"), true, false);
2627 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2628 CleanupResultsModelColumns() {
2632 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2633 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2637 CleanupResultsModelColumns results_columns;
2638 Glib::RefPtr<Gtk::ListStore> results_model;
2639 Gtk::TreeView results_display;
2641 results_model = ListStore::create (results_columns);
2642 results_display.set_model (results_model);
2643 results_display.append_column (list_title, results_columns.visible_name);
2645 results_display.set_name ("CleanupResultsList");
2646 results_display.set_headers_visible (true);
2647 results_display.set_headers_clickable (false);
2648 results_display.set_reorderable (false);
2650 Gtk::ScrolledWindow list_scroller;
2653 Gtk::HBox dhbox; // the hbox for the image and text
2654 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2655 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2657 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2659 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2661 if (rep.space < 1048576.0f) {
2663 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2665 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2669 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2671 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2675 dhbox.pack_start (*dimage, true, false, 5);
2676 dhbox.pack_start (txt, true, false, 5);
2678 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2679 TreeModel::Row row = *(results_model->append());
2680 row[results_columns.visible_name] = *i;
2681 row[results_columns.fullpath] = *i;
2684 list_scroller.add (results_display);
2685 list_scroller.set_size_request (-1, 150);
2686 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2688 dvbox.pack_start (dhbox, true, false, 5);
2689 dvbox.pack_start (list_scroller, true, false, 5);
2690 ddhbox.pack_start (dvbox, true, false, 5);
2692 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2693 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2694 results.set_default_response (RESPONSE_CLOSE);
2695 results.set_position (Gtk::WIN_POS_MOUSE);
2697 results_display.show();
2698 list_scroller.show();
2705 //results.get_vbox()->show();
2706 results.set_resizable (false);
2713 ARDOUR_UI::cleanup ()
2716 /* shouldn't happen: menu item is insensitive */
2721 MessageDialog checker (_("Are you sure you want to cleanup?"),
2723 Gtk::MESSAGE_QUESTION,
2724 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2726 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2727 ALL undo/redo information will be lost if you cleanup.\n\
2728 After cleanup, unused audio files will be moved to a \
2729 \"dead sounds\" location."));
2731 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2732 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2733 checker.set_default_response (RESPONSE_CANCEL);
2735 checker.set_name (_("CleanupDialog"));
2736 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2737 checker.set_position (Gtk::WIN_POS_MOUSE);
2739 switch (checker.run()) {
2740 case RESPONSE_ACCEPT:
2746 Session::cleanup_report rep;
2748 editor->prepare_for_cleanup ();
2750 /* do not allow flush until a session is reloaded */
2752 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2754 act->set_sensitive (false);
2757 if (session->cleanup_sources (rep)) {
2758 editor->finish_cleanup ();
2762 editor->finish_cleanup ();
2765 display_cleanup_results (rep,
2768 The following %1 %2 not in use and \n\
2769 have been moved to:\n\
2771 Flushing the wastebasket will \n\
2772 release an additional\n\
2773 %4 %5bytes of disk space.\n"
2779 ARDOUR_UI::flush_trash ()
2782 /* shouldn't happen: menu item is insensitive */
2786 Session::cleanup_report rep;
2788 if (session->cleanup_trash_sources (rep)) {
2792 display_cleanup_results (rep,
2794 _("The following %1 %2 deleted from\n\
2796 releasing %4 %5bytes of disk space"));
2800 ARDOUR_UI::add_route (Gtk::Window* float_window)
2808 if (add_route_dialog == 0) {
2809 add_route_dialog = new AddRouteDialog;
2811 add_route_dialog->set_transient_for (*float_window);
2815 if (add_route_dialog->is_visible()) {
2816 /* we're already doing this */
2820 ResponseType r = (ResponseType) add_route_dialog->run ();
2822 add_route_dialog->hide();
2825 case RESPONSE_ACCEPT:
2832 if ((count = add_route_dialog->count()) <= 0) {
2836 string template_path = add_route_dialog->track_template();
2838 if (!template_path.empty()) {
2839 session->new_route_from_template (count, template_path);
2843 uint32_t input_chan = add_route_dialog->channels ();
2844 uint32_t output_chan;
2845 string name_template = add_route_dialog->name_template ();
2846 bool track = add_route_dialog->track ();
2848 AutoConnectOption oac = Config->get_output_auto_connect();
2850 if (oac & AutoConnectMaster) {
2851 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2853 output_chan = input_chan;
2856 /* XXX do something with name template */
2858 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2860 session_add_midi_track(count);
2862 MessageDialog msg (*editor,
2863 _("Sorry, MIDI Busses are not supported at this time."));
2865 //session_add_midi_bus();
2869 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2871 session_add_audio_bus (input_chan, output_chan, count);
2877 ARDOUR_UI::mixer_settings () const
2882 node = session->instant_xml(X_("Mixer"));
2884 node = Config->instant_xml(X_("Mixer"));
2888 node = new XMLNode (X_("Mixer"));
2895 ARDOUR_UI::editor_settings () const
2900 node = session->instant_xml(X_("Editor"));
2902 node = Config->instant_xml(X_("Editor"));
2906 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2907 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2912 node = new XMLNode (X_("Editor"));
2919 ARDOUR_UI::keyboard_settings () const
2923 node = Config->extra_xml(X_("Keyboard"));
2926 node = new XMLNode (X_("Keyboard"));
2932 ARDOUR_UI::create_xrun_marker(nframes_t where)
2934 editor->mouse_add_new_marker (where, false, true);
2938 ARDOUR_UI::halt_on_xrun_message ()
2940 MessageDialog msg (*editor,
2941 _("Recording was stopped because your system could not keep up."));
2946 ARDOUR_UI::xrun_handler(nframes_t where)
2952 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2954 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2955 create_xrun_marker(where);
2958 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2959 halt_on_xrun_message ();
2964 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2969 while (disk_buffer_stats.size() > 60) {
2970 disk_buffer_stats.pop_front ();
2973 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2977 ARDOUR_UI::write_buffer_stats ()
2983 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2984 int fd = mkstemp (tmplt);
2986 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
2990 FILE* fout = fdopen (fd, "w");
2992 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
2996 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
2997 std::ostringstream ss;
2998 localtime_r (&(*i).when, &tm);
2999 strftime (buf, sizeof (buf), "%T", &tm);
3000 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
3003 disk_buffer_stats.clear ();
3008 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3014 ARDOUR_UI::disk_overrun_handler ()
3016 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3018 write_buffer_stats ();
3020 if (!have_disk_speed_dialog_displayed) {
3021 have_disk_speed_dialog_displayed = true;
3022 MessageDialog* msg = new MessageDialog (*editor, _("\
3023 The disk system on your computer\n\
3024 was not able to keep up with Ardour.\n\
3026 Specifically, it failed to write data to disk\n\
3027 quickly enough to keep up with recording.\n"));
3028 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3034 ARDOUR_UI::disk_underrun_handler ()
3036 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3038 write_buffer_stats ();
3040 if (!have_disk_speed_dialog_displayed) {
3041 have_disk_speed_dialog_displayed = true;
3042 MessageDialog* msg = new MessageDialog (*editor,
3043 _("The disk system on your computer\n\
3044 was not able to keep up with Ardour.\n\
3046 Specifically, it failed to read data from disk\n\
3047 quickly enough to keep up with playback.\n"));
3048 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3054 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3056 have_disk_speed_dialog_displayed = false;
3061 ARDOUR_UI::session_dialog (std::string msg)
3063 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3068 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3070 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3079 ARDOUR_UI::pending_state_dialog ()
3081 HBox* hbox = new HBox();
3082 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3083 ArdourDialog dialog (_("Crash Recovery"), true);
3085 This session appears to have been in\n\
3086 middle of recording when ardour or\n\
3087 the computer was shutdown.\n\
3089 Ardour can recover any captured audio for\n\
3090 you, or it can ignore it. Please decide\n\
3091 what you would like to do.\n"));
3092 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3093 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3094 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3095 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3096 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3097 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3098 dialog.set_default_response (RESPONSE_ACCEPT);
3099 dialog.set_position (WIN_POS_CENTER);
3104 switch (dialog.run ()) {
3105 case RESPONSE_ACCEPT:
3113 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3115 HBox* hbox = new HBox();
3116 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3117 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3118 Label message (string_compose (_("\
3119 This session was created with a sample rate of %1 Hz\n\
3121 The audioengine is currently running at %2 Hz\n"), desired, actual));
3123 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3124 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3125 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3126 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3127 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3128 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3129 dialog.set_default_response (RESPONSE_ACCEPT);
3130 dialog.set_position (WIN_POS_CENTER);
3135 switch (dialog.run ()) {
3136 case RESPONSE_ACCEPT:
3145 ARDOUR_UI::disconnect_from_jack ()
3148 if( engine->disconnect_from_jack ()) {
3149 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3153 update_sample_rate (0);
3158 ARDOUR_UI::reconnect_to_jack ()
3161 if (engine->reconnect_to_jack ()) {
3162 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3166 update_sample_rate (0);
3171 ARDOUR_UI::use_config ()
3173 Glib::RefPtr<Action> act;
3175 switch (Config->get_native_file_data_format ()) {
3177 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3180 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3183 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3188 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3189 ract->set_active ();
3192 switch (Config->get_native_file_header_format ()) {
3194 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3197 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3200 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3203 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3206 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3209 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3212 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3217 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3218 ract->set_active ();
3221 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3223 set_transport_controllable_state (*node);
3228 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3230 if (Config->get_primary_clock_delta_edit_cursor()) {
3231 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3233 primary_clock.set (pos, 0, true);
3236 if (Config->get_secondary_clock_delta_edit_cursor()) {
3237 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3239 secondary_clock.set (pos);
3242 if (big_clock_window) {
3243 big_clock.set (pos);
3248 ARDOUR_UI::record_state_changed ()
3250 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3252 if (!session || !big_clock_window) {
3253 /* why bother - the clock isn't visible */
3257 Session::RecordState const r = session->record_status ();
3258 bool const h = session->have_rec_enabled_diskstream ();
3260 if (r == Session::Recording && h) {
3261 big_clock.set_widget_name ("BigClockRecording");
3263 big_clock.set_widget_name ("BigClockNonRecording");
3268 ARDOUR_UI::first_idle ()
3271 session->allow_auto_play (true);
3275 editor->first_idle();
3278 Keyboard::set_can_save_keybindings (true);
3283 ARDOUR_UI::store_clock_modes ()
3285 XMLNode* node = new XMLNode(X_("ClockModes"));
3287 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3288 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3291 session->add_extra_xml (*node);
3292 session->set_dirty ();
3297 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3298 : Controllable (name), ui (u), type(tp)
3304 ARDOUR_UI::TransportControllable::set_value (float val)
3306 if (type == ShuttleControl) {
3313 fract = -((0.5f - val)/0.5f);
3315 fract = ((val - 0.5f)/0.5f);
3319 ui.set_shuttle_fract (fract);
3324 /* do nothing: these are radio-style actions */
3328 const char *action = 0;
3332 action = X_("Roll");
3335 action = X_("Stop");
3338 action = X_("Goto Start");
3341 action = X_("Goto End");
3344 action = X_("Loop");
3347 action = X_("Play Selection");
3350 action = X_("Record");
3360 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3368 ARDOUR_UI::TransportControllable::get_value (void) const
3387 case ShuttleControl:
3397 ARDOUR_UI::TransportControllable::set_id (const string& str)
3403 ARDOUR_UI::setup_profile ()
3405 if (gdk_screen_width() < 1200) {
3406 Profile->set_small_screen ();
3410 if (getenv ("ARDOUR_SAE")) {
3411 Profile->set_sae ();
3412 Profile->set_single_package ();