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"
87 #include "new_session_dialog.h"
91 #include "gui_thread.h"
92 #include "theme_manager.h"
93 #include "bundle_manager.h"
94 #include "session_metadata_dialog.h"
95 #include "gain_meter.h"
96 #include "route_time_axis.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 new_session_dialog = 0;
200 add_route_dialog = 0;
204 open_session_selector = 0;
205 have_configure_timeout = false;
206 have_disk_speed_dialog_displayed = false;
207 session_loaded = false;
208 last_speed_displayed = -1.0f;
209 ignore_dual_punch = false;
210 _mixer_on_top = false;
212 roll_button.unset_flags (Gtk::CAN_FOCUS);
213 stop_button.unset_flags (Gtk::CAN_FOCUS);
214 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
215 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
216 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
217 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
218 rec_button.unset_flags (Gtk::CAN_FOCUS);
220 last_configure_time= 0;
222 shuttle_grabbed = false;
224 shuttle_max_speed = 8.0f;
226 shuttle_style_menu = 0;
227 shuttle_unit_menu = 0;
229 // We do not have jack linked in yet so;
231 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
233 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
234 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
236 /* handle dialog requests */
238 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
240 /* handle pending state with a dialog */
242 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
244 /* handle sr mismatch with a dialog */
246 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
248 /* lets get this party started */
251 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
252 throw failed_constructor ();
255 setup_gtk_ardour_enums ();
256 Config->set_current_owner (ConfigVariableBase::Interface);
259 GainMeter::setup_slider_pix ();
260 RouteTimeAxisView::setup_slider_pix ();
262 } catch (failed_constructor& err) {
263 error << _("could not initialize Ardour.") << endmsg;
268 /* we like keyboards */
270 keyboard = new Keyboard;
274 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
275 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
281 ARDOUR_UI::run_startup ()
284 _startup = new ArdourStartup ();
287 _startup->present ();
292 ARDOUR_UI::create_engine ()
294 // this gets called every time by new_session()
300 loading_message (_("Starting audio engine"));
303 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
310 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
311 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
312 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
313 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
321 ARDOUR_UI::post_engine ()
323 /* Things to be done once we create the AudioEngine
326 MIDI::Manager::instance()->set_api_data (engine->jack());
329 ActionManager::init ();
332 if (setup_windows ()) {
333 throw failed_constructor ();
336 check_memory_locking();
338 /* this is the first point at which all the keybindings are available */
340 if (ARDOUR_COMMAND_LINE::show_key_actions) {
341 vector<string> names;
342 vector<string> paths;
344 vector<AccelKey> bindings;
346 ActionManager::get_all_actions (names, paths, keys, bindings);
348 vector<string>::iterator n;
349 vector<string>::iterator k;
350 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
351 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
357 blink_timeout_tag = -1;
359 /* the global configuration object is now valid */
363 /* this being a GUI and all, we want peakfiles */
365 AudioFileSource::set_build_peakfiles (true);
366 AudioFileSource::set_build_missing_peakfiles (true);
368 /* set default clock modes */
370 if (Profile->get_sae()) {
371 primary_clock.set_mode (AudioClock::BBT);
372 secondary_clock.set_mode (AudioClock::MinSec);
374 primary_clock.set_mode (AudioClock::SMPTE);
375 secondary_clock.set_mode (AudioClock::BBT);
378 /* start the time-of-day-clock */
381 /* OS X provides an always visible wallclock, so don't be stupid */
382 update_wall_clock ();
383 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
386 update_disk_space ();
388 update_sample_rate (engine->frame_rate());
390 /* now start and maybe save state */
392 if (do_engine_start () == 0) {
393 if (session && _session_is_new) {
394 /* we need to retain initial visual
395 settings for a new session
397 session->save_state ("");
402 ARDOUR_UI::~ARDOUR_UI ()
404 save_ardour_state ();
409 delete add_route_dialog;
410 delete new_session_dialog;
414 ARDOUR_UI::pop_back_splash ()
416 if (Splash::instance()) {
417 // Splash::instance()->pop_back();
418 Splash::instance()->hide ();
423 ARDOUR_UI::configure_timeout ()
425 if (last_configure_time == 0) {
426 /* no configure events yet */
430 /* force a gap of 0.5 seconds since the last configure event
433 if (get_microseconds() - last_configure_time < 500000) {
436 have_configure_timeout = false;
437 save_ardour_state ();
443 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
445 if (have_configure_timeout) {
446 last_configure_time = get_microseconds();
448 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
449 have_configure_timeout = true;
456 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
458 const XMLProperty* prop;
460 if ((prop = node.property ("roll")) != 0) {
461 roll_controllable->set_id (prop->value());
463 if ((prop = node.property ("stop")) != 0) {
464 stop_controllable->set_id (prop->value());
466 if ((prop = node.property ("goto-start")) != 0) {
467 goto_start_controllable->set_id (prop->value());
469 if ((prop = node.property ("goto-end")) != 0) {
470 goto_end_controllable->set_id (prop->value());
472 if ((prop = node.property ("auto-loop")) != 0) {
473 auto_loop_controllable->set_id (prop->value());
475 if ((prop = node.property ("play-selection")) != 0) {
476 play_selection_controllable->set_id (prop->value());
478 if ((prop = node.property ("rec")) != 0) {
479 rec_controllable->set_id (prop->value());
481 if ((prop = node.property ("shuttle")) != 0) {
482 shuttle_controllable->set_id (prop->value());
487 ARDOUR_UI::get_transport_controllable_state ()
489 XMLNode* node = new XMLNode(X_("TransportControllables"));
492 roll_controllable->id().print (buf, sizeof (buf));
493 node->add_property (X_("roll"), buf);
494 stop_controllable->id().print (buf, sizeof (buf));
495 node->add_property (X_("stop"), buf);
496 goto_start_controllable->id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_start"), buf);
498 goto_end_controllable->id().print (buf, sizeof (buf));
499 node->add_property (X_("goto_end"), buf);
500 auto_loop_controllable->id().print (buf, sizeof (buf));
501 node->add_property (X_("auto_loop"), buf);
502 play_selection_controllable->id().print (buf, sizeof (buf));
503 node->add_property (X_("play_selection"), buf);
504 rec_controllable->id().print (buf, sizeof (buf));
505 node->add_property (X_("rec"), buf);
506 shuttle_controllable->id().print (buf, sizeof (buf));
507 node->add_property (X_("shuttle"), buf);
513 ARDOUR_UI::save_ardour_state ()
515 if (!keyboard || !mixer || !editor) {
519 /* XXX this is all a bit dubious. add_extra_xml() uses
520 a different lifetime model from add_instant_xml().
523 XMLNode* node = new XMLNode (keyboard->get_state());
524 Config->add_extra_xml (*node);
525 Config->add_extra_xml (get_transport_controllable_state());
526 if (new_session_dialog && new_session_dialog->engine_control.was_used()) {
527 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
529 Config->save_state();
530 ui_config->save_state ();
532 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
533 XMLNode mnode(mixer->get_state());
536 session->add_instant_xml (enode);
537 session->add_instant_xml (mnode);
539 Config->add_instant_xml (enode);
540 Config->add_instant_xml (mnode);
543 Keyboard::save_keybindings ();
547 ARDOUR_UI::autosave_session ()
549 if (g_main_depth() > 1) {
550 /* inside a recursive main loop,
551 give up because we may not be able to
557 if (!Config->get_periodic_safety_backups()) {
562 session->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
573 if (session->dirty()) {
574 if (_autosave_connection.connected()) {
575 _autosave_connection.disconnect();
578 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
579 Config->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection.connected()) {
583 _autosave_connection.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
593 title = _("Ardour could not start JACK");
595 title = _("Ardour could not connect to JACK.");
598 MessageDialog win (title,
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win.set_transient_for (*toplevel);
625 win.add_button (Stock::OK, RESPONSE_CLOSE);
627 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
630 win.set_default_response (RESPONSE_CLOSE);
633 win.set_position (Gtk::WIN_POS_CENTER);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
646 new_session_dialog = new NewSessionDialog();
648 bool backend_audio_is_running = EngineControl::engine_running();
649 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
652 new_session_dialog->engine_control.set_state (*audio_setup);
655 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
659 BootMessage (_("Ardour is ready for use"));
664 ARDOUR_UI::no_memory_warning ()
666 XMLNode node (X_("no-memory-warning"));
667 Config->add_instant_xml (node);
671 ARDOUR_UI::check_memory_locking ()
674 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
678 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
680 if (engine->is_realtime() && memory_warning_node == 0) {
682 struct rlimit limits;
684 long pages, page_size;
686 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
689 ram = (int64_t) pages * (int64_t) page_size;
692 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
696 if (limits.rlim_cur != RLIM_INFINITY) {
698 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
701 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
702 "This might cause Ardour to run out of memory before your system "
703 "runs out of memory. \n\n"
704 "You can view the memory limit with 'ulimit -l', "
705 "and it is normally controlled by /etc/security/limits.conf"));
707 VBox* vbox = msg.get_vbox();
709 CheckButton cb (_("Do not show this window again"));
711 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
713 hbox.pack_start (cb, true, false);
714 vbox->pack_start (hbox);
721 editor->ensure_float (msg);
735 if (session->transport_rolling()) {
736 session->request_stop ();
740 if (session->dirty()) {
741 switch (ask_about_saving_session(_("quit"))) {
746 /* use the default name */
747 if (save_state_canfail ("")) {
748 /* failed - don't quit */
749 MessageDialog msg (*editor,
751 Ardour was unable to save your session.\n\n\
752 If you still wish to quit, please use the\n\n\
753 \"Just quit\" option."));
764 session->set_deletion_in_progress ();
767 ArdourDialog::close_all_dialogs ();
769 save_ardour_state ();
774 ARDOUR_UI::ask_about_saving_session (const string & what)
776 ArdourDialog window (_("ardour: save session?"));
777 Gtk::HBox dhbox; // the hbox for the image and text
778 Gtk::Label prompt_label;
779 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
783 msg = string_compose(_("Don't %1"), what);
784 window.add_button (msg, RESPONSE_REJECT);
785 msg = string_compose(_("Just %1"), what);
786 window.add_button (msg, RESPONSE_APPLY);
787 msg = string_compose(_("Save and %1"), what);
788 window.add_button (msg, RESPONSE_ACCEPT);
790 window.set_default_response (RESPONSE_ACCEPT);
792 Gtk::Button noquit_button (msg);
793 noquit_button.set_name ("EditorGTKButton");
798 if (session->snap_name() == session->name()) {
801 type = _("snapshot");
803 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?"),
804 type, session->snap_name());
806 prompt_label.set_text (prompt);
807 prompt_label.set_name (X_("PrompterLabel"));
808 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
810 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
811 dhbox.set_homogeneous (false);
812 dhbox.pack_start (*dimage, false, false, 5);
813 dhbox.pack_start (prompt_label, true, false, 5);
814 window.get_vbox()->pack_start (dhbox);
816 window.set_name (_("Prompter"));
817 window.set_position (Gtk::WIN_POS_MOUSE);
818 window.set_modal (true);
819 window.set_resizable (false);
825 window.set_keep_above (true);
828 ResponseType r = (ResponseType) window.run();
833 case RESPONSE_ACCEPT: // save and get out of here
835 case RESPONSE_APPLY: // get out of here
845 ARDOUR_UI::every_second ()
848 update_buffer_load ();
849 update_disk_space ();
854 ARDOUR_UI::every_point_one_seconds ()
856 update_speed_display ();
857 RapidScreenUpdate(); /* EMIT_SIGNAL */
862 ARDOUR_UI::every_point_zero_one_seconds ()
864 // august 2007: actual update frequency: 40Hz, not 100Hz
866 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
871 ARDOUR_UI::update_sample_rate (nframes_t ignored)
875 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
877 if (!engine->connected()) {
879 snprintf (buf, sizeof (buf), _("disconnected"));
883 nframes_t rate = engine->frame_rate();
885 if (fmod (rate, 1000.0) != 0.0) {
886 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
887 (float) rate/1000.0f,
888 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
890 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
892 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
896 sample_rate_label.set_text (buf);
900 ARDOUR_UI::update_cpu_load ()
903 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
904 cpu_load_label.set_text (buf);
908 ARDOUR_UI::update_buffer_load ()
913 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
914 session->playback_load(), session->capture_load());
915 buffer_load_label.set_text (buf);
917 buffer_load_label.set_text ("");
922 ARDOUR_UI::count_recenabled_streams (Route& route)
924 Track* track = dynamic_cast<Track*>(&route);
925 if (track && track->diskstream()->record_enabled()) {
926 rec_enabled_streams += track->n_inputs().n_total();
931 ARDOUR_UI::update_disk_space()
937 nframes_t frames = session->available_capture_duration();
939 nframes_t fr = session->frame_rate();
941 if (frames == max_frames) {
942 strcpy (buf, _("Disk: 24hrs+"));
944 rec_enabled_streams = 0;
945 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
947 if (rec_enabled_streams) {
948 frames /= rec_enabled_streams;
955 hrs = frames / (fr * 3600);
956 frames -= hrs * fr * 3600;
957 mins = frames / (fr * 60);
958 frames -= mins * fr * 60;
961 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
964 disk_space_label.set_text (buf);
966 // An attempt to make the disk space label flash red when space has run out.
968 if (frames < fr * 60 * 5) {
969 /* disk_space_box.style ("disk_space_label_empty"); */
971 /* disk_space_box.style ("disk_space_label"); */
977 ARDOUR_UI::update_wall_clock ()
984 tm_now = localtime (&now);
986 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
987 wall_clock_label.set_text (buf);
993 ARDOUR_UI::session_menu (GdkEventButton *ev)
995 session_popup_menu->popup (0, 0);
1000 ARDOUR_UI::redisplay_recent_sessions ()
1002 std::vector<sys::path> session_directories;
1003 RecentSessionsSorter cmp;
1005 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1006 recent_session_model->clear ();
1008 ARDOUR::RecentSessions rs;
1009 ARDOUR::read_recent_sessions (rs);
1012 recent_session_display.set_model (recent_session_model);
1016 // sort them alphabetically
1017 sort (rs.begin(), rs.end(), cmp);
1019 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1020 session_directories.push_back ((*i).second);
1023 for (vector<sys::path>::const_iterator i = session_directories.begin();
1024 i != session_directories.end(); ++i)
1026 std::vector<sys::path> state_file_paths;
1028 // now get available states for this session
1030 get_state_files_in_directory (*i, state_file_paths);
1032 vector<string*>* states;
1033 vector<const gchar*> item;
1034 string fullpath = (*i).to_string();
1036 /* remove any trailing / */
1038 if (fullpath[fullpath.length()-1] == '/') {
1039 fullpath = fullpath.substr (0, fullpath.length()-1);
1042 /* check whether session still exists */
1043 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1044 /* session doesn't exist */
1045 cerr << "skipping non-existent session " << fullpath << endl;
1049 /* now get available states for this session */
1051 if ((states = Session::possible_states (fullpath)) == 0) {
1052 /* no state file? */
1056 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1058 Gtk::TreeModel::Row row = *(recent_session_model->append());
1060 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1061 row[recent_session_columns.fullpath] = fullpath;
1063 if (state_file_names.size() > 1) {
1067 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1068 i2 != state_file_names.end(); ++i2)
1071 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1073 child_row[recent_session_columns.visible_name] = *i2;
1074 child_row[recent_session_columns.fullpath] = fullpath;
1079 recent_session_display.set_model (recent_session_model);
1083 ARDOUR_UI::build_session_selector ()
1085 session_selector_window = new ArdourDialog ("session selector");
1087 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1089 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1090 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1091 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1092 recent_session_model = TreeStore::create (recent_session_columns);
1093 recent_session_display.set_model (recent_session_model);
1094 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1095 recent_session_display.set_headers_visible (false);
1096 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1097 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1099 scroller->add (recent_session_display);
1100 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1102 session_selector_window->set_name ("SessionSelectorWindow");
1103 session_selector_window->set_size_request (200, 400);
1104 session_selector_window->get_vbox()->pack_start (*scroller);
1106 recent_session_display.show();
1108 //session_selector_window->get_vbox()->show();
1112 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1114 session_selector_window->response (RESPONSE_ACCEPT);
1118 ARDOUR_UI::open_recent_session ()
1120 bool can_return = (session != 0);
1122 if (session_selector_window == 0) {
1123 build_session_selector ();
1126 redisplay_recent_sessions ();
1130 session_selector_window->set_position (WIN_POS_MOUSE);
1132 ResponseType r = (ResponseType) session_selector_window->run ();
1135 case RESPONSE_ACCEPT:
1139 session_selector_window->hide();
1146 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1150 session_selector_window->hide();
1152 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1154 if (i == recent_session_model->children().end()) {
1158 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1159 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1161 _session_is_new = false;
1163 if (load_session (path, state) == 0) {
1172 ARDOUR_UI::check_audioengine ()
1175 if (!engine->connected()) {
1176 MessageDialog msg (_("Ardour is not connected to JACK\n"
1177 "You cannot open or close sessions in this condition"));
1189 ARDOUR_UI::open_session ()
1191 if (!check_audioengine()) {
1196 /* popup selector window */
1198 if (open_session_selector == 0) {
1200 /* ardour sessions are folders */
1202 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1203 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1204 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1205 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1207 FileFilter session_filter;
1208 session_filter.add_pattern ("*.ardour");
1209 session_filter.set_name (_("Ardour sessions"));
1210 open_session_selector->add_filter (session_filter);
1211 open_session_selector->set_filter (session_filter);
1214 int response = open_session_selector->run();
1215 open_session_selector->hide ();
1218 case RESPONSE_ACCEPT:
1221 open_session_selector->hide();
1225 open_session_selector->hide();
1226 string session_path = open_session_selector->get_filename();
1230 if (session_path.length() > 0) {
1231 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1232 _session_is_new = isnew;
1233 load_session (path, name);
1240 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1242 list<boost::shared_ptr<MidiTrack> > tracks;
1245 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1252 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1254 if (tracks.size() != how_many) {
1255 if (how_many == 1) {
1256 error << _("could not create a new midi track") << endmsg;
1258 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1262 if ((route = session->new_midi_route ()) == 0) {
1263 error << _("could not create new midi bus") << endmsg;
1269 MessageDialog msg (*editor,
1270 _("There are insufficient JACK ports available\n\
1271 to create a new track or bus.\n\
1272 You should save Ardour, exit and\n\
1273 restart JACK with more ports."));
1280 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1282 list<boost::shared_ptr<AudioTrack> > tracks;
1286 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1292 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1294 if (tracks.size() != how_many) {
1295 if (how_many == 1) {
1296 error << _("could not create a new audio track") << endmsg;
1298 error << string_compose (_("could only create %1 of %2 new audio %3"),
1299 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1305 routes = session->new_audio_route (input_channels, output_channels, how_many);
1307 if (routes.size() != how_many) {
1308 if (how_many == 1) {
1309 error << _("could not create a new audio track") << endmsg;
1311 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1317 if (need_control_room_outs) {
1323 route->set_stereo_control_outs (control_lr_channels);
1324 route->control_outs()->set_stereo_pan (pans, this);
1326 #endif /* CONTROLOUTS */
1330 MessageDialog msg (*editor,
1331 _("There are insufficient JACK ports available\n\
1332 to create a new track or bus.\n\
1333 You should save Ardour, exit and\n\
1334 restart JACK with more ports."));
1341 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1343 nframes_t _preroll = 0;
1346 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1347 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1349 if (new_position > _preroll) {
1350 new_position -= _preroll;
1355 session->request_locate (new_position);
1360 ARDOUR_UI::transport_goto_start ()
1363 session->goto_start();
1366 /* force displayed area in editor to start no matter
1367 what "follow playhead" setting is.
1371 editor->reset_x_origin (session->current_start_frame());
1377 ARDOUR_UI::transport_goto_zero ()
1380 session->request_locate (0);
1383 /* force displayed area in editor to start no matter
1384 what "follow playhead" setting is.
1388 editor->reset_x_origin (0);
1394 ARDOUR_UI::transport_goto_wallclock ()
1396 if (session && editor) {
1403 localtime_r (&now, &tmnow);
1405 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1406 frames += tmnow.tm_min * (60 * session->frame_rate());
1407 frames += tmnow.tm_sec * session->frame_rate();
1409 session->request_locate (frames);
1411 /* force displayed area in editor to start no matter
1412 what "follow playhead" setting is.
1416 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1422 ARDOUR_UI::transport_goto_end ()
1425 nframes_t frame = session->current_end_frame();
1426 session->request_locate (frame);
1428 /* force displayed area in editor to start no matter
1429 what "follow playhead" setting is.
1433 editor->reset_x_origin (frame);
1439 ARDOUR_UI::transport_stop ()
1445 if (session->is_auditioning()) {
1446 session->cancel_audition ();
1450 if (session->get_play_loop ()) {
1451 session->request_play_loop (false);
1454 session->request_stop ();
1458 ARDOUR_UI::transport_stop_and_forget_capture ()
1461 session->request_stop (true);
1466 ARDOUR_UI::remove_last_capture()
1469 editor->remove_last_capture();
1474 ARDOUR_UI::transport_record (bool roll)
1478 switch (session->record_status()) {
1479 case Session::Disabled:
1480 if (session->ntracks() == 0) {
1481 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1485 session->maybe_enable_record ();
1490 case Session::Recording:
1492 session->request_stop();
1494 session->disable_record (false, true);
1498 case Session::Enabled:
1499 session->disable_record (false, true);
1502 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1506 ARDOUR_UI::transport_roll ()
1514 rolling = session->transport_rolling ();
1516 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1518 if (session->get_play_loop()) {
1519 session->request_play_loop (false);
1520 auto_loop_button.set_visual_state (1);
1521 roll_button.set_visual_state (1);
1522 } else if (session->get_play_range ()) {
1523 session->request_play_range (false);
1524 play_selection_button.set_visual_state (0);
1525 } else if (rolling) {
1526 session->request_locate (session->last_transport_start(), true);
1529 session->request_transport_speed (1.0f);
1533 ARDOUR_UI::transport_loop()
1536 if (session->get_play_loop()) {
1537 if (session->transport_rolling()) {
1538 Location * looploc = session->locations()->auto_loop_location();
1540 session->request_locate (looploc->start(), true);
1545 session->request_play_loop (true);
1551 ARDOUR_UI::transport_play_selection ()
1557 if (!session->get_play_range()) {
1558 session->request_stop ();
1561 editor->play_selection ();
1565 ARDOUR_UI::transport_rewind (int option)
1567 float current_transport_speed;
1570 current_transport_speed = session->transport_speed();
1572 if (current_transport_speed >= 0.0f) {
1575 session->request_transport_speed (-1.0f);
1578 session->request_transport_speed (-4.0f);
1581 session->request_transport_speed (-0.5f);
1586 session->request_transport_speed (current_transport_speed * 1.5f);
1592 ARDOUR_UI::transport_forward (int option)
1594 float current_transport_speed;
1597 current_transport_speed = session->transport_speed();
1599 if (current_transport_speed <= 0.0f) {
1602 session->request_transport_speed (1.0f);
1605 session->request_transport_speed (4.0f);
1608 session->request_transport_speed (0.5f);
1613 session->request_transport_speed (current_transport_speed * 1.5f);
1619 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1625 boost::shared_ptr<Route> r;
1627 if ((r = session->route_by_remote_id (dstream)) != 0) {
1631 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1632 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1641 ARDOUR_UI::queue_transport_change ()
1643 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1647 ARDOUR_UI::map_transport_state ()
1649 float sp = session->transport_speed();
1652 transport_rolling ();
1653 } else if (sp < 0.0f) {
1654 transport_rewinding ();
1655 } else if (sp > 0.0f) {
1656 transport_forwarding ();
1658 transport_stopped ();
1663 ARDOUR_UI::engine_stopped ()
1665 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1666 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1667 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1671 ARDOUR_UI::engine_running ()
1673 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1674 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1675 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1677 Glib::RefPtr<Action> action;
1678 const char* action_name = 0;
1680 switch (engine->frames_per_cycle()) {
1682 action_name = X_("JACKLatency32");
1685 action_name = X_("JACKLatency64");
1688 action_name = X_("JACKLatency128");
1691 action_name = X_("JACKLatency512");
1694 action_name = X_("JACKLatency1024");
1697 action_name = X_("JACKLatency2048");
1700 action_name = X_("JACKLatency4096");
1703 action_name = X_("JACKLatency8192");
1706 /* XXX can we do anything useful ? */
1712 action = ActionManager::get_action (X_("JACK"), action_name);
1715 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1716 ract->set_active ();
1722 ARDOUR_UI::engine_halted ()
1724 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1726 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1727 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1729 update_sample_rate (0);
1731 MessageDialog msg (*editor,
1733 JACK has either been shutdown or it\n\
1734 disconnected Ardour because Ardour\n\
1735 was not fast enough. Try to restart\n\
1736 JACK, reconnect and save the session."));
1742 ARDOUR_UI::do_engine_start ()
1750 error << _("Unable to start the session running")
1760 ARDOUR_UI::setup_theme ()
1762 theme_manager->setup_theme();
1766 ARDOUR_UI::update_clocks ()
1768 if (!editor || !editor->dragging_playhead()) {
1769 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1774 ARDOUR_UI::start_clocking ()
1776 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1780 ARDOUR_UI::stop_clocking ()
1782 clock_signal_connection.disconnect ();
1786 ARDOUR_UI::toggle_clocking ()
1789 if (clock_button.get_active()) {
1798 ARDOUR_UI::_blink (void *arg)
1801 ((ARDOUR_UI *) arg)->blink ();
1808 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1812 ARDOUR_UI::start_blinking ()
1814 /* Start the blink signal. Everybody with a blinking widget
1815 uses Blink to drive the widget's state.
1818 if (blink_timeout_tag < 0) {
1820 blink_timeout_tag = g_timeout_add (240, _blink, this);
1825 ARDOUR_UI::stop_blinking ()
1827 if (blink_timeout_tag >= 0) {
1828 g_source_remove (blink_timeout_tag);
1829 blink_timeout_tag = -1;
1834 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1839 vector<string> connections;
1842 if (io.n_inputs().n_total() == 0) {
1847 /* XXX we're not handling multiple ports yet. */
1849 if (io.input(0)->get_connections(connections) == 0) {
1852 buf = connections.front();
1857 if (io.n_outputs().n_total() == 0) {
1862 /* XXX we're not handling multiple ports yet. */
1864 if (io.output(0)->get_connections(connections) == 0) {
1867 buf = connections.front();
1872 /** Ask the user for the name of a new shapshot and then take it.
1875 ARDOUR_UI::snapshot_session ()
1877 ArdourPrompter prompter (true);
1881 struct tm local_time;
1884 localtime_r (&n, &local_time);
1885 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1887 prompter.set_name ("Prompter");
1888 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1889 prompter.set_prompt (_("Name of New Snapshot"));
1890 prompter.set_initial_text (timebuf);
1892 switch (prompter.run()) {
1893 case RESPONSE_ACCEPT:
1894 prompter.get_result (snapname);
1895 if (snapname.length()){
1896 save_state (snapname);
1906 ARDOUR_UI::save_state (const string & name)
1908 (void) save_state_canfail (name);
1912 ARDOUR_UI::save_state_canfail (string name)
1917 if (name.length() == 0) {
1918 name = session->snap_name();
1921 if ((ret = session->save_state (name)) != 0) {
1925 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1930 ARDOUR_UI::primary_clock_value_changed ()
1933 session->request_locate (primary_clock.current_time ());
1938 ARDOUR_UI::big_clock_value_changed ()
1941 session->request_locate (big_clock.current_time ());
1946 ARDOUR_UI::secondary_clock_value_changed ()
1949 session->request_locate (secondary_clock.current_time ());
1954 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1960 switch (session->record_status()) {
1961 case Session::Enabled:
1963 rec_button.set_visual_state (2);
1965 rec_button.set_visual_state (0);
1969 case Session::Recording:
1970 rec_button.set_visual_state (1);
1974 rec_button.set_visual_state (0);
1980 ARDOUR_UI::save_template ()
1983 ArdourPrompter prompter (true);
1986 if (!check_audioengine()) {
1990 prompter.set_name (X_("Prompter"));
1991 prompter.set_prompt (_("Name for mix template:"));
1992 prompter.set_initial_text(session->name() + _("-template"));
1993 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1995 switch (prompter.run()) {
1996 case RESPONSE_ACCEPT:
1997 prompter.get_result (name);
1999 if (name.length()) {
2000 session->save_template (name);
2010 ARDOUR_UI::edit_metadata ()
2012 SessionMetadataEditor dialog;
2013 dialog.set_session (session);
2014 editor->ensure_float (dialog);
2019 ARDOUR_UI::import_metadata ()
2021 SessionMetadataImporter dialog;
2022 dialog.set_session (session);
2023 editor->ensure_float (dialog);
2028 ARDOUR_UI::fontconfig_dialog ()
2031 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2032 may not and it can take a while to build it. Warn them.
2035 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2037 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2038 MessageDialog msg (*new_session_dialog,
2039 _("Welcome to Ardour.\n\n"
2040 "The program will take a bit longer to start up\n"
2041 "while the system fonts are checked.\n\n"
2042 "This will only be done once, and you will\n"
2043 "not see this message again\n"),
2056 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2058 existing_session = false;
2060 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2061 session_path = cmdline_path;
2062 existing_session = true;
2063 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2064 session_path = Glib::path_get_dirname (string (cmdline_path));
2065 existing_session = true;
2067 /* it doesn't exist, assume the best */
2068 session_path = Glib::path_get_dirname (string (cmdline_path));
2071 session_name = basename_nosuffix (string (cmdline_path));
2075 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2077 /* when this is called, the backend audio system must be running */
2079 /* the main idea here is to deal with the fact that a cmdline argument for the session
2080 can be interpreted in different ways - it could be a directory or a file, and before
2081 we load, we need to know both the session directory and the snapshot (statefile) within it
2082 that we are supposed to use.
2085 if (session_name.length() == 0 || session_path.length() == 0) {
2089 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2091 Glib::ustring predicted_session_file;
2093 predicted_session_file = session_path;
2094 predicted_session_file += '/';
2095 predicted_session_file += session_name;
2096 predicted_session_file += ARDOUR::statefile_suffix;
2098 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2099 existing_session = true;
2102 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2104 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2105 /* existing .ardour file */
2106 existing_session = true;
2110 existing_session = false;
2113 /* lets just try to load it */
2115 if (create_engine ()) {
2116 backend_audio_error (false, new_session_dialog);
2120 return load_session (session_path, session_name);
2124 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2126 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2128 MessageDialog msg (str,
2130 Gtk::MESSAGE_WARNING,
2131 Gtk::BUTTONS_YES_NO,
2135 msg.set_name (X_("CleanupDialog"));
2136 msg.set_wmclass (X_("existing_session"), "Ardour");
2137 msg.set_position (Gtk::WIN_POS_MOUSE);
2140 switch (msg.run()) {
2149 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2154 AutoConnectOption iconnect;
2155 AutoConnectOption oconnect;
2159 if (Profile->get_sae()) {
2163 iconnect = AutoConnectPhysical;
2164 oconnect = AutoConnectMaster;
2165 nphysin = 0; // use all available
2166 nphysout = 0; // use all available
2170 /* get settings from advanced section of NSD */
2172 if (new_session_dialog->create_control_bus()) {
2173 cchns = (uint32_t) new_session_dialog->control_channel_count();
2178 if (new_session_dialog->create_master_bus()) {
2179 mchns = (uint32_t) new_session_dialog->master_channel_count();
2184 if (new_session_dialog->connect_inputs()) {
2185 iconnect = AutoConnectPhysical;
2187 iconnect = AutoConnectOption (0);
2190 /// @todo some minor tweaks.
2192 if (new_session_dialog->connect_outs_to_master()) {
2193 oconnect = AutoConnectMaster;
2194 } else if (new_session_dialog->connect_outs_to_physical()) {
2195 oconnect = AutoConnectPhysical;
2197 oconnect = AutoConnectOption (0);
2200 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2201 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2204 if (build_session (session_path,
2212 engine->frame_rate() * 60 * 5)) {
2221 ARDOUR_UI::end_loading_messages ()
2227 ARDOUR_UI::loading_message (const std::string& msg)
2230 // splash->message (msg);
2235 ARDOUR_UI::idle_load (const Glib::ustring& path)
2238 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2239 /* /path/to/foo => /path/to/foo, foo */
2240 load_session (path, basename_nosuffix (path));
2242 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2243 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2247 ARDOUR_COMMAND_LINE::session_name = path;
2249 if (new_session_dialog) {
2252 /* make it break out of Dialog::run() and
2256 new_session_dialog->response (1);
2261 /** @param offer_quit true to offer a Cancel button, otherwise call it Quit */
2263 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new, bool offer_cancel)
2265 bool existing_session = false;
2266 Glib::ustring session_name;
2267 Glib::ustring session_path;
2268 Glib::ustring template_name;
2272 response = Gtk::RESPONSE_NONE;
2274 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2276 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2278 /* don't ever reuse this */
2280 ARDOUR_COMMAND_LINE::session_name = string();
2282 if (existing_session && backend_audio_is_running) {
2284 /* just load the thing already */
2286 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2291 /* make the NSD use whatever information we have */
2293 new_session_dialog->set_session_name (session_name);
2294 new_session_dialog->set_session_folder (session_path);
2297 /* loading failed, or we need the NSD for something */
2299 new_session_dialog->set_modal (false);
2300 new_session_dialog->set_position (WIN_POS_CENTER);
2301 new_session_dialog->set_current_page (0);
2302 new_session_dialog->set_existing_session (existing_session);
2303 new_session_dialog->reset_recent();
2304 new_session_dialog->set_offer_cancel (offer_cancel);
2307 new_session_dialog->set_have_engine (backend_audio_is_running);
2308 new_session_dialog->present ();
2309 end_loading_messages ();
2310 response = new_session_dialog->run ();
2312 _session_is_new = false;
2314 /* handle possible negative responses */
2318 /* sent by idle_load, meaning restart the whole process again */
2319 new_session_dialog->hide();
2320 new_session_dialog->reset();
2324 case Gtk::RESPONSE_CANCEL:
2325 case Gtk::RESPONSE_DELETE_EVENT:
2327 if (engine && engine->running()) {
2328 engine->stop (true);
2332 new_session_dialog->hide ();
2335 case Gtk::RESPONSE_NONE:
2336 /* "Clear" was pressed */
2340 fontconfig_dialog();
2342 if (!backend_audio_is_running) {
2343 int ret = new_session_dialog->engine_control.setup_engine ();
2346 } else if (ret > 0) {
2347 response = Gtk::RESPONSE_REJECT;
2352 if (create_engine ()) {
2354 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2357 new_session_dialog->set_existing_session (false);
2358 new_session_dialog->set_current_page (2);
2360 response = Gtk::RESPONSE_NONE;
2364 backend_audio_is_running = true;
2366 if (response == Gtk::RESPONSE_OK) {
2368 session_name = new_session_dialog->session_name();
2370 if (session_name.empty()) {
2371 response = Gtk::RESPONSE_NONE;
2375 /* if the user mistakenly typed path information into the session filename entry,
2376 convert what they typed into a path & a name
2379 if (session_name[0] == '/' ||
2380 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2381 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2383 session_path = Glib::path_get_dirname (session_name);
2384 session_name = Glib::path_get_basename (session_name);
2388 session_path = new_session_dialog->session_folder();
2391 template_name = Glib::ustring();
2392 switch (new_session_dialog->which_page()) {
2394 case NewSessionDialog::OpenPage:
2395 case NewSessionDialog::EnginePage:
2399 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2401 should_be_new = true;
2403 //XXX This is needed because session constructor wants a
2404 //non-existant path. hopefully this will be fixed at some point.
2406 session_path = Glib::build_filename (session_path, session_name);
2408 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2410 if (ask_about_loading_existing_session (session_path)) {
2413 response = RESPONSE_NONE;
2418 _session_is_new = true;
2420 if (new_session_dialog->use_session_template()) {
2422 template_name = new_session_dialog->session_template_name();
2426 if (build_session_from_nsd (session_path, session_name)) {
2427 response = RESPONSE_NONE;
2439 new_session_dialog->hide ();
2441 if (load_session (session_path, session_name, template_name)) {
2443 response = Gtk::RESPONSE_NONE;
2447 if (response == Gtk::RESPONSE_NONE) {
2448 new_session_dialog->set_existing_session (false);
2449 new_session_dialog->reset ();
2453 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2457 new_session_dialog->hide();
2458 new_session_dialog->reset();
2459 goto_editor_window ();
2464 ARDOUR_UI::close_session()
2466 if (!check_audioengine()) {
2470 unload_session (true);
2472 get_session_parameters (true, false);
2476 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2478 Session *new_session;
2482 session_loaded = false;
2484 if (!check_audioengine()) {
2488 unload_status = unload_session ();
2490 if (unload_status < 0) {
2492 } else if (unload_status > 0) {
2497 /* if it already exists, we must have write access */
2499 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2500 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2501 "This prevents the session from being loaded."));
2507 loading_message (_("Please wait while Ardour loads your session"));
2510 new_session = new Session (*engine, path, snap_name, mix_template);
2513 /* this one is special */
2515 catch (AudioEngine::PortRegistrationFailure& err) {
2517 MessageDialog msg (err.what(),
2520 Gtk::BUTTONS_CLOSE);
2522 msg.set_title (_("Port Registration Error"));
2523 msg.set_secondary_text (_("Click the Close button to try again."));
2524 msg.set_position (Gtk::WIN_POS_CENTER);
2528 int response = msg.run ();
2533 case RESPONSE_CANCEL:
2543 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2546 Gtk::BUTTONS_CLOSE);
2548 msg.set_title (_("Loading Error"));
2549 msg.set_secondary_text (_("Click the Close button to try again."));
2550 msg.set_position (Gtk::WIN_POS_CENTER);
2554 int response = msg.run ();
2559 case RESPONSE_CANCEL:
2567 connect_to_session (new_session);
2569 Config->set_current_owner (ConfigVariableBase::Interface);
2571 session_loaded = true;
2573 goto_editor_window ();
2576 session->set_clean ();
2587 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2588 uint32_t control_channels,
2589 uint32_t master_channels,
2590 AutoConnectOption input_connect,
2591 AutoConnectOption output_connect,
2594 nframes_t initial_length)
2596 Session *new_session;
2599 if (!check_audioengine()) {
2603 session_loaded = false;
2605 x = unload_session ();
2613 _session_is_new = true;
2616 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2617 control_channels, master_channels, nphysin, nphysout, initial_length);
2622 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2628 connect_to_session (new_session);
2630 session_loaded = true;
2632 new_session->save_state(new_session->name());
2641 editor->show_window ();
2652 ARDOUR_UI::show_about ()
2656 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2663 ARDOUR_UI::hide_about ()
2666 about->get_window()->set_cursor ();
2672 ARDOUR_UI::about_signal_response(int response)
2678 ARDOUR_UI::show_splash ()
2682 splash = new Splash;
2690 splash->queue_draw ();
2691 splash->get_window()->process_updates (true);
2696 ARDOUR_UI::hide_splash ()
2704 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2708 removed = rep.paths.size();
2711 MessageDialog msgd (*editor,
2712 _("No audio files were ready for cleanup"),
2715 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2716 msgd.set_secondary_text (_("If this seems suprising, \n\
2717 check for any existing snapshots.\n\
2718 These may still include regions that\n\
2719 require some unused files to continue to exist."));
2725 ArdourDialog results (_("ardour: cleanup"), true, false);
2727 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2728 CleanupResultsModelColumns() {
2732 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2733 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2737 CleanupResultsModelColumns results_columns;
2738 Glib::RefPtr<Gtk::ListStore> results_model;
2739 Gtk::TreeView results_display;
2741 results_model = ListStore::create (results_columns);
2742 results_display.set_model (results_model);
2743 results_display.append_column (list_title, results_columns.visible_name);
2745 results_display.set_name ("CleanupResultsList");
2746 results_display.set_headers_visible (true);
2747 results_display.set_headers_clickable (false);
2748 results_display.set_reorderable (false);
2750 Gtk::ScrolledWindow list_scroller;
2753 Gtk::HBox dhbox; // the hbox for the image and text
2754 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2755 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2757 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2759 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2761 if (rep.space < 1048576.0f) {
2763 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2765 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2769 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2771 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2775 dhbox.pack_start (*dimage, true, false, 5);
2776 dhbox.pack_start (txt, true, false, 5);
2778 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2779 TreeModel::Row row = *(results_model->append());
2780 row[results_columns.visible_name] = *i;
2781 row[results_columns.fullpath] = *i;
2784 list_scroller.add (results_display);
2785 list_scroller.set_size_request (-1, 150);
2786 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2788 dvbox.pack_start (dhbox, true, false, 5);
2789 dvbox.pack_start (list_scroller, true, false, 5);
2790 ddhbox.pack_start (dvbox, true, false, 5);
2792 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2793 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2794 results.set_default_response (RESPONSE_CLOSE);
2795 results.set_position (Gtk::WIN_POS_MOUSE);
2797 results_display.show();
2798 list_scroller.show();
2805 //results.get_vbox()->show();
2806 results.set_resizable (false);
2813 ARDOUR_UI::cleanup ()
2816 /* shouldn't happen: menu item is insensitive */
2821 MessageDialog checker (_("Are you sure you want to cleanup?"),
2823 Gtk::MESSAGE_QUESTION,
2824 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2826 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2827 ALL undo/redo information will be lost if you cleanup.\n\
2828 After cleanup, unused audio files will be moved to a \
2829 \"dead sounds\" location."));
2831 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2832 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2833 checker.set_default_response (RESPONSE_CANCEL);
2835 checker.set_name (_("CleanupDialog"));
2836 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2837 checker.set_position (Gtk::WIN_POS_MOUSE);
2839 switch (checker.run()) {
2840 case RESPONSE_ACCEPT:
2846 Session::cleanup_report rep;
2848 editor->prepare_for_cleanup ();
2850 /* do not allow flush until a session is reloaded */
2852 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2854 act->set_sensitive (false);
2857 if (session->cleanup_sources (rep)) {
2858 editor->finish_cleanup ();
2862 editor->finish_cleanup ();
2865 display_cleanup_results (rep,
2868 The following %1 %2 not in use and \n\
2869 have been moved to:\n\
2871 Flushing the wastebasket will \n\
2872 release an additional\n\
2873 %4 %5bytes of disk space.\n"
2879 ARDOUR_UI::flush_trash ()
2882 /* shouldn't happen: menu item is insensitive */
2886 Session::cleanup_report rep;
2888 if (session->cleanup_trash_sources (rep)) {
2892 display_cleanup_results (rep,
2894 _("The following %1 %2 deleted from\n\
2896 releasing %4 %5bytes of disk space"));
2900 ARDOUR_UI::add_route (Gtk::Window* float_window)
2908 if (add_route_dialog == 0) {
2909 add_route_dialog = new AddRouteDialog;
2911 add_route_dialog->set_transient_for (*float_window);
2915 if (add_route_dialog->is_visible()) {
2916 /* we're already doing this */
2920 ResponseType r = (ResponseType) add_route_dialog->run ();
2922 add_route_dialog->hide();
2925 case RESPONSE_ACCEPT:
2932 if ((count = add_route_dialog->count()) <= 0) {
2936 string template_path = add_route_dialog->track_template();
2938 if (!template_path.empty()) {
2939 session->new_route_from_template (count, template_path);
2943 uint32_t input_chan = add_route_dialog->channels ();
2944 uint32_t output_chan;
2945 string name_template = add_route_dialog->name_template ();
2946 bool track = add_route_dialog->track ();
2948 AutoConnectOption oac = Config->get_output_auto_connect();
2950 if (oac & AutoConnectMaster) {
2951 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2953 output_chan = input_chan;
2956 /* XXX do something with name template */
2958 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2960 session_add_midi_track(count);
2962 MessageDialog msg (*editor,
2963 _("Sorry, MIDI Busses are not supported at this time."));
2965 //session_add_midi_bus();
2969 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2971 session_add_audio_bus (input_chan, output_chan, count);
2977 ARDOUR_UI::mixer_settings () const
2982 node = session->instant_xml(X_("Mixer"));
2984 node = Config->instant_xml(X_("Mixer"));
2988 node = new XMLNode (X_("Mixer"));
2995 ARDOUR_UI::editor_settings () const
3000 node = session->instant_xml(X_("Editor"));
3002 node = Config->instant_xml(X_("Editor"));
3006 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3007 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3012 node = new XMLNode (X_("Editor"));
3019 ARDOUR_UI::keyboard_settings () const
3023 node = Config->extra_xml(X_("Keyboard"));
3026 node = new XMLNode (X_("Keyboard"));
3032 ARDOUR_UI::create_xrun_marker(nframes_t where)
3034 editor->mouse_add_new_marker (where, false, true);
3038 ARDOUR_UI::halt_on_xrun_message ()
3040 MessageDialog msg (*editor,
3041 _("Recording was stopped because your system could not keep up."));
3046 ARDOUR_UI::xrun_handler(nframes_t where)
3052 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3054 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3055 create_xrun_marker(where);
3058 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3059 halt_on_xrun_message ();
3064 ARDOUR_UI::disk_overrun_handler ()
3066 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3068 if (!have_disk_speed_dialog_displayed) {
3069 have_disk_speed_dialog_displayed = true;
3070 MessageDialog* msg = new MessageDialog (*editor, _("\
3071 The disk system on your computer\n\
3072 was not able to keep up with Ardour.\n\
3074 Specifically, it failed to write data to disk\n\
3075 quickly enough to keep up with recording.\n"));
3076 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3082 ARDOUR_UI::disk_underrun_handler ()
3084 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3086 if (!have_disk_speed_dialog_displayed) {
3087 have_disk_speed_dialog_displayed = true;
3088 MessageDialog* msg = new MessageDialog (*editor,
3089 _("The disk system on your computer\n\
3090 was not able to keep up with Ardour.\n\
3092 Specifically, it failed to read data from disk\n\
3093 quickly enough to keep up with playback.\n"));
3094 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3100 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3102 have_disk_speed_dialog_displayed = false;
3107 ARDOUR_UI::session_dialog (std::string msg)
3109 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3114 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3116 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3125 ARDOUR_UI::pending_state_dialog ()
3127 HBox* hbox = new HBox();
3128 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3129 ArdourDialog dialog (_("Crash Recovery"), true);
3131 This session appears to have been in\n\
3132 middle of recording when ardour or\n\
3133 the computer was shutdown.\n\
3135 Ardour can recover any captured audio for\n\
3136 you, or it can ignore it. Please decide\n\
3137 what you would like to do.\n"));
3138 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3139 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3140 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3141 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3142 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3143 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3144 dialog.set_default_response (RESPONSE_ACCEPT);
3145 dialog.set_position (WIN_POS_CENTER);
3150 switch (dialog.run ()) {
3151 case RESPONSE_ACCEPT:
3159 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3161 HBox* hbox = new HBox();
3162 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3163 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3164 Label message (string_compose (_("\
3165 This session was created with a sample rate of %1 Hz\n\
3167 The audioengine is currently running at %2 Hz\n"), desired, actual));
3169 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3170 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3171 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3172 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3173 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3174 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3175 dialog.set_default_response (RESPONSE_ACCEPT);
3176 dialog.set_position (WIN_POS_CENTER);
3181 switch (dialog.run ()) {
3182 case RESPONSE_ACCEPT:
3191 ARDOUR_UI::disconnect_from_jack ()
3194 if( engine->disconnect_from_jack ()) {
3195 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3199 update_sample_rate (0);
3204 ARDOUR_UI::reconnect_to_jack ()
3207 if (engine->reconnect_to_jack ()) {
3208 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3212 update_sample_rate (0);
3217 ARDOUR_UI::use_config ()
3219 Glib::RefPtr<Action> act;
3221 switch (Config->get_native_file_data_format ()) {
3223 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3226 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3229 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3234 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3235 ract->set_active ();
3238 switch (Config->get_native_file_header_format ()) {
3240 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3243 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3246 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3249 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3252 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3255 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3258 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3263 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3264 ract->set_active ();
3267 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3269 set_transport_controllable_state (*node);
3274 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3276 if (Config->get_primary_clock_delta_edit_cursor()) {
3277 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3279 primary_clock.set (pos, 0, true);
3282 if (Config->get_secondary_clock_delta_edit_cursor()) {
3283 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3285 secondary_clock.set (pos);
3288 if (big_clock_window) {
3289 big_clock.set (pos);
3294 ARDOUR_UI::record_state_changed ()
3296 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3298 if (!session || !big_clock_window) {
3299 /* why bother - the clock isn't visible */
3303 switch (session->record_status()) {
3304 case Session::Recording:
3305 big_clock.set_widget_name ("BigClockRecording");
3308 big_clock.set_widget_name ("BigClockNonRecording");
3314 ARDOUR_UI::first_idle ()
3317 session->allow_auto_play (true);
3321 editor->first_idle();
3324 Keyboard::set_can_save_keybindings (true);
3329 ARDOUR_UI::store_clock_modes ()
3331 XMLNode* node = new XMLNode(X_("ClockModes"));
3333 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3334 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3337 session->add_extra_xml (*node);
3338 session->set_dirty ();
3343 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3344 : Controllable (name), ui (u), type(tp)
3350 ARDOUR_UI::TransportControllable::set_value (float val)
3352 if (type == ShuttleControl) {
3359 fract = -((0.5f - val)/0.5f);
3361 fract = ((val - 0.5f)/0.5f);
3365 ui.set_shuttle_fract (fract);
3370 /* do nothing: these are radio-style actions */
3374 const char *action = 0;
3378 action = X_("Roll");
3381 action = X_("Stop");
3384 action = X_("Goto Start");
3387 action = X_("Goto End");
3390 action = X_("Loop");
3393 action = X_("Play Selection");
3396 action = X_("Record");
3406 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3414 ARDOUR_UI::TransportControllable::get_value (void) const
3433 case ShuttleControl:
3443 ARDOUR_UI::TransportControllable::set_id (const string& str)
3449 ARDOUR_UI::setup_profile ()
3451 if (gdk_screen_width() < 1200) {
3452 Profile->set_small_screen ();
3456 if (getenv ("ARDOUR_SAE")) {
3457 Profile->set_sae ();
3458 Profile->set_single_package ();