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"
100 using namespace ARDOUR;
102 using namespace Gtkmm2ext;
104 using namespace sigc;
106 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
107 UIConfiguration *ARDOUR_UI::ui_config = 0;
109 sigc::signal<void,bool> ARDOUR_UI::Blink;
110 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
111 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
112 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
114 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
116 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
118 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
119 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
120 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
121 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
125 preroll_button (_("pre\nroll")),
126 postroll_button (_("post\nroll")),
130 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
134 roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
135 stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
136 goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
137 goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
138 auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
139 play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
140 rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
141 shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
142 shuttle_controller_binding_proxy (shuttle_controllable),
144 roll_button (roll_controllable),
145 stop_button (stop_controllable),
146 goto_start_button (goto_start_controllable),
147 goto_end_button (goto_end_controllable),
148 auto_loop_button (auto_loop_controllable),
149 play_selection_button (play_selection_controllable),
150 rec_button (rec_controllable),
152 shuttle_units_button (_("% ")),
154 punch_in_button (_("Punch In")),
155 punch_out_button (_("Punch Out")),
156 auto_return_button (_("Auto Return")),
157 auto_play_button (_("Auto Play")),
158 auto_input_button (_("Auto Input")),
159 click_button (_("Click")),
160 time_master_button (_("time\nmaster")),
162 auditioning_alert_button (_("AUDITION")),
163 solo_alert_button (_("SOLO")),
165 error_log_button (_("Errors"))
168 using namespace Gtk::Menu_Helpers;
174 _auto_display_errors = false;
180 if (ARDOUR_COMMAND_LINE::session_name.length()) {
181 /* only show this if we're not going to post the new session dialog */
185 if (theArdourUI == 0) {
189 ui_config = new UIConfiguration();
190 theme_manager = new ThemeManager();
197 _session_is_new = false;
198 big_clock_window = 0;
199 session_selector_window = 0;
200 last_key_press_time = 0;
201 connection_editor = 0;
202 _will_create_new_session_automatically = false;
203 new_session_dialog = 0;
204 add_route_dialog = 0;
208 open_session_selector = 0;
209 have_configure_timeout = false;
210 have_disk_speed_dialog_displayed = false;
211 session_loaded = false;
212 last_speed_displayed = -1.0f;
213 ignore_dual_punch = false;
214 _mixer_on_top = false;
216 roll_button.unset_flags (Gtk::CAN_FOCUS);
217 stop_button.unset_flags (Gtk::CAN_FOCUS);
218 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
219 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
220 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
221 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
222 rec_button.unset_flags (Gtk::CAN_FOCUS);
224 last_configure_time= 0;
226 shuttle_grabbed = false;
228 shuttle_max_speed = 8.0f;
230 shuttle_style_menu = 0;
231 shuttle_unit_menu = 0;
233 // We do not have jack linked in yet so;
235 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
237 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
238 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
240 /* handle dialog requests */
242 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
244 /* handle pending state with a dialog */
246 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
248 /* handle sr mismatch with a dialog */
250 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
252 /* lets get this party started */
255 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
256 throw failed_constructor ();
259 setup_gtk_ardour_enums ();
260 Config->set_current_owner (ConfigVariableBase::Interface);
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::create_engine ()
287 // this gets called every time by new_session()
293 loading_message (_("Starting audio engine"));
296 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
303 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
304 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
305 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
306 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
314 ARDOUR_UI::post_engine ()
316 /* Things to be done once we create the AudioEngine
319 MIDI::Manager::instance()->set_api_data (engine->jack());
322 ActionManager::init ();
325 if (setup_windows ()) {
326 throw failed_constructor ();
329 check_memory_locking();
331 /* this is the first point at which all the keybindings are available */
333 if (ARDOUR_COMMAND_LINE::show_key_actions) {
334 vector<string> names;
335 vector<string> paths;
337 vector<AccelKey> bindings;
339 ActionManager::get_all_actions (names, paths, keys, bindings);
341 vector<string>::iterator n;
342 vector<string>::iterator k;
343 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
344 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
350 blink_timeout_tag = -1;
352 /* the global configuration object is now valid */
356 /* this being a GUI and all, we want peakfiles */
358 AudioFileSource::set_build_peakfiles (true);
359 AudioFileSource::set_build_missing_peakfiles (true);
361 /* set default clock modes */
363 if (Profile->get_sae()) {
364 primary_clock.set_mode (AudioClock::BBT);
365 secondary_clock.set_mode (AudioClock::MinSec);
367 primary_clock.set_mode (AudioClock::SMPTE);
368 secondary_clock.set_mode (AudioClock::BBT);
371 /* start the time-of-day-clock */
374 /* OS X provides an always visible wallclock, so don't be stupid */
375 update_wall_clock ();
376 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
379 update_disk_space ();
381 update_sample_rate (engine->frame_rate());
383 /* now start and maybe save state */
385 if (do_engine_start () == 0) {
386 if (session && _session_is_new) {
387 /* we need to retain initial visual
388 settings for a new session
390 session->save_state ("");
395 ARDOUR_UI::~ARDOUR_UI ()
397 save_ardour_state ();
402 delete add_route_dialog;
403 delete new_session_dialog;
407 ARDOUR_UI::pop_back_splash ()
409 if (Splash::instance()) {
410 // Splash::instance()->pop_back();
411 Splash::instance()->hide ();
416 ARDOUR_UI::configure_timeout ()
418 if (last_configure_time == 0) {
419 /* no configure events yet */
423 /* force a gap of 0.5 seconds since the last configure event
426 if (get_microseconds() - last_configure_time < 500000) {
429 have_configure_timeout = false;
430 save_ardour_state ();
436 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
438 if (have_configure_timeout) {
439 last_configure_time = get_microseconds();
441 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
442 have_configure_timeout = true;
449 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
451 const XMLProperty* prop;
453 if ((prop = node.property ("roll")) != 0) {
454 roll_controllable->set_id (prop->value());
456 if ((prop = node.property ("stop")) != 0) {
457 stop_controllable->set_id (prop->value());
459 if ((prop = node.property ("goto-start")) != 0) {
460 goto_start_controllable->set_id (prop->value());
462 if ((prop = node.property ("goto-end")) != 0) {
463 goto_end_controllable->set_id (prop->value());
465 if ((prop = node.property ("auto-loop")) != 0) {
466 auto_loop_controllable->set_id (prop->value());
468 if ((prop = node.property ("play-selection")) != 0) {
469 play_selection_controllable->set_id (prop->value());
471 if ((prop = node.property ("rec")) != 0) {
472 rec_controllable->set_id (prop->value());
474 if ((prop = node.property ("shuttle")) != 0) {
475 shuttle_controllable->set_id (prop->value());
480 ARDOUR_UI::get_transport_controllable_state ()
482 XMLNode* node = new XMLNode(X_("TransportControllables"));
485 roll_controllable->id().print (buf, sizeof (buf));
486 node->add_property (X_("roll"), buf);
487 stop_controllable->id().print (buf, sizeof (buf));
488 node->add_property (X_("stop"), buf);
489 goto_start_controllable->id().print (buf, sizeof (buf));
490 node->add_property (X_("goto_start"), buf);
491 goto_end_controllable->id().print (buf, sizeof (buf));
492 node->add_property (X_("goto_end"), buf);
493 auto_loop_controllable->id().print (buf, sizeof (buf));
494 node->add_property (X_("auto_loop"), buf);
495 play_selection_controllable->id().print (buf, sizeof (buf));
496 node->add_property (X_("play_selection"), buf);
497 rec_controllable->id().print (buf, sizeof (buf));
498 node->add_property (X_("rec"), buf);
499 shuttle_controllable->id().print (buf, sizeof (buf));
500 node->add_property (X_("shuttle"), buf);
506 ARDOUR_UI::save_ardour_state ()
508 if (!keyboard || !mixer || !editor) {
512 /* XXX this is all a bit dubious. add_extra_xml() uses
513 a different lifetime model from add_instant_xml().
516 XMLNode* node = new XMLNode (keyboard->get_state());
517 Config->add_extra_xml (*node);
518 Config->add_extra_xml (get_transport_controllable_state());
519 if (new_session_dialog && new_session_dialog->engine_control.was_used()) {
520 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
522 Config->save_state();
523 ui_config->save_state ();
525 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
526 XMLNode mnode(mixer->get_state());
529 session->add_instant_xml (enode);
530 session->add_instant_xml (mnode);
532 Config->add_instant_xml (enode);
533 Config->add_instant_xml (mnode);
536 Keyboard::save_keybindings ();
540 ARDOUR_UI::autosave_session ()
542 if (g_main_depth() > 1) {
543 /* inside a recursive main loop,
544 give up because we may not be able to
550 if (!Config->get_periodic_safety_backups()) {
555 session->maybe_write_autosave();
562 ARDOUR_UI::update_autosave ()
564 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
566 if (session->dirty()) {
567 if (_autosave_connection.connected()) {
568 _autosave_connection.disconnect();
571 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
572 Config->get_periodic_safety_backup_interval() * 1000);
575 if (_autosave_connection.connected()) {
576 _autosave_connection.disconnect();
582 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
586 title = _("Ardour could not start JACK");
588 title = _("Ardour could not connect to JACK.");
591 MessageDialog win (title,
597 win.set_secondary_text(_("There are several possible reasons:\n\
599 1) You requested audio parameters that are not supported..\n\
600 2) JACK is running as another user.\n\
602 Please consider the possibilities, and perhaps try different parameters."));
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) JACK is not running.\n\
607 2) JACK is running as another user, perhaps root.\n\
608 3) There is already another client called \"ardour\".\n\
610 Please consider the possibilities, and perhaps (re)start JACK."));
614 win.set_transient_for (*toplevel);
618 win.add_button (Stock::OK, RESPONSE_CLOSE);
620 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
623 win.set_default_response (RESPONSE_CLOSE);
626 win.set_position (Gtk::WIN_POS_CENTER);
629 /* we just don't care about the result, but we want to block */
635 ARDOUR_UI::startup ()
639 new_session_dialog = new NewSessionDialog();
641 bool backend_audio_is_running = EngineControl::engine_running();
642 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
645 new_session_dialog->engine_control.set_state (*audio_setup);
648 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
652 BootMessage (_("Ardour is ready for use"));
657 ARDOUR_UI::no_memory_warning ()
659 XMLNode node (X_("no-memory-warning"));
660 Config->add_instant_xml (node);
664 ARDOUR_UI::check_memory_locking ()
667 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
671 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
673 if (engine->is_realtime() && memory_warning_node == 0) {
675 struct rlimit limits;
677 long pages, page_size;
679 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
682 ram = (int64_t) pages * (int64_t) page_size;
685 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
689 if (limits.rlim_cur != RLIM_INFINITY) {
691 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
694 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
695 "This might cause Ardour to run out of memory before your system "
696 "runs out of memory. \n\n"
697 "You can view the memory limit with 'ulimit -l', "
698 "and it is normally controlled by /etc/security/limits.conf"));
700 VBox* vbox = msg.get_vbox();
702 CheckButton cb (_("Do not show this window again"));
704 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
706 hbox.pack_start (cb, true, false);
707 vbox->pack_start (hbox);
714 editor->ensure_float (msg);
728 if (session->transport_rolling()) {
729 session->request_stop ();
733 if (session->dirty()) {
734 switch (ask_about_saving_session(_("quit"))) {
739 /* use the default name */
740 if (save_state_canfail ("")) {
741 /* failed - don't quit */
742 MessageDialog msg (*editor,
744 Ardour was unable to save your session.\n\n\
745 If you still wish to quit, please use the\n\n\
746 \"Just quit\" option."));
757 session->set_deletion_in_progress ();
760 ArdourDialog::close_all_dialogs ();
762 save_ardour_state ();
767 ARDOUR_UI::ask_about_saving_session (const string & what)
769 ArdourDialog window (_("ardour: save session?"));
770 Gtk::HBox dhbox; // the hbox for the image and text
771 Gtk::Label prompt_label;
772 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
776 msg = string_compose(_("Don't %1"), what);
777 window.add_button (msg, RESPONSE_REJECT);
778 msg = string_compose(_("Just %1"), what);
779 window.add_button (msg, RESPONSE_APPLY);
780 msg = string_compose(_("Save and %1"), what);
781 window.add_button (msg, RESPONSE_ACCEPT);
783 window.set_default_response (RESPONSE_ACCEPT);
785 Gtk::Button noquit_button (msg);
786 noquit_button.set_name ("EditorGTKButton");
791 if (session->snap_name() == session->name()) {
794 type = _("snapshot");
796 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?"),
797 type, session->snap_name());
799 prompt_label.set_text (prompt);
800 prompt_label.set_name (X_("PrompterLabel"));
801 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
803 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
804 dhbox.set_homogeneous (false);
805 dhbox.pack_start (*dimage, false, false, 5);
806 dhbox.pack_start (prompt_label, true, false, 5);
807 window.get_vbox()->pack_start (dhbox);
809 window.set_name (_("Prompter"));
810 window.set_position (Gtk::WIN_POS_MOUSE);
811 window.set_modal (true);
812 window.set_resizable (false);
818 window.set_keep_above (true);
821 ResponseType r = (ResponseType) window.run();
826 case RESPONSE_ACCEPT: // save and get out of here
828 case RESPONSE_APPLY: // get out of here
838 ARDOUR_UI::every_second ()
841 update_buffer_load ();
842 update_disk_space ();
847 ARDOUR_UI::every_point_one_seconds ()
849 update_speed_display ();
850 RapidScreenUpdate(); /* EMIT_SIGNAL */
855 ARDOUR_UI::every_point_zero_one_seconds ()
857 // august 2007: actual update frequency: 40Hz, not 100Hz
859 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
864 ARDOUR_UI::update_sample_rate (nframes_t ignored)
868 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
870 if (!engine->connected()) {
872 snprintf (buf, sizeof (buf), _("disconnected"));
876 nframes_t rate = engine->frame_rate();
878 if (fmod (rate, 1000.0) != 0.0) {
879 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
880 (float) rate/1000.0f,
881 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
883 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
889 sample_rate_label.set_text (buf);
893 ARDOUR_UI::update_cpu_load ()
896 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
897 cpu_load_label.set_text (buf);
901 ARDOUR_UI::update_buffer_load ()
906 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
907 session->playback_load(), session->capture_load());
908 buffer_load_label.set_text (buf);
910 buffer_load_label.set_text ("");
915 ARDOUR_UI::count_recenabled_streams (Route& route)
917 Track* track = dynamic_cast<Track*>(&route);
918 if (track && track->diskstream()->record_enabled()) {
919 rec_enabled_streams += track->n_inputs().n_total();
924 ARDOUR_UI::update_disk_space()
930 nframes_t frames = session->available_capture_duration();
932 nframes_t fr = session->frame_rate();
934 if (frames == max_frames) {
935 strcpy (buf, _("Disk: 24hrs+"));
937 rec_enabled_streams = 0;
938 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
940 if (rec_enabled_streams) {
941 frames /= rec_enabled_streams;
948 hrs = frames / (fr * 3600);
949 frames -= hrs * fr * 3600;
950 mins = frames / (fr * 60);
951 frames -= mins * fr * 60;
954 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
957 disk_space_label.set_text (buf);
959 // An attempt to make the disk space label flash red when space has run out.
961 if (frames < fr * 60 * 5) {
962 /* disk_space_box.style ("disk_space_label_empty"); */
964 /* disk_space_box.style ("disk_space_label"); */
970 ARDOUR_UI::update_wall_clock ()
977 tm_now = localtime (&now);
979 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
980 wall_clock_label.set_text (buf);
986 ARDOUR_UI::session_menu (GdkEventButton *ev)
988 session_popup_menu->popup (0, 0);
993 ARDOUR_UI::redisplay_recent_sessions ()
995 std::vector<sys::path> session_directories;
996 RecentSessionsSorter cmp;
998 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
999 recent_session_model->clear ();
1001 ARDOUR::RecentSessions rs;
1002 ARDOUR::read_recent_sessions (rs);
1005 recent_session_display.set_model (recent_session_model);
1009 // sort them alphabetically
1010 sort (rs.begin(), rs.end(), cmp);
1012 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1013 session_directories.push_back ((*i).second);
1016 for (vector<sys::path>::const_iterator i = session_directories.begin();
1017 i != session_directories.end(); ++i)
1019 std::vector<sys::path> state_file_paths;
1021 // now get available states for this session
1023 get_state_files_in_directory (*i, state_file_paths);
1025 vector<string*>* states;
1026 vector<const gchar*> item;
1027 string fullpath = (*i).to_string();
1029 /* remove any trailing / */
1031 if (fullpath[fullpath.length()-1] == '/') {
1032 fullpath = fullpath.substr (0, fullpath.length()-1);
1035 /* check whether session still exists */
1036 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1037 /* session doesn't exist */
1038 cerr << "skipping non-existent session " << fullpath << endl;
1042 /* now get available states for this session */
1044 if ((states = Session::possible_states (fullpath)) == 0) {
1045 /* no state file? */
1049 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1051 Gtk::TreeModel::Row row = *(recent_session_model->append());
1053 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1054 row[recent_session_columns.fullpath] = fullpath;
1056 if (state_file_names.size() > 1) {
1060 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1061 i2 != state_file_names.end(); ++i2)
1064 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1066 child_row[recent_session_columns.visible_name] = *i2;
1067 child_row[recent_session_columns.fullpath] = fullpath;
1072 recent_session_display.set_model (recent_session_model);
1076 ARDOUR_UI::build_session_selector ()
1078 session_selector_window = new ArdourDialog ("session selector");
1080 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1082 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1083 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1084 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1085 recent_session_model = TreeStore::create (recent_session_columns);
1086 recent_session_display.set_model (recent_session_model);
1087 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1088 recent_session_display.set_headers_visible (false);
1089 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1090 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1092 scroller->add (recent_session_display);
1093 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1095 session_selector_window->set_name ("SessionSelectorWindow");
1096 session_selector_window->set_size_request (200, 400);
1097 session_selector_window->get_vbox()->pack_start (*scroller);
1099 recent_session_display.show();
1101 //session_selector_window->get_vbox()->show();
1105 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1107 session_selector_window->response (RESPONSE_ACCEPT);
1111 ARDOUR_UI::open_recent_session ()
1113 bool can_return = (session != 0);
1115 if (session_selector_window == 0) {
1116 build_session_selector ();
1119 redisplay_recent_sessions ();
1123 session_selector_window->set_position (WIN_POS_MOUSE);
1125 ResponseType r = (ResponseType) session_selector_window->run ();
1128 case RESPONSE_ACCEPT:
1132 session_selector_window->hide();
1139 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1143 session_selector_window->hide();
1145 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1147 if (i == recent_session_model->children().end()) {
1151 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1152 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1154 _session_is_new = false;
1156 if (load_session (path, state) == 0) {
1165 ARDOUR_UI::check_audioengine ()
1168 if (!engine->connected()) {
1169 MessageDialog msg (_("Ardour is not connected to JACK\n"
1170 "You cannot open or close sessions in this condition"));
1182 ARDOUR_UI::open_session ()
1184 if (!check_audioengine()) {
1189 /* popup selector window */
1191 if (open_session_selector == 0) {
1193 /* ardour sessions are folders */
1195 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1196 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1197 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1198 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1200 FileFilter session_filter;
1201 session_filter.add_pattern ("*.ardour");
1202 session_filter.set_name (_("Ardour sessions"));
1203 open_session_selector->add_filter (session_filter);
1204 open_session_selector->set_filter (session_filter);
1207 int response = open_session_selector->run();
1208 open_session_selector->hide ();
1211 case RESPONSE_ACCEPT:
1214 open_session_selector->hide();
1218 open_session_selector->hide();
1219 string session_path = open_session_selector->get_filename();
1223 if (session_path.length() > 0) {
1224 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1225 _session_is_new = isnew;
1226 load_session (path, name);
1233 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1235 list<boost::shared_ptr<MidiTrack> > tracks;
1238 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1245 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1247 if (tracks.size() != how_many) {
1248 if (how_many == 1) {
1249 error << _("could not create a new midi track") << endmsg;
1251 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1255 if ((route = session->new_midi_route ()) == 0) {
1256 error << _("could not create new midi bus") << endmsg;
1262 MessageDialog msg (*editor,
1263 _("There are insufficient JACK ports available\n\
1264 to create a new track or bus.\n\
1265 You should save Ardour, exit and\n\
1266 restart JACK with more ports."));
1273 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1275 list<boost::shared_ptr<AudioTrack> > tracks;
1276 Session::RouteList routes;
1279 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1285 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1287 if (tracks.size() != how_many) {
1288 if (how_many == 1) {
1289 error << _("could not create a new audio track") << endmsg;
1291 error << string_compose (_("could only create %1 of %2 new audio %3"),
1292 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1298 routes = session->new_audio_route (input_channels, output_channels, how_many);
1300 if (routes.size() != how_many) {
1301 if (how_many == 1) {
1302 error << _("could not create a new audio track") << endmsg;
1304 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1310 if (need_control_room_outs) {
1316 route->set_stereo_control_outs (control_lr_channels);
1317 route->control_outs()->set_stereo_pan (pans, this);
1319 #endif /* CONTROLOUTS */
1323 MessageDialog msg (*editor,
1324 _("There are insufficient JACK ports available\n\
1325 to create a new track or bus.\n\
1326 You should save Ardour, exit and\n\
1327 restart JACK with more ports."));
1334 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1336 nframes_t _preroll = 0;
1339 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1340 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1342 if (new_position > _preroll) {
1343 new_position -= _preroll;
1348 session->request_locate (new_position);
1353 ARDOUR_UI::transport_goto_start ()
1356 session->goto_start();
1359 /* force displayed area in editor to start no matter
1360 what "follow playhead" setting is.
1364 editor->reset_x_origin (session->current_start_frame());
1370 ARDOUR_UI::transport_goto_zero ()
1373 session->request_locate (0);
1376 /* force displayed area in editor to start no matter
1377 what "follow playhead" setting is.
1381 editor->reset_x_origin (0);
1387 ARDOUR_UI::transport_goto_wallclock ()
1389 if (session && editor) {
1396 localtime_r (&now, &tmnow);
1398 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1399 frames += tmnow.tm_min * (60 * session->frame_rate());
1400 frames += tmnow.tm_sec * session->frame_rate();
1402 session->request_locate (frames);
1404 /* force displayed area in editor to start no matter
1405 what "follow playhead" setting is.
1409 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1415 ARDOUR_UI::transport_goto_end ()
1418 nframes_t frame = session->current_end_frame();
1419 session->request_locate (frame);
1421 /* force displayed area in editor to start no matter
1422 what "follow playhead" setting is.
1426 editor->reset_x_origin (frame);
1432 ARDOUR_UI::transport_stop ()
1438 if (session->is_auditioning()) {
1439 session->cancel_audition ();
1443 if (session->get_play_loop ()) {
1444 session->request_play_loop (false);
1447 session->request_stop ();
1451 ARDOUR_UI::transport_stop_and_forget_capture ()
1454 session->request_stop (true);
1459 ARDOUR_UI::remove_last_capture()
1462 editor->remove_last_capture();
1467 ARDOUR_UI::transport_record (bool roll)
1471 switch (session->record_status()) {
1472 case Session::Disabled:
1473 if (session->ntracks() == 0) {
1474 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1478 session->maybe_enable_record ();
1483 case Session::Recording:
1485 session->request_stop();
1487 session->disable_record (false, true);
1491 case Session::Enabled:
1492 session->disable_record (false, true);
1495 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1499 ARDOUR_UI::transport_roll ()
1507 rolling = session->transport_rolling ();
1509 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1511 if (session->get_play_loop()) {
1512 session->request_play_loop (false);
1513 auto_loop_button.set_visual_state (1);
1514 roll_button.set_visual_state (1);
1515 } else if (session->get_play_range ()) {
1516 session->request_play_range (false);
1517 play_selection_button.set_visual_state (0);
1518 } else if (rolling) {
1519 session->request_locate (session->last_transport_start(), true);
1522 session->request_transport_speed (1.0f);
1526 ARDOUR_UI::transport_loop()
1529 if (session->get_play_loop()) {
1530 if (session->transport_rolling()) {
1531 Location * looploc = session->locations()->auto_loop_location();
1533 session->request_locate (looploc->start(), true);
1538 session->request_play_loop (true);
1544 ARDOUR_UI::transport_play_selection ()
1550 if (!session->get_play_range()) {
1551 session->request_stop ();
1554 editor->play_selection ();
1558 ARDOUR_UI::transport_rewind (int option)
1560 float current_transport_speed;
1563 current_transport_speed = session->transport_speed();
1565 if (current_transport_speed >= 0.0f) {
1568 session->request_transport_speed (-1.0f);
1571 session->request_transport_speed (-4.0f);
1574 session->request_transport_speed (-0.5f);
1579 session->request_transport_speed (current_transport_speed * 1.5f);
1585 ARDOUR_UI::transport_forward (int option)
1587 float current_transport_speed;
1590 current_transport_speed = session->transport_speed();
1592 if (current_transport_speed <= 0.0f) {
1595 session->request_transport_speed (1.0f);
1598 session->request_transport_speed (4.0f);
1601 session->request_transport_speed (0.5f);
1606 session->request_transport_speed (current_transport_speed * 1.5f);
1612 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1618 boost::shared_ptr<Route> r;
1620 if ((r = session->route_by_remote_id (dstream)) != 0) {
1624 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1625 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1634 ARDOUR_UI::queue_transport_change ()
1636 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1640 ARDOUR_UI::map_transport_state ()
1642 float sp = session->transport_speed();
1645 transport_rolling ();
1646 } else if (sp < 0.0f) {
1647 transport_rewinding ();
1648 } else if (sp > 0.0f) {
1649 transport_forwarding ();
1651 transport_stopped ();
1656 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1658 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1659 (int) adj.get_value()].c_str());
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);
2262 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2264 bool existing_session = false;
2265 Glib::ustring session_name;
2266 Glib::ustring session_path;
2267 Glib::ustring template_name;
2271 response = Gtk::RESPONSE_NONE;
2273 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2275 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2277 /* don't ever reuse this */
2279 ARDOUR_COMMAND_LINE::session_name = string();
2281 if (existing_session && backend_audio_is_running) {
2283 /* just load the thing already */
2285 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2290 /* make the NSD use whatever information we have */
2292 new_session_dialog->set_session_name (session_name);
2293 new_session_dialog->set_session_folder (session_path);
2296 /* loading failed, or we need the NSD for something */
2298 new_session_dialog->set_modal (false);
2299 new_session_dialog->set_position (WIN_POS_CENTER);
2300 new_session_dialog->set_current_page (0);
2301 new_session_dialog->set_existing_session (existing_session);
2302 new_session_dialog->reset_recent();
2305 new_session_dialog->set_have_engine (backend_audio_is_running);
2306 new_session_dialog->present ();
2307 end_loading_messages ();
2308 response = new_session_dialog->run ();
2310 _session_is_new = false;
2312 /* handle possible negative responses */
2316 /* sent by idle_load, meaning restart the whole process again */
2317 new_session_dialog->hide();
2318 new_session_dialog->reset();
2322 case Gtk::RESPONSE_CANCEL:
2323 case Gtk::RESPONSE_DELETE_EVENT:
2325 if (engine && engine->running()) {
2326 engine->stop (true);
2330 new_session_dialog->hide ();
2333 case Gtk::RESPONSE_NONE:
2334 /* "Clear" was pressed */
2338 fontconfig_dialog();
2340 if (!backend_audio_is_running) {
2341 int ret = new_session_dialog->engine_control.setup_engine ();
2344 } else if (ret > 0) {
2345 response = Gtk::RESPONSE_REJECT;
2350 if (create_engine ()) {
2352 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2355 new_session_dialog->set_existing_session (false);
2356 new_session_dialog->set_current_page (2);
2358 response = Gtk::RESPONSE_NONE;
2362 backend_audio_is_running = true;
2364 if (response == Gtk::RESPONSE_OK) {
2366 session_name = new_session_dialog->session_name();
2368 if (session_name.empty()) {
2369 response = Gtk::RESPONSE_NONE;
2373 /* if the user mistakenly typed path information into the session filename entry,
2374 convert what they typed into a path & a name
2377 if (session_name[0] == '/' ||
2378 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2379 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2381 session_path = Glib::path_get_dirname (session_name);
2382 session_name = Glib::path_get_basename (session_name);
2386 session_path = new_session_dialog->session_folder();
2389 template_name = Glib::ustring();
2390 switch (new_session_dialog->which_page()) {
2392 case NewSessionDialog::OpenPage:
2393 case NewSessionDialog::EnginePage:
2397 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2399 should_be_new = true;
2401 //XXX This is needed because session constructor wants a
2402 //non-existant path. hopefully this will be fixed at some point.
2404 session_path = Glib::build_filename (session_path, session_name);
2406 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2408 if (ask_about_loading_existing_session (session_path)) {
2411 response = RESPONSE_NONE;
2416 _session_is_new = true;
2418 if (new_session_dialog->use_session_template()) {
2420 template_name = new_session_dialog->session_template_name();
2424 if (build_session_from_nsd (session_path, session_name)) {
2425 response = RESPONSE_NONE;
2437 new_session_dialog->hide ();
2439 if (load_session (session_path, session_name, template_name)) {
2441 response = Gtk::RESPONSE_NONE;
2445 if (response == Gtk::RESPONSE_NONE) {
2446 new_session_dialog->set_existing_session (false);
2447 new_session_dialog->reset ();
2451 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2455 new_session_dialog->hide();
2456 new_session_dialog->reset();
2457 goto_editor_window ();
2462 ARDOUR_UI::close_session()
2464 if (!check_audioengine()) {
2468 unload_session (true);
2470 get_session_parameters (true, false);
2474 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2476 Session *new_session;
2480 session_loaded = false;
2482 if (!check_audioengine()) {
2486 unload_status = unload_session ();
2488 if (unload_status < 0) {
2490 } else if (unload_status > 0) {
2495 /* if it already exists, we must have write access */
2497 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2498 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2499 "This prevents the session from being loaded."));
2505 loading_message (_("Please wait while Ardour loads your session"));
2508 new_session = new Session (*engine, path, snap_name, mix_template);
2511 /* this one is special */
2513 catch (AudioEngine::PortRegistrationFailure& err) {
2515 MessageDialog msg (err.what(),
2518 Gtk::BUTTONS_CLOSE);
2520 msg.set_title (_("Port Registration Error"));
2521 msg.set_secondary_text (_("Click the Close button to try again."));
2522 msg.set_position (Gtk::WIN_POS_CENTER);
2526 int response = msg.run ();
2531 case RESPONSE_CANCEL:
2541 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2544 Gtk::BUTTONS_CLOSE);
2546 msg.set_title (_("Loading Error"));
2547 msg.set_secondary_text (_("Click the Close button to try again."));
2548 msg.set_position (Gtk::WIN_POS_CENTER);
2552 int response = msg.run ();
2557 case RESPONSE_CANCEL:
2565 connect_to_session (new_session);
2567 Config->set_current_owner (ConfigVariableBase::Interface);
2569 session_loaded = true;
2571 goto_editor_window ();
2574 session->set_clean ();
2585 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2586 uint32_t control_channels,
2587 uint32_t master_channels,
2588 AutoConnectOption input_connect,
2589 AutoConnectOption output_connect,
2592 nframes_t initial_length)
2594 Session *new_session;
2597 if (!check_audioengine()) {
2601 session_loaded = false;
2603 x = unload_session ();
2611 _session_is_new = true;
2614 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2615 control_channels, master_channels, nphysin, nphysout, initial_length);
2620 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2626 connect_to_session (new_session);
2628 session_loaded = true;
2630 new_session->save_state(new_session->name());
2639 editor->show_window ();
2650 ARDOUR_UI::show_about ()
2654 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2661 ARDOUR_UI::hide_about ()
2664 about->get_window()->set_cursor ();
2670 ARDOUR_UI::about_signal_response(int response)
2676 ARDOUR_UI::show_splash ()
2680 splash = new Splash;
2688 splash->queue_draw ();
2689 splash->get_window()->process_updates (true);
2694 ARDOUR_UI::hide_splash ()
2702 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2706 removed = rep.paths.size();
2709 MessageDialog msgd (*editor,
2710 _("No audio files were ready for cleanup"),
2713 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2714 msgd.set_secondary_text (_("If this seems suprising, \n\
2715 check for any existing snapshots.\n\
2716 These may still include regions that\n\
2717 require some unused files to continue to exist."));
2723 ArdourDialog results (_("ardour: cleanup"), true, false);
2725 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2726 CleanupResultsModelColumns() {
2730 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2731 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2735 CleanupResultsModelColumns results_columns;
2736 Glib::RefPtr<Gtk::ListStore> results_model;
2737 Gtk::TreeView results_display;
2739 results_model = ListStore::create (results_columns);
2740 results_display.set_model (results_model);
2741 results_display.append_column (list_title, results_columns.visible_name);
2743 results_display.set_name ("CleanupResultsList");
2744 results_display.set_headers_visible (true);
2745 results_display.set_headers_clickable (false);
2746 results_display.set_reorderable (false);
2748 Gtk::ScrolledWindow list_scroller;
2751 Gtk::HBox dhbox; // the hbox for the image and text
2752 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2753 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2755 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2757 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2759 if (rep.space < 1048576.0f) {
2761 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2763 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2767 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2769 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2773 dhbox.pack_start (*dimage, true, false, 5);
2774 dhbox.pack_start (txt, true, false, 5);
2776 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2777 TreeModel::Row row = *(results_model->append());
2778 row[results_columns.visible_name] = *i;
2779 row[results_columns.fullpath] = *i;
2782 list_scroller.add (results_display);
2783 list_scroller.set_size_request (-1, 150);
2784 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2786 dvbox.pack_start (dhbox, true, false, 5);
2787 dvbox.pack_start (list_scroller, true, false, 5);
2788 ddhbox.pack_start (dvbox, true, false, 5);
2790 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2791 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2792 results.set_default_response (RESPONSE_CLOSE);
2793 results.set_position (Gtk::WIN_POS_MOUSE);
2795 results_display.show();
2796 list_scroller.show();
2803 //results.get_vbox()->show();
2804 results.set_resizable (false);
2811 ARDOUR_UI::cleanup ()
2814 /* shouldn't happen: menu item is insensitive */
2819 MessageDialog checker (_("Are you sure you want to cleanup?"),
2821 Gtk::MESSAGE_QUESTION,
2822 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2824 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2825 ALL undo/redo information will be lost if you cleanup.\n\
2826 After cleanup, unused audio files will be moved to a \
2827 \"dead sounds\" location."));
2829 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2830 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2831 checker.set_default_response (RESPONSE_CANCEL);
2833 checker.set_name (_("CleanupDialog"));
2834 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2835 checker.set_position (Gtk::WIN_POS_MOUSE);
2837 switch (checker.run()) {
2838 case RESPONSE_ACCEPT:
2844 Session::cleanup_report rep;
2846 editor->prepare_for_cleanup ();
2848 /* do not allow flush until a session is reloaded */
2850 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2852 act->set_sensitive (false);
2855 if (session->cleanup_sources (rep)) {
2856 editor->finish_cleanup ();
2860 editor->finish_cleanup ();
2863 display_cleanup_results (rep,
2866 The following %1 %2 not in use and \n\
2867 have been moved to:\n\
2869 Flushing the wastebasket will \n\
2870 release an additional\n\
2871 %4 %5bytes of disk space.\n"
2877 ARDOUR_UI::flush_trash ()
2880 /* shouldn't happen: menu item is insensitive */
2884 Session::cleanup_report rep;
2886 if (session->cleanup_trash_sources (rep)) {
2890 display_cleanup_results (rep,
2892 _("The following %1 %2 deleted from\n\
2894 releasing %4 %5bytes of disk space"));
2898 ARDOUR_UI::add_route (Gtk::Window* float_window)
2906 if (add_route_dialog == 0) {
2907 add_route_dialog = new AddRouteDialog;
2909 add_route_dialog->set_transient_for (*float_window);
2913 if (add_route_dialog->is_visible()) {
2914 /* we're already doing this */
2918 ResponseType r = (ResponseType) add_route_dialog->run ();
2920 add_route_dialog->hide();
2923 case RESPONSE_ACCEPT:
2930 if ((count = add_route_dialog->count()) <= 0) {
2934 uint32_t input_chan = add_route_dialog->channels ();
2935 uint32_t output_chan;
2936 string name_template = add_route_dialog->name_template ();
2937 bool track = add_route_dialog->track ();
2939 AutoConnectOption oac = Config->get_output_auto_connect();
2941 if (oac & AutoConnectMaster) {
2942 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2944 output_chan = input_chan;
2947 /* XXX do something with name template */
2949 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2951 session_add_midi_track(count);
2953 MessageDialog msg (*editor,
2954 _("Sorry, MIDI Busses are not supported at this time."));
2956 //session_add_midi_bus();
2960 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2962 session_add_audio_bus (input_chan, output_chan, count);
2968 ARDOUR_UI::mixer_settings () const
2973 node = session->instant_xml(X_("Mixer"));
2975 node = Config->instant_xml(X_("Mixer"));
2979 node = new XMLNode (X_("Mixer"));
2986 ARDOUR_UI::editor_settings () const
2991 node = session->instant_xml(X_("Editor"));
2993 node = Config->instant_xml(X_("Editor"));
2997 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2998 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3003 node = new XMLNode (X_("Editor"));
3010 ARDOUR_UI::keyboard_settings () const
3014 node = Config->extra_xml(X_("Keyboard"));
3017 node = new XMLNode (X_("Keyboard"));
3023 ARDOUR_UI::create_xrun_marker(nframes_t where)
3025 editor->mouse_add_new_marker (where, false, true);
3029 ARDOUR_UI::halt_on_xrun_message ()
3031 MessageDialog msg (*editor,
3032 _("Recording was stopped because your system could not keep up."));
3037 ARDOUR_UI::xrun_handler(nframes_t where)
3043 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3045 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3046 create_xrun_marker(where);
3049 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3050 halt_on_xrun_message ();
3055 ARDOUR_UI::disk_overrun_handler ()
3057 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3059 if (!have_disk_speed_dialog_displayed) {
3060 have_disk_speed_dialog_displayed = true;
3061 MessageDialog* msg = new MessageDialog (*editor, _("\
3062 The disk system on your computer\n\
3063 was not able to keep up with Ardour.\n\
3065 Specifically, it failed to write data to disk\n\
3066 quickly enough to keep up with recording.\n"));
3067 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3073 ARDOUR_UI::disk_underrun_handler ()
3075 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3077 if (!have_disk_speed_dialog_displayed) {
3078 have_disk_speed_dialog_displayed = true;
3079 MessageDialog* msg = new MessageDialog (*editor,
3080 _("The disk system on your computer\n\
3081 was not able to keep up with Ardour.\n\
3083 Specifically, it failed to read data from disk\n\
3084 quickly enough to keep up with playback.\n"));
3085 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3091 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3093 have_disk_speed_dialog_displayed = false;
3098 ARDOUR_UI::session_dialog (std::string msg)
3100 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3105 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3107 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3116 ARDOUR_UI::pending_state_dialog ()
3118 HBox* hbox = new HBox();
3119 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3120 ArdourDialog dialog (_("Crash Recovery"), true);
3122 This session appears to have been in\n\
3123 middle of recording when ardour or\n\
3124 the computer was shutdown.\n\
3126 Ardour can recover any captured audio for\n\
3127 you, or it can ignore it. Please decide\n\
3128 what you would like to do.\n"));
3129 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3130 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3131 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3132 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3133 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3134 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3135 dialog.set_default_response (RESPONSE_ACCEPT);
3136 dialog.set_position (WIN_POS_CENTER);
3141 switch (dialog.run ()) {
3142 case RESPONSE_ACCEPT:
3150 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3152 HBox* hbox = new HBox();
3153 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3154 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3155 Label message (string_compose (_("\
3156 This session was created with a sample rate of %1 Hz\n\
3158 The audioengine is currently running at %2 Hz\n"), desired, actual));
3160 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3161 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3162 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3163 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3164 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3165 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3166 dialog.set_default_response (RESPONSE_ACCEPT);
3167 dialog.set_position (WIN_POS_CENTER);
3172 switch (dialog.run ()) {
3173 case RESPONSE_ACCEPT:
3182 ARDOUR_UI::disconnect_from_jack ()
3185 if( engine->disconnect_from_jack ()) {
3186 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3190 update_sample_rate (0);
3195 ARDOUR_UI::reconnect_to_jack ()
3198 if (engine->reconnect_to_jack ()) {
3199 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3203 update_sample_rate (0);
3208 ARDOUR_UI::use_config ()
3210 Glib::RefPtr<Action> act;
3212 switch (Config->get_native_file_data_format ()) {
3214 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3217 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3220 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3225 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3226 ract->set_active ();
3229 switch (Config->get_native_file_header_format ()) {
3231 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3234 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3237 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3240 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3243 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3246 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3249 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3254 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3255 ract->set_active ();
3258 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3260 set_transport_controllable_state (*node);
3265 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3267 if (Config->get_primary_clock_delta_edit_cursor()) {
3268 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3270 primary_clock.set (pos, 0, true);
3273 if (Config->get_secondary_clock_delta_edit_cursor()) {
3274 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3276 secondary_clock.set (pos);
3279 if (big_clock_window) {
3280 big_clock.set (pos);
3285 ARDOUR_UI::record_state_changed ()
3287 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3289 if (!session || !big_clock_window) {
3290 /* why bother - the clock isn't visible */
3294 switch (session->record_status()) {
3295 case Session::Recording:
3296 big_clock.set_widget_name ("BigClockRecording");
3299 big_clock.set_widget_name ("BigClockNonRecording");
3305 ARDOUR_UI::first_idle ()
3308 session->allow_auto_play (true);
3312 editor->first_idle();
3315 Keyboard::set_can_save_keybindings (true);
3320 ARDOUR_UI::store_clock_modes ()
3322 XMLNode* node = new XMLNode(X_("ClockModes"));
3324 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3325 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3328 session->add_extra_xml (*node);
3329 session->set_dirty ();
3334 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3335 : Controllable (name), ui (u), type(tp)
3341 ARDOUR_UI::TransportControllable::set_value (float val)
3343 if (type == ShuttleControl) {
3350 fract = -((0.5f - val)/0.5f);
3352 fract = ((val - 0.5f)/0.5f);
3356 ui.set_shuttle_fract (fract);
3361 /* do nothing: these are radio-style actions */
3365 const char *action = 0;
3369 action = X_("Roll");
3372 action = X_("Stop");
3375 action = X_("Goto Start");
3378 action = X_("Goto End");
3381 action = X_("Loop");
3384 action = X_("Play Selection");
3387 action = X_("Record");
3397 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3405 ARDOUR_UI::TransportControllable::get_value (void) const
3424 case ShuttleControl:
3434 ARDOUR_UI::TransportControllable::set_id (const string& str)
3440 ARDOUR_UI::setup_profile ()
3442 if (gdk_screen_width() < 1200) {
3443 Profile->set_small_screen ();
3447 if (getenv ("ARDOUR_SAE")) {
3448 Profile->set_sae ();
3449 Profile->set_single_package ();