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;
177 * This was commented out as it wasn't defined
178 * in A3 IIRC. If this is not needed it should
179 * be completely removed.
187 if (theArdourUI == 0) {
191 ui_config = new UIConfiguration();
192 theme_manager = new ThemeManager();
199 _session_is_new = false;
200 big_clock_window = 0;
201 session_selector_window = 0;
202 last_key_press_time = 0;
203 _will_create_new_session_automatically = false;
204 add_route_dialog = 0;
206 rc_option_editor = 0;
207 session_option_editor = 0;
209 open_session_selector = 0;
210 have_configure_timeout = false;
211 have_disk_speed_dialog_displayed = false;
212 session_loaded = false;
213 last_speed_displayed = -1.0f;
214 ignore_dual_punch = false;
215 _mixer_on_top = false;
217 roll_button.unset_flags (Gtk::CAN_FOCUS);
218 stop_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
220 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
221 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
222 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
223 rec_button.unset_flags (Gtk::CAN_FOCUS);
225 last_configure_time= 0;
227 shuttle_grabbed = false;
229 shuttle_max_speed = 8.0f;
231 shuttle_style_menu = 0;
232 shuttle_unit_menu = 0;
234 // We do not have jack linked in yet so;
236 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
238 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
241 /* handle dialog requests */
243 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
245 /* handle pending state with a dialog */
247 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
249 /* handle sr mismatch with a dialog */
251 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
253 /* lets get this party started */
256 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
257 throw failed_constructor ();
260 setup_gtk_ardour_enums ();
263 GainMeter::setup_slider_pix ();
264 RouteTimeAxisView::setup_slider_pix ();
266 } catch (failed_constructor& err) {
267 error << _("could not initialize Ardour.") << endmsg;
272 /* we like keyboards */
274 keyboard = new Keyboard;
278 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
279 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
285 ARDOUR_UI::run_startup (bool should_be_new)
288 _startup = new ArdourStartup ();
291 _startup->set_new_only (should_be_new);
292 _startup->present ();
296 /* we don't return here until the startup assistant is finished */
302 ARDOUR_UI::create_engine ()
304 // this gets called every time by new_session()
310 loading_message (_("Starting audio engine"));
313 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
320 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
321 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
322 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
323 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
331 ARDOUR_UI::post_engine ()
333 /* Things to be done once we create the AudioEngine
336 MIDI::Manager::instance()->set_api_data (engine->jack());
339 ActionManager::init ();
342 if (setup_windows ()) {
343 throw failed_constructor ();
346 check_memory_locking();
348 /* this is the first point at which all the keybindings are available */
350 if (ARDOUR_COMMAND_LINE::show_key_actions) {
351 vector<string> names;
352 vector<string> paths;
354 vector<AccelKey> bindings;
356 ActionManager::get_all_actions (names, paths, keys, bindings);
358 vector<string>::iterator n;
359 vector<string>::iterator k;
360 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
361 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
367 blink_timeout_tag = -1;
369 /* this being a GUI and all, we want peakfiles */
371 AudioFileSource::set_build_peakfiles (true);
372 AudioFileSource::set_build_missing_peakfiles (true);
374 /* set default clock modes */
376 if (Profile->get_sae()) {
377 primary_clock.set_mode (AudioClock::BBT);
378 secondary_clock.set_mode (AudioClock::MinSec);
380 primary_clock.set_mode (AudioClock::SMPTE);
381 secondary_clock.set_mode (AudioClock::BBT);
384 /* start the time-of-day-clock */
387 /* OS X provides an always visible wallclock, so don't be stupid */
388 update_wall_clock ();
389 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
392 update_disk_space ();
394 update_sample_rate (engine->frame_rate());
396 /* now start and maybe save state */
398 if (do_engine_start () == 0) {
399 if (session && _session_is_new) {
400 /* we need to retain initial visual
401 settings for a new session
403 session->save_state ("");
408 ARDOUR_UI::~ARDOUR_UI ()
410 save_ardour_state ();
415 delete add_route_dialog;
419 ARDOUR_UI::pop_back_splash ()
421 if (Splash::instance()) {
422 // Splash::instance()->pop_back();
423 Splash::instance()->hide ();
428 ARDOUR_UI::configure_timeout ()
430 if (last_configure_time == 0) {
431 /* no configure events yet */
435 /* force a gap of 0.5 seconds since the last configure event
438 if (get_microseconds() - last_configure_time < 500000) {
441 have_configure_timeout = false;
442 save_ardour_state ();
448 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
450 if (have_configure_timeout) {
451 last_configure_time = get_microseconds();
453 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
454 have_configure_timeout = true;
461 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
463 const XMLProperty* prop;
465 if ((prop = node.property ("roll")) != 0) {
466 roll_controllable->set_id (prop->value());
468 if ((prop = node.property ("stop")) != 0) {
469 stop_controllable->set_id (prop->value());
471 if ((prop = node.property ("goto-start")) != 0) {
472 goto_start_controllable->set_id (prop->value());
474 if ((prop = node.property ("goto-end")) != 0) {
475 goto_end_controllable->set_id (prop->value());
477 if ((prop = node.property ("auto-loop")) != 0) {
478 auto_loop_controllable->set_id (prop->value());
480 if ((prop = node.property ("play-selection")) != 0) {
481 play_selection_controllable->set_id (prop->value());
483 if ((prop = node.property ("rec")) != 0) {
484 rec_controllable->set_id (prop->value());
486 if ((prop = node.property ("shuttle")) != 0) {
487 shuttle_controllable->set_id (prop->value());
492 ARDOUR_UI::get_transport_controllable_state ()
494 XMLNode* node = new XMLNode(X_("TransportControllables"));
497 roll_controllable->id().print (buf, sizeof (buf));
498 node->add_property (X_("roll"), buf);
499 stop_controllable->id().print (buf, sizeof (buf));
500 node->add_property (X_("stop"), buf);
501 goto_start_controllable->id().print (buf, sizeof (buf));
502 node->add_property (X_("goto_start"), buf);
503 goto_end_controllable->id().print (buf, sizeof (buf));
504 node->add_property (X_("goto_end"), buf);
505 auto_loop_controllable->id().print (buf, sizeof (buf));
506 node->add_property (X_("auto_loop"), buf);
507 play_selection_controllable->id().print (buf, sizeof (buf));
508 node->add_property (X_("play_selection"), buf);
509 rec_controllable->id().print (buf, sizeof (buf));
510 node->add_property (X_("rec"), buf);
511 shuttle_controllable->id().print (buf, sizeof (buf));
512 node->add_property (X_("shuttle"), buf);
518 ARDOUR_UI::save_ardour_state ()
520 if (!keyboard || !mixer || !editor) {
524 /* XXX this is all a bit dubious. add_extra_xml() uses
525 a different lifetime model from add_instant_xml().
528 XMLNode* node = new XMLNode (keyboard->get_state());
529 Config->add_extra_xml (*node);
530 Config->add_extra_xml (get_transport_controllable_state());
531 if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
532 Config->add_extra_xml (_startup->engine_control()->get_state());
534 Config->save_state();
535 ui_config->save_state ();
537 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
538 XMLNode mnode(mixer->get_state());
541 session->add_instant_xml (enode);
542 session->add_instant_xml (mnode);
544 Config->add_instant_xml (enode);
545 Config->add_instant_xml (mnode);
548 Keyboard::save_keybindings ();
552 ARDOUR_UI::autosave_session ()
554 if (g_main_depth() > 1) {
555 /* inside a recursive main loop,
556 give up because we may not be able to
562 if (!Config->get_periodic_safety_backups()) {
567 session->maybe_write_autosave();
574 ARDOUR_UI::update_autosave ()
576 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
578 if (session->dirty()) {
579 if (_autosave_connection.connected()) {
580 _autosave_connection.disconnect();
583 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
584 Config->get_periodic_safety_backup_interval() * 1000);
587 if (_autosave_connection.connected()) {
588 _autosave_connection.disconnect();
594 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
598 title = _("Ardour could not start JACK");
600 title = _("Ardour could not connect to JACK.");
603 MessageDialog win (title,
609 win.set_secondary_text(_("There are several possible reasons:\n\
611 1) You requested audio parameters that are not supported..\n\
612 2) JACK is running as another user.\n\
614 Please consider the possibilities, and perhaps try different parameters."));
616 win.set_secondary_text(_("There are several possible reasons:\n\
618 1) JACK is not running.\n\
619 2) JACK is running as another user, perhaps root.\n\
620 3) There is already another client called \"ardour\".\n\
622 Please consider the possibilities, and perhaps (re)start JACK."));
626 win.set_transient_for (*toplevel);
630 win.add_button (Stock::OK, RESPONSE_CLOSE);
632 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
635 win.set_default_response (RESPONSE_CLOSE);
638 win.set_position (Gtk::WIN_POS_CENTER);
641 /* we just don't care about the result, but we want to block */
647 ARDOUR_UI::startup ()
649 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
651 if (audio_setup && _startup && _startup->engine_control()) {
652 _startup->engine_control()->set_state (*audio_setup);
655 if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
661 goto_editor_window ();
663 BootMessage (_("Ardour is ready for use"));
668 ARDOUR_UI::no_memory_warning ()
670 XMLNode node (X_("no-memory-warning"));
671 Config->add_instant_xml (node);
675 ARDOUR_UI::check_memory_locking ()
678 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
682 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
684 if (engine->is_realtime() && memory_warning_node == 0) {
686 struct rlimit limits;
688 long pages, page_size;
690 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
693 ram = (int64_t) pages * (int64_t) page_size;
696 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
700 if (limits.rlim_cur != RLIM_INFINITY) {
702 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
705 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
706 "This might cause Ardour to run out of memory before your system "
707 "runs out of memory. \n\n"
708 "You can view the memory limit with 'ulimit -l', "
709 "and it is normally controlled by /etc/security/limits.conf"));
711 VBox* vbox = msg.get_vbox();
713 CheckButton cb (_("Do not show this window again"));
715 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
717 hbox.pack_start (cb, true, false);
718 vbox->pack_start (hbox);
725 editor->ensure_float (msg);
739 if (session->transport_rolling()) {
740 session->request_stop ();
744 if (session->dirty()) {
745 switch (ask_about_saving_session(_("quit"))) {
750 /* use the default name */
751 if (save_state_canfail ("")) {
752 /* failed - don't quit */
753 MessageDialog msg (*editor,
755 Ardour was unable to save your session.\n\n\
756 If you still wish to quit, please use the\n\n\
757 \"Just quit\" option."));
768 session->set_deletion_in_progress ();
771 ArdourDialog::close_all_dialogs ();
773 save_ardour_state ();
778 ARDOUR_UI::ask_about_saving_session (const string & what)
780 ArdourDialog window (_("ardour: save session?"));
781 Gtk::HBox dhbox; // the hbox for the image and text
782 Gtk::Label prompt_label;
783 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
787 msg = string_compose(_("Don't %1"), what);
788 window.add_button (msg, RESPONSE_REJECT);
789 msg = string_compose(_("Just %1"), what);
790 window.add_button (msg, RESPONSE_APPLY);
791 msg = string_compose(_("Save and %1"), what);
792 window.add_button (msg, RESPONSE_ACCEPT);
794 window.set_default_response (RESPONSE_ACCEPT);
796 Gtk::Button noquit_button (msg);
797 noquit_button.set_name ("EditorGTKButton");
802 if (session->snap_name() == session->name()) {
805 type = _("snapshot");
807 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?"),
808 type, session->snap_name());
810 prompt_label.set_text (prompt);
811 prompt_label.set_name (X_("PrompterLabel"));
812 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
814 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
815 dhbox.set_homogeneous (false);
816 dhbox.pack_start (*dimage, false, false, 5);
817 dhbox.pack_start (prompt_label, true, false, 5);
818 window.get_vbox()->pack_start (dhbox);
820 window.set_name (_("Prompter"));
821 window.set_position (Gtk::WIN_POS_MOUSE);
822 window.set_modal (true);
823 window.set_resizable (false);
829 window.set_keep_above (true);
832 ResponseType r = (ResponseType) window.run();
837 case RESPONSE_ACCEPT: // save and get out of here
839 case RESPONSE_APPLY: // get out of here
849 ARDOUR_UI::every_second ()
852 update_buffer_load ();
853 update_disk_space ();
858 ARDOUR_UI::every_point_one_seconds ()
860 update_speed_display ();
861 RapidScreenUpdate(); /* EMIT_SIGNAL */
866 ARDOUR_UI::every_point_zero_one_seconds ()
868 // august 2007: actual update frequency: 40Hz, not 100Hz
870 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
875 ARDOUR_UI::update_sample_rate (nframes_t ignored)
879 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
881 if (!engine->connected()) {
883 snprintf (buf, sizeof (buf), _("disconnected"));
887 nframes_t rate = engine->frame_rate();
889 if (fmod (rate, 1000.0) != 0.0) {
890 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
891 (float) rate/1000.0f,
892 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
894 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
896 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
900 sample_rate_label.set_text (buf);
904 ARDOUR_UI::update_cpu_load ()
907 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
908 cpu_load_label.set_text (buf);
912 ARDOUR_UI::update_buffer_load ()
918 c = session->capture_load ();
919 p = session->playback_load ();
921 push_buffer_stats (c, p);
923 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
924 session->playback_load(), session->capture_load());
925 buffer_load_label.set_text (buf);
927 buffer_load_label.set_text ("");
932 ARDOUR_UI::count_recenabled_streams (Route& route)
934 Track* track = dynamic_cast<Track*>(&route);
935 if (track && track->diskstream()->record_enabled()) {
936 rec_enabled_streams += track->n_inputs().n_total();
941 ARDOUR_UI::update_disk_space()
947 nframes_t frames = session->available_capture_duration();
949 nframes_t fr = session->frame_rate();
951 if (frames == max_frames) {
952 strcpy (buf, _("Disk: 24hrs+"));
954 rec_enabled_streams = 0;
955 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
957 if (rec_enabled_streams) {
958 frames /= rec_enabled_streams;
965 hrs = frames / (fr * 3600);
966 frames -= hrs * fr * 3600;
967 mins = frames / (fr * 60);
968 frames -= mins * fr * 60;
971 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
974 disk_space_label.set_text (buf);
976 // An attempt to make the disk space label flash red when space has run out.
978 if (frames < fr * 60 * 5) {
979 /* disk_space_box.style ("disk_space_label_empty"); */
981 /* disk_space_box.style ("disk_space_label"); */
987 ARDOUR_UI::update_wall_clock ()
994 tm_now = localtime (&now);
996 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
997 wall_clock_label.set_text (buf);
1003 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1005 session_popup_menu->popup (0, 0);
1010 ARDOUR_UI::redisplay_recent_sessions ()
1012 std::vector<sys::path> session_directories;
1013 RecentSessionsSorter cmp;
1015 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1016 recent_session_model->clear ();
1018 ARDOUR::RecentSessions rs;
1019 ARDOUR::read_recent_sessions (rs);
1022 recent_session_display.set_model (recent_session_model);
1026 // sort them alphabetically
1027 sort (rs.begin(), rs.end(), cmp);
1029 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1030 session_directories.push_back ((*i).second);
1033 for (vector<sys::path>::const_iterator i = session_directories.begin();
1034 i != session_directories.end(); ++i)
1036 std::vector<sys::path> state_file_paths;
1038 // now get available states for this session
1040 get_state_files_in_directory (*i, state_file_paths);
1042 vector<string*>* states;
1043 vector<const gchar*> item;
1044 string fullpath = (*i).to_string();
1046 /* remove any trailing / */
1048 if (fullpath[fullpath.length()-1] == '/') {
1049 fullpath = fullpath.substr (0, fullpath.length()-1);
1052 /* check whether session still exists */
1053 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1054 /* session doesn't exist */
1055 cerr << "skipping non-existent session " << fullpath << endl;
1059 /* now get available states for this session */
1061 if ((states = Session::possible_states (fullpath)) == 0) {
1062 /* no state file? */
1066 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1068 Gtk::TreeModel::Row row = *(recent_session_model->append());
1070 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1071 row[recent_session_columns.fullpath] = fullpath;
1073 if (state_file_names.size() > 1) {
1077 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1078 i2 != state_file_names.end(); ++i2)
1081 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1083 child_row[recent_session_columns.visible_name] = *i2;
1084 child_row[recent_session_columns.fullpath] = fullpath;
1089 recent_session_display.set_model (recent_session_model);
1093 ARDOUR_UI::build_session_selector ()
1095 session_selector_window = new ArdourDialog (_("Recent Sessions"));
1097 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1099 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1100 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1101 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1102 recent_session_model = TreeStore::create (recent_session_columns);
1103 recent_session_display.set_model (recent_session_model);
1104 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1105 recent_session_display.set_headers_visible (false);
1106 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1107 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1109 scroller->add (recent_session_display);
1110 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1112 session_selector_window->set_name ("SessionSelectorWindow");
1113 session_selector_window->set_size_request (200, 400);
1114 session_selector_window->get_vbox()->pack_start (*scroller);
1116 recent_session_display.show();
1118 //session_selector_window->get_vbox()->show();
1122 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1124 session_selector_window->response (RESPONSE_ACCEPT);
1128 ARDOUR_UI::open_recent_session ()
1130 bool can_return = (session != 0);
1132 if (session_selector_window == 0) {
1133 build_session_selector ();
1136 redisplay_recent_sessions ();
1140 session_selector_window->set_position (WIN_POS_MOUSE);
1142 ResponseType r = (ResponseType) session_selector_window->run ();
1145 case RESPONSE_ACCEPT:
1149 session_selector_window->hide();
1156 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1160 session_selector_window->hide();
1162 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1164 if (i == recent_session_model->children().end()) {
1168 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1169 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1171 _session_is_new = false;
1173 if (load_session (path, state) == 0) {
1182 ARDOUR_UI::check_audioengine ()
1185 if (!engine->connected()) {
1186 MessageDialog msg (_("Ardour is not connected to JACK\n"
1187 "You cannot open or close sessions in this condition"));
1199 ARDOUR_UI::open_session ()
1201 if (!check_audioengine()) {
1206 /* popup selector window */
1208 if (open_session_selector == 0) {
1210 /* ardour sessions are folders */
1212 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1213 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1214 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1215 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1217 FileFilter session_filter;
1218 session_filter.add_pattern ("*.ardour");
1219 session_filter.set_name (_("Ardour sessions"));
1220 open_session_selector->add_filter (session_filter);
1221 open_session_selector->set_filter (session_filter);
1224 int response = open_session_selector->run();
1225 open_session_selector->hide ();
1228 case RESPONSE_ACCEPT:
1231 open_session_selector->hide();
1235 open_session_selector->hide();
1236 string session_path = open_session_selector->get_filename();
1240 if (session_path.length() > 0) {
1241 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1242 _session_is_new = isnew;
1243 load_session (path, name);
1250 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1252 list<boost::shared_ptr<MidiTrack> > tracks;
1255 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1262 tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1264 if (tracks.size() != how_many) {
1265 if (how_many == 1) {
1266 error << _("could not create a new midi track") << endmsg;
1268 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1272 if ((route = session->new_midi_route ()) == 0) {
1273 error << _("could not create new midi bus") << endmsg;
1279 MessageDialog msg (*editor,
1280 _("There are insufficient JACK ports available\n\
1281 to create a new track or bus.\n\
1282 You should save Ardour, exit and\n\
1283 restart JACK with more ports."));
1290 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1292 list<boost::shared_ptr<AudioTrack> > tracks;
1296 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1302 tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1304 if (tracks.size() != how_many) {
1305 if (how_many == 1) {
1306 error << _("could not create a new audio track") << endmsg;
1308 error << string_compose (_("could only create %1 of %2 new audio %3"),
1309 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1315 routes = session->new_audio_route (input_channels, output_channels, route_group, how_many);
1317 if (routes.size() != how_many) {
1318 if (how_many == 1) {
1319 error << _("could not create a new audio track") << endmsg;
1321 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1327 if (need_control_room_outs) {
1333 route->set_stereo_control_outs (control_lr_channels);
1334 route->control_outs()->set_stereo_pan (pans, this);
1336 #endif /* CONTROLOUTS */
1340 MessageDialog msg (*editor,
1341 _("There are insufficient JACK ports available\n\
1342 to create a new track or bus.\n\
1343 You should save Ardour, exit and\n\
1344 restart JACK with more ports."));
1351 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1353 nframes_t _preroll = 0;
1356 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1357 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1359 if (new_position > _preroll) {
1360 new_position -= _preroll;
1365 session->request_locate (new_position);
1370 ARDOUR_UI::transport_goto_start ()
1373 session->goto_start();
1376 /* force displayed area in editor to start no matter
1377 what "follow playhead" setting is.
1381 editor->reset_x_origin (session->current_start_frame());
1387 ARDOUR_UI::transport_goto_zero ()
1390 session->request_locate (0);
1393 /* force displayed area in editor to start no matter
1394 what "follow playhead" setting is.
1398 editor->reset_x_origin (0);
1404 ARDOUR_UI::transport_goto_wallclock ()
1406 if (session && editor) {
1413 localtime_r (&now, &tmnow);
1415 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1416 frames += tmnow.tm_min * (60 * session->frame_rate());
1417 frames += tmnow.tm_sec * session->frame_rate();
1419 session->request_locate (frames);
1421 /* force displayed area in editor to start no matter
1422 what "follow playhead" setting is.
1426 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1432 ARDOUR_UI::transport_goto_end ()
1435 nframes_t frame = session->current_end_frame();
1436 session->request_locate (frame);
1438 /* force displayed area in editor to start no matter
1439 what "follow playhead" setting is.
1443 editor->reset_x_origin (frame);
1449 ARDOUR_UI::transport_stop ()
1455 if (session->is_auditioning()) {
1456 session->cancel_audition ();
1460 if (session->get_play_loop ()) {
1461 session->request_play_loop (false);
1464 session->request_stop ();
1468 ARDOUR_UI::transport_stop_and_forget_capture ()
1471 session->request_stop (true);
1476 ARDOUR_UI::remove_last_capture()
1479 editor->remove_last_capture();
1484 ARDOUR_UI::transport_record (bool roll)
1488 switch (session->record_status()) {
1489 case Session::Disabled:
1490 if (session->ntracks() == 0) {
1491 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1495 session->maybe_enable_record ();
1500 case Session::Recording:
1502 session->request_stop();
1504 session->disable_record (false, true);
1508 case Session::Enabled:
1509 session->disable_record (false, true);
1512 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1516 ARDOUR_UI::transport_roll ()
1524 rolling = session->transport_rolling ();
1526 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1528 if (session->get_play_loop()) {
1529 session->request_play_loop (false);
1530 auto_loop_button.set_visual_state (1);
1531 roll_button.set_visual_state (1);
1532 } else if (session->get_play_range ()) {
1533 session->request_play_range (false);
1534 play_selection_button.set_visual_state (0);
1535 } else if (rolling) {
1536 session->request_locate (session->last_transport_start(), true);
1539 session->request_transport_speed (1.0f);
1543 ARDOUR_UI::transport_loop()
1546 if (session->get_play_loop()) {
1547 if (session->transport_rolling()) {
1548 Location * looploc = session->locations()->auto_loop_location();
1550 session->request_locate (looploc->start(), true);
1555 session->request_play_loop (true);
1561 ARDOUR_UI::transport_play_selection ()
1567 if (!session->get_play_range()) {
1568 session->request_stop ();
1571 editor->play_selection ();
1575 ARDOUR_UI::transport_rewind (int option)
1577 float current_transport_speed;
1580 current_transport_speed = session->transport_speed();
1582 if (current_transport_speed >= 0.0f) {
1585 session->request_transport_speed (-1.0f);
1588 session->request_transport_speed (-4.0f);
1591 session->request_transport_speed (-0.5f);
1596 session->request_transport_speed (current_transport_speed * 1.5f);
1602 ARDOUR_UI::transport_forward (int option)
1604 float current_transport_speed;
1607 current_transport_speed = session->transport_speed();
1609 if (current_transport_speed <= 0.0f) {
1612 session->request_transport_speed (1.0f);
1615 session->request_transport_speed (4.0f);
1618 session->request_transport_speed (0.5f);
1623 session->request_transport_speed (current_transport_speed * 1.5f);
1629 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1635 boost::shared_ptr<Route> r;
1637 if ((r = session->route_by_remote_id (dstream)) != 0) {
1641 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1642 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1651 ARDOUR_UI::queue_transport_change ()
1653 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1657 ARDOUR_UI::map_transport_state ()
1659 float sp = session->transport_speed();
1662 transport_rolling ();
1663 } else if (sp < 0.0f) {
1664 transport_rewinding ();
1665 } else if (sp > 0.0f) {
1666 transport_forwarding ();
1668 transport_stopped ();
1673 ARDOUR_UI::engine_stopped ()
1675 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1676 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1677 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1681 ARDOUR_UI::engine_running ()
1683 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1684 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1685 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1687 Glib::RefPtr<Action> action;
1688 const char* action_name = 0;
1690 switch (engine->frames_per_cycle()) {
1692 action_name = X_("JACKLatency32");
1695 action_name = X_("JACKLatency64");
1698 action_name = X_("JACKLatency128");
1701 action_name = X_("JACKLatency512");
1704 action_name = X_("JACKLatency1024");
1707 action_name = X_("JACKLatency2048");
1710 action_name = X_("JACKLatency4096");
1713 action_name = X_("JACKLatency8192");
1716 /* XXX can we do anything useful ? */
1722 action = ActionManager::get_action (X_("JACK"), action_name);
1725 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1726 ract->set_active ();
1732 ARDOUR_UI::engine_halted ()
1734 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1736 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1737 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1739 update_sample_rate (0);
1741 MessageDialog msg (*editor,
1743 JACK has either been shutdown or it\n\
1744 disconnected Ardour because Ardour\n\
1745 was not fast enough. Try to restart\n\
1746 JACK, reconnect and save the session."));
1752 ARDOUR_UI::do_engine_start ()
1760 error << _("Unable to start the session running")
1770 ARDOUR_UI::setup_theme ()
1772 theme_manager->setup_theme();
1776 ARDOUR_UI::update_clocks ()
1778 if (!editor || !editor->dragging_playhead()) {
1779 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1784 ARDOUR_UI::start_clocking ()
1786 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1790 ARDOUR_UI::stop_clocking ()
1792 clock_signal_connection.disconnect ();
1796 ARDOUR_UI::toggle_clocking ()
1799 if (clock_button.get_active()) {
1808 ARDOUR_UI::_blink (void *arg)
1811 ((ARDOUR_UI *) arg)->blink ();
1818 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1822 ARDOUR_UI::start_blinking ()
1824 /* Start the blink signal. Everybody with a blinking widget
1825 uses Blink to drive the widget's state.
1828 if (blink_timeout_tag < 0) {
1830 blink_timeout_tag = g_timeout_add (240, _blink, this);
1835 ARDOUR_UI::stop_blinking ()
1837 if (blink_timeout_tag >= 0) {
1838 g_source_remove (blink_timeout_tag);
1839 blink_timeout_tag = -1;
1844 /** Ask the user for the name of a new shapshot and then take it.
1847 ARDOUR_UI::snapshot_session ()
1849 ArdourPrompter prompter (true);
1853 struct tm local_time;
1856 localtime_r (&n, &local_time);
1857 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1859 prompter.set_name ("Prompter");
1860 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1861 prompter.set_prompt (_("Name of New Snapshot"));
1862 prompter.set_initial_text (timebuf);
1864 switch (prompter.run()) {
1865 case RESPONSE_ACCEPT:
1867 prompter.get_result (snapname);
1869 bool do_save = (snapname.length() != 0);
1871 vector<sys::path> p;
1872 get_state_files_in_directory (session->session_directory().root_path(), p);
1873 vector<string> n = get_file_names_no_extension (p);
1874 if (find (n.begin(), n.end(), snapname) != n.end()) {
1876 ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1877 Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
1878 confirm.get_vbox()->pack_start (m, true, true);
1879 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1880 confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1881 confirm.show_all ();
1882 switch (confirm.run()) {
1883 case RESPONSE_CANCEL:
1889 save_state (snapname);
1900 ARDOUR_UI::save_state (const string & name)
1902 (void) save_state_canfail (name);
1906 ARDOUR_UI::save_state_canfail (string name)
1911 if (name.length() == 0) {
1912 name = session->snap_name();
1915 if ((ret = session->save_state (name)) != 0) {
1919 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1924 ARDOUR_UI::primary_clock_value_changed ()
1927 session->request_locate (primary_clock.current_time ());
1932 ARDOUR_UI::big_clock_value_changed ()
1935 session->request_locate (big_clock.current_time ());
1940 ARDOUR_UI::secondary_clock_value_changed ()
1943 session->request_locate (secondary_clock.current_time ());
1948 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1954 Session::RecordState const r = session->record_status ();
1955 bool const h = session->have_rec_enabled_diskstream ();
1957 if (r == Session::Enabled || (r == Session::Recording && !h)) {
1959 rec_button.set_visual_state (2);
1961 rec_button.set_visual_state (0);
1963 } else if (r == Session::Recording && h) {
1964 rec_button.set_visual_state (1);
1966 rec_button.set_visual_state (0);
1971 ARDOUR_UI::save_template ()
1974 ArdourPrompter prompter (true);
1977 if (!check_audioengine()) {
1981 prompter.set_name (X_("Prompter"));
1982 prompter.set_prompt (_("Name for mix template:"));
1983 prompter.set_initial_text(session->name() + _("-template"));
1984 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1986 switch (prompter.run()) {
1987 case RESPONSE_ACCEPT:
1988 prompter.get_result (name);
1990 if (name.length()) {
1991 session->save_template (name);
2001 ARDOUR_UI::edit_metadata ()
2003 SessionMetadataEditor dialog;
2004 dialog.set_session (session);
2005 editor->ensure_float (dialog);
2010 ARDOUR_UI::import_metadata ()
2012 SessionMetadataImporter dialog;
2013 dialog.set_session (session);
2014 editor->ensure_float (dialog);
2019 ARDOUR_UI::fontconfig_dialog ()
2022 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2023 may not and it can take a while to build it. Warn them.
2026 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2028 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2029 MessageDialog msg (*_startup,
2030 _("Welcome to Ardour.\n\n"
2031 "The program will take a bit longer to start up\n"
2032 "while the system fonts are checked.\n\n"
2033 "This will only be done once, and you will\n"
2034 "not see this message again\n"),
2047 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2049 existing_session = false;
2051 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2052 session_path = cmdline_path;
2053 existing_session = true;
2054 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2055 session_path = Glib::path_get_dirname (string (cmdline_path));
2056 existing_session = true;
2058 /* it doesn't exist, assume the best */
2059 session_path = Glib::path_get_dirname (string (cmdline_path));
2062 session_name = basename_nosuffix (string (cmdline_path));
2066 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2068 /* when this is called, the backend audio system must be running */
2070 /* the main idea here is to deal with the fact that a cmdline argument for the session
2071 can be interpreted in different ways - it could be a directory or a file, and before
2072 we load, we need to know both the session directory and the snapshot (statefile) within it
2073 that we are supposed to use.
2076 if (session_name.length() == 0 || session_path.length() == 0) {
2080 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2082 Glib::ustring predicted_session_file;
2084 predicted_session_file = session_path;
2085 predicted_session_file += '/';
2086 predicted_session_file += session_name;
2087 predicted_session_file += ARDOUR::statefile_suffix;
2089 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2090 existing_session = true;
2093 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2095 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2096 /* existing .ardour file */
2097 existing_session = true;
2101 existing_session = false;
2104 /* lets just try to load it */
2106 if (create_engine ()) {
2107 backend_audio_error (false, _startup);
2111 return load_session (session_path, session_name);
2115 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2117 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2119 MessageDialog msg (str,
2121 Gtk::MESSAGE_WARNING,
2122 Gtk::BUTTONS_YES_NO,
2126 msg.set_name (X_("CleanupDialog"));
2127 msg.set_wmclass (X_("existing_session"), "Ardour");
2128 msg.set_position (Gtk::WIN_POS_MOUSE);
2131 switch (msg.run()) {
2140 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2145 AutoConnectOption iconnect;
2146 AutoConnectOption oconnect;
2150 if (Profile->get_sae()) {
2154 iconnect = AutoConnectPhysical;
2155 oconnect = AutoConnectMaster;
2156 nphysin = 0; // use all available
2157 nphysout = 0; // use all available
2161 /* get settings from advanced section of NSD */
2163 if (_startup->create_control_bus()) {
2164 cchns = (uint32_t) _startup->control_channel_count();
2169 if (_startup->create_master_bus()) {
2170 mchns = (uint32_t) _startup->master_channel_count();
2175 if (_startup->connect_inputs()) {
2176 iconnect = AutoConnectPhysical;
2178 iconnect = AutoConnectOption (0);
2181 /// @todo some minor tweaks.
2183 if (_startup->connect_outs_to_master()) {
2184 oconnect = AutoConnectMaster;
2185 } else if (_startup->connect_outs_to_physical()) {
2186 oconnect = AutoConnectPhysical;
2188 oconnect = AutoConnectOption (0);
2191 nphysin = (uint32_t) _startup->input_limit_count();
2192 nphysout = (uint32_t) _startup->output_limit_count();
2195 if (build_session (session_path,
2203 engine->frame_rate() * 60 * 5)) {
2212 ARDOUR_UI::idle_load (const Glib::ustring& path)
2215 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2216 /* /path/to/foo => /path/to/foo, foo */
2217 load_session (path, basename_nosuffix (path));
2219 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2220 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2224 ARDOUR_COMMAND_LINE::session_name = path;
2227 * new_session_dialog doens't exist in A3
2228 * Try to remove all references to it to
2229 * see if it will compile. NOTE: this will
2230 * likely cause a runtime issue is my somewhat
2234 //if (new_session_dialog) {
2237 /* make it break out of Dialog::run() and
2241 //new_session_dialog->response (1);
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 Glib::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 ARDOUR_COMMAND_LINE::session_name = "";
2373 get_session_parameters (false);
2377 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2379 Session *new_session;
2383 session_loaded = false;
2385 if (!check_audioengine()) {
2389 unload_status = unload_session ();
2391 if (unload_status < 0) {
2393 } else if (unload_status > 0) {
2398 /* if it already exists, we must have write access */
2400 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2401 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2402 "This prevents the session from being loaded."));
2408 loading_message (_("Please wait while Ardour loads your session"));
2411 new_session = new Session (*engine, path, snap_name, mix_template);
2414 /* this one is special */
2416 catch (AudioEngine::PortRegistrationFailure& err) {
2418 MessageDialog msg (err.what(),
2421 Gtk::BUTTONS_CLOSE);
2423 msg.set_title (_("Port Registration Error"));
2424 msg.set_secondary_text (_("Click the Close button to try again."));
2425 msg.set_position (Gtk::WIN_POS_CENTER);
2429 int response = msg.run ();
2434 case RESPONSE_CANCEL:
2444 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2447 Gtk::BUTTONS_CLOSE);
2449 msg.set_title (_("Loading Error"));
2450 msg.set_secondary_text (_("Click the Close button to try again."));
2451 msg.set_position (Gtk::WIN_POS_CENTER);
2455 int response = msg.run ();
2460 case RESPONSE_CANCEL:
2468 connect_to_session (new_session);
2470 session_loaded = true;
2472 goto_editor_window ();
2475 session->set_clean ();
2486 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2487 uint32_t control_channels,
2488 uint32_t master_channels,
2489 AutoConnectOption input_connect,
2490 AutoConnectOption output_connect,
2493 nframes_t initial_length)
2495 Session *new_session;
2498 if (!check_audioengine()) {
2502 session_loaded = false;
2504 x = unload_session ();
2512 _session_is_new = true;
2515 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2516 control_channels, master_channels, nphysin, nphysout, initial_length);
2521 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2527 connect_to_session (new_session);
2529 session_loaded = true;
2531 new_session->save_state(new_session->name());
2540 editor->show_window ();
2551 ARDOUR_UI::show_about ()
2555 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2562 ARDOUR_UI::hide_about ()
2565 about->get_window()->set_cursor ();
2571 ARDOUR_UI::about_signal_response (int /*response*/)
2577 ARDOUR_UI::show_splash ()
2581 splash = new Splash;
2589 splash->queue_draw ();
2590 splash->get_window()->process_updates (true);
2595 ARDOUR_UI::hide_splash ()
2603 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2604 const string& plural_msg, const string& singular_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();
2665 %1 - number of files removed
2666 %2 - location of "dead_sounds"
2667 %3 - size of files affected
2668 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2671 const char* bprefix;
2673 if (rep.space < 1048576.0f) {
2674 bprefix = X_("kilo");
2675 } else if (rep.space < 1048576.0f * 1000) {
2676 bprefix = X_("mega");
2678 bprefix = X_("giga");
2682 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2684 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2687 dhbox.pack_start (*dimage, true, false, 5);
2688 dhbox.pack_start (txt, true, false, 5);
2690 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2691 TreeModel::Row row = *(results_model->append());
2692 row[results_columns.visible_name] = *i;
2693 row[results_columns.fullpath] = *i;
2696 list_scroller.add (results_display);
2697 list_scroller.set_size_request (-1, 150);
2698 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2700 dvbox.pack_start (dhbox, true, false, 5);
2701 dvbox.pack_start (list_scroller, true, false, 5);
2702 ddhbox.pack_start (dvbox, true, false, 5);
2704 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2705 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2706 results.set_default_response (RESPONSE_CLOSE);
2707 results.set_position (Gtk::WIN_POS_MOUSE);
2709 results_display.show();
2710 list_scroller.show();
2717 //results.get_vbox()->show();
2718 results.set_resizable (false);
2725 ARDOUR_UI::cleanup ()
2728 /* shouldn't happen: menu item is insensitive */
2733 MessageDialog checker (_("Are you sure you want to cleanup?"),
2735 Gtk::MESSAGE_QUESTION,
2736 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2738 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2739 ALL undo/redo information will be lost if you cleanup.\n\
2740 After cleanup, unused audio files will be moved to a \
2741 \"dead sounds\" location."));
2743 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2744 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2745 checker.set_default_response (RESPONSE_CANCEL);
2747 checker.set_name (_("CleanupDialog"));
2748 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2749 checker.set_position (Gtk::WIN_POS_MOUSE);
2751 switch (checker.run()) {
2752 case RESPONSE_ACCEPT:
2758 Session::cleanup_report rep;
2760 editor->prepare_for_cleanup ();
2762 /* do not allow flush until a session is reloaded */
2764 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2766 act->set_sensitive (false);
2769 if (session->cleanup_sources (rep)) {
2770 editor->finish_cleanup ();
2774 editor->finish_cleanup ();
2777 display_cleanup_results (rep,
2780 The following %1 files were not in use and \n\
2781 have been moved to:\n\
2783 Flushing the wastebasket will \n\
2784 release an additional\n\
2785 %3 %4bytes of disk space.\n"),
2787 The following file was not in use and \n \
2788 has been moved to:\n \
2790 Flushing the wastebasket will \n\
2791 release an additional\n\
2792 %3 %4bytes of disk space.\n"
2798 ARDOUR_UI::flush_trash ()
2801 /* shouldn't happen: menu item is insensitive */
2805 Session::cleanup_report rep;
2807 if (session->cleanup_trash_sources (rep)) {
2811 display_cleanup_results (rep,
2813 _("The following %1 files were deleted from\n\
2815 releasing %3 %4bytes of disk space"),
2816 _("The following file was deleted from\n\
2818 releasing %3 %4bytes of disk space"));
2822 ARDOUR_UI::add_route (Gtk::Window* float_window)
2830 if (add_route_dialog == 0) {
2831 add_route_dialog = new AddRouteDialog (*session);
2833 add_route_dialog->set_transient_for (*float_window);
2837 if (add_route_dialog->is_visible()) {
2838 /* we're already doing this */
2842 ResponseType r = (ResponseType) add_route_dialog->run ();
2844 add_route_dialog->hide();
2847 case RESPONSE_ACCEPT:
2854 if ((count = add_route_dialog->count()) <= 0) {
2858 string template_path = add_route_dialog->track_template();
2860 if (!template_path.empty()) {
2861 session->new_route_from_template (count, template_path);
2865 uint32_t input_chan = add_route_dialog->channels ();
2866 uint32_t output_chan;
2867 string name_template = add_route_dialog->name_template ();
2868 bool track = add_route_dialog->track ();
2869 RouteGroup* route_group = add_route_dialog->route_group ();
2871 AutoConnectOption oac = Config->get_output_auto_connect();
2873 if (oac & AutoConnectMaster) {
2874 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2876 output_chan = input_chan;
2879 /* XXX do something with name template */
2881 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2883 session_add_midi_track (route_group, count);
2885 MessageDialog msg (*editor,
2886 _("Sorry, MIDI Busses are not supported at this time."));
2888 //session_add_midi_bus();
2892 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
2894 session_add_audio_bus (input_chan, output_chan, route_group, count);
2900 ARDOUR_UI::mixer_settings () const
2905 node = session->instant_xml(X_("Mixer"));
2907 node = Config->instant_xml(X_("Mixer"));
2911 node = new XMLNode (X_("Mixer"));
2918 ARDOUR_UI::editor_settings () const
2923 node = session->instant_xml(X_("Editor"));
2925 node = Config->instant_xml(X_("Editor"));
2929 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2930 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2935 node = new XMLNode (X_("Editor"));
2942 ARDOUR_UI::keyboard_settings () const
2946 node = Config->extra_xml(X_("Keyboard"));
2949 node = new XMLNode (X_("Keyboard"));
2955 ARDOUR_UI::create_xrun_marker(nframes_t where)
2957 editor->mouse_add_new_marker (where, false, true);
2961 ARDOUR_UI::halt_on_xrun_message ()
2963 MessageDialog msg (*editor,
2964 _("Recording was stopped because your system could not keep up."));
2969 ARDOUR_UI::xrun_handler(nframes_t where)
2975 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2977 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2978 create_xrun_marker(where);
2981 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2982 halt_on_xrun_message ();
2987 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2992 while (disk_buffer_stats.size() > 60) {
2993 disk_buffer_stats.pop_front ();
2996 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3000 ARDOUR_UI::write_buffer_stats ()
3005 char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
3006 int fd = mkstemp (tmplt);
3008 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3012 FILE* fout = fdopen (fd, "w");
3014 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), tmplt) << endl;
3018 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3019 std::ostringstream ss;
3020 localtime_r (&(*i).when, &tm);
3021 strftime (buf, sizeof (buf), "%T", &tm);
3022 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
3025 disk_buffer_stats.clear ();
3030 cerr << "Ardour buffering statistics can be found in: " << tmplt << endl;
3035 ARDOUR_UI::disk_overrun_handler ()
3037 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3039 write_buffer_stats ();
3041 if (!have_disk_speed_dialog_displayed) {
3042 have_disk_speed_dialog_displayed = true;
3043 MessageDialog* msg = new MessageDialog (*editor, _("\
3044 The disk system on your computer\n\
3045 was not able to keep up with Ardour.\n\
3047 Specifically, it failed to write data to disk\n\
3048 quickly enough to keep up with recording.\n"));
3049 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3055 ARDOUR_UI::disk_underrun_handler ()
3057 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3059 write_buffer_stats ();
3061 if (!have_disk_speed_dialog_displayed) {
3062 have_disk_speed_dialog_displayed = true;
3063 MessageDialog* msg = new MessageDialog (*editor,
3064 _("The disk system on your computer\n\
3065 was not able to keep up with Ardour.\n\
3067 Specifically, it failed to read data from disk\n\
3068 quickly enough to keep up with playback.\n"));
3069 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3075 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3077 have_disk_speed_dialog_displayed = false;
3082 ARDOUR_UI::session_dialog (std::string msg)
3084 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3089 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3091 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3100 ARDOUR_UI::pending_state_dialog ()
3102 HBox* hbox = new HBox();
3103 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3104 ArdourDialog dialog (_("Crash Recovery"), true);
3106 This session appears to have been in\n\
3107 middle of recording when ardour or\n\
3108 the computer was shutdown.\n\
3110 Ardour can recover any captured audio for\n\
3111 you, or it can ignore it. Please decide\n\
3112 what you would like to do.\n"));
3113 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3114 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3115 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3116 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3117 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3118 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3119 dialog.set_default_response (RESPONSE_ACCEPT);
3120 dialog.set_position (WIN_POS_CENTER);
3125 switch (dialog.run ()) {
3126 case RESPONSE_ACCEPT:
3134 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3136 HBox* hbox = new HBox();
3137 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3138 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3139 Label message (string_compose (_("\
3140 This session was created with a sample rate of %1 Hz\n\
3142 The audioengine is currently running at %2 Hz\n"), desired, actual));
3144 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3145 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3146 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3147 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3148 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3149 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3150 dialog.set_default_response (RESPONSE_ACCEPT);
3151 dialog.set_position (WIN_POS_CENTER);
3156 switch (dialog.run ()) {
3157 case RESPONSE_ACCEPT:
3166 ARDOUR_UI::disconnect_from_jack ()
3169 if( engine->disconnect_from_jack ()) {
3170 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3174 update_sample_rate (0);
3179 ARDOUR_UI::reconnect_to_jack ()
3182 if (engine->reconnect_to_jack ()) {
3183 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3187 update_sample_rate (0);
3192 ARDOUR_UI::use_config ()
3195 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3197 set_transport_controllable_state (*node);
3202 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3204 if (Config->get_primary_clock_delta_edit_cursor()) {
3205 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3207 primary_clock.set (pos, 0, true);
3210 if (Config->get_secondary_clock_delta_edit_cursor()) {
3211 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3213 secondary_clock.set (pos);
3216 if (big_clock_window) {
3217 big_clock.set (pos);
3222 ARDOUR_UI::record_state_changed ()
3224 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3226 if (!session || !big_clock_window) {
3227 /* why bother - the clock isn't visible */
3231 Session::RecordState const r = session->record_status ();
3232 bool const h = session->have_rec_enabled_diskstream ();
3234 if (r == Session::Recording && h) {
3235 big_clock.set_widget_name ("BigClockRecording");
3237 big_clock.set_widget_name ("BigClockNonRecording");
3242 ARDOUR_UI::first_idle ()
3245 session->allow_auto_play (true);
3249 editor->first_idle();
3252 Keyboard::set_can_save_keybindings (true);
3257 ARDOUR_UI::store_clock_modes ()
3259 XMLNode* node = new XMLNode(X_("ClockModes"));
3261 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3262 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3265 session->add_extra_xml (*node);
3266 session->set_dirty ();
3271 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3272 : Controllable (name), ui (u), type(tp)
3278 ARDOUR_UI::TransportControllable::set_value (float val)
3280 if (type == ShuttleControl) {
3287 fract = -((0.5f - val)/0.5f);
3289 fract = ((val - 0.5f)/0.5f);
3293 ui.set_shuttle_fract (fract);
3298 /* do nothing: these are radio-style actions */
3302 const char *action = 0;
3306 action = X_("Roll");
3309 action = X_("Stop");
3312 action = X_("Goto Start");
3315 action = X_("Goto End");
3318 action = X_("Loop");
3321 action = X_("Play Selection");
3324 action = X_("Record");
3334 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3342 ARDOUR_UI::TransportControllable::get_value (void) const
3361 case ShuttleControl:
3371 ARDOUR_UI::TransportControllable::set_id (const string& str)
3377 ARDOUR_UI::setup_profile ()
3379 if (gdk_screen_width() < 1200) {
3380 Profile->set_small_screen ();
3384 if (getenv ("ARDOUR_SAE")) {
3385 Profile->set_sae ();
3386 Profile->set_single_package ();