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.
32 #include <sys/resource.h>
34 #include <gtkmm/messagedialog.h>
35 #include <gtkmm/accelmap.h>
37 #include <pbd/error.h>
38 #include <pbd/basename.h>
39 #include <pbd/compose.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/stacktrace.h>
44 #include <gtkmm2ext/gtk_ui.h>
45 #include <gtkmm2ext/utils.h>
46 #include <gtkmm2ext/click_box.h>
47 #include <gtkmm2ext/fastmeter.h>
48 #include <gtkmm2ext/stop_signal.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/window_title.h>
52 #include <midi++/port.h>
53 #include <midi++/mmc.h>
55 #include <ardour/ardour.h>
56 #include <ardour/profile.h>
57 #include <ardour/session_route.h>
58 #include <ardour/port.h>
59 #include <ardour/audioengine.h>
60 #include <ardour/playlist.h>
61 #include <ardour/utils.h>
62 #include <ardour/plugin.h>
63 #include <ardour/audio_diskstream.h>
64 #include <ardour/audiofilesource.h>
65 #include <ardour/recent_sessions.h>
66 #include <ardour/port.h>
67 #include <ardour/audio_track.h>
69 typedef uint64_t microseconds_t;
72 #include "ardour_ui.h"
73 #include "public_editor.h"
74 #include "audio_clock.h"
79 #include "add_route_dialog.h"
80 #include "new_session_dialog.h"
85 #include "gui_thread.h"
86 #include "theme_manager.h"
87 #include "engine_dialog.h"
88 #include "gain_meter.h"
89 #include "route_time_axis.h"
93 using namespace ARDOUR;
95 using namespace Gtkmm2ext;
99 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
100 UIConfiguration *ARDOUR_UI::ui_config = 0;
102 sigc::signal<void,bool> ARDOUR_UI::Blink;
103 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
104 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
105 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
107 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
109 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
111 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
112 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
113 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
114 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
118 preroll_button (_("pre\nroll")),
119 postroll_button (_("post\nroll")),
123 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
127 roll_controllable ("transport roll", *this, TransportControllable::Roll),
128 stop_controllable ("transport stop", *this, TransportControllable::Stop),
129 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
130 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
131 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
132 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
133 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
134 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
135 shuttle_controller_binding_proxy (shuttle_controllable),
137 roll_button (&roll_controllable),
138 stop_button (&stop_controllable),
139 goto_start_button (&goto_start_controllable),
140 goto_end_button (&goto_end_controllable),
141 auto_loop_button (&auto_loop_controllable),
142 play_selection_button (&play_selection_controllable),
143 rec_button (&rec_controllable),
145 shuttle_units_button (_("% ")),
147 punch_in_button (_("Punch In")),
148 punch_out_button (_("Punch Out")),
149 auto_return_button (_("Auto Return")),
150 auto_play_button (_("Auto Play")),
151 auto_input_button (_("Auto Input")),
152 click_button (_("Click")),
153 time_master_button (_("time\nmaster")),
155 auditioning_alert_button (_("AUDITION")),
156 solo_alert_button (_("SOLO")),
158 error_log_button (_("Errors"))
160 using namespace Gtk::Menu_Helpers;
165 _auto_display_errors = false;
171 if (ARDOUR_COMMAND_LINE::session_name.length()) {
172 /* only show this if we're not going to post the new session dialog */
176 if (theArdourUI == 0) {
180 ui_config = new UIConfiguration();
181 theme_manager = new ThemeManager();
187 _session_is_new = false;
188 big_clock_window = 0;
189 session_selector_window = 0;
190 new_session_dialog = 0;
191 last_key_press_time = 0;
192 connection_editor = 0;
193 add_route_dialog = 0;
198 open_session_selector = 0;
199 have_configure_timeout = false;
200 have_disk_speed_dialog_displayed = false;
201 _will_create_new_session_automatically = false;
202 session_loaded = false;
203 last_speed_displayed = -1.0f;
204 ignore_dual_punch = false;
205 _mixer_on_top = false;
207 roll_button.unset_flags (Gtk::CAN_FOCUS);
208 stop_button.unset_flags (Gtk::CAN_FOCUS);
209 goto_start_button.unset_flags (Gtk::CAN_FOCUS);
210 goto_end_button.unset_flags (Gtk::CAN_FOCUS);
211 auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
212 play_selection_button.unset_flags (Gtk::CAN_FOCUS);
213 rec_button.unset_flags (Gtk::CAN_FOCUS);
215 last_configure_time= 0;
217 shuttle_grabbed = false;
219 shuttle_max_speed = 8.0f;
221 shuttle_style_menu = 0;
222 shuttle_unit_menu = 0;
224 // We do not have jack linked in yet so;
226 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
228 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
229 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
231 ARDOUR::Plugin::PresetFileExists.connect (mem_fun(*this, &ARDOUR_UI::preset_file_exists_handler));
233 /* handle dialog requests */
235 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
237 /* handle pending state with a dialog */
239 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
241 /* handle sr mismatch with a dialog */
243 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
245 /* lets get this party started */
248 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
249 throw failed_constructor ();
252 setup_gtk_ardour_enums ();
253 Config->set_current_owner (ConfigVariableBase::Interface);
256 GainMeter::setup_slider_pix ();
257 RouteTimeAxisView::setup_slider_pix ();
259 } catch (failed_constructor& err) {
260 error << _("could not initialize Ardour.") << endmsg;
265 /* we like keyboards */
267 keyboard = new Keyboard;
271 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
272 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
278 ARDOUR_UI::create_engine ()
280 // this gets called every time by new_session()
286 loading_message (_("Starting audio engine"));
289 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
296 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
297 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
298 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
299 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
307 ARDOUR_UI::post_engine ()
309 /* Things to be done once we create the AudioEngine
312 check_memory_locking();
314 ActionManager::init ();
317 if (setup_windows ()) {
318 throw failed_constructor ();
321 /* this is the first point at which all the keybindings are available */
323 if (ARDOUR_COMMAND_LINE::show_key_actions) {
324 vector<string> names;
325 vector<string> paths;
327 vector<AccelKey> bindings;
329 ActionManager::get_all_actions (names, paths, keys, bindings);
331 vector<string>::iterator n;
332 vector<string>::iterator k;
333 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
334 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
340 blink_timeout_tag = -1;
342 /* the global configuration object is now valid */
346 /* this being a GUI and all, we want peakfiles */
348 AudioFileSource::set_build_peakfiles (true);
349 AudioFileSource::set_build_missing_peakfiles (true);
351 /* set default clock modes */
353 if (Profile->get_sae()) {
354 primary_clock.set_mode (AudioClock::BBT);
355 secondary_clock.set_mode (AudioClock::MinSec);
357 primary_clock.set_mode (AudioClock::SMPTE);
358 secondary_clock.set_mode (AudioClock::BBT);
361 /* start the time-of-day-clock */
364 /* OS X provides an always visible wallclock, so don't be stupid */
365 update_wall_clock ();
366 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
369 update_disk_space ();
371 update_sample_rate (engine->frame_rate());
373 platform_specific ();
375 /* now start and maybe save state */
377 if (do_engine_start () == 0) {
378 if (session && _session_is_new) {
379 /* we need to retain initial visual
380 settings for a new session
382 session->save_state ("");
387 ARDOUR_UI::~ARDOUR_UI ()
389 save_ardour_state ();
403 if (add_route_dialog) {
404 delete add_route_dialog;
407 if (new_session_dialog) {
408 delete new_session_dialog;
413 ARDOUR_UI::pop_back_splash ()
415 if (Splash::instance()) {
416 // Splash::instance()->pop_back();
417 Splash::instance()->hide ();
422 ARDOUR_UI::configure_timeout ()
424 if (last_configure_time == 0) {
425 /* no configure events yet */
429 /* force a gap of 0.5 seconds since the last configure event
432 if (get_microseconds() - last_configure_time < 500000) {
435 have_configure_timeout = false;
436 save_ardour_state ();
442 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
444 if (have_configure_timeout) {
445 last_configure_time = get_microseconds();
447 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
448 have_configure_timeout = true;
455 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
457 const XMLProperty* prop;
459 if ((prop = node.property ("roll")) != 0) {
460 roll_controllable.set_id (prop->value());
462 if ((prop = node.property ("stop")) != 0) {
463 stop_controllable.set_id (prop->value());
465 if ((prop = node.property ("goto_start")) != 0) {
466 goto_start_controllable.set_id (prop->value());
468 if ((prop = node.property ("goto_end")) != 0) {
469 goto_end_controllable.set_id (prop->value());
471 if ((prop = node.property ("auto_loop")) != 0) {
472 auto_loop_controllable.set_id (prop->value());
474 if ((prop = node.property ("play_selection")) != 0) {
475 play_selection_controllable.set_id (prop->value());
477 if ((prop = node.property ("rec")) != 0) {
478 rec_controllable.set_id (prop->value());
480 if ((prop = node.property ("shuttle")) != 0) {
481 shuttle_controllable.set_id (prop->value());
486 ARDOUR_UI::get_transport_controllable_state ()
488 XMLNode* node = new XMLNode(X_("TransportControllables"));
491 roll_controllable.id().print (buf, sizeof (buf));
492 node->add_property (X_("roll"), buf);
493 stop_controllable.id().print (buf, sizeof (buf));
494 node->add_property (X_("stop"), buf);
495 goto_start_controllable.id().print (buf, sizeof (buf));
496 node->add_property (X_("goto_start"), buf);
497 goto_end_controllable.id().print (buf, sizeof (buf));
498 node->add_property (X_("goto_end"), buf);
499 auto_loop_controllable.id().print (buf, sizeof (buf));
500 node->add_property (X_("auto_loop"), buf);
501 play_selection_controllable.id().print (buf, sizeof (buf));
502 node->add_property (X_("play_selection"), buf);
503 rec_controllable.id().print (buf, sizeof (buf));
504 node->add_property (X_("rec"), buf);
505 shuttle_controllable.id().print (buf, sizeof (buf));
506 node->add_property (X_("shuttle"), buf);
512 ARDOUR_UI::save_ardour_state ()
514 if (!keyboard || !mixer || !editor) {
518 /* XXX this is all a bit dubious. add_extra_xml() uses
519 a different lifetime model from add_instant_xml().
522 XMLNode* node = new XMLNode (keyboard->get_state());
523 Config->add_extra_xml (*node);
524 Config->add_extra_xml (get_transport_controllable_state());
525 if (new_session_dialog) {
526 if (new_session_dialog->engine_control.was_used()) {
527 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
530 Config->save_state();
531 ui_config->save_state ();
533 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
534 XMLNode mnode(mixer->get_state());
537 session->add_instant_xml (enode, session->path());
538 session->add_instant_xml (mnode, session->path());
540 Config->add_instant_xml (enode, get_user_ardour_path());
541 Config->add_instant_xml (mnode, get_user_ardour_path());
544 Keyboard::save_keybindings ();
548 ARDOUR_UI::autosave_session ()
550 if (g_main_depth() > 1) {
551 /* inside a recursive main loop,
552 give up because we may not be able to
558 if (!Config->get_periodic_safety_backups())
562 session->maybe_write_autosave();
569 ARDOUR_UI::update_autosave ()
571 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
573 if (session && session->dirty()) {
574 if (_autosave_connection.connected()) {
575 _autosave_connection.disconnect();
578 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
579 Config->get_periodic_safety_backup_interval() * 1000);
582 if (_autosave_connection.connected()) {
583 _autosave_connection.disconnect();
589 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
593 title = _("Ardour could not start JACK");
595 title = _("Ardour could not connect to JACK.");
598 MessageDialog win (title,
604 win.set_secondary_text(_("There are several possible reasons:\n\
606 1) You requested audio parameters that are not supported..\n\
607 2) JACK is running as another user.\n\
609 Please consider the possibilities, and perhaps try different parameters."));
611 win.set_secondary_text(_("There are several possible reasons:\n\
613 1) JACK is not running.\n\
614 2) JACK is running as another user, perhaps root.\n\
615 3) There is already another client called \"ardour\".\n\
617 Please consider the possibilities, and perhaps (re)start JACK."));
621 win.set_transient_for (*toplevel);
625 win.add_button (Stock::OK, RESPONSE_CLOSE);
627 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
630 win.set_default_response (RESPONSE_CLOSE);
633 win.set_position (Gtk::WIN_POS_CENTER);
636 /* we just don't care about the result, but we want to block */
642 ARDOUR_UI::startup ()
646 new_session_dialog = new NewSessionDialog();
648 bool backend_audio_is_running = EngineControl::engine_running();
649 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
652 new_session_dialog->engine_control.set_state (*audio_setup);
655 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
659 BootMessage (_("Ardour is ready for use"));
664 ARDOUR_UI::no_memory_warning ()
666 XMLNode node (X_("no-memory-warning"));
667 Config->add_instant_xml (node, get_user_ardour_path());
671 ARDOUR_UI::check_memory_locking ()
674 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
678 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
680 if (engine->is_realtime() && memory_warning_node == 0) {
682 struct rlimit limits;
684 long pages, page_size;
686 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
689 ram = (int64_t) pages * (int64_t) page_size;
692 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
696 if (limits.rlim_cur != RLIM_INFINITY) {
698 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
701 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
702 "This might cause Ardour to run out of memory before your system "
703 "runs out of memory. \n\n"
704 "You can view the memory limit with 'ulimit -l', "
705 "and it is normally controlled by /etc/security/limits.conf"));
707 VBox* vbox = msg.get_vbox();
709 CheckButton cb (_("Do not show this window again"));
711 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
713 hbox.pack_start (cb, true, false);
714 vbox->pack_start (hbox);
734 while (session->transport_rolling() && (++tries < 8)) {
735 session->request_stop (true, false);
739 if (session->dirty()) {
740 switch (ask_about_saving_session(_("quit"))) {
745 /* use the default name */
746 if (save_state_canfail ("")) {
747 /* failed - don't quit */
748 MessageDialog msg (*editor,
750 Ardour was unable to save your session.\n\n\
751 If you still wish to quit, please use the\n\n\
752 \"Just quit\" option."));
763 session->set_deletion_in_progress ();
766 ArdourDialog::close_all_dialogs ();
768 save_ardour_state ();
773 ARDOUR_UI::ask_about_saving_session (const string & what)
775 ArdourDialog window (_("ardour: save session?"));
776 Gtk::HBox dhbox; // the hbox for the image and text
777 Gtk::Label prompt_label;
778 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
782 msg = string_compose(_("Don't %1"), what);
783 window.add_button (msg, RESPONSE_REJECT);
784 msg = string_compose(_("Just %1"), what);
785 window.add_button (msg, RESPONSE_APPLY);
786 msg = string_compose(_("Save and %1"), what);
787 window.add_button (msg, RESPONSE_ACCEPT);
789 window.set_default_response (RESPONSE_ACCEPT);
791 Gtk::Button noquit_button (msg);
792 noquit_button.set_name ("EditorGTKButton");
797 if (session->snap_name() == session->name()) {
800 type = _("snapshot");
802 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?"),
803 type, session->snap_name());
805 prompt_label.set_text (prompt);
806 prompt_label.set_name (X_("PrompterLabel"));
807 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
809 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
811 dhbox.set_homogeneous (false);
812 dhbox.pack_start (*dimage, false, false, 5);
813 dhbox.pack_start (prompt_label, true, false, 5);
814 window.get_vbox()->pack_start (dhbox);
816 window.set_name (_("Prompter"));
817 window.set_position (Gtk::WIN_POS_MOUSE);
818 window.set_modal (true);
819 window.set_resizable (false);
822 window.set_keep_above (true);
825 ResponseType r = (ResponseType) window.run();
830 case RESPONSE_ACCEPT: // save and get out of here
832 case RESPONSE_APPLY: // get out of here
842 ARDOUR_UI::every_second ()
845 update_buffer_load ();
846 update_disk_space ();
851 ARDOUR_UI::every_point_one_seconds ()
853 update_speed_display ();
854 RapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::every_point_zero_one_seconds ()
861 // august 2007: actual update frequency: 40Hz, not 100Hz
863 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::update_sample_rate (nframes_t ignored)
872 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
874 if (!engine->connected()) {
876 snprintf (buf, sizeof (buf), _("disconnected"));
880 nframes_t rate = engine->frame_rate();
882 if (fmod (rate, 1000.0) != 0.0) {
883 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
884 (float) rate/1000.0f,
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
887 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
893 sample_rate_label.set_text (buf);
897 ARDOUR_UI::update_cpu_load ()
900 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
901 cpu_load_label.set_text (buf);
905 ARDOUR_UI::update_buffer_load ()
911 c = session->capture_load ();
912 p = session->playback_load ();
914 push_buffer_stats (c, p);
916 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
917 session->playback_load(), session->capture_load());
918 buffer_load_label.set_text (buf);
920 buffer_load_label.set_text ("");
925 ARDOUR_UI::count_recenabled_streams (Route& route)
927 Track* track = dynamic_cast<Track*>(&route);
928 if (track && track->diskstream()->record_enabled()) {
929 rec_enabled_streams += track->n_inputs();
934 ARDOUR_UI::update_disk_space()
940 nframes_t frames = session->available_capture_duration();
943 if (frames == max_frames) {
944 strcpy (buf, _("Disk: 24hrs+"));
949 nframes_t fr = session->frame_rate();
951 rec_enabled_streams = 0;
952 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
954 if (rec_enabled_streams) {
955 frames /= rec_enabled_streams;
958 hrs = frames / (fr * 3600);
959 frames -= hrs * fr * 3600;
960 mins = frames / (fr * 60);
961 frames -= mins * fr * 60;
964 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
967 disk_space_label.set_text (buf);
971 ARDOUR_UI::update_wall_clock ()
978 tm_now = localtime (&now);
980 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
981 wall_clock_label.set_text (buf);
987 ARDOUR_UI::session_menu (GdkEventButton *ev)
989 session_popup_menu->popup (0, 0);
994 ARDOUR_UI::redisplay_recent_sessions ()
996 vector<string *> *sessions;
997 vector<string *>::iterator i;
998 RecentSessionsSorter cmp;
1000 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1001 recent_session_model->clear ();
1004 ARDOUR::read_recent_sessions (rs);
1007 recent_session_display.set_model (recent_session_model);
1011 /* sort them alphabetically */
1012 sort (rs.begin(), rs.end(), cmp);
1013 sessions = new vector<string*>;
1015 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1016 sessions->push_back (new string ((*i).second));
1019 for (i = sessions->begin(); i != sessions->end(); ++i) {
1021 vector<string*>* states;
1022 vector<const gchar*> item;
1023 string fullpath = *(*i);
1025 /* remove any trailing / */
1027 if (fullpath[fullpath.length()-1] == '/') {
1028 fullpath = fullpath.substr (0, fullpath.length()-1);
1031 /* check whether session still exists */
1032 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1033 /* session doesn't exist */
1034 cerr << "skipping non-existent session " << fullpath << endl;
1038 /* now get available states for this session */
1040 if ((states = Session::possible_states (fullpath)) == 0) {
1041 /* no state file? */
1045 TreeModel::Row row = *(recent_session_model->append());
1047 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1048 row[recent_session_columns.fullpath] = fullpath;
1050 if (states->size() > 1) {
1052 /* add the children */
1054 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1056 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1058 child_row[recent_session_columns.visible_name] = **i2;
1059 child_row[recent_session_columns.fullpath] = fullpath;
1068 recent_session_display.set_model (recent_session_model);
1073 ARDOUR_UI::build_session_selector ()
1075 session_selector_window = new ArdourDialog ("session selector");
1077 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1079 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1080 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1081 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1082 recent_session_model = TreeStore::create (recent_session_columns);
1083 recent_session_display.set_model (recent_session_model);
1084 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1085 recent_session_display.set_headers_visible (false);
1086 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1087 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1089 scroller->add (recent_session_display);
1090 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1092 session_selector_window->set_name ("SessionSelectorWindow");
1093 session_selector_window->set_size_request (200, 400);
1094 session_selector_window->get_vbox()->pack_start (*scroller);
1095 session_selector_window->show_all_children();
1099 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1101 session_selector_window->response (RESPONSE_ACCEPT);
1105 ARDOUR_UI::open_recent_session ()
1107 bool can_return = (session != 0);
1109 if (session_selector_window == 0) {
1110 build_session_selector ();
1113 redisplay_recent_sessions ();
1117 session_selector_window->set_position (WIN_POS_MOUSE);
1119 ResponseType r = (ResponseType) session_selector_window->run ();
1122 case RESPONSE_ACCEPT:
1126 session_selector_window->hide();
1133 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1137 session_selector_window->hide();
1139 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1141 if (i == recent_session_model->children().end()) {
1145 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1146 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1148 _session_is_new = false;
1150 if (load_session (path, state) == 0) {
1159 ARDOUR_UI::check_audioengine ()
1162 if (!engine->connected()) {
1163 MessageDialog msg (_("Ardour is not connected to JACK\n"
1164 "You cannot open or close sessions in this condition"));
1166 msg.set_position (WIN_POS_CENTER);
1177 ARDOUR_UI::open_session ()
1179 if (!check_audioengine()) {
1183 /* popup selector window */
1185 if (open_session_selector == 0) {
1187 /* ardour sessions are folders */
1189 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1190 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1191 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1192 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1194 FileFilter session_filter;
1195 session_filter.add_pattern ("*.ardour");
1196 session_filter.set_name (_("Ardour sessions"));
1197 open_session_selector->add_filter (session_filter);
1198 open_session_selector->set_filter (session_filter);
1201 int response = open_session_selector->run();
1202 open_session_selector->hide ();
1205 case RESPONSE_ACCEPT:
1208 open_session_selector->hide();
1212 open_session_selector->hide();
1213 string session_path = open_session_selector->get_filename();
1217 if (session_path.length() > 0) {
1218 if (Session::find_session (session_path, path, name, isnew) == 0) {
1219 _session_is_new = isnew;
1220 load_session (path, name);
1227 ARDOUR_UI::session_add_midi_track ()
1229 cerr << _("Patience is a virtue.\n");
1233 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1235 list<boost::shared_ptr<AudioTrack> > tracks;
1236 Session::RouteList routes;
1239 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1245 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1247 if (tracks.size() != how_many) {
1248 if (how_many == 1) {
1249 error << _("could not create a new audio track") << endmsg;
1251 error << string_compose (_("could only create %1 of %2 new audio %3"),
1252 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1258 routes = session->new_audio_route (input_channels, output_channels, how_many);
1260 if (routes.size() != how_many) {
1261 if (how_many == 1) {
1262 error << _("could not create a new audio track") << endmsg;
1264 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1270 if (need_control_room_outs) {
1276 route->set_stereo_control_outs (control_lr_channels);
1277 route->control_outs()->set_stereo_pan (pans, this);
1279 #endif /* CONTROLOUTS */
1283 MessageDialog msg (*editor,
1284 _("There are insufficient JACK ports available\n\
1285 to create a new track or bus.\n\
1286 You should save Ardour, exit and\n\
1287 restart JACK with more ports."));
1294 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1296 nframes_t _preroll = 0;
1299 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1300 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1302 if (new_position > _preroll) {
1303 new_position -= _preroll;
1308 session->request_locate (new_position);
1313 ARDOUR_UI::transport_goto_start ()
1316 session->goto_start();
1319 /* force displayed area in editor to start no matter
1320 what "follow playhead" setting is.
1324 editor->reset_x_origin (session->current_start_frame());
1330 ARDOUR_UI::transport_goto_zero ()
1333 session->request_locate (0);
1336 /* force displayed area in editor to start no matter
1337 what "follow playhead" setting is.
1341 editor->reset_x_origin (0);
1347 ARDOUR_UI::transport_goto_wallclock ()
1349 if (session && editor) {
1356 localtime_r (&now, &tmnow);
1358 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1359 frames += tmnow.tm_min * (60 * session->frame_rate());
1360 frames += tmnow.tm_sec * session->frame_rate();
1362 session->request_locate (frames);
1364 /* force displayed area in editor to start no matter
1365 what "follow playhead" setting is.
1369 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1375 ARDOUR_UI::transport_goto_end ()
1378 nframes_t frame = session->current_end_frame();
1379 session->request_locate (frame);
1381 /* force displayed area in editor to start no matter
1382 what "follow playhead" setting is.
1386 editor->reset_x_origin (frame);
1392 ARDOUR_UI::transport_stop ()
1398 if (session->is_auditioning()) {
1399 session->cancel_audition ();
1403 session->request_stop (false, true);
1407 ARDOUR_UI::transport_stop_and_forget_capture ()
1410 session->request_stop (true, 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 ()
1461 if (session->is_auditioning()) {
1465 switch (Config->get_slave_source()) {
1470 /* transport controlled by the master */
1474 bool rolling = session->transport_rolling();
1476 if (session->get_play_loop()) {
1477 /* XXX it is not possible to just leave seamless loop and keep
1478 playing at present (nov 4th 2009)
1480 if (!Config->get_seamless_loop()) {
1482 session->request_play_loop (false, true);
1486 } else if (session->get_play_range ()) {
1487 list<AudioRange> empty;
1488 session->request_play_range (empty, false, true);
1492 session->request_transport_speed (1.0f);
1495 map_transport_state ();
1499 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1506 if (session->is_auditioning()) {
1507 session->cancel_audition ();
1511 switch (Config->get_slave_source()) {
1516 /* transport controlled by the master */
1520 bool rolling = session->transport_rolling();
1521 bool affect_transport = true;
1523 if (rolling && roll_out_of_bounded_mode) {
1524 /* drop out of loop/range playback but leave transport rolling */
1525 if (session->get_play_loop()) {
1526 if (Config->get_seamless_loop()) {
1527 /* the disk buffers contain copies of the loop - we can't
1528 just keep playing, so stop the transport. the user
1529 can restart as they wish.
1531 affect_transport = true;
1533 /* disk buffers are normal, so we can keep playing */
1534 affect_transport = false;
1536 session->request_play_loop (false, true);
1537 } else if (session->get_play_range ()) {
1538 affect_transport = false;
1539 list<AudioRange> empty;
1540 session->request_play_range (empty, false, true);
1544 if (affect_transport) {
1546 session->request_stop (with_abort, true);
1548 session->request_transport_speed (1.0f);
1552 map_transport_state ();
1556 ARDOUR_UI::toggle_session_auto_loop ()
1559 if (session->get_play_loop()) {
1560 if (session->transport_rolling()) {
1561 Location * looploc = session->locations()->auto_loop_location();
1563 session->request_locate (looploc->start(), true);
1566 session->request_play_loop (false);
1569 Location * looploc = session->locations()->auto_loop_location();
1571 session->request_play_loop (true);
1578 ARDOUR_UI::transport_play_selection ()
1584 editor->play_selection ();
1588 ARDOUR_UI::transport_rewind (int option)
1590 float current_transport_speed;
1593 current_transport_speed = session->transport_speed();
1595 if (current_transport_speed >= 0.0f) {
1598 session->request_transport_speed (-1.0f);
1601 session->request_transport_speed (-4.0f);
1604 session->request_transport_speed (-0.5f);
1609 session->request_transport_speed (current_transport_speed * 1.5f);
1615 ARDOUR_UI::transport_forward (int option)
1617 float current_transport_speed;
1620 current_transport_speed = session->transport_speed();
1622 if (current_transport_speed <= 0.0f) {
1625 session->request_transport_speed (1.0f);
1628 session->request_transport_speed (4.0f);
1631 session->request_transport_speed (0.5f);
1636 session->request_transport_speed (current_transport_speed * 1.5f);
1642 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1648 boost::shared_ptr<Route> r;
1650 if ((r = session->route_by_remote_id (dstream)) != 0) {
1654 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1655 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1664 ARDOUR_UI::queue_transport_change ()
1666 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1670 ARDOUR_UI::map_transport_state ()
1673 auto_loop_button.set_visual_state (0);
1674 play_selection_button.set_visual_state (0);
1675 roll_button.set_visual_state (0);
1676 stop_button.set_visual_state (1);
1680 float sp = session->transport_speed();
1683 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1684 shuttle_box.queue_draw ();
1685 } else if (sp == 0.0f) {
1687 shuttle_box.queue_draw ();
1688 update_disk_space ();
1693 if (session->get_play_range()) {
1695 play_selection_button.set_visual_state (1);
1696 roll_button.set_visual_state (0);
1697 auto_loop_button.set_visual_state (0);
1699 } else if (session->get_play_loop ()) {
1701 auto_loop_button.set_visual_state (1);
1702 play_selection_button.set_visual_state (0);
1703 roll_button.set_visual_state (0);
1707 roll_button.set_visual_state (1);
1708 play_selection_button.set_visual_state (0);
1709 auto_loop_button.set_visual_state (0);
1712 stop_button.set_visual_state (0);
1716 stop_button.set_visual_state (1);
1717 roll_button.set_visual_state (0);
1718 play_selection_button.set_visual_state (0);
1719 auto_loop_button.set_visual_state (0);
1725 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1727 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1728 (int) adj.get_value()].c_str());
1732 ARDOUR_UI::engine_stopped ()
1734 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1735 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1736 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1740 ARDOUR_UI::engine_running ()
1742 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1743 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1744 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1746 Glib::RefPtr<Action> action;
1747 const char* action_name = 0;
1749 switch (engine->frames_per_cycle()) {
1751 action_name = X_("JACKLatency32");
1754 action_name = X_("JACKLatency64");
1757 action_name = X_("JACKLatency128");
1760 action_name = X_("JACKLatency512");
1763 action_name = X_("JACKLatency1024");
1766 action_name = X_("JACKLatency2048");
1769 action_name = X_("JACKLatency4096");
1772 action_name = X_("JACKLatency8192");
1775 /* XXX can we do anything useful ? */
1781 action = ActionManager::get_action (X_("JACK"), action_name);
1784 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1785 ract->set_active ();
1791 ARDOUR_UI::engine_halted ()
1793 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1795 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1796 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1798 update_sample_rate (0);
1800 MessageDialog msg (*editor,
1802 JACK has either been shutdown or it\n\
1803 disconnected Ardour because Ardour\n\
1804 was not fast enough. Try to restart\n\
1805 JACK, reconnect and save the session."));
1811 ARDOUR_UI::do_engine_start ()
1819 error << _("Unable to start the session running")
1829 ARDOUR_UI::setup_theme ()
1831 theme_manager->setup_theme();
1835 ARDOUR_UI::update_clocks ()
1837 if (!editor || !editor->dragging_playhead()) {
1838 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1843 ARDOUR_UI::start_clocking ()
1845 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1849 ARDOUR_UI::stop_clocking ()
1851 clock_signal_connection.disconnect ();
1855 ARDOUR_UI::toggle_clocking ()
1858 if (clock_button.get_active()) {
1867 ARDOUR_UI::_blink (void *arg)
1870 ((ARDOUR_UI *) arg)->blink ();
1877 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1881 ARDOUR_UI::start_blinking ()
1883 /* Start the blink signal. Everybody with a blinking widget
1884 uses Blink to drive the widget's state.
1887 if (blink_timeout_tag < 0) {
1889 blink_timeout_tag = g_timeout_add (240, _blink, this);
1894 ARDOUR_UI::stop_blinking ()
1896 if (blink_timeout_tag >= 0) {
1897 g_source_remove (blink_timeout_tag);
1898 blink_timeout_tag = -1;
1903 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1909 if (io.n_inputs() == 0) {
1914 /* XXX we're not handling multiple ports yet. */
1916 const char **connections = io.input(0)->get_connections();
1918 if (connections == 0 || connections[0] == '\0') {
1921 buf = connections[0];
1928 if (io.n_outputs() == 0) {
1933 /* XXX we're not handling multiple ports yet. */
1935 const char **connections = io.output(0)->get_connections();
1937 if (connections == 0 || connections[0] == '\0') {
1940 buf = connections[0];
1947 /** Ask the user for the name of a new shapshot and then take it.
1950 ARDOUR_UI::snapshot_session ()
1952 ArdourPrompter prompter (true);
1956 struct tm local_time;
1959 localtime_r (&n, &local_time);
1960 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1962 prompter.set_name ("Prompter");
1963 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1964 prompter.set_title (_("Take Snapshot"));
1965 prompter.set_prompt (_("Name of New Snapshot"));
1966 prompter.set_initial_text (timebuf);
1969 switch (prompter.run()) {
1970 case RESPONSE_ACCEPT:
1971 prompter.get_result (snapname);
1972 if (snapname.length()){
1973 if (snapname.find ('/') != string::npos) {
1974 MessageDialog msg (_("To ensure compatibility with various systems\n"
1975 "snapshot names may not contain a '/' character"));
1979 if (snapname.find ('\\') != string::npos) {
1980 MessageDialog msg (_("To ensure compatibility with various systems\n"
1981 "snapshot names may not contain a '\\' character"));
1985 save_state (snapname);
1995 ARDOUR_UI::save_state (const string & name)
1997 (void) save_state_canfail (name);
2001 ARDOUR_UI::save_state_canfail (string name)
2006 if (name.length() == 0) {
2007 name = session->snap_name();
2010 if ((ret = session->save_state (name)) != 0) {
2014 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2019 ARDOUR_UI::primary_clock_value_changed ()
2022 session->request_locate (primary_clock.current_time ());
2027 ARDOUR_UI::big_clock_value_changed ()
2030 session->request_locate (big_clock.current_time ());
2035 ARDOUR_UI::secondary_clock_value_changed ()
2038 session->request_locate (secondary_clock.current_time ());
2043 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2049 switch (session->record_status()) {
2050 case Session::Enabled:
2052 rec_button.set_visual_state (2);
2054 rec_button.set_visual_state (0);
2058 case Session::Recording:
2059 rec_button.set_visual_state (1);
2063 rec_button.set_visual_state (0);
2069 ARDOUR_UI::save_template ()
2071 ArdourPrompter prompter (true);
2074 if (!check_audioengine()) {
2078 prompter.set_name (X_("Prompter"));
2079 prompter.set_title (_("Save Mix Template"));
2080 prompter.set_prompt (_("Name for mix template:"));
2081 prompter.set_initial_text(session->name() + _("-template"));
2082 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2084 switch (prompter.run()) {
2085 case RESPONSE_ACCEPT:
2086 prompter.get_result (name);
2088 if (name.length()) {
2089 session->save_template (name);
2099 ARDOUR_UI::fontconfig_dialog ()
2102 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
2105 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2106 may not and it can take a while to build it. Warn them.
2109 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2111 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2112 MessageDialog msg (*new_session_dialog,
2113 _("Welcome to Ardour.\n\n"
2114 "The program will take a bit longer to start up\n"
2115 "while the system fonts are checked.\n\n"
2116 "This will only be done once, and you will\n"
2117 "not see this message again\n"),
2131 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2133 existing_session = false;
2135 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2136 session_path = cmdline_path;
2137 existing_session = true;
2138 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2139 session_path = Glib::path_get_dirname (string (cmdline_path));
2140 existing_session = true;
2142 /* it doesn't exist, assume the best */
2143 session_path = Glib::path_get_dirname (string (cmdline_path));
2146 session_name = basename_nosuffix (string (cmdline_path));
2150 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2152 /* when this is called, the backend audio system must be running */
2154 /* the main idea here is to deal with the fact that a cmdline argument for the session
2155 can be interpreted in different ways - it could be a directory or a file, and before
2156 we load, we need to know both the session directory and the snapshot (statefile) within it
2157 that we are supposed to use.
2160 if (session_name.length() == 0 || session_path.length() == 0) {
2164 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2166 Glib::ustring predicted_session_file;
2168 predicted_session_file = session_path;
2169 predicted_session_file += '/';
2170 predicted_session_file += session_name;
2171 predicted_session_file += Session::statefile_suffix();
2173 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2174 existing_session = true;
2177 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2179 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2180 /* existing .ardour file */
2181 existing_session = true;
2185 existing_session = false;
2188 /* lets just try to load it */
2190 if (create_engine ()) {
2191 backend_audio_error (false, new_session_dialog);
2195 return load_session (session_path, session_name);
2199 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2201 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2203 MessageDialog msg (str,
2205 Gtk::MESSAGE_WARNING,
2206 Gtk::BUTTONS_YES_NO,
2210 msg.set_name (X_("CleanupDialog"));
2211 msg.set_title (_("Cleanup Unused Sources"));
2212 msg.set_wmclass (X_("existing_session"), "Ardour");
2213 msg.set_position (Gtk::WIN_POS_MOUSE);
2216 switch (msg.run()) {
2225 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2230 AutoConnectOption iconnect;
2231 AutoConnectOption oconnect;
2235 if (Profile->get_sae()) {
2239 iconnect = AutoConnectPhysical;
2240 oconnect = AutoConnectMaster;
2241 nphysin = 0; // use all available
2242 nphysout = 0; // use all available
2246 /* get settings from advanced section of NSD */
2248 if (new_session_dialog->create_control_bus()) {
2249 cchns = (uint32_t) new_session_dialog->control_channel_count();
2254 if (new_session_dialog->create_master_bus()) {
2255 mchns = (uint32_t) new_session_dialog->master_channel_count();
2260 if (new_session_dialog->connect_inputs()) {
2261 iconnect = AutoConnectPhysical;
2263 iconnect = AutoConnectOption (0);
2266 /// @todo some minor tweaks.
2268 oconnect = AutoConnectOption (0);
2270 if (new_session_dialog->connect_outputs()) {
2271 if (new_session_dialog->connect_outs_to_master()) {
2272 oconnect = AutoConnectMaster;
2273 } else if (new_session_dialog->connect_outs_to_physical()) {
2274 oconnect = AutoConnectPhysical;
2278 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2279 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2282 if (build_session (session_path,
2290 engine->frame_rate() * 60 * 5)) {
2299 ARDOUR_UI::end_loading_messages ()
2305 ARDOUR_UI::loading_message (const std::string& msg)
2308 splash->message (msg);
2313 ARDOUR_UI::idle_load (const Glib::ustring& path)
2316 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2317 /* /path/to/foo => /path/to/foo, foo */
2318 load_session (path, basename_nosuffix (path));
2320 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2321 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2325 ARDOUR_COMMAND_LINE::session_name = path;
2327 if (new_session_dialog) {
2330 /* make it break out of Dialog::run() and
2334 new_session_dialog->response (1);
2340 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2342 bool existing_session = false;
2343 Glib::ustring session_name;
2344 Glib::ustring session_path;
2345 Glib::ustring template_name;
2349 response = Gtk::RESPONSE_NONE;
2351 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2353 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2355 /* don't ever reuse this */
2357 ARDOUR_COMMAND_LINE::session_name = string();
2359 if (existing_session && backend_audio_is_running) {
2361 /* just load the thing already */
2363 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2368 /* make the NSD use whatever information we have */
2370 new_session_dialog->set_session_name (session_name);
2371 new_session_dialog->set_session_folder (session_path);
2374 /* loading failed, or we need the NSD for something */
2376 new_session_dialog->set_modal (false);
2377 new_session_dialog->set_position (WIN_POS_CENTER);
2378 new_session_dialog->set_current_page (0);
2379 new_session_dialog->set_existing_session (existing_session);
2380 new_session_dialog->reset_recent();
2383 new_session_dialog->set_have_engine (backend_audio_is_running);
2384 new_session_dialog->present ();
2385 response = new_session_dialog->run ();
2387 _session_is_new = false;
2389 /* handle possible negative responses */
2393 /* sent by idle_load, meaning restart the whole process again */
2394 new_session_dialog->hide();
2395 new_session_dialog->reset();
2399 case Gtk::RESPONSE_CANCEL:
2400 case Gtk::RESPONSE_DELETE_EVENT:
2402 if (engine && engine->running()) {
2403 engine->stop (true);
2407 new_session_dialog->hide ();
2410 case Gtk::RESPONSE_NONE:
2411 /* "Clear" was pressed */
2415 fontconfig_dialog();
2417 if (!backend_audio_is_running) {
2418 int ret = new_session_dialog->engine_control.setup_engine ();
2421 } else if (ret > 0) {
2422 response = Gtk::RESPONSE_REJECT;
2426 /* hide the NSD while we start up the engine */
2428 new_session_dialog->hide ();
2432 if (create_engine ()) {
2434 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2437 new_session_dialog->set_existing_session (false);
2438 new_session_dialog->set_current_page (0); // new engine page
2439 new_session_dialog->engine_control.unset_interface_chosen ();
2441 response = Gtk::RESPONSE_NONE;
2445 backend_audio_is_running = true;
2447 if (response == Gtk::RESPONSE_OK) {
2449 session_name = new_session_dialog->session_name();
2451 if (session_name.empty()) {
2452 response = Gtk::RESPONSE_NONE;
2456 /* if the user mistakenly typed path information into the session filename entry,
2457 convert what they typed into a path & a name
2460 if (session_name[0] == '/' ||
2461 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2462 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2464 session_path = Glib::path_get_dirname (session_name);
2465 session_name = Glib::path_get_basename (session_name);
2469 session_path = new_session_dialog->session_folder();
2473 template_name = Glib::ustring();
2474 switch (new_session_dialog->which_page()) {
2476 case NewSessionDialog::OpenPage:
2480 case NewSessionDialog::EnginePage:
2481 if (new_session_dialog->engine_control.interface_chosen() && !session_path.empty()) {
2488 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2490 should_be_new = true;
2492 if (session_name.find ('/') != Glib::ustring::npos) {
2493 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2494 "session names may not contain a '/' character"));
2496 response = RESPONSE_NONE;
2500 if (session_name.find ('\\') != Glib::ustring::npos) {
2501 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2502 "session names may not contain a '\\' character"));
2504 response = RESPONSE_NONE;
2508 //XXX This is needed because session constructor wants a
2509 //non-existant path. hopefully this will be fixed at some point.
2511 session_path = Glib::build_filename (session_path, session_name);
2513 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2515 new_session_dialog->hide ();
2517 if (ask_about_loading_existing_session (session_path)) {
2520 response = RESPONSE_NONE;
2525 _session_is_new = true;
2527 if (new_session_dialog->use_session_template()) {
2529 template_name = new_session_dialog->session_template_name();
2533 if (build_session_from_nsd (session_path, session_name)) {
2534 response = RESPONSE_NONE;
2546 new_session_dialog->hide ();
2548 if (load_session (session_path, session_name, template_name)) {
2550 response = Gtk::RESPONSE_NONE;
2554 if (response == Gtk::RESPONSE_NONE) {
2555 new_session_dialog->set_existing_session (false);
2556 new_session_dialog->reset ();
2560 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2564 new_session_dialog->hide();
2565 new_session_dialog->reset();
2566 goto_editor_window ();
2571 ARDOUR_UI::close_session ()
2573 if (!check_audioengine()) {
2577 if (unload_session (true)) {
2581 get_session_parameters (true, false);
2585 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2587 Session *new_session;
2591 session_loaded = false;
2593 if (!check_audioengine()) {
2597 unload_status = unload_session ();
2599 if (unload_status < 0) {
2601 } else if (unload_status > 0) {
2606 loading_message (_("Please wait while Ardour loads your session"));
2609 new_session = new Session (*engine, path, snap_name, mix_template);
2612 /* this one is special */
2614 catch (AudioEngine::PortRegistrationFailure& err) {
2616 MessageDialog msg (err.what(),
2619 Gtk::BUTTONS_CLOSE);
2621 msg.set_title (_("Port Registration Error"));
2622 msg.set_secondary_text (_("Click the Close button to try again."));
2623 msg.set_position (Gtk::WIN_POS_CENTER);
2627 int response = msg.run ();
2632 case RESPONSE_CANCEL:
2640 /* this exception is also special */
2642 catch (Session::SRMismatchRejected& err) {
2643 goto out; /* just go back and reload something else, etc. */
2648 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2651 Gtk::BUTTONS_CLOSE);
2653 msg.set_title (_("Loading Error"));
2654 msg.set_secondary_text (_("Click the Close button to try again."));
2655 msg.set_position (Gtk::WIN_POS_CENTER);
2659 int response = msg.run ();
2664 case RESPONSE_CANCEL:
2672 connect_to_session (new_session);
2674 Config->set_current_owner (ConfigVariableBase::Interface);
2676 session_loaded = true;
2678 goto_editor_window ();
2681 session->set_clean ();
2692 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2693 uint32_t control_channels,
2694 uint32_t master_channels,
2695 AutoConnectOption input_connect,
2696 AutoConnectOption output_connect,
2699 nframes_t initial_length)
2701 Session *new_session;
2704 if (!check_audioengine()) {
2708 session_loaded = false;
2710 x = unload_session ();
2718 _session_is_new = true;
2721 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2722 control_channels, master_channels, nphysin, nphysout, initial_length);
2727 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2733 connect_to_session (new_session);
2735 session_loaded = true;
2737 new_session->save_state(new_session->name());
2746 editor->show_window ();
2757 ARDOUR_UI::show_about ()
2761 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2764 about->set_transient_for(*editor);
2770 ARDOUR_UI::launch_chat ()
2773 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2775 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2780 ARDOUR_UI::hide_about ()
2783 about->get_window()->set_cursor ();
2789 ARDOUR_UI::about_signal_response(int response)
2795 ARDOUR_UI::show_splash ()
2799 splash = new Splash;
2807 splash->queue_draw ();
2808 splash->get_window()->process_updates (true);
2813 ARDOUR_UI::hide_splash ()
2821 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2822 const string& plural_msg, const string& singular_msg)
2826 removed = rep.paths.size();
2829 MessageDialog msgd (*editor,
2830 _("No audio files were ready for cleanup"),
2833 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2834 msgd.set_secondary_text (_("If this seems suprising, \n\
2835 check for any existing snapshots.\n\
2836 These may still include regions that\n\
2837 require some unused files to continue to exist."));
2843 ArdourDialog results (_("ardour: cleanup"), true, false);
2845 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2846 CleanupResultsModelColumns() {
2850 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2851 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2855 CleanupResultsModelColumns results_columns;
2856 Glib::RefPtr<Gtk::ListStore> results_model;
2857 Gtk::TreeView results_display;
2859 results_model = ListStore::create (results_columns);
2860 results_display.set_model (results_model);
2861 results_display.append_column (list_title, results_columns.visible_name);
2863 results_display.set_name ("CleanupResultsList");
2864 results_display.set_headers_visible (true);
2865 results_display.set_headers_clickable (false);
2866 results_display.set_reorderable (false);
2868 Gtk::ScrolledWindow list_scroller;
2871 Gtk::HBox dhbox; // the hbox for the image and text
2872 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2873 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2875 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2879 %1 - number of files removed
2880 %2 - location of "dead_sounds"
2881 %3 - size of files affected
2882 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2885 const char* bprefix;
2886 float space_adjusted;
2888 if (rep.space < 1000000.0f) {
2889 bprefix = X_("kilo");
2890 space_adjusted = truncf((float)rep.space / 1000.0f);
2891 } else if (rep.space < (1000000.0f * 1000)) {
2892 bprefix = X_("mega");
2893 space_adjusted = truncf((float)rep.space / (1000000.0f));
2895 bprefix = X_("giga");
2896 space_adjusted = truncf((float)rep.space / (1000000.0f * 1000));
2900 txt.set_text (string_compose (plural_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2902 txt.set_text (string_compose (singular_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2905 dhbox.pack_start (*dimage, true, false, 5);
2906 dhbox.pack_start (txt, true, false, 5);
2908 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2909 TreeModel::Row row = *(results_model->append());
2910 row[results_columns.visible_name] = *i;
2911 row[results_columns.fullpath] = *i;
2914 list_scroller.add (results_display);
2915 list_scroller.set_size_request (-1, 150);
2916 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2918 dvbox.pack_start (dhbox, true, false, 5);
2919 dvbox.pack_start (list_scroller, true, false, 5);
2920 ddhbox.pack_start (dvbox, true, false, 5);
2922 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2923 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2924 results.set_default_response (RESPONSE_CLOSE);
2925 results.set_position (Gtk::WIN_POS_MOUSE);
2926 results.show_all_children ();
2927 results.set_resizable (false);
2934 ARDOUR_UI::cleanup ()
2937 /* shouldn't happen: menu item is insensitive */
2942 MessageDialog checker (_("Are you sure you want to cleanup?"),
2944 Gtk::MESSAGE_QUESTION,
2945 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2947 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2948 ALL undo/redo information will be lost if you cleanup.\n\
2949 After cleanup, unused audio files will be moved to a \
2950 \"dead sounds\" location."));
2952 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2953 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2954 checker.set_default_response (RESPONSE_CANCEL);
2956 checker.set_name (_("CleanupDialog"));
2957 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2958 checker.set_position (Gtk::WIN_POS_MOUSE);
2960 switch (checker.run()) {
2961 case RESPONSE_ACCEPT:
2967 Session::cleanup_report rep;
2969 editor->prepare_for_cleanup ();
2971 /* do not allow flush until a session is reloaded */
2973 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2975 act->set_sensitive (false);
2978 if (session->cleanup_sources (rep)) {
2979 editor->finish_cleanup ();
2983 editor->finish_cleanup ();
2986 display_cleanup_results (rep,
2989 The following %1 files were not in use and \n\
2990 have been moved to:\n\
2992 Flushing the wastebasket will \n\
2993 release an additional\n\
2994 %3 %4bytes of disk space.\n"),
2996 The following file was not in use and \n \
2997 has been moved to:\n \
2999 Flushing the wastebasket will \n\
3000 release an additional\n\
3001 %3 %4bytes of disk space.\n"
3007 ARDOUR_UI::flush_trash ()
3010 /* shouldn't happen: menu item is insensitive */
3014 Session::cleanup_report rep;
3016 if (session->cleanup_trash_sources (rep)) {
3020 display_cleanup_results (rep,
3022 _("The following %1 files were deleted from\n\
3024 releasing %3 %4bytes of disk space"),
3025 _("The following file was deleted from\n\
3027 releasing %3 %4bytes of disk space"));
3031 ARDOUR_UI::add_route (Gtk::Window* float_window)
3039 if (add_route_dialog == 0) {
3040 add_route_dialog = new AddRouteDialog;
3042 add_route_dialog->set_transient_for (*float_window);
3046 if (add_route_dialog->is_visible()) {
3047 /* we're already doing this */
3051 ResponseType r = (ResponseType) add_route_dialog->run ();
3053 add_route_dialog->hide();
3056 case RESPONSE_ACCEPT:
3063 if ((count = add_route_dialog->count()) <= 0) {
3067 string template_path = add_route_dialog->track_template();
3069 if (!template_path.empty()) {
3070 session->new_route_from_template (count, template_path);
3074 uint32_t input_chan = add_route_dialog->channels ();
3075 uint32_t output_chan;
3076 string name_template = add_route_dialog->name_template ();
3077 bool track = add_route_dialog->track ();
3079 AutoConnectOption oac = Config->get_output_auto_connect();
3081 if (oac & AutoConnectMaster) {
3082 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3084 output_chan = input_chan;
3087 /* XXX do something with name template */
3090 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
3092 session_add_audio_bus (input_chan, output_chan, count);
3097 ARDOUR_UI::mixer_settings () const
3102 node = session->instant_xml(X_("Mixer"), session->path());
3104 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
3108 node = new XMLNode (X_("Mixer"));
3115 ARDOUR_UI::editor_settings () const
3120 node = session->instant_xml(X_("Editor"), session->path());
3122 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
3126 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3127 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3132 node = new XMLNode (X_("Editor"));
3138 ARDOUR_UI::keyboard_settings () const
3142 node = Config->extra_xml(X_("Keyboard"));
3145 node = new XMLNode (X_("Keyboard"));
3151 ARDOUR_UI::create_xrun_marker(nframes_t where)
3153 editor->mouse_add_new_marker (where, false, true);
3157 ARDOUR_UI::halt_on_xrun_message ()
3159 MessageDialog msg (*editor,
3160 _("Recording was stopped because your system could not keep up."));
3165 ARDOUR_UI::xrun_handler(nframes_t where)
3171 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3173 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3174 create_xrun_marker(where);
3177 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3178 halt_on_xrun_message ();
3183 ARDOUR_UI::preset_file_exists_handler ()
3185 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3188 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3192 HBox* hbox = new HBox();
3193 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3194 Gtk::Dialog dialog (_("Preset Exists"), true, false);
3196 A preset with this name already exists for this plugin.\n\
3198 What you would like to do?\n"));
3199 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3200 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3201 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3202 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3203 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3204 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3205 dialog.set_default_response (RESPONSE_ACCEPT);
3206 dialog.set_position (WIN_POS_MOUSE);
3207 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3213 switch (dialog.run ()) {
3214 case RESPONSE_ACCEPT:
3222 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3227 while (disk_buffer_stats.size() > 60) {
3228 disk_buffer_stats.pop_front ();
3231 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3235 ARDOUR_UI::write_buffer_stats ()
3240 char path[PATH_MAX+1]; int fd;
3242 strcpy (path, "ardourBufferingXXXXXX");
3244 if ((fd = mkstemp (path )) < 0) {
3245 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3253 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3257 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3258 localtime_r (&(*i).when, &tm);
3259 strftime (buf, sizeof (buf), "%T", &tm);
3260 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3263 disk_buffer_stats.clear ();
3267 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3271 ARDOUR_UI::disk_overrun_handler ()
3274 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3276 write_buffer_stats ();
3278 if (!have_disk_speed_dialog_displayed) {
3279 have_disk_speed_dialog_displayed = true;
3280 MessageDialog* msg = new MessageDialog (*editor, _("\
3281 The disk system on your computer\n\
3282 was not able to keep up with Ardour.\n\
3284 Specifically, it failed to write data to disk\n\
3285 quickly enough to keep up with recording.\n"));
3286 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3292 ARDOUR_UI::disk_underrun_handler ()
3295 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3297 write_buffer_stats ();
3299 if (!have_disk_speed_dialog_displayed) {
3300 have_disk_speed_dialog_displayed = true;
3301 MessageDialog* msg = new MessageDialog (*editor,
3302 _("The disk system on your computer\n\
3303 was not able to keep up with Ardour.\n\
3305 Specifically, it failed to read data from disk\n\
3306 quickly enough to keep up with playback.\n"));
3307 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3313 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3315 have_disk_speed_dialog_displayed = false;
3320 ARDOUR_UI::session_dialog (std::string msg)
3322 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3327 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3329 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3338 ARDOUR_UI::pending_state_dialog ()
3340 HBox* hbox = new HBox();
3341 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3342 ArdourDialog dialog (_("Crash Recovery"), true);
3344 This session appears to have been in\n\
3345 middle of recording when ardour or\n\
3346 the computer was shutdown.\n\
3348 Ardour can recover any captured audio for\n\
3349 you, or it can ignore it. Please decide\n\
3350 what you would like to do.\n"));
3351 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3352 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3353 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3354 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3355 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3356 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3357 dialog.set_default_response (RESPONSE_ACCEPT);
3358 dialog.set_position (WIN_POS_CENTER);
3365 switch (dialog.run ()) {
3366 case RESPONSE_ACCEPT:
3374 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3376 HBox* hbox = new HBox();
3377 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3378 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3379 Label message (string_compose (_("\
3380 This session was created with a sample rate of %1 Hz\n\
3382 The audioengine is currently running at %2 Hz\n"), desired, actual));
3384 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3385 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3386 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3387 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3388 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3389 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3390 dialog.set_default_response (RESPONSE_ACCEPT);
3391 dialog.set_position (WIN_POS_CENTER);
3396 switch (dialog.run ()) {
3397 case RESPONSE_ACCEPT:
3406 ARDOUR_UI::disconnect_from_jack ()
3409 if( engine->disconnect_from_jack ()) {
3410 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3414 update_sample_rate (0);
3419 ARDOUR_UI::reconnect_to_jack ()
3422 if (engine->reconnect_to_jack ()) {
3423 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3427 update_sample_rate (0);
3432 ARDOUR_UI::use_config ()
3434 Glib::RefPtr<Action> act;
3436 switch (Config->get_native_file_data_format ()) {
3438 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3441 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3444 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3449 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3450 ract->set_active ();
3453 switch (Config->get_native_file_header_format ()) {
3455 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3458 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3461 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3464 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3467 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3470 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3473 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3478 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3479 ract->set_active ();
3482 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3484 set_transport_controllable_state (*node);
3489 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3491 if (Config->get_primary_clock_delta_edit_cursor()) {
3492 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3494 primary_clock.set (pos, 0, true);
3497 if (Config->get_secondary_clock_delta_edit_cursor()) {
3498 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3500 secondary_clock.set (pos);
3503 if (big_clock_window) {
3504 big_clock.set (pos);
3509 ARDOUR_UI::record_state_changed ()
3511 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3513 if (!session || !big_clock_window) {
3514 /* why bother - the clock isn't visible */
3518 switch (session->record_status()) {
3519 case Session::Recording:
3520 big_clock.set_widget_name ("BigClockRecording");
3523 big_clock.set_widget_name ("BigClockNonRecording");
3529 ARDOUR_UI::first_idle ()
3532 session->allow_auto_play (true);
3536 editor->first_idle();
3539 Keyboard::set_can_save_keybindings (true);
3544 ARDOUR_UI::store_clock_modes ()
3546 XMLNode* node = new XMLNode(X_("ClockModes"));
3548 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3549 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3552 session->add_extra_xml (*node);
3553 session->set_dirty ();
3558 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3559 : Controllable (name), ui (u), type(tp)
3565 ARDOUR_UI::TransportControllable::set_value (float val)
3567 if (type == ShuttleControl) {
3574 fract = -((0.5f - val)/0.5f);
3576 fract = ((val - 0.5f)/0.5f);
3580 ui.set_shuttle_fract (fract);
3585 /* do nothing: these are radio-style actions */
3589 const char *action = 0;
3593 action = X_("Roll");
3596 action = X_("Stop");
3599 action = X_("Goto Start");
3602 action = X_("Goto End");
3605 action = X_("Loop");
3608 action = X_("Play Selection");
3611 action = X_("Record");
3621 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3629 ARDOUR_UI::TransportControllable::get_value (void) const
3648 case ShuttleControl:
3658 ARDOUR_UI::TransportControllable::set_id (const string& str)
3664 ARDOUR_UI::setup_profile ()
3666 if (gdk_screen_width() < 1200) {
3667 Profile->set_small_screen ();
3670 if (getenv ("ARDOUR_SAE")) {
3671 Profile->set_sae ();
3672 Profile->set_single_package ();