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.
31 #include <sys/resource.h>
33 #include <gtkmm/messagedialog.h>
34 #include <gtkmm/accelmap.h>
36 #include <pbd/error.h>
37 #include <pbd/basename.h>
38 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/plugin.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/audiofilesource.h>
64 #include <ardour/recent_sessions.h>
65 #include <ardour/port.h>
66 #include <ardour/audio_track.h>
68 typedef uint64_t microseconds_t;
71 #include "ardour_ui.h"
72 #include "public_editor.h"
73 #include "audio_clock.h"
78 #include "add_route_dialog.h"
79 #include "new_session_dialog.h"
84 #include "gui_thread.h"
85 #include "theme_manager.h"
86 #include "engine_dialog.h"
87 #include "gain_meter.h"
88 #include "route_time_axis.h"
92 using namespace ARDOUR;
94 using namespace Gtkmm2ext;
98 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
99 UIConfiguration *ARDOUR_UI::ui_config = 0;
101 sigc::signal<void,bool> ARDOUR_UI::Blink;
102 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
103 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
104 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
106 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
108 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
110 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
111 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
112 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
113 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
117 preroll_button (_("pre\nroll")),
118 postroll_button (_("post\nroll")),
122 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
126 roll_controllable ("transport roll", *this, TransportControllable::Roll),
127 stop_controllable ("transport stop", *this, TransportControllable::Stop),
128 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
129 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
130 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
131 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
132 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
133 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
134 shuttle_controller_binding_proxy (shuttle_controllable),
136 roll_button (&roll_controllable),
137 stop_button (&stop_controllable),
138 goto_start_button (&goto_start_controllable),
139 goto_end_button (&goto_end_controllable),
140 auto_loop_button (&auto_loop_controllable),
141 play_selection_button (&play_selection_controllable),
142 rec_button (&rec_controllable),
144 shuttle_units_button (_("% ")),
146 punch_in_button (_("Punch In")),
147 punch_out_button (_("Punch Out")),
148 auto_return_button (_("Auto Return")),
149 auto_play_button (_("Auto Play")),
150 auto_input_button (_("Auto Input")),
151 click_button (_("Click")),
152 time_master_button (_("time\nmaster")),
154 auditioning_alert_button (_("AUDITION")),
155 solo_alert_button (_("SOLO")),
157 error_log_button (_("Errors"))
159 using namespace Gtk::Menu_Helpers;
164 _auto_display_errors = false;
170 if (ARDOUR_COMMAND_LINE::session_name.length()) {
171 /* only show this if we're not going to post the new session dialog */
175 if (theArdourUI == 0) {
179 ui_config = new UIConfiguration();
180 theme_manager = new ThemeManager();
186 _session_is_new = false;
187 big_clock_window = 0;
188 session_selector_window = 0;
189 new_session_dialog = 0;
190 last_key_press_time = 0;
191 connection_editor = 0;
192 add_route_dialog = 0;
197 open_session_selector = 0;
198 have_configure_timeout = false;
199 have_disk_speed_dialog_displayed = false;
200 _will_create_new_session_automatically = false;
201 session_loaded = false;
202 last_speed_displayed = -1.0f;
203 ignore_dual_punch = false;
204 _mixer_on_top = false;
206 roll_button.unset_flags (Gtk::CAN_FOCUS);
207 stop_button.unset_flags (Gtk::CAN_FOCUS);
208 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
209 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
210 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
211 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
212 rec_button.unset_flags (Gtk::CAN_FOCUS);
214 last_configure_time= 0;
216 shuttle_grabbed = false;
218 shuttle_max_speed = 8.0f;
220 shuttle_style_menu = 0;
221 shuttle_unit_menu = 0;
223 // We do not have jack linked in yet so;
225 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
227 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
228 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
230 ARDOUR::Plugin::PresetFileExists.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler));
232 /* handle dialog requests */
234 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
236 /* handle pending state with a dialog */
238 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
240 /* handle sr mismatch with a dialog */
242 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
244 /* lets get this party started */
247 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
248 throw failed_constructor ();
251 setup_gtk_ardour_enums ();
252 Config->set_current_owner (ConfigVariableBase::Interface);
255 GainMeter::setup_slider_pix ();
256 RouteTimeAxisView::setup_slider_pix ();
258 } catch (failed_constructor& err) {
259 error << _("could not initialize Ardour.") << endmsg;
264 /* we like keyboards */
266 keyboard = new Keyboard;
270 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
271 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
277 ARDOUR_UI::create_engine ()
279 // this gets called every time by new_session()
285 loading_message (_("Starting audio engine"));
288 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
295 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
296 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
297 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
298 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
306 ARDOUR_UI::post_engine ()
308 /* Things to be done once we create the AudioEngine
311 check_memory_locking();
313 ActionManager::init ();
316 if (setup_windows ()) {
317 throw failed_constructor ();
320 /* this is the first point at which all the keybindings are available */
322 if (ARDOUR_COMMAND_LINE::show_key_actions) {
323 vector<string> names;
324 vector<string> paths;
326 vector<AccelKey> bindings;
328 ActionManager::get_all_actions (names, paths, keys, bindings);
330 vector<string>::iterator n;
331 vector<string>::iterator k;
332 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
333 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
339 blink_timeout_tag = -1;
341 /* the global configuration object is now valid */
345 /* this being a GUI and all, we want peakfiles */
347 AudioFileSource::set_build_peakfiles (true);
348 AudioFileSource::set_build_missing_peakfiles (true);
350 /* set default clock modes */
352 if (Profile->get_sae()) {
353 primary_clock.set_mode (AudioClock::BBT);
354 secondary_clock.set_mode (AudioClock::MinSec);
356 primary_clock.set_mode (AudioClock::SMPTE);
357 secondary_clock.set_mode (AudioClock::BBT);
360 /* start the time-of-day-clock */
363 /* OS X provides an always visible wallclock, so don't be stupid */
364 update_wall_clock ();
365 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
368 update_disk_space ();
370 update_sample_rate (engine->frame_rate());
372 platform_specific ();
374 /* now start and maybe save state */
376 if (do_engine_start () == 0) {
377 if (session && _session_is_new) {
378 /* we need to retain initial visual
379 settings for a new session
381 session->save_state ("");
386 ARDOUR_UI::~ARDOUR_UI ()
388 save_ardour_state ();
402 if (add_route_dialog) {
403 delete add_route_dialog;
406 if (new_session_dialog) {
407 delete new_session_dialog;
412 ARDOUR_UI::pop_back_splash ()
414 if (Splash::instance()) {
415 // Splash::instance()->pop_back();
416 Splash::instance()->hide ();
421 ARDOUR_UI::configure_timeout ()
423 if (last_configure_time == 0) {
424 /* no configure events yet */
428 /* force a gap of 0.5 seconds since the last configure event
431 if (get_microseconds() - last_configure_time < 500000) {
434 have_configure_timeout = false;
435 save_ardour_state ();
441 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
443 if (have_configure_timeout) {
444 last_configure_time = get_microseconds();
446 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
447 have_configure_timeout = true;
454 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
456 const XMLProperty* prop;
458 if ((prop = node.property ("roll")) != 0) {
459 roll_controllable.set_id (prop->value());
461 if ((prop = node.property ("stop")) != 0) {
462 stop_controllable.set_id (prop->value());
464 if ((prop = node.property ("goto_start")) != 0) {
465 goto_start_controllable.set_id (prop->value());
467 if ((prop = node.property ("goto_end")) != 0) {
468 goto_end_controllable.set_id (prop->value());
470 if ((prop = node.property ("auto_loop")) != 0) {
471 auto_loop_controllable.set_id (prop->value());
473 if ((prop = node.property ("play_selection")) != 0) {
474 play_selection_controllable.set_id (prop->value());
476 if ((prop = node.property ("rec")) != 0) {
477 rec_controllable.set_id (prop->value());
479 if ((prop = node.property ("shuttle")) != 0) {
480 shuttle_controllable.set_id (prop->value());
485 ARDOUR_UI::get_transport_controllable_state ()
487 XMLNode* node = new XMLNode(X_("TransportControllables"));
490 roll_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("roll"), buf);
492 stop_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("stop"), buf);
494 goto_start_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("goto_start"), buf);
496 goto_end_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("goto_end"), buf);
498 auto_loop_controllable.id().print (buf, sizeof (buf));
499 node->add_property (X_("auto_loop"), buf);
500 play_selection_controllable.id().print (buf, sizeof (buf));
501 node->add_property (X_("play_selection"), buf);
502 rec_controllable.id().print (buf, sizeof (buf));
503 node->add_property (X_("rec"), buf);
504 shuttle_controllable.id().print (buf, sizeof (buf));
505 node->add_property (X_("shuttle"), buf);
511 ARDOUR_UI::save_ardour_state ()
513 if (!keyboard || !mixer || !editor) {
517 /* XXX this is all a bit dubious. add_extra_xml() uses
518 a different lifetime model from add_instant_xml().
521 XMLNode* node = new XMLNode (keyboard->get_state());
522 Config->add_extra_xml (*node);
523 Config->add_extra_xml (get_transport_controllable_state());
524 if (new_session_dialog) {
525 if (new_session_dialog->engine_control.was_used()) {
526 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
529 Config->save_state();
530 ui_config->save_state ();
532 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
533 XMLNode mnode(mixer->get_state());
536 session->add_instant_xml (enode, session->path());
537 session->add_instant_xml (mnode, session->path());
539 Config->add_instant_xml (enode, get_user_ardour_path());
540 Config->add_instant_xml (mnode, get_user_ardour_path());
543 Keyboard::save_keybindings ();
547 ARDOUR_UI::autosave_session ()
549 if (g_main_depth() > 1) {
550 /* inside a recursive main loop,
551 give up because we may not be able to
557 if (!Config->get_periodic_safety_backups())
561 session->maybe_write_autosave();
568 ARDOUR_UI::update_autosave ()
570 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
572 if (session->dirty()) {
573 if (_autosave_connection.connected()) {
574 _autosave_connection.disconnect();
577 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
578 Config->get_periodic_safety_backup_interval() * 1000);
581 if (_autosave_connection.connected()) {
582 _autosave_connection.disconnect();
588 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
592 title = _("Ardour could not start JACK");
594 title = _("Ardour could not connect to JACK.");
597 MessageDialog win (title,
603 win.set_secondary_text(_("There are several possible reasons:\n\
605 1) You requested audio parameters that are not supported..\n\
606 2) JACK is running as another user.\n\
608 Please consider the possibilities, and perhaps try different parameters."));
610 win.set_secondary_text(_("There are several possible reasons:\n\
612 1) JACK is not running.\n\
613 2) JACK is running as another user, perhaps root.\n\
614 3) There is already another client called \"ardour\".\n\
616 Please consider the possibilities, and perhaps (re)start JACK."));
620 win.set_transient_for (*toplevel);
624 win.add_button (Stock::OK, RESPONSE_CLOSE);
626 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
629 win.set_default_response (RESPONSE_CLOSE);
632 win.set_position (Gtk::WIN_POS_CENTER);
635 /* we just don't care about the result, but we want to block */
641 ARDOUR_UI::startup ()
645 new_session_dialog = new NewSessionDialog();
647 bool backend_audio_is_running = EngineControl::engine_running();
648 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
651 new_session_dialog->engine_control.set_state (*audio_setup);
654 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
658 BootMessage (_("Ardour is ready for use"));
663 ARDOUR_UI::no_memory_warning ()
665 XMLNode node (X_("no-memory-warning"));
666 Config->add_instant_xml (node, get_user_ardour_path());
670 ARDOUR_UI::check_memory_locking ()
673 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
677 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
679 if (engine->is_realtime() && memory_warning_node == 0) {
681 struct rlimit limits;
683 long pages, page_size;
685 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
688 ram = (int64_t) pages * (int64_t) page_size;
691 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
695 if (limits.rlim_cur != RLIM_INFINITY) {
697 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
700 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
701 "This might cause Ardour to run out of memory before your system "
702 "runs out of memory. \n\n"
703 "You can view the memory limit with 'ulimit -l', "
704 "and it is normally controlled by /etc/security/limits.conf"));
706 VBox* vbox = msg.get_vbox();
708 CheckButton cb (_("Do not show this window again"));
710 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
712 hbox.pack_start (cb, true, false);
713 vbox->pack_start (hbox);
731 if (session->transport_rolling()) {
732 session->request_stop ();
736 if (session->dirty()) {
737 switch (ask_about_saving_session(_("quit"))) {
742 /* use the default name */
743 if (save_state_canfail ("")) {
744 /* failed - don't quit */
745 MessageDialog msg (*editor,
747 Ardour was unable to save your session.\n\n\
748 If you still wish to quit, please use the\n\n\
749 \"Just quit\" option."));
760 session->set_deletion_in_progress ();
763 ArdourDialog::close_all_dialogs ();
765 save_ardour_state ();
770 ARDOUR_UI::ask_about_saving_session (const string & what)
772 ArdourDialog window (_("ardour: save session?"));
773 Gtk::HBox dhbox; // the hbox for the image and text
774 Gtk::Label prompt_label;
775 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
779 msg = string_compose(_("Don't %1"), what);
780 window.add_button (msg, RESPONSE_REJECT);
781 msg = string_compose(_("Just %1"), what);
782 window.add_button (msg, RESPONSE_APPLY);
783 msg = string_compose(_("Save and %1"), what);
784 window.add_button (msg, RESPONSE_ACCEPT);
786 window.set_default_response (RESPONSE_ACCEPT);
788 Gtk::Button noquit_button (msg);
789 noquit_button.set_name ("EditorGTKButton");
794 if (session->snap_name() == session->name()) {
797 type = _("snapshot");
799 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?"),
800 type, session->snap_name());
802 prompt_label.set_text (prompt);
803 prompt_label.set_name (X_("PrompterLabel"));
804 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
806 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
808 dhbox.set_homogeneous (false);
809 dhbox.pack_start (*dimage, false, false, 5);
810 dhbox.pack_start (prompt_label, true, false, 5);
811 window.get_vbox()->pack_start (dhbox);
813 window.set_name (_("Prompter"));
814 window.set_position (Gtk::WIN_POS_MOUSE);
815 window.set_modal (true);
816 window.set_resizable (false);
819 window.set_keep_above (true);
822 ResponseType r = (ResponseType) window.run();
827 case RESPONSE_ACCEPT: // save and get out of here
829 case RESPONSE_APPLY: // get out of here
839 ARDOUR_UI::every_second ()
842 update_buffer_load ();
843 update_disk_space ();
848 ARDOUR_UI::every_point_one_seconds ()
850 update_speed_display ();
851 RapidScreenUpdate(); /* EMIT_SIGNAL */
856 ARDOUR_UI::every_point_zero_one_seconds ()
858 // august 2007: actual update frequency: 40Hz, not 100Hz
860 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
865 ARDOUR_UI::update_sample_rate (nframes_t ignored)
869 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
871 if (!engine->connected()) {
873 snprintf (buf, sizeof (buf), _("disconnected"));
877 nframes_t rate = engine->frame_rate();
879 if (fmod (rate, 1000.0) != 0.0) {
880 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
881 (float) rate/1000.0f,
882 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
884 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
886 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
890 sample_rate_label.set_text (buf);
894 ARDOUR_UI::update_cpu_load ()
897 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
898 cpu_load_label.set_text (buf);
902 ARDOUR_UI::update_buffer_load ()
908 c = session->capture_load ();
909 p = session->playback_load ();
911 push_buffer_stats (c, p);
913 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
914 session->playback_load(), session->capture_load());
915 buffer_load_label.set_text (buf);
917 buffer_load_label.set_text ("");
922 ARDOUR_UI::count_recenabled_streams (Route& route)
924 Track* track = dynamic_cast<Track*>(&route);
925 if (track && track->diskstream()->record_enabled()) {
926 rec_enabled_streams += track->n_inputs();
931 ARDOUR_UI::update_disk_space()
937 nframes_t frames = session->available_capture_duration();
940 if (frames == max_frames) {
941 strcpy (buf, _("Disk: 24hrs+"));
946 nframes_t fr = session->frame_rate();
948 rec_enabled_streams = 0;
949 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
951 if (rec_enabled_streams) {
952 frames /= rec_enabled_streams;
955 hrs = frames / (fr * 3600);
956 frames -= hrs * fr * 3600;
957 mins = frames / (fr * 60);
958 frames -= mins * fr * 60;
961 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
964 disk_space_label.set_text (buf);
968 ARDOUR_UI::update_wall_clock ()
975 tm_now = localtime (&now);
977 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
978 wall_clock_label.set_text (buf);
984 ARDOUR_UI::session_menu (GdkEventButton *ev)
986 session_popup_menu->popup (0, 0);
991 ARDOUR_UI::redisplay_recent_sessions ()
993 vector<string *> *sessions;
994 vector<string *>::iterator i;
995 RecentSessionsSorter cmp;
997 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
998 recent_session_model->clear ();
1001 ARDOUR::read_recent_sessions (rs);
1004 recent_session_display.set_model (recent_session_model);
1008 /* sort them alphabetically */
1009 sort (rs.begin(), rs.end(), cmp);
1010 sessions = new vector<string*>;
1012 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1013 sessions->push_back (new string ((*i).second));
1016 for (i = sessions->begin(); i != sessions->end(); ++i) {
1018 vector<string*>* states;
1019 vector<const gchar*> item;
1020 string fullpath = *(*i);
1022 /* remove any trailing / */
1024 if (fullpath[fullpath.length()-1] == '/') {
1025 fullpath = fullpath.substr (0, fullpath.length()-1);
1028 /* check whether session still exists */
1029 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1030 /* session doesn't exist */
1031 cerr << "skipping non-existent session " << fullpath << endl;
1035 /* now get available states for this session */
1037 if ((states = Session::possible_states (fullpath)) == 0) {
1038 /* no state file? */
1042 TreeModel::Row row = *(recent_session_model->append());
1044 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1045 row[recent_session_columns.fullpath] = fullpath;
1047 if (states->size() > 1) {
1049 /* add the children */
1051 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1053 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1055 child_row[recent_session_columns.visible_name] = **i2;
1056 child_row[recent_session_columns.fullpath] = fullpath;
1065 recent_session_display.set_model (recent_session_model);
1070 ARDOUR_UI::build_session_selector ()
1072 session_selector_window = new ArdourDialog ("session selector");
1074 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1076 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1077 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1078 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1079 recent_session_model = TreeStore::create (recent_session_columns);
1080 recent_session_display.set_model (recent_session_model);
1081 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1082 recent_session_display.set_headers_visible (false);
1083 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1084 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1086 scroller->add (recent_session_display);
1087 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1089 session_selector_window->set_name ("SessionSelectorWindow");
1090 session_selector_window->set_size_request (200, 400);
1091 session_selector_window->get_vbox()->pack_start (*scroller);
1092 session_selector_window->show_all_children();
1096 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1098 session_selector_window->response (RESPONSE_ACCEPT);
1102 ARDOUR_UI::open_recent_session ()
1104 bool can_return = (session != 0);
1106 if (session_selector_window == 0) {
1107 build_session_selector ();
1110 redisplay_recent_sessions ();
1114 session_selector_window->set_position (WIN_POS_MOUSE);
1116 ResponseType r = (ResponseType) session_selector_window->run ();
1119 case RESPONSE_ACCEPT:
1123 session_selector_window->hide();
1130 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1134 session_selector_window->hide();
1136 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1138 if (i == recent_session_model->children().end()) {
1142 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1143 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1145 _session_is_new = false;
1147 if (load_session (path, state) == 0) {
1156 ARDOUR_UI::check_audioengine ()
1159 if (!engine->connected()) {
1160 MessageDialog msg (_("Ardour is not connected to JACK\n"
1161 "You cannot open or close sessions in this condition"));
1173 ARDOUR_UI::open_session ()
1175 if (!check_audioengine()) {
1179 /* popup selector window */
1181 if (open_session_selector == 0) {
1183 /* ardour sessions are folders */
1185 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1186 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1187 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1188 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1190 FileFilter session_filter;
1191 session_filter.add_pattern ("*.ardour");
1192 session_filter.set_name (_("Ardour sessions"));
1193 open_session_selector->add_filter (session_filter);
1194 open_session_selector->set_filter (session_filter);
1197 int response = open_session_selector->run();
1198 open_session_selector->hide ();
1201 case RESPONSE_ACCEPT:
1204 open_session_selector->hide();
1208 open_session_selector->hide();
1209 string session_path = open_session_selector->get_filename();
1213 if (session_path.length() > 0) {
1214 if (Session::find_session (session_path, path, name, isnew) == 0) {
1215 _session_is_new = isnew;
1216 load_session (path, name);
1223 ARDOUR_UI::session_add_midi_track ()
1225 cerr << _("Patience is a virtue.\n");
1229 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1231 list<boost::shared_ptr<AudioTrack> > tracks;
1232 Session::RouteList routes;
1235 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1241 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1243 if (tracks.size() != how_many) {
1244 if (how_many == 1) {
1245 error << _("could not create a new audio track") << endmsg;
1247 error << string_compose (_("could only create %1 of %2 new audio %3"),
1248 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1254 routes = session->new_audio_route (input_channels, output_channels, how_many);
1256 if (routes.size() != how_many) {
1257 if (how_many == 1) {
1258 error << _("could not create a new audio track") << endmsg;
1260 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1266 if (need_control_room_outs) {
1272 route->set_stereo_control_outs (control_lr_channels);
1273 route->control_outs()->set_stereo_pan (pans, this);
1275 #endif /* CONTROLOUTS */
1279 MessageDialog msg (*editor,
1280 _("There are insufficient JACK ports available\n\
1281 to create a new track or bus.\n\
1282 You should save Ardour, exit and\n\
1283 restart JACK with more ports."));
1290 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1292 nframes_t _preroll = 0;
1295 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1296 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1298 if (new_position > _preroll) {
1299 new_position -= _preroll;
1304 session->request_locate (new_position);
1309 ARDOUR_UI::transport_goto_start ()
1312 session->goto_start();
1315 /* force displayed area in editor to start no matter
1316 what "follow playhead" setting is.
1320 editor->reset_x_origin (session->current_start_frame());
1326 ARDOUR_UI::transport_goto_zero ()
1329 session->request_locate (0);
1332 /* force displayed area in editor to start no matter
1333 what "follow playhead" setting is.
1337 editor->reset_x_origin (0);
1343 ARDOUR_UI::transport_goto_wallclock ()
1345 if (session && editor) {
1352 localtime_r (&now, &tmnow);
1354 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1355 frames += tmnow.tm_min * (60 * session->frame_rate());
1356 frames += tmnow.tm_sec * session->frame_rate();
1358 session->request_locate (frames);
1360 /* force displayed area in editor to start no matter
1361 what "follow playhead" setting is.
1365 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1371 ARDOUR_UI::transport_goto_end ()
1374 nframes_t frame = session->current_end_frame();
1375 session->request_locate (frame);
1377 /* force displayed area in editor to start no matter
1378 what "follow playhead" setting is.
1382 editor->reset_x_origin (frame);
1388 ARDOUR_UI::transport_stop ()
1394 if (session->is_auditioning()) {
1395 session->cancel_audition ();
1399 if (session->get_play_loop ()) {
1400 session->request_play_loop (false);
1403 session->request_stop ();
1407 ARDOUR_UI::transport_stop_and_forget_capture ()
1410 session->request_stop (true);
1415 ARDOUR_UI::remove_last_capture()
1418 editor->remove_last_capture();
1423 ARDOUR_UI::transport_record (bool roll)
1427 switch (session->record_status()) {
1428 case Session::Disabled:
1429 if (session->ntracks() == 0) {
1430 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1434 session->maybe_enable_record ();
1439 case Session::Recording:
1441 session->request_stop();
1443 session->disable_record (false, true);
1447 case Session::Enabled:
1448 session->disable_record (false, true);
1451 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1455 ARDOUR_UI::transport_roll ()
1463 rolling = session->transport_rolling ();
1465 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1467 if (session->get_play_loop()) {
1468 session->request_play_loop (false);
1469 auto_loop_button.set_visual_state (1);
1470 roll_button.set_visual_state (1);
1471 } else if (session->get_play_range ()) {
1472 session->request_play_range (false);
1473 play_selection_button.set_visual_state (0);
1474 } else if (rolling) {
1475 session->request_locate (session->last_transport_start(), true);
1478 session->request_transport_speed (1.0f);
1482 ARDOUR_UI::transport_loop()
1485 if (session->get_play_loop()) {
1486 if (session->transport_rolling()) {
1487 Location * looploc = session->locations()->auto_loop_location();
1489 session->request_locate (looploc->start(), true);
1494 session->request_play_loop (true);
1500 ARDOUR_UI::transport_play_selection ()
1506 if (!session->get_play_range()) {
1507 session->request_stop ();
1510 editor->play_selection ();
1514 ARDOUR_UI::transport_rewind (int option)
1516 float current_transport_speed;
1519 current_transport_speed = session->transport_speed();
1521 if (current_transport_speed >= 0.0f) {
1524 session->request_transport_speed (-1.0f);
1527 session->request_transport_speed (-4.0f);
1530 session->request_transport_speed (-0.5f);
1535 session->request_transport_speed (current_transport_speed * 1.5f);
1541 ARDOUR_UI::transport_forward (int option)
1543 float current_transport_speed;
1546 current_transport_speed = session->transport_speed();
1548 if (current_transport_speed <= 0.0f) {
1551 session->request_transport_speed (1.0f);
1554 session->request_transport_speed (4.0f);
1557 session->request_transport_speed (0.5f);
1562 session->request_transport_speed (current_transport_speed * 1.5f);
1568 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1574 boost::shared_ptr<Route> r;
1576 if ((r = session->route_by_remote_id (dstream)) != 0) {
1580 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1581 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1590 ARDOUR_UI::queue_transport_change ()
1592 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1596 ARDOUR_UI::map_transport_state ()
1598 float sp = session->transport_speed();
1601 transport_rolling ();
1602 } else if (sp < 0.0f) {
1603 transport_rewinding ();
1604 } else if (sp > 0.0f) {
1605 transport_forwarding ();
1607 transport_stopped ();
1612 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1614 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1615 (int) adj.get_value()].c_str());
1619 ARDOUR_UI::engine_stopped ()
1621 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1622 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1623 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1627 ARDOUR_UI::engine_running ()
1629 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1630 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1631 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1633 Glib::RefPtr<Action> action;
1634 const char* action_name = 0;
1636 switch (engine->frames_per_cycle()) {
1638 action_name = X_("JACKLatency32");
1641 action_name = X_("JACKLatency64");
1644 action_name = X_("JACKLatency128");
1647 action_name = X_("JACKLatency512");
1650 action_name = X_("JACKLatency1024");
1653 action_name = X_("JACKLatency2048");
1656 action_name = X_("JACKLatency4096");
1659 action_name = X_("JACKLatency8192");
1662 /* XXX can we do anything useful ? */
1668 action = ActionManager::get_action (X_("JACK"), action_name);
1671 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1672 ract->set_active ();
1678 ARDOUR_UI::engine_halted ()
1680 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1682 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1683 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1685 update_sample_rate (0);
1687 MessageDialog msg (*editor,
1689 JACK has either been shutdown or it\n\
1690 disconnected Ardour because Ardour\n\
1691 was not fast enough. Try to restart\n\
1692 JACK, reconnect and save the session."));
1698 ARDOUR_UI::do_engine_start ()
1706 error << _("Unable to start the session running")
1716 ARDOUR_UI::setup_theme ()
1718 theme_manager->setup_theme();
1722 ARDOUR_UI::update_clocks ()
1724 if (!editor || !editor->dragging_playhead()) {
1725 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1730 ARDOUR_UI::start_clocking ()
1732 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1736 ARDOUR_UI::stop_clocking ()
1738 clock_signal_connection.disconnect ();
1742 ARDOUR_UI::toggle_clocking ()
1745 if (clock_button.get_active()) {
1754 ARDOUR_UI::_blink (void *arg)
1757 ((ARDOUR_UI *) arg)->blink ();
1764 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1768 ARDOUR_UI::start_blinking ()
1770 /* Start the blink signal. Everybody with a blinking widget
1771 uses Blink to drive the widget's state.
1774 if (blink_timeout_tag < 0) {
1776 blink_timeout_tag = g_timeout_add (240, _blink, this);
1781 ARDOUR_UI::stop_blinking ()
1783 if (blink_timeout_tag >= 0) {
1784 g_source_remove (blink_timeout_tag);
1785 blink_timeout_tag = -1;
1790 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1796 if (io.n_inputs() == 0) {
1801 /* XXX we're not handling multiple ports yet. */
1803 const char **connections = io.input(0)->get_connections();
1805 if (connections == 0 || connections[0] == '\0') {
1808 buf = connections[0];
1815 if (io.n_outputs() == 0) {
1820 /* XXX we're not handling multiple ports yet. */
1822 const char **connections = io.output(0)->get_connections();
1824 if (connections == 0 || connections[0] == '\0') {
1827 buf = connections[0];
1834 /** Ask the user for the name of a new shapshot and then take it.
1837 ARDOUR_UI::snapshot_session ()
1839 ArdourPrompter prompter (true);
1843 struct tm local_time;
1846 localtime_r (&n, &local_time);
1847 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1849 prompter.set_name ("Prompter");
1850 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1851 prompter.set_prompt (_("Name of New Snapshot"));
1852 prompter.set_initial_text (timebuf);
1854 switch (prompter.run()) {
1855 case RESPONSE_ACCEPT:
1856 prompter.get_result (snapname);
1857 if (snapname.length()){
1858 save_state (snapname);
1868 ARDOUR_UI::save_state (const string & name)
1870 (void) save_state_canfail (name);
1874 ARDOUR_UI::save_state_canfail (string name)
1879 if (name.length() == 0) {
1880 name = session->snap_name();
1883 if ((ret = session->save_state (name)) != 0) {
1887 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1892 ARDOUR_UI::primary_clock_value_changed ()
1895 session->request_locate (primary_clock.current_time ());
1900 ARDOUR_UI::big_clock_value_changed ()
1903 session->request_locate (big_clock.current_time ());
1908 ARDOUR_UI::secondary_clock_value_changed ()
1911 session->request_locate (secondary_clock.current_time ());
1916 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1922 switch (session->record_status()) {
1923 case Session::Enabled:
1925 rec_button.set_visual_state (2);
1927 rec_button.set_visual_state (0);
1931 case Session::Recording:
1932 rec_button.set_visual_state (1);
1936 rec_button.set_visual_state (0);
1942 ARDOUR_UI::save_template ()
1945 ArdourPrompter prompter (true);
1948 if (!check_audioengine()) {
1952 prompter.set_name (X_("Prompter"));
1953 prompter.set_prompt (_("Name for mix template:"));
1954 prompter.set_initial_text(session->name() + _("-template"));
1955 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1957 switch (prompter.run()) {
1958 case RESPONSE_ACCEPT:
1959 prompter.get_result (name);
1961 if (name.length()) {
1962 session->save_template (name);
1972 ARDOUR_UI::fontconfig_dialog ()
1975 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1976 may not and it can take a while to build it. Warn them.
1979 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1981 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1982 MessageDialog msg (*new_session_dialog,
1983 _("Welcome to Ardour.\n\n"
1984 "The program will take a bit longer to start up\n"
1985 "while the system fonts are checked.\n\n"
1986 "This will only be done once, and you will\n"
1987 "not see this message again\n"),
2000 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2002 existing_session = false;
2004 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2005 session_path = cmdline_path;
2006 existing_session = true;
2007 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2008 session_path = Glib::path_get_dirname (string (cmdline_path));
2009 existing_session = true;
2011 /* it doesn't exist, assume the best */
2012 session_path = Glib::path_get_dirname (string (cmdline_path));
2015 session_name = basename_nosuffix (string (cmdline_path));
2019 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2021 /* when this is called, the backend audio system must be running */
2023 /* the main idea here is to deal with the fact that a cmdline argument for the session
2024 can be interpreted in different ways - it could be a directory or a file, and before
2025 we load, we need to know both the session directory and the snapshot (statefile) within it
2026 that we are supposed to use.
2029 if (session_name.length() == 0 || session_path.length() == 0) {
2033 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2035 Glib::ustring predicted_session_file;
2037 predicted_session_file = session_path;
2038 predicted_session_file += '/';
2039 predicted_session_file += session_name;
2040 predicted_session_file += Session::statefile_suffix();
2042 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2043 existing_session = true;
2046 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2048 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2049 /* existing .ardour file */
2050 existing_session = true;
2054 existing_session = false;
2057 /* lets just try to load it */
2059 if (create_engine ()) {
2060 backend_audio_error (false, new_session_dialog);
2064 return load_session (session_path, session_name);
2068 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2070 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2072 MessageDialog msg (str,
2074 Gtk::MESSAGE_WARNING,
2075 Gtk::BUTTONS_YES_NO,
2079 msg.set_name (X_("CleanupDialog"));
2080 msg.set_wmclass (X_("existing_session"), "Ardour");
2081 msg.set_position (Gtk::WIN_POS_MOUSE);
2084 switch (msg.run()) {
2093 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2098 AutoConnectOption iconnect;
2099 AutoConnectOption oconnect;
2103 if (Profile->get_sae()) {
2107 iconnect = AutoConnectPhysical;
2108 oconnect = AutoConnectMaster;
2109 nphysin = 0; // use all available
2110 nphysout = 0; // use all available
2114 /* get settings from advanced section of NSD */
2116 if (new_session_dialog->create_control_bus()) {
2117 cchns = (uint32_t) new_session_dialog->control_channel_count();
2122 if (new_session_dialog->create_master_bus()) {
2123 mchns = (uint32_t) new_session_dialog->master_channel_count();
2128 if (new_session_dialog->connect_inputs()) {
2129 iconnect = AutoConnectPhysical;
2131 iconnect = AutoConnectOption (0);
2134 /// @todo some minor tweaks.
2136 if (new_session_dialog->connect_outs_to_master()) {
2137 oconnect = AutoConnectMaster;
2138 } else if (new_session_dialog->connect_outs_to_physical()) {
2139 oconnect = AutoConnectPhysical;
2141 oconnect = AutoConnectOption (0);
2144 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2145 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2148 if (build_session (session_path,
2156 engine->frame_rate() * 60 * 5)) {
2165 ARDOUR_UI::end_loading_messages ()
2171 ARDOUR_UI::loading_message (const std::string& msg)
2174 splash->message (msg);
2179 ARDOUR_UI::idle_load (const Glib::ustring& path)
2182 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2183 /* /path/to/foo => /path/to/foo, foo */
2184 load_session (path, basename_nosuffix (path));
2186 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2187 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2191 ARDOUR_COMMAND_LINE::session_name = path;
2193 if (new_session_dialog) {
2196 /* make it break out of Dialog::run() and
2200 new_session_dialog->response (1);
2206 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2208 bool existing_session = false;
2209 Glib::ustring session_name;
2210 Glib::ustring session_path;
2211 Glib::ustring template_name;
2215 response = Gtk::RESPONSE_NONE;
2217 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2219 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2221 /* don't ever reuse this */
2223 ARDOUR_COMMAND_LINE::session_name = string();
2225 if (existing_session && backend_audio_is_running) {
2227 /* just load the thing already */
2229 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2234 /* make the NSD use whatever information we have */
2236 new_session_dialog->set_session_name (session_name);
2237 new_session_dialog->set_session_folder (session_path);
2240 /* loading failed, or we need the NSD for something */
2242 new_session_dialog->set_modal (false);
2243 new_session_dialog->set_position (WIN_POS_CENTER);
2244 new_session_dialog->set_current_page (0);
2245 new_session_dialog->set_existing_session (existing_session);
2246 new_session_dialog->reset_recent();
2249 new_session_dialog->set_have_engine (backend_audio_is_running);
2250 new_session_dialog->present ();
2251 response = new_session_dialog->run ();
2253 _session_is_new = false;
2255 /* handle possible negative responses */
2259 /* sent by idle_load, meaning restart the whole process again */
2260 new_session_dialog->hide();
2261 new_session_dialog->reset();
2265 case Gtk::RESPONSE_CANCEL:
2266 case Gtk::RESPONSE_DELETE_EVENT:
2268 if (engine && engine->running()) {
2269 engine->stop (true);
2273 new_session_dialog->hide ();
2276 case Gtk::RESPONSE_NONE:
2277 /* "Clear" was pressed */
2281 fontconfig_dialog();
2283 if (!backend_audio_is_running) {
2284 int ret = new_session_dialog->engine_control.setup_engine ();
2287 } else if (ret > 0) {
2288 response = Gtk::RESPONSE_REJECT;
2293 if (create_engine ()) {
2295 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2298 new_session_dialog->set_existing_session (false);
2299 new_session_dialog->set_current_page (2);
2301 response = Gtk::RESPONSE_NONE;
2305 backend_audio_is_running = true;
2307 if (response == Gtk::RESPONSE_OK) {
2309 session_name = new_session_dialog->session_name();
2311 if (session_name.empty()) {
2312 response = Gtk::RESPONSE_NONE;
2316 /* if the user mistakenly typed path information into the session filename entry,
2317 convert what they typed into a path & a name
2320 if (session_name[0] == '/' ||
2321 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2322 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2324 session_path = Glib::path_get_dirname (session_name);
2325 session_name = Glib::path_get_basename (session_name);
2329 session_path = new_session_dialog->session_folder();
2332 template_name = Glib::ustring();
2333 switch (new_session_dialog->which_page()) {
2335 case NewSessionDialog::OpenPage:
2336 case NewSessionDialog::EnginePage:
2340 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2342 should_be_new = true;
2344 //XXX This is needed because session constructor wants a
2345 //non-existant path. hopefully this will be fixed at some point.
2347 session_path = Glib::build_filename (session_path, session_name);
2349 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2351 if (ask_about_loading_existing_session (session_path)) {
2354 response = RESPONSE_NONE;
2359 _session_is_new = true;
2361 if (new_session_dialog->use_session_template()) {
2363 template_name = new_session_dialog->session_template_name();
2367 if (build_session_from_nsd (session_path, session_name)) {
2368 response = RESPONSE_NONE;
2380 new_session_dialog->hide ();
2382 if (load_session (session_path, session_name, template_name)) {
2384 response = Gtk::RESPONSE_NONE;
2388 if (response == Gtk::RESPONSE_NONE) {
2389 new_session_dialog->set_existing_session (false);
2390 new_session_dialog->reset ();
2394 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2398 new_session_dialog->hide();
2399 new_session_dialog->reset();
2400 goto_editor_window ();
2405 ARDOUR_UI::close_session ()
2407 if (!check_audioengine()) {
2411 if (unload_session (true)) {
2415 get_session_parameters (true, false);
2419 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2421 Session *new_session;
2425 session_loaded = false;
2427 if (!check_audioengine()) {
2431 unload_status = unload_session ();
2433 if (unload_status < 0) {
2435 } else if (unload_status > 0) {
2440 /* if it already exists, we must have write access */
2442 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2443 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2444 "This prevents the session from being loaded."));
2450 loading_message (_("Please wait while Ardour loads your session"));
2453 new_session = new Session (*engine, path, snap_name, mix_template);
2456 /* this one is special */
2458 catch (AudioEngine::PortRegistrationFailure& err) {
2460 MessageDialog msg (err.what(),
2463 Gtk::BUTTONS_CLOSE);
2465 msg.set_title (_("Port Registration Error"));
2466 msg.set_secondary_text (_("Click the Close button to try again."));
2467 msg.set_position (Gtk::WIN_POS_CENTER);
2471 int response = msg.run ();
2476 case RESPONSE_CANCEL:
2486 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2489 Gtk::BUTTONS_CLOSE);
2491 msg.set_title (_("Loading Error"));
2492 msg.set_secondary_text (_("Click the Close button to try again."));
2493 msg.set_position (Gtk::WIN_POS_CENTER);
2497 int response = msg.run ();
2502 case RESPONSE_CANCEL:
2510 connect_to_session (new_session);
2512 Config->set_current_owner (ConfigVariableBase::Interface);
2514 session_loaded = true;
2516 goto_editor_window ();
2519 session->set_clean ();
2530 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2531 uint32_t control_channels,
2532 uint32_t master_channels,
2533 AutoConnectOption input_connect,
2534 AutoConnectOption output_connect,
2537 nframes_t initial_length)
2539 Session *new_session;
2542 if (!check_audioengine()) {
2546 session_loaded = false;
2548 x = unload_session ();
2556 _session_is_new = true;
2559 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2560 control_channels, master_channels, nphysin, nphysout, initial_length);
2565 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2571 connect_to_session (new_session);
2573 session_loaded = true;
2575 new_session->save_state(new_session->name());
2584 editor->show_window ();
2595 ARDOUR_UI::show_about ()
2599 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2606 ARDOUR_UI::launch_chat ()
2609 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2611 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2616 ARDOUR_UI::hide_about ()
2619 about->get_window()->set_cursor ();
2625 ARDOUR_UI::about_signal_response(int response)
2631 ARDOUR_UI::show_splash ()
2635 splash = new Splash;
2643 splash->queue_draw ();
2644 splash->get_window()->process_updates (true);
2649 ARDOUR_UI::hide_splash ()
2657 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2661 removed = rep.paths.size();
2664 MessageDialog msgd (*editor,
2665 _("No audio files were ready for cleanup"),
2668 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2669 msgd.set_secondary_text (_("If this seems suprising, \n\
2670 check for any existing snapshots.\n\
2671 These may still include regions that\n\
2672 require some unused files to continue to exist."));
2678 ArdourDialog results (_("ardour: cleanup"), true, false);
2680 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2681 CleanupResultsModelColumns() {
2685 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2686 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2690 CleanupResultsModelColumns results_columns;
2691 Glib::RefPtr<Gtk::ListStore> results_model;
2692 Gtk::TreeView results_display;
2694 results_model = ListStore::create (results_columns);
2695 results_display.set_model (results_model);
2696 results_display.append_column (list_title, results_columns.visible_name);
2698 results_display.set_name ("CleanupResultsList");
2699 results_display.set_headers_visible (true);
2700 results_display.set_headers_clickable (false);
2701 results_display.set_reorderable (false);
2703 Gtk::ScrolledWindow list_scroller;
2706 Gtk::HBox dhbox; // the hbox for the image and text
2707 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2708 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2710 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2712 if (rep.space < 1048576.0f) {
2714 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2716 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2720 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2722 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2726 dhbox.pack_start (*dimage, true, false, 5);
2727 dhbox.pack_start (txt, true, false, 5);
2729 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2730 TreeModel::Row row = *(results_model->append());
2731 row[results_columns.visible_name] = *i;
2732 row[results_columns.fullpath] = *i;
2735 list_scroller.add (results_display);
2736 list_scroller.set_size_request (-1, 150);
2737 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2739 dvbox.pack_start (dhbox, true, false, 5);
2740 dvbox.pack_start (list_scroller, true, false, 5);
2741 ddhbox.pack_start (dvbox, true, false, 5);
2743 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2744 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2745 results.set_default_response (RESPONSE_CLOSE);
2746 results.set_position (Gtk::WIN_POS_MOUSE);
2747 results.show_all_children ();
2748 results.set_resizable (false);
2755 ARDOUR_UI::cleanup ()
2758 /* shouldn't happen: menu item is insensitive */
2763 MessageDialog checker (_("Are you sure you want to cleanup?"),
2765 Gtk::MESSAGE_QUESTION,
2766 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2768 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2769 ALL undo/redo information will be lost if you cleanup.\n\
2770 After cleanup, unused audio files will be moved to a \
2771 \"dead sounds\" location."));
2773 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2774 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2775 checker.set_default_response (RESPONSE_CANCEL);
2777 checker.set_name (_("CleanupDialog"));
2778 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2779 checker.set_position (Gtk::WIN_POS_MOUSE);
2781 switch (checker.run()) {
2782 case RESPONSE_ACCEPT:
2788 Session::cleanup_report rep;
2790 editor->prepare_for_cleanup ();
2792 /* do not allow flush until a session is reloaded */
2794 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2796 act->set_sensitive (false);
2799 if (session->cleanup_sources (rep)) {
2800 editor->finish_cleanup ();
2804 editor->finish_cleanup ();
2807 display_cleanup_results (rep,
2810 The following %1 %2 not in use and \n\
2811 have been moved to:\n\
2813 Flushing the wastebasket will \n\
2814 release an additional\n\
2815 %4 %5bytes of disk space.\n"
2821 ARDOUR_UI::flush_trash ()
2824 /* shouldn't happen: menu item is insensitive */
2828 Session::cleanup_report rep;
2830 if (session->cleanup_trash_sources (rep)) {
2834 display_cleanup_results (rep,
2836 _("The following %1 %2 deleted from\n\
2838 releasing %4 %5bytes of disk space"));
2842 ARDOUR_UI::add_route (Gtk::Window* float_window)
2850 if (add_route_dialog == 0) {
2851 add_route_dialog = new AddRouteDialog;
2853 add_route_dialog->set_transient_for (*float_window);
2857 if (add_route_dialog->is_visible()) {
2858 /* we're already doing this */
2862 ResponseType r = (ResponseType) add_route_dialog->run ();
2864 add_route_dialog->hide();
2867 case RESPONSE_ACCEPT:
2874 if ((count = add_route_dialog->count()) <= 0) {
2878 string template_path = add_route_dialog->track_template();
2880 if (!template_path.empty()) {
2881 session->new_route_from_template (count, template_path);
2885 uint32_t input_chan = add_route_dialog->channels ();
2886 uint32_t output_chan;
2887 string name_template = add_route_dialog->name_template ();
2888 bool track = add_route_dialog->track ();
2890 AutoConnectOption oac = Config->get_output_auto_connect();
2892 if (oac & AutoConnectMaster) {
2893 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2895 output_chan = input_chan;
2898 /* XXX do something with name template */
2901 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2903 session_add_audio_bus (input_chan, output_chan, count);
2908 ARDOUR_UI::mixer_settings () const
2913 node = session->instant_xml(X_("Mixer"), session->path());
2915 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2919 node = new XMLNode (X_("Mixer"));
2926 ARDOUR_UI::editor_settings () const
2931 node = session->instant_xml(X_("Editor"), session->path());
2933 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2937 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2938 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2943 node = new XMLNode (X_("Editor"));
2949 ARDOUR_UI::keyboard_settings () const
2953 node = Config->extra_xml(X_("Keyboard"));
2956 node = new XMLNode (X_("Keyboard"));
2962 ARDOUR_UI::create_xrun_marker(nframes_t where)
2964 editor->mouse_add_new_marker (where, false, true);
2968 ARDOUR_UI::halt_on_xrun_message ()
2970 MessageDialog msg (*editor,
2971 _("Recording was stopped because your system could not keep up."));
2976 ARDOUR_UI::xrun_handler(nframes_t where)
2982 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2984 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2985 create_xrun_marker(where);
2988 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2989 halt_on_xrun_message ();
2994 ARDOUR_UI::preset_file_exists_handler ()
2996 /* if driven from another thread, say "do not overwrite" and show the user nothing.
2999 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3003 HBox* hbox = new HBox();
3004 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3005 Gtk::Dialog dialog (_("Preset Exists"), true, false);
3007 A preset with this name already exists for this plugin.\n\
3009 What you would like to do?\n"));
3010 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3011 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3012 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3013 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3014 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3015 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3016 dialog.set_default_response (RESPONSE_ACCEPT);
3017 dialog.set_position (WIN_POS_MOUSE);
3018 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3024 switch (dialog.run ()) {
3025 case RESPONSE_ACCEPT:
3033 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3038 while (disk_buffer_stats.size() > 60) {
3039 disk_buffer_stats.pop_front ();
3042 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3046 ARDOUR_UI::write_buffer_stats ()
3053 if ((path = tempnam (0, "ardourBuffering")) == 0) {
3054 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3061 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3065 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3066 localtime_r (&(*i).when, &tm);
3067 strftime (buf, sizeof (buf), "%T", &tm);
3068 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3071 disk_buffer_stats.clear ();
3075 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3080 ARDOUR_UI::disk_overrun_handler ()
3083 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3085 write_buffer_stats ();
3087 if (!have_disk_speed_dialog_displayed) {
3088 have_disk_speed_dialog_displayed = true;
3089 MessageDialog* msg = new MessageDialog (*editor, _("\
3090 The disk system on your computer\n\
3091 was not able to keep up with Ardour.\n\
3093 Specifically, it failed to write data to disk\n\
3094 quickly enough to keep up with recording.\n"));
3095 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3101 ARDOUR_UI::disk_underrun_handler ()
3104 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3106 write_buffer_stats ();
3108 if (!have_disk_speed_dialog_displayed) {
3109 have_disk_speed_dialog_displayed = true;
3110 MessageDialog* msg = new MessageDialog (*editor,
3111 _("The disk system on your computer\n\
3112 was not able to keep up with Ardour.\n\
3114 Specifically, it failed to read data from disk\n\
3115 quickly enough to keep up with playback.\n"));
3116 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3122 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3124 have_disk_speed_dialog_displayed = false;
3129 ARDOUR_UI::session_dialog (std::string msg)
3131 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3136 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3138 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3147 ARDOUR_UI::pending_state_dialog ()
3149 HBox* hbox = new HBox();
3150 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3151 ArdourDialog dialog (_("Crash Recovery"), true);
3153 This session appears to have been in\n\
3154 middle of recording when ardour or\n\
3155 the computer was shutdown.\n\
3157 Ardour can recover any captured audio for\n\
3158 you, or it can ignore it. Please decide\n\
3159 what you would like to do.\n"));
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 (_("Ignore crash data"), RESPONSE_REJECT);
3165 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3166 dialog.set_default_response (RESPONSE_ACCEPT);
3167 dialog.set_position (WIN_POS_CENTER);
3174 switch (dialog.run ()) {
3175 case RESPONSE_ACCEPT:
3183 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3185 HBox* hbox = new HBox();
3186 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3187 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3188 Label message (string_compose (_("\
3189 This session was created with a sample rate of %1 Hz\n\
3191 The audioengine is currently running at %2 Hz\n"), desired, actual));
3193 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3194 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3195 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3196 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3197 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3198 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3199 dialog.set_default_response (RESPONSE_ACCEPT);
3200 dialog.set_position (WIN_POS_CENTER);
3205 switch (dialog.run ()) {
3206 case RESPONSE_ACCEPT:
3215 ARDOUR_UI::disconnect_from_jack ()
3218 if( engine->disconnect_from_jack ()) {
3219 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3223 update_sample_rate (0);
3228 ARDOUR_UI::reconnect_to_jack ()
3231 if (engine->reconnect_to_jack ()) {
3232 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3236 update_sample_rate (0);
3241 ARDOUR_UI::use_config ()
3243 Glib::RefPtr<Action> act;
3245 switch (Config->get_native_file_data_format ()) {
3247 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3250 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3253 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3258 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3259 ract->set_active ();
3262 switch (Config->get_native_file_header_format ()) {
3264 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3267 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3270 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3273 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3276 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3279 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3282 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3287 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3288 ract->set_active ();
3291 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3293 set_transport_controllable_state (*node);
3298 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3300 if (Config->get_primary_clock_delta_edit_cursor()) {
3301 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3303 primary_clock.set (pos, 0, true);
3306 if (Config->get_secondary_clock_delta_edit_cursor()) {
3307 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3309 secondary_clock.set (pos);
3312 if (big_clock_window) {
3313 big_clock.set (pos);
3318 ARDOUR_UI::record_state_changed ()
3320 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3322 if (!session || !big_clock_window) {
3323 /* why bother - the clock isn't visible */
3327 switch (session->record_status()) {
3328 case Session::Recording:
3329 big_clock.set_widget_name ("BigClockRecording");
3332 big_clock.set_widget_name ("BigClockNonRecording");
3338 ARDOUR_UI::first_idle ()
3341 session->allow_auto_play (true);
3345 editor->first_idle();
3348 Keyboard::set_can_save_keybindings (true);
3353 ARDOUR_UI::store_clock_modes ()
3355 XMLNode* node = new XMLNode(X_("ClockModes"));
3357 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3358 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3361 session->add_extra_xml (*node);
3362 session->set_dirty ();
3367 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3368 : Controllable (name), ui (u), type(tp)
3374 ARDOUR_UI::TransportControllable::set_value (float val)
3376 if (type == ShuttleControl) {
3383 fract = -((0.5f - val)/0.5f);
3385 fract = ((val - 0.5f)/0.5f);
3389 ui.set_shuttle_fract (fract);
3394 /* do nothing: these are radio-style actions */
3398 const char *action = 0;
3402 action = X_("Roll");
3405 action = X_("Stop");
3408 action = X_("Goto Start");
3411 action = X_("Goto End");
3414 action = X_("Loop");
3417 action = X_("Play Selection");
3420 action = X_("Record");
3430 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3438 ARDOUR_UI::TransportControllable::get_value (void) const
3457 case ShuttleControl:
3467 ARDOUR_UI::TransportControllable::set_id (const string& str)
3473 ARDOUR_UI::setup_profile ()
3475 if (gdk_screen_width() < 1200) {
3476 Profile->set_small_screen ();
3479 if (getenv ("ARDOUR_SAE")) {
3480 Profile->set_sae ();
3481 Profile->set_single_package ();