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);
1855 switch (prompter.run()) {
1856 case RESPONSE_ACCEPT:
1857 prompter.get_result (snapname);
1858 if (snapname.length()){
1859 if (snapname.find ('/') != string::npos) {
1860 MessageDialog msg (_("To ensure compatibility with various systems\n"
1861 "snapshot names may not contain a '/' character"));
1865 if (snapname.find ('\\') != string::npos) {
1866 MessageDialog msg (_("To ensure compatibility with various systems\n"
1867 "snapshot names may not contain a '\\' character"));
1871 save_state (snapname);
1881 ARDOUR_UI::save_state (const string & name)
1883 (void) save_state_canfail (name);
1887 ARDOUR_UI::save_state_canfail (string name)
1892 if (name.length() == 0) {
1893 name = session->snap_name();
1896 if ((ret = session->save_state (name)) != 0) {
1900 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1905 ARDOUR_UI::primary_clock_value_changed ()
1908 session->request_locate (primary_clock.current_time ());
1913 ARDOUR_UI::big_clock_value_changed ()
1916 session->request_locate (big_clock.current_time ());
1921 ARDOUR_UI::secondary_clock_value_changed ()
1924 session->request_locate (secondary_clock.current_time ());
1929 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1935 switch (session->record_status()) {
1936 case Session::Enabled:
1938 rec_button.set_visual_state (2);
1940 rec_button.set_visual_state (0);
1944 case Session::Recording:
1945 rec_button.set_visual_state (1);
1949 rec_button.set_visual_state (0);
1955 ARDOUR_UI::save_template ()
1958 ArdourPrompter prompter (true);
1961 if (!check_audioengine()) {
1965 prompter.set_name (X_("Prompter"));
1966 prompter.set_prompt (_("Name for mix template:"));
1967 prompter.set_initial_text(session->name() + _("-template"));
1968 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1970 switch (prompter.run()) {
1971 case RESPONSE_ACCEPT:
1972 prompter.get_result (name);
1974 if (name.length()) {
1975 session->save_template (name);
1985 ARDOUR_UI::fontconfig_dialog ()
1988 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1989 may not and it can take a while to build it. Warn them.
1992 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1994 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1995 MessageDialog msg (*new_session_dialog,
1996 _("Welcome to Ardour.\n\n"
1997 "The program will take a bit longer to start up\n"
1998 "while the system fonts are checked.\n\n"
1999 "This will only be done once, and you will\n"
2000 "not see this message again\n"),
2013 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2015 existing_session = false;
2017 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2018 session_path = cmdline_path;
2019 existing_session = true;
2020 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2021 session_path = Glib::path_get_dirname (string (cmdline_path));
2022 existing_session = true;
2024 /* it doesn't exist, assume the best */
2025 session_path = Glib::path_get_dirname (string (cmdline_path));
2028 session_name = basename_nosuffix (string (cmdline_path));
2032 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2034 /* when this is called, the backend audio system must be running */
2036 /* the main idea here is to deal with the fact that a cmdline argument for the session
2037 can be interpreted in different ways - it could be a directory or a file, and before
2038 we load, we need to know both the session directory and the snapshot (statefile) within it
2039 that we are supposed to use.
2042 if (session_name.length() == 0 || session_path.length() == 0) {
2046 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2048 Glib::ustring predicted_session_file;
2050 predicted_session_file = session_path;
2051 predicted_session_file += '/';
2052 predicted_session_file += session_name;
2053 predicted_session_file += Session::statefile_suffix();
2055 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2056 existing_session = true;
2059 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2061 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2062 /* existing .ardour file */
2063 existing_session = true;
2067 existing_session = false;
2070 /* lets just try to load it */
2072 if (create_engine ()) {
2073 backend_audio_error (false, new_session_dialog);
2077 return load_session (session_path, session_name);
2081 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2083 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2085 MessageDialog msg (str,
2087 Gtk::MESSAGE_WARNING,
2088 Gtk::BUTTONS_YES_NO,
2092 msg.set_name (X_("CleanupDialog"));
2093 msg.set_wmclass (X_("existing_session"), "Ardour");
2094 msg.set_position (Gtk::WIN_POS_MOUSE);
2097 switch (msg.run()) {
2106 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2111 AutoConnectOption iconnect;
2112 AutoConnectOption oconnect;
2116 if (Profile->get_sae()) {
2120 iconnect = AutoConnectPhysical;
2121 oconnect = AutoConnectMaster;
2122 nphysin = 0; // use all available
2123 nphysout = 0; // use all available
2127 /* get settings from advanced section of NSD */
2129 if (new_session_dialog->create_control_bus()) {
2130 cchns = (uint32_t) new_session_dialog->control_channel_count();
2135 if (new_session_dialog->create_master_bus()) {
2136 mchns = (uint32_t) new_session_dialog->master_channel_count();
2141 if (new_session_dialog->connect_inputs()) {
2142 iconnect = AutoConnectPhysical;
2144 iconnect = AutoConnectOption (0);
2147 /// @todo some minor tweaks.
2149 if (new_session_dialog->connect_outs_to_master()) {
2150 oconnect = AutoConnectMaster;
2151 } else if (new_session_dialog->connect_outs_to_physical()) {
2152 oconnect = AutoConnectPhysical;
2154 oconnect = AutoConnectOption (0);
2157 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2158 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2161 if (build_session (session_path,
2169 engine->frame_rate() * 60 * 5)) {
2178 ARDOUR_UI::end_loading_messages ()
2184 ARDOUR_UI::loading_message (const std::string& msg)
2187 splash->message (msg);
2192 ARDOUR_UI::idle_load (const Glib::ustring& path)
2195 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2196 /* /path/to/foo => /path/to/foo, foo */
2197 load_session (path, basename_nosuffix (path));
2199 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2200 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2204 ARDOUR_COMMAND_LINE::session_name = path;
2206 if (new_session_dialog) {
2209 /* make it break out of Dialog::run() and
2213 new_session_dialog->response (1);
2219 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2221 bool existing_session = false;
2222 Glib::ustring session_name;
2223 Glib::ustring session_path;
2224 Glib::ustring template_name;
2228 response = Gtk::RESPONSE_NONE;
2230 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2232 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2234 /* don't ever reuse this */
2236 ARDOUR_COMMAND_LINE::session_name = string();
2238 if (existing_session && backend_audio_is_running) {
2240 /* just load the thing already */
2242 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2247 /* make the NSD use whatever information we have */
2249 new_session_dialog->set_session_name (session_name);
2250 new_session_dialog->set_session_folder (session_path);
2253 /* loading failed, or we need the NSD for something */
2255 new_session_dialog->set_modal (false);
2256 new_session_dialog->set_position (WIN_POS_CENTER);
2257 new_session_dialog->set_current_page (0);
2258 new_session_dialog->set_existing_session (existing_session);
2259 new_session_dialog->reset_recent();
2262 new_session_dialog->set_have_engine (backend_audio_is_running);
2263 new_session_dialog->present ();
2264 response = new_session_dialog->run ();
2266 _session_is_new = false;
2268 /* handle possible negative responses */
2272 /* sent by idle_load, meaning restart the whole process again */
2273 new_session_dialog->hide();
2274 new_session_dialog->reset();
2278 case Gtk::RESPONSE_CANCEL:
2279 case Gtk::RESPONSE_DELETE_EVENT:
2281 if (engine && engine->running()) {
2282 engine->stop (true);
2286 new_session_dialog->hide ();
2289 case Gtk::RESPONSE_NONE:
2290 /* "Clear" was pressed */
2294 fontconfig_dialog();
2296 if (!backend_audio_is_running) {
2297 int ret = new_session_dialog->engine_control.setup_engine ();
2300 } else if (ret > 0) {
2301 response = Gtk::RESPONSE_REJECT;
2306 if (create_engine ()) {
2308 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2311 new_session_dialog->set_existing_session (false);
2312 new_session_dialog->set_current_page (2);
2314 response = Gtk::RESPONSE_NONE;
2318 backend_audio_is_running = true;
2320 if (response == Gtk::RESPONSE_OK) {
2322 session_name = new_session_dialog->session_name();
2324 if (session_name.empty()) {
2325 response = Gtk::RESPONSE_NONE;
2329 /* if the user mistakenly typed path information into the session filename entry,
2330 convert what they typed into a path & a name
2333 if (session_name[0] == '/' ||
2334 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2335 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2337 session_path = Glib::path_get_dirname (session_name);
2338 session_name = Glib::path_get_basename (session_name);
2342 session_path = new_session_dialog->session_folder();
2345 template_name = Glib::ustring();
2346 switch (new_session_dialog->which_page()) {
2348 case NewSessionDialog::OpenPage:
2349 case NewSessionDialog::EnginePage:
2353 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2355 should_be_new = true;
2357 if (session_name.find ('/') != Glib::ustring::npos) {
2358 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2359 "session names may not contain a '/' character"));
2361 response = RESPONSE_NONE;
2365 if (session_name.find ('\\') != Glib::ustring::npos) {
2366 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2367 "session names may not contain a '\\' character"));
2369 response = RESPONSE_NONE;
2373 //XXX This is needed because session constructor wants a
2374 //non-existant path. hopefully this will be fixed at some point.
2376 session_path = Glib::build_filename (session_path, session_name);
2378 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2380 if (ask_about_loading_existing_session (session_path)) {
2383 response = RESPONSE_NONE;
2388 _session_is_new = true;
2390 if (new_session_dialog->use_session_template()) {
2392 template_name = new_session_dialog->session_template_name();
2396 if (build_session_from_nsd (session_path, session_name)) {
2397 response = RESPONSE_NONE;
2409 new_session_dialog->hide ();
2411 if (load_session (session_path, session_name, template_name)) {
2413 response = Gtk::RESPONSE_NONE;
2417 if (response == Gtk::RESPONSE_NONE) {
2418 new_session_dialog->set_existing_session (false);
2419 new_session_dialog->reset ();
2423 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2427 new_session_dialog->hide();
2428 new_session_dialog->reset();
2429 goto_editor_window ();
2434 ARDOUR_UI::close_session ()
2436 if (!check_audioengine()) {
2440 if (unload_session (true)) {
2444 get_session_parameters (true, false);
2448 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2450 Session *new_session;
2454 session_loaded = false;
2456 if (!check_audioengine()) {
2460 unload_status = unload_session ();
2462 if (unload_status < 0) {
2464 } else if (unload_status > 0) {
2469 /* if it already exists, we must have write access */
2471 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2472 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2473 "This prevents the session from being loaded."));
2479 loading_message (_("Please wait while Ardour loads your session"));
2482 new_session = new Session (*engine, path, snap_name, mix_template);
2485 /* this one is special */
2487 catch (AudioEngine::PortRegistrationFailure& err) {
2489 MessageDialog msg (err.what(),
2492 Gtk::BUTTONS_CLOSE);
2494 msg.set_title (_("Port Registration Error"));
2495 msg.set_secondary_text (_("Click the Close button to try again."));
2496 msg.set_position (Gtk::WIN_POS_CENTER);
2500 int response = msg.run ();
2505 case RESPONSE_CANCEL:
2515 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2518 Gtk::BUTTONS_CLOSE);
2520 msg.set_title (_("Loading Error"));
2521 msg.set_secondary_text (_("Click the Close button to try again."));
2522 msg.set_position (Gtk::WIN_POS_CENTER);
2526 int response = msg.run ();
2531 case RESPONSE_CANCEL:
2539 connect_to_session (new_session);
2541 Config->set_current_owner (ConfigVariableBase::Interface);
2543 session_loaded = true;
2545 goto_editor_window ();
2548 session->set_clean ();
2559 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2560 uint32_t control_channels,
2561 uint32_t master_channels,
2562 AutoConnectOption input_connect,
2563 AutoConnectOption output_connect,
2566 nframes_t initial_length)
2568 Session *new_session;
2571 if (!check_audioengine()) {
2575 session_loaded = false;
2577 x = unload_session ();
2585 _session_is_new = true;
2588 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2589 control_channels, master_channels, nphysin, nphysout, initial_length);
2594 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2600 connect_to_session (new_session);
2602 session_loaded = true;
2604 new_session->save_state(new_session->name());
2613 editor->show_window ();
2624 ARDOUR_UI::show_about ()
2628 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2635 ARDOUR_UI::launch_chat ()
2638 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2640 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2645 ARDOUR_UI::hide_about ()
2648 about->get_window()->set_cursor ();
2654 ARDOUR_UI::about_signal_response(int response)
2660 ARDOUR_UI::show_splash ()
2664 splash = new Splash;
2672 splash->queue_draw ();
2673 splash->get_window()->process_updates (true);
2678 ARDOUR_UI::hide_splash ()
2686 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2687 const string& plural_msg, const string& singular_msg)
2691 removed = rep.paths.size();
2694 MessageDialog msgd (*editor,
2695 _("No audio files were ready for cleanup"),
2698 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2699 msgd.set_secondary_text (_("If this seems suprising, \n\
2700 check for any existing snapshots.\n\
2701 These may still include regions that\n\
2702 require some unused files to continue to exist."));
2708 ArdourDialog results (_("ardour: cleanup"), true, false);
2710 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2711 CleanupResultsModelColumns() {
2715 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2716 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2720 CleanupResultsModelColumns results_columns;
2721 Glib::RefPtr<Gtk::ListStore> results_model;
2722 Gtk::TreeView results_display;
2724 results_model = ListStore::create (results_columns);
2725 results_display.set_model (results_model);
2726 results_display.append_column (list_title, results_columns.visible_name);
2728 results_display.set_name ("CleanupResultsList");
2729 results_display.set_headers_visible (true);
2730 results_display.set_headers_clickable (false);
2731 results_display.set_reorderable (false);
2733 Gtk::ScrolledWindow list_scroller;
2736 Gtk::HBox dhbox; // the hbox for the image and text
2737 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2738 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2740 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2744 %1 - number of files removed
2745 %2 - location of "dead_sounds"
2746 %3 - size of files affected
2747 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2750 const char* bprefix;
2751 float space_adjusted;
2753 if (rep.space < 1000000.0f) {
2754 bprefix = X_("kilo");
2755 space_adjusted = truncf((float)rep.space / 1000.0f);
2756 } else if (rep.space < (1000000.0f * 1000)) {
2757 bprefix = X_("mega");
2758 space_adjusted = truncf((float)rep.space / (1000000.0f));
2760 bprefix = X_("giga");
2761 space_adjusted = truncf((float)rep.space / (1000000.0f * 1000));
2765 txt.set_text (string_compose (plural_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2767 txt.set_text (string_compose (singular_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2770 dhbox.pack_start (*dimage, true, false, 5);
2771 dhbox.pack_start (txt, true, false, 5);
2773 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2774 TreeModel::Row row = *(results_model->append());
2775 row[results_columns.visible_name] = *i;
2776 row[results_columns.fullpath] = *i;
2779 list_scroller.add (results_display);
2780 list_scroller.set_size_request (-1, 150);
2781 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2783 dvbox.pack_start (dhbox, true, false, 5);
2784 dvbox.pack_start (list_scroller, true, false, 5);
2785 ddhbox.pack_start (dvbox, true, false, 5);
2787 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2788 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2789 results.set_default_response (RESPONSE_CLOSE);
2790 results.set_position (Gtk::WIN_POS_MOUSE);
2791 results.show_all_children ();
2792 results.set_resizable (false);
2799 ARDOUR_UI::cleanup ()
2802 /* shouldn't happen: menu item is insensitive */
2807 MessageDialog checker (_("Are you sure you want to cleanup?"),
2809 Gtk::MESSAGE_QUESTION,
2810 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2812 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2813 ALL undo/redo information will be lost if you cleanup.\n\
2814 After cleanup, unused audio files will be moved to a \
2815 \"dead sounds\" location."));
2817 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2818 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2819 checker.set_default_response (RESPONSE_CANCEL);
2821 checker.set_name (_("CleanupDialog"));
2822 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2823 checker.set_position (Gtk::WIN_POS_MOUSE);
2825 switch (checker.run()) {
2826 case RESPONSE_ACCEPT:
2832 Session::cleanup_report rep;
2834 editor->prepare_for_cleanup ();
2836 /* do not allow flush until a session is reloaded */
2838 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2840 act->set_sensitive (false);
2843 if (session->cleanup_sources (rep)) {
2844 editor->finish_cleanup ();
2848 editor->finish_cleanup ();
2851 display_cleanup_results (rep,
2854 The following %1 files were not in use and \n\
2855 have been moved to:\n\
2857 Flushing the wastebasket will \n\
2858 release an additional\n\
2859 %3 %4bytes of disk space.\n"),
2861 The following file was not in use and \n \
2862 has been moved to:\n \
2864 Flushing the wastebasket will \n\
2865 release an additional\n\
2866 %3 %4bytes of disk space.\n"
2872 ARDOUR_UI::flush_trash ()
2875 /* shouldn't happen: menu item is insensitive */
2879 Session::cleanup_report rep;
2881 if (session->cleanup_trash_sources (rep)) {
2885 display_cleanup_results (rep,
2887 _("The following %1 files were deleted from\n\
2889 releasing %3 %4bytes of disk space"),
2890 _("The following file was deleted from\n\
2892 releasing %3 %4bytes of disk space"));
2896 ARDOUR_UI::add_route (Gtk::Window* float_window)
2904 if (add_route_dialog == 0) {
2905 add_route_dialog = new AddRouteDialog;
2907 add_route_dialog->set_transient_for (*float_window);
2911 if (add_route_dialog->is_visible()) {
2912 /* we're already doing this */
2916 ResponseType r = (ResponseType) add_route_dialog->run ();
2918 add_route_dialog->hide();
2921 case RESPONSE_ACCEPT:
2928 if ((count = add_route_dialog->count()) <= 0) {
2932 string template_path = add_route_dialog->track_template();
2934 if (!template_path.empty()) {
2935 session->new_route_from_template (count, template_path);
2939 uint32_t input_chan = add_route_dialog->channels ();
2940 uint32_t output_chan;
2941 string name_template = add_route_dialog->name_template ();
2942 bool track = add_route_dialog->track ();
2944 AutoConnectOption oac = Config->get_output_auto_connect();
2946 if (oac & AutoConnectMaster) {
2947 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2949 output_chan = input_chan;
2952 /* XXX do something with name template */
2955 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2957 session_add_audio_bus (input_chan, output_chan, count);
2962 ARDOUR_UI::mixer_settings () const
2967 node = session->instant_xml(X_("Mixer"), session->path());
2969 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2973 node = new XMLNode (X_("Mixer"));
2980 ARDOUR_UI::editor_settings () const
2985 node = session->instant_xml(X_("Editor"), session->path());
2987 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2991 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2992 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
2997 node = new XMLNode (X_("Editor"));
3003 ARDOUR_UI::keyboard_settings () const
3007 node = Config->extra_xml(X_("Keyboard"));
3010 node = new XMLNode (X_("Keyboard"));
3016 ARDOUR_UI::create_xrun_marker(nframes_t where)
3018 editor->mouse_add_new_marker (where, false, true);
3022 ARDOUR_UI::halt_on_xrun_message ()
3024 MessageDialog msg (*editor,
3025 _("Recording was stopped because your system could not keep up."));
3030 ARDOUR_UI::xrun_handler(nframes_t where)
3036 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3038 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3039 create_xrun_marker(where);
3042 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3043 halt_on_xrun_message ();
3048 ARDOUR_UI::preset_file_exists_handler ()
3050 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3053 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3057 HBox* hbox = new HBox();
3058 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3059 Gtk::Dialog dialog (_("Preset Exists"), true, false);
3061 A preset with this name already exists for this plugin.\n\
3063 What you would like to do?\n"));
3064 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3065 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3066 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3067 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3068 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3069 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3070 dialog.set_default_response (RESPONSE_ACCEPT);
3071 dialog.set_position (WIN_POS_MOUSE);
3072 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3078 switch (dialog.run ()) {
3079 case RESPONSE_ACCEPT:
3087 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3092 while (disk_buffer_stats.size() > 60) {
3093 disk_buffer_stats.pop_front ();
3096 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3100 ARDOUR_UI::write_buffer_stats ()
3107 if ((path = tempnam (0, "ardourBuffering")) == 0) {
3108 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3115 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3119 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3120 localtime_r (&(*i).when, &tm);
3121 strftime (buf, sizeof (buf), "%T", &tm);
3122 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3125 disk_buffer_stats.clear ();
3129 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3134 ARDOUR_UI::disk_overrun_handler ()
3137 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3139 write_buffer_stats ();
3141 if (!have_disk_speed_dialog_displayed) {
3142 have_disk_speed_dialog_displayed = true;
3143 MessageDialog* msg = new MessageDialog (*editor, _("\
3144 The disk system on your computer\n\
3145 was not able to keep up with Ardour.\n\
3147 Specifically, it failed to write data to disk\n\
3148 quickly enough to keep up with recording.\n"));
3149 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3155 ARDOUR_UI::disk_underrun_handler ()
3158 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3160 write_buffer_stats ();
3162 if (!have_disk_speed_dialog_displayed) {
3163 have_disk_speed_dialog_displayed = true;
3164 MessageDialog* msg = new MessageDialog (*editor,
3165 _("The disk system on your computer\n\
3166 was not able to keep up with Ardour.\n\
3168 Specifically, it failed to read data from disk\n\
3169 quickly enough to keep up with playback.\n"));
3170 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3176 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3178 have_disk_speed_dialog_displayed = false;
3183 ARDOUR_UI::session_dialog (std::string msg)
3185 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3190 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3192 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3201 ARDOUR_UI::pending_state_dialog ()
3203 HBox* hbox = new HBox();
3204 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3205 ArdourDialog dialog (_("Crash Recovery"), true);
3207 This session appears to have been in\n\
3208 middle of recording when ardour or\n\
3209 the computer was shutdown.\n\
3211 Ardour can recover any captured audio for\n\
3212 you, or it can ignore it. Please decide\n\
3213 what you would like to do.\n"));
3214 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3215 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3216 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3217 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3218 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3219 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3220 dialog.set_default_response (RESPONSE_ACCEPT);
3221 dialog.set_position (WIN_POS_CENTER);
3228 switch (dialog.run ()) {
3229 case RESPONSE_ACCEPT:
3237 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3239 HBox* hbox = new HBox();
3240 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3241 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3242 Label message (string_compose (_("\
3243 This session was created with a sample rate of %1 Hz\n\
3245 The audioengine is currently running at %2 Hz\n"), desired, actual));
3247 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3248 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3249 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3250 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3251 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3252 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3253 dialog.set_default_response (RESPONSE_ACCEPT);
3254 dialog.set_position (WIN_POS_CENTER);
3259 switch (dialog.run ()) {
3260 case RESPONSE_ACCEPT:
3269 ARDOUR_UI::disconnect_from_jack ()
3272 if( engine->disconnect_from_jack ()) {
3273 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3277 update_sample_rate (0);
3282 ARDOUR_UI::reconnect_to_jack ()
3285 if (engine->reconnect_to_jack ()) {
3286 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3290 update_sample_rate (0);
3295 ARDOUR_UI::use_config ()
3297 Glib::RefPtr<Action> act;
3299 switch (Config->get_native_file_data_format ()) {
3301 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3304 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3307 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3312 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3313 ract->set_active ();
3316 switch (Config->get_native_file_header_format ()) {
3318 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3321 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3324 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3327 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3330 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3333 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3336 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3341 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3342 ract->set_active ();
3345 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3347 set_transport_controllable_state (*node);
3352 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3354 if (Config->get_primary_clock_delta_edit_cursor()) {
3355 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3357 primary_clock.set (pos, 0, true);
3360 if (Config->get_secondary_clock_delta_edit_cursor()) {
3361 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3363 secondary_clock.set (pos);
3366 if (big_clock_window) {
3367 big_clock.set (pos);
3372 ARDOUR_UI::record_state_changed ()
3374 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3376 if (!session || !big_clock_window) {
3377 /* why bother - the clock isn't visible */
3381 switch (session->record_status()) {
3382 case Session::Recording:
3383 big_clock.set_widget_name ("BigClockRecording");
3386 big_clock.set_widget_name ("BigClockNonRecording");
3392 ARDOUR_UI::first_idle ()
3395 session->allow_auto_play (true);
3399 editor->first_idle();
3402 Keyboard::set_can_save_keybindings (true);
3407 ARDOUR_UI::store_clock_modes ()
3409 XMLNode* node = new XMLNode(X_("ClockModes"));
3411 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3412 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3415 session->add_extra_xml (*node);
3416 session->set_dirty ();
3421 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3422 : Controllable (name), ui (u), type(tp)
3428 ARDOUR_UI::TransportControllable::set_value (float val)
3430 if (type == ShuttleControl) {
3437 fract = -((0.5f - val)/0.5f);
3439 fract = ((val - 0.5f)/0.5f);
3443 ui.set_shuttle_fract (fract);
3448 /* do nothing: these are radio-style actions */
3452 const char *action = 0;
3456 action = X_("Roll");
3459 action = X_("Stop");
3462 action = X_("Goto Start");
3465 action = X_("Goto End");
3468 action = X_("Loop");
3471 action = X_("Play Selection");
3474 action = X_("Record");
3484 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3492 ARDOUR_UI::TransportControllable::get_value (void) const
3511 case ShuttleControl:
3521 ARDOUR_UI::TransportControllable::set_id (const string& str)
3527 ARDOUR_UI::setup_profile ()
3529 if (gdk_screen_width() < 1200) {
3530 Profile->set_small_screen ();
3533 if (getenv ("ARDOUR_SAE")) {
3534 Profile->set_sae ();
3535 Profile->set_single_package ();