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;
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);
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 uint32_t input_chan = add_route_dialog->channels ();
2937 uint32_t output_chan;
2938 string name_template = add_route_dialog->name_template ();
2939 bool track = add_route_dialog->track ();
2941 AutoConnectOption oac = Config->get_output_auto_connect();
2943 if (oac & AutoConnectMaster) {
2944 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2946 output_chan = input_chan;
2949 /* XXX do something with name template */
2951 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2953 session_add_midi_track(count);
2955 MessageDialog msg (*editor,
2956 _("Sorry, MIDI Busses are not supported at this time."));
2958 //session_add_midi_bus();
2962 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2964 session_add_audio_bus (input_chan, output_chan, count);
2970 ARDOUR_UI::mixer_settings () const
2975 node = session->instant_xml(X_("Mixer"));
2977 node = Config->instant_xml(X_("Mixer"));
2981 node = new XMLNode (X_("Mixer"));
2988 ARDOUR_UI::editor_settings () const
2993 node = session->instant_xml(X_("Editor"));
2995 node = Config->instant_xml(X_("Editor"));
2999 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3000 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3005 node = new XMLNode (X_("Editor"));
3012 ARDOUR_UI::keyboard_settings () const
3016 node = Config->extra_xml(X_("Keyboard"));
3019 node = new XMLNode (X_("Keyboard"));
3025 ARDOUR_UI::create_xrun_marker(nframes_t where)
3027 editor->mouse_add_new_marker (where, false, true);
3031 ARDOUR_UI::halt_on_xrun_message ()
3033 MessageDialog msg (*editor,
3034 _("Recording was stopped because your system could not keep up."));
3039 ARDOUR_UI::xrun_handler(nframes_t where)
3045 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3047 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3048 create_xrun_marker(where);
3051 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3052 halt_on_xrun_message ();
3057 ARDOUR_UI::disk_overrun_handler ()
3059 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3061 if (!have_disk_speed_dialog_displayed) {
3062 have_disk_speed_dialog_displayed = true;
3063 MessageDialog* msg = new MessageDialog (*editor, _("\
3064 The disk system on your computer\n\
3065 was not able to keep up with Ardour.\n\
3067 Specifically, it failed to write data to disk\n\
3068 quickly enough to keep up with recording.\n"));
3069 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3075 ARDOUR_UI::disk_underrun_handler ()
3077 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3079 if (!have_disk_speed_dialog_displayed) {
3080 have_disk_speed_dialog_displayed = true;
3081 MessageDialog* msg = new MessageDialog (*editor,
3082 _("The disk system on your computer\n\
3083 was not able to keep up with Ardour.\n\
3085 Specifically, it failed to read data from disk\n\
3086 quickly enough to keep up with playback.\n"));
3087 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3093 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3095 have_disk_speed_dialog_displayed = false;
3100 ARDOUR_UI::session_dialog (std::string msg)
3102 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3107 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3109 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3118 ARDOUR_UI::pending_state_dialog ()
3120 HBox* hbox = new HBox();
3121 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3122 ArdourDialog dialog (_("Crash Recovery"), true);
3124 This session appears to have been in\n\
3125 middle of recording when ardour or\n\
3126 the computer was shutdown.\n\
3128 Ardour can recover any captured audio for\n\
3129 you, or it can ignore it. Please decide\n\
3130 what you would like to do.\n"));
3131 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3132 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3133 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3134 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3135 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3136 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3137 dialog.set_default_response (RESPONSE_ACCEPT);
3138 dialog.set_position (WIN_POS_CENTER);
3143 switch (dialog.run ()) {
3144 case RESPONSE_ACCEPT:
3152 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3154 HBox* hbox = new HBox();
3155 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3156 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3157 Label message (string_compose (_("\
3158 This session was created with a sample rate of %1 Hz\n\
3160 The audioengine is currently running at %2 Hz\n"), desired, actual));
3162 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3163 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3164 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3165 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3166 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3167 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3168 dialog.set_default_response (RESPONSE_ACCEPT);
3169 dialog.set_position (WIN_POS_CENTER);
3174 switch (dialog.run ()) {
3175 case RESPONSE_ACCEPT:
3184 ARDOUR_UI::disconnect_from_jack ()
3187 if( engine->disconnect_from_jack ()) {
3188 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3192 update_sample_rate (0);
3197 ARDOUR_UI::reconnect_to_jack ()
3200 if (engine->reconnect_to_jack ()) {
3201 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3205 update_sample_rate (0);
3210 ARDOUR_UI::use_config ()
3212 Glib::RefPtr<Action> act;
3214 switch (Config->get_native_file_data_format ()) {
3216 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3219 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3222 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3227 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3228 ract->set_active ();
3231 switch (Config->get_native_file_header_format ()) {
3233 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3236 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3239 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3242 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3245 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3248 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3251 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3256 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3257 ract->set_active ();
3260 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3262 set_transport_controllable_state (*node);
3267 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3269 if (Config->get_primary_clock_delta_edit_cursor()) {
3270 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3272 primary_clock.set (pos, 0, true);
3275 if (Config->get_secondary_clock_delta_edit_cursor()) {
3276 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3278 secondary_clock.set (pos);
3281 if (big_clock_window) {
3282 big_clock.set (pos);
3287 ARDOUR_UI::record_state_changed ()
3289 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3291 if (!session || !big_clock_window) {
3292 /* why bother - the clock isn't visible */
3296 switch (session->record_status()) {
3297 case Session::Recording:
3298 big_clock.set_widget_name ("BigClockRecording");
3301 big_clock.set_widget_name ("BigClockNonRecording");
3307 ARDOUR_UI::first_idle ()
3310 session->allow_auto_play (true);
3314 editor->first_idle();
3317 Keyboard::set_can_save_keybindings (true);
3322 ARDOUR_UI::store_clock_modes ()
3324 XMLNode* node = new XMLNode(X_("ClockModes"));
3326 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3327 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3330 session->add_extra_xml (*node);
3331 session->set_dirty ();
3336 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3337 : Controllable (name), ui (u), type(tp)
3343 ARDOUR_UI::TransportControllable::set_value (float val)
3345 if (type == ShuttleControl) {
3352 fract = -((0.5f - val)/0.5f);
3354 fract = ((val - 0.5f)/0.5f);
3358 ui.set_shuttle_fract (fract);
3363 /* do nothing: these are radio-style actions */
3367 const char *action = 0;
3371 action = X_("Roll");
3374 action = X_("Stop");
3377 action = X_("Goto Start");
3380 action = X_("Goto End");
3383 action = X_("Loop");
3386 action = X_("Play Selection");
3389 action = X_("Record");
3399 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3407 ARDOUR_UI::TransportControllable::get_value (void) const
3426 case ShuttleControl:
3436 ARDOUR_UI::TransportControllable::set_id (const string& str)
3442 ARDOUR_UI::setup_profile ()
3444 if (gdk_screen_width() < 1200) {
3445 Profile->set_small_screen ();
3449 if (getenv ("ARDOUR_SAE")) {
3450 Profile->set_sae ();
3451 Profile->set_single_package ();