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 session->request_play_range (0, true);
1491 session->request_transport_speed (1.0f);
1494 map_transport_state ();
1498 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1505 if (session->is_auditioning()) {
1506 session->cancel_audition ();
1510 switch (Config->get_slave_source()) {
1515 /* transport controlled by the master */
1519 bool rolling = session->transport_rolling();
1520 bool affect_transport = true;
1522 if (rolling && roll_out_of_bounded_mode) {
1523 /* drop out of loop/range playback but leave transport rolling */
1524 if (session->get_play_loop()) {
1525 if (Config->get_seamless_loop()) {
1526 /* the disk buffers contain copies of the loop - we can't
1527 just keep playing, so stop the transport. the user
1528 can restart as they wish.
1530 affect_transport = true;
1532 /* disk buffers are normal, so we can keep playing */
1533 affect_transport = false;
1535 session->request_play_loop (false, true);
1536 } else if (session->get_play_range ()) {
1537 affect_transport = false;
1538 session->request_play_range (0, true);
1542 if (affect_transport) {
1544 session->request_stop (with_abort, true);
1546 session->request_transport_speed (1.0f);
1550 map_transport_state ();
1554 ARDOUR_UI::toggle_session_auto_loop ()
1557 if (session->get_play_loop()) {
1558 if (session->transport_rolling()) {
1559 Location * looploc = session->locations()->auto_loop_location();
1561 session->request_locate (looploc->start(), true);
1564 session->request_play_loop (false);
1567 Location * looploc = session->locations()->auto_loop_location();
1569 session->request_play_loop (true);
1576 ARDOUR_UI::transport_play_selection ()
1582 editor->play_selection ();
1586 ARDOUR_UI::transport_rewind (int option)
1588 float current_transport_speed;
1591 current_transport_speed = session->transport_speed();
1593 if (current_transport_speed >= 0.0f) {
1596 session->request_transport_speed (-1.0f);
1599 session->request_transport_speed (-4.0f);
1602 session->request_transport_speed (-0.5f);
1607 session->request_transport_speed (current_transport_speed * 1.5f);
1613 ARDOUR_UI::transport_forward (int option)
1615 float current_transport_speed;
1618 current_transport_speed = session->transport_speed();
1620 if (current_transport_speed <= 0.0f) {
1623 session->request_transport_speed (1.0f);
1626 session->request_transport_speed (4.0f);
1629 session->request_transport_speed (0.5f);
1634 session->request_transport_speed (current_transport_speed * 1.5f);
1640 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1646 boost::shared_ptr<Route> r;
1648 if ((r = session->route_by_remote_id (dstream)) != 0) {
1652 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1653 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1662 ARDOUR_UI::queue_transport_change ()
1664 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1668 ARDOUR_UI::map_transport_state ()
1671 auto_loop_button.set_visual_state (0);
1672 play_selection_button.set_visual_state (0);
1673 roll_button.set_visual_state (0);
1674 stop_button.set_visual_state (1);
1678 float sp = session->transport_speed();
1681 shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
1682 shuttle_box.queue_draw ();
1683 } else if (sp == 0.0f) {
1685 shuttle_box.queue_draw ();
1686 update_disk_space ();
1691 if (session->get_play_range()) {
1693 play_selection_button.set_visual_state (1);
1694 roll_button.set_visual_state (0);
1695 auto_loop_button.set_visual_state (0);
1697 } else if (session->get_play_loop ()) {
1699 auto_loop_button.set_visual_state (1);
1700 play_selection_button.set_visual_state (0);
1701 roll_button.set_visual_state (0);
1705 roll_button.set_visual_state (1);
1706 play_selection_button.set_visual_state (0);
1707 auto_loop_button.set_visual_state (0);
1710 stop_button.set_visual_state (0);
1714 stop_button.set_visual_state (1);
1715 roll_button.set_visual_state (0);
1716 play_selection_button.set_visual_state (0);
1717 auto_loop_button.set_visual_state (0);
1723 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1725 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1726 (int) adj.get_value()].c_str());
1730 ARDOUR_UI::engine_stopped ()
1732 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1733 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1734 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1738 ARDOUR_UI::engine_running ()
1740 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1741 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1742 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1744 Glib::RefPtr<Action> action;
1745 const char* action_name = 0;
1747 switch (engine->frames_per_cycle()) {
1749 action_name = X_("JACKLatency32");
1752 action_name = X_("JACKLatency64");
1755 action_name = X_("JACKLatency128");
1758 action_name = X_("JACKLatency512");
1761 action_name = X_("JACKLatency1024");
1764 action_name = X_("JACKLatency2048");
1767 action_name = X_("JACKLatency4096");
1770 action_name = X_("JACKLatency8192");
1773 /* XXX can we do anything useful ? */
1779 action = ActionManager::get_action (X_("JACK"), action_name);
1782 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1783 ract->set_active ();
1789 ARDOUR_UI::engine_halted ()
1791 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1793 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1794 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1796 update_sample_rate (0);
1798 MessageDialog msg (*editor,
1800 JACK has either been shutdown or it\n\
1801 disconnected Ardour because Ardour\n\
1802 was not fast enough. Try to restart\n\
1803 JACK, reconnect and save the session."));
1809 ARDOUR_UI::do_engine_start ()
1817 error << _("Unable to start the session running")
1827 ARDOUR_UI::setup_theme ()
1829 theme_manager->setup_theme();
1833 ARDOUR_UI::update_clocks ()
1835 if (!editor || !editor->dragging_playhead()) {
1836 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1841 ARDOUR_UI::start_clocking ()
1843 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1847 ARDOUR_UI::stop_clocking ()
1849 clock_signal_connection.disconnect ();
1853 ARDOUR_UI::toggle_clocking ()
1856 if (clock_button.get_active()) {
1865 ARDOUR_UI::_blink (void *arg)
1868 ((ARDOUR_UI *) arg)->blink ();
1875 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1879 ARDOUR_UI::start_blinking ()
1881 /* Start the blink signal. Everybody with a blinking widget
1882 uses Blink to drive the widget's state.
1885 if (blink_timeout_tag < 0) {
1887 blink_timeout_tag = g_timeout_add (240, _blink, this);
1892 ARDOUR_UI::stop_blinking ()
1894 if (blink_timeout_tag >= 0) {
1895 g_source_remove (blink_timeout_tag);
1896 blink_timeout_tag = -1;
1901 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1907 if (io.n_inputs() == 0) {
1912 /* XXX we're not handling multiple ports yet. */
1914 const char **connections = io.input(0)->get_connections();
1916 if (connections == 0 || connections[0] == '\0') {
1919 buf = connections[0];
1926 if (io.n_outputs() == 0) {
1931 /* XXX we're not handling multiple ports yet. */
1933 const char **connections = io.output(0)->get_connections();
1935 if (connections == 0 || connections[0] == '\0') {
1938 buf = connections[0];
1945 /** Ask the user for the name of a new shapshot and then take it.
1948 ARDOUR_UI::snapshot_session ()
1950 ArdourPrompter prompter (true);
1954 struct tm local_time;
1957 localtime_r (&n, &local_time);
1958 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1960 prompter.set_name ("Prompter");
1961 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1962 prompter.set_title (_("Take Snapshot"));
1963 prompter.set_prompt (_("Name of New Snapshot"));
1964 prompter.set_initial_text (timebuf);
1967 switch (prompter.run()) {
1968 case RESPONSE_ACCEPT:
1969 prompter.get_result (snapname);
1970 if (snapname.length()){
1971 if (snapname.find ('/') != string::npos) {
1972 MessageDialog msg (_("To ensure compatibility with various systems\n"
1973 "snapshot names may not contain a '/' character"));
1977 if (snapname.find ('\\') != string::npos) {
1978 MessageDialog msg (_("To ensure compatibility with various systems\n"
1979 "snapshot names may not contain a '\\' character"));
1983 save_state (snapname);
1993 ARDOUR_UI::save_state (const string & name)
1995 (void) save_state_canfail (name);
1999 ARDOUR_UI::save_state_canfail (string name)
2004 if (name.length() == 0) {
2005 name = session->snap_name();
2008 if ((ret = session->save_state (name)) != 0) {
2012 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2017 ARDOUR_UI::primary_clock_value_changed ()
2020 session->request_locate (primary_clock.current_time ());
2025 ARDOUR_UI::big_clock_value_changed ()
2028 session->request_locate (big_clock.current_time ());
2033 ARDOUR_UI::secondary_clock_value_changed ()
2036 session->request_locate (secondary_clock.current_time ());
2041 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2047 switch (session->record_status()) {
2048 case Session::Enabled:
2050 rec_button.set_visual_state (2);
2052 rec_button.set_visual_state (0);
2056 case Session::Recording:
2057 rec_button.set_visual_state (1);
2061 rec_button.set_visual_state (0);
2067 ARDOUR_UI::save_template ()
2069 ArdourPrompter prompter (true);
2072 if (!check_audioengine()) {
2076 prompter.set_name (X_("Prompter"));
2077 prompter.set_title (_("Save Mix Template"));
2078 prompter.set_prompt (_("Name for mix template:"));
2079 prompter.set_initial_text(session->name() + _("-template"));
2080 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2082 switch (prompter.run()) {
2083 case RESPONSE_ACCEPT:
2084 prompter.get_result (name);
2086 if (name.length()) {
2087 session->save_template (name);
2097 ARDOUR_UI::fontconfig_dialog ()
2100 /* this issue seems to have gone away with changes to font handling in GTK/Quartz
2103 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2104 may not and it can take a while to build it. Warn them.
2107 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2109 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2110 MessageDialog msg (*new_session_dialog,
2111 _("Welcome to Ardour.\n\n"
2112 "The program will take a bit longer to start up\n"
2113 "while the system fonts are checked.\n\n"
2114 "This will only be done once, and you will\n"
2115 "not see this message again\n"),
2129 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2131 existing_session = false;
2133 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2134 session_path = cmdline_path;
2135 existing_session = true;
2136 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2137 session_path = Glib::path_get_dirname (string (cmdline_path));
2138 existing_session = true;
2140 /* it doesn't exist, assume the best */
2141 session_path = Glib::path_get_dirname (string (cmdline_path));
2144 session_name = basename_nosuffix (string (cmdline_path));
2148 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2150 /* when this is called, the backend audio system must be running */
2152 /* the main idea here is to deal with the fact that a cmdline argument for the session
2153 can be interpreted in different ways - it could be a directory or a file, and before
2154 we load, we need to know both the session directory and the snapshot (statefile) within it
2155 that we are supposed to use.
2158 if (session_name.length() == 0 || session_path.length() == 0) {
2162 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2164 Glib::ustring predicted_session_file;
2166 predicted_session_file = session_path;
2167 predicted_session_file += '/';
2168 predicted_session_file += session_name;
2169 predicted_session_file += Session::statefile_suffix();
2171 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2172 existing_session = true;
2175 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2177 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2178 /* existing .ardour file */
2179 existing_session = true;
2183 existing_session = false;
2186 /* lets just try to load it */
2188 if (create_engine ()) {
2189 backend_audio_error (false, new_session_dialog);
2193 return load_session (session_path, session_name);
2197 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2199 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2201 MessageDialog msg (str,
2203 Gtk::MESSAGE_WARNING,
2204 Gtk::BUTTONS_YES_NO,
2208 msg.set_name (X_("CleanupDialog"));
2209 msg.set_title (_("Cleanup Unused Sources"));
2210 msg.set_wmclass (X_("existing_session"), "Ardour");
2211 msg.set_position (Gtk::WIN_POS_MOUSE);
2214 switch (msg.run()) {
2223 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2228 AutoConnectOption iconnect;
2229 AutoConnectOption oconnect;
2233 if (Profile->get_sae()) {
2237 iconnect = AutoConnectPhysical;
2238 oconnect = AutoConnectMaster;
2239 nphysin = 0; // use all available
2240 nphysout = 0; // use all available
2244 /* get settings from advanced section of NSD */
2246 if (new_session_dialog->create_control_bus()) {
2247 cchns = (uint32_t) new_session_dialog->control_channel_count();
2252 if (new_session_dialog->create_master_bus()) {
2253 mchns = (uint32_t) new_session_dialog->master_channel_count();
2258 if (new_session_dialog->connect_inputs()) {
2259 iconnect = AutoConnectPhysical;
2261 iconnect = AutoConnectOption (0);
2264 /// @todo some minor tweaks.
2266 oconnect = AutoConnectOption (0);
2268 if (new_session_dialog->connect_outputs()) {
2269 if (new_session_dialog->connect_outs_to_master()) {
2270 oconnect = AutoConnectMaster;
2271 } else if (new_session_dialog->connect_outs_to_physical()) {
2272 oconnect = AutoConnectPhysical;
2276 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2277 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2280 if (build_session (session_path,
2288 engine->frame_rate() * 60 * 5)) {
2297 ARDOUR_UI::end_loading_messages ()
2303 ARDOUR_UI::loading_message (const std::string& msg)
2306 splash->message (msg);
2311 ARDOUR_UI::idle_load (const Glib::ustring& path)
2314 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2315 /* /path/to/foo => /path/to/foo, foo */
2316 load_session (path, basename_nosuffix (path));
2318 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2319 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2323 ARDOUR_COMMAND_LINE::session_name = path;
2325 if (new_session_dialog) {
2328 /* make it break out of Dialog::run() and
2332 new_session_dialog->response (1);
2338 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2340 bool existing_session = false;
2341 Glib::ustring session_name;
2342 Glib::ustring session_path;
2343 Glib::ustring template_name;
2347 response = Gtk::RESPONSE_NONE;
2349 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2351 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2353 /* don't ever reuse this */
2355 ARDOUR_COMMAND_LINE::session_name = string();
2357 if (existing_session && backend_audio_is_running) {
2359 /* just load the thing already */
2361 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2366 /* make the NSD use whatever information we have */
2368 new_session_dialog->set_session_name (session_name);
2369 new_session_dialog->set_session_folder (session_path);
2372 /* loading failed, or we need the NSD for something */
2374 new_session_dialog->set_modal (false);
2375 new_session_dialog->set_position (WIN_POS_CENTER);
2376 new_session_dialog->set_current_page (0);
2377 new_session_dialog->set_existing_session (existing_session);
2378 new_session_dialog->reset_recent();
2381 new_session_dialog->set_have_engine (backend_audio_is_running);
2382 new_session_dialog->present ();
2383 response = new_session_dialog->run ();
2385 _session_is_new = false;
2387 /* handle possible negative responses */
2391 /* sent by idle_load, meaning restart the whole process again */
2392 new_session_dialog->hide();
2393 new_session_dialog->reset();
2397 case Gtk::RESPONSE_CANCEL:
2398 case Gtk::RESPONSE_DELETE_EVENT:
2400 if (engine && engine->running()) {
2401 engine->stop (true);
2405 new_session_dialog->hide ();
2408 case Gtk::RESPONSE_NONE:
2409 /* "Clear" was pressed */
2413 fontconfig_dialog();
2415 if (!backend_audio_is_running) {
2416 int ret = new_session_dialog->engine_control.setup_engine ();
2419 } else if (ret > 0) {
2420 response = Gtk::RESPONSE_REJECT;
2424 /* hide the NSD while we start up the engine */
2426 new_session_dialog->hide ();
2430 if (create_engine ()) {
2432 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2435 new_session_dialog->set_existing_session (false);
2436 new_session_dialog->set_current_page (0); // new engine page
2437 new_session_dialog->engine_control.unset_interface_chosen ();
2439 response = Gtk::RESPONSE_NONE;
2443 backend_audio_is_running = true;
2445 if (response == Gtk::RESPONSE_OK) {
2447 session_name = new_session_dialog->session_name();
2449 if (session_name.empty()) {
2450 response = Gtk::RESPONSE_NONE;
2454 /* if the user mistakenly typed path information into the session filename entry,
2455 convert what they typed into a path & a name
2458 if (session_name[0] == '/' ||
2459 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2460 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2462 session_path = Glib::path_get_dirname (session_name);
2463 session_name = Glib::path_get_basename (session_name);
2467 session_path = new_session_dialog->session_folder();
2471 template_name = Glib::ustring();
2472 switch (new_session_dialog->which_page()) {
2474 case NewSessionDialog::OpenPage:
2478 case NewSessionDialog::EnginePage:
2479 if (new_session_dialog->engine_control.interface_chosen() && !session_path.empty()) {
2486 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2488 should_be_new = true;
2490 if (session_name.find ('/') != Glib::ustring::npos) {
2491 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2492 "session names may not contain a '/' character"));
2494 response = RESPONSE_NONE;
2498 if (session_name.find ('\\') != Glib::ustring::npos) {
2499 MessageDialog msg (*new_session_dialog, _("To ensure compatibility with various systems\n"
2500 "session names may not contain a '\\' character"));
2502 response = RESPONSE_NONE;
2506 //XXX This is needed because session constructor wants a
2507 //non-existant path. hopefully this will be fixed at some point.
2509 session_path = Glib::build_filename (session_path, session_name);
2511 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2513 new_session_dialog->hide ();
2515 if (ask_about_loading_existing_session (session_path)) {
2518 response = RESPONSE_NONE;
2523 _session_is_new = true;
2525 if (new_session_dialog->use_session_template()) {
2527 template_name = new_session_dialog->session_template_name();
2531 if (build_session_from_nsd (session_path, session_name)) {
2532 response = RESPONSE_NONE;
2544 new_session_dialog->hide ();
2546 if (load_session (session_path, session_name, template_name)) {
2548 response = Gtk::RESPONSE_NONE;
2552 if (response == Gtk::RESPONSE_NONE) {
2553 new_session_dialog->set_existing_session (false);
2554 new_session_dialog->reset ();
2558 } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
2562 new_session_dialog->hide();
2563 new_session_dialog->reset();
2564 goto_editor_window ();
2569 ARDOUR_UI::close_session ()
2571 if (!check_audioengine()) {
2575 if (unload_session (true)) {
2579 get_session_parameters (true, false);
2583 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2585 Session *new_session;
2589 session_loaded = false;
2591 if (!check_audioengine()) {
2595 unload_status = unload_session ();
2597 if (unload_status < 0) {
2599 } else if (unload_status > 0) {
2604 loading_message (_("Please wait while Ardour loads your session"));
2607 new_session = new Session (*engine, path, snap_name, mix_template);
2610 /* this one is special */
2612 catch (AudioEngine::PortRegistrationFailure& err) {
2614 MessageDialog msg (err.what(),
2617 Gtk::BUTTONS_CLOSE);
2619 msg.set_title (_("Port Registration Error"));
2620 msg.set_secondary_text (_("Click the Close button to try again."));
2621 msg.set_position (Gtk::WIN_POS_CENTER);
2625 int response = msg.run ();
2630 case RESPONSE_CANCEL:
2638 /* this exception is also special */
2640 catch (Session::SRMismatchRejected& err) {
2641 goto out; /* just go back and reload something else, etc. */
2646 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2649 Gtk::BUTTONS_CLOSE);
2651 msg.set_title (_("Loading Error"));
2652 msg.set_secondary_text (_("Click the Close button to try again."));
2653 msg.set_position (Gtk::WIN_POS_CENTER);
2657 int response = msg.run ();
2662 case RESPONSE_CANCEL:
2670 connect_to_session (new_session);
2672 Config->set_current_owner (ConfigVariableBase::Interface);
2674 session_loaded = true;
2676 goto_editor_window ();
2679 session->set_clean ();
2690 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2691 uint32_t control_channels,
2692 uint32_t master_channels,
2693 AutoConnectOption input_connect,
2694 AutoConnectOption output_connect,
2697 nframes_t initial_length)
2699 Session *new_session;
2702 if (!check_audioengine()) {
2706 session_loaded = false;
2708 x = unload_session ();
2716 _session_is_new = true;
2719 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2720 control_channels, master_channels, nphysin, nphysout, initial_length);
2725 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2731 connect_to_session (new_session);
2733 session_loaded = true;
2735 new_session->save_state(new_session->name());
2744 editor->show_window ();
2755 ARDOUR_UI::show_about ()
2759 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2762 about->set_transient_for(*editor);
2768 ARDOUR_UI::launch_chat ()
2771 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2773 NagScreen::open_uri("http://webchat.freenode.net/?channels=ardour");
2778 ARDOUR_UI::hide_about ()
2781 about->get_window()->set_cursor ();
2787 ARDOUR_UI::about_signal_response(int response)
2793 ARDOUR_UI::show_splash ()
2797 splash = new Splash;
2805 splash->queue_draw ();
2806 splash->get_window()->process_updates (true);
2811 ARDOUR_UI::hide_splash ()
2819 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2820 const string& plural_msg, const string& singular_msg)
2824 removed = rep.paths.size();
2827 MessageDialog msgd (*editor,
2828 _("No audio files were ready for cleanup"),
2831 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2832 msgd.set_secondary_text (_("If this seems suprising, \n\
2833 check for any existing snapshots.\n\
2834 These may still include regions that\n\
2835 require some unused files to continue to exist."));
2841 ArdourDialog results (_("ardour: cleanup"), true, false);
2843 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2844 CleanupResultsModelColumns() {
2848 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2849 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2853 CleanupResultsModelColumns results_columns;
2854 Glib::RefPtr<Gtk::ListStore> results_model;
2855 Gtk::TreeView results_display;
2857 results_model = ListStore::create (results_columns);
2858 results_display.set_model (results_model);
2859 results_display.append_column (list_title, results_columns.visible_name);
2861 results_display.set_name ("CleanupResultsList");
2862 results_display.set_headers_visible (true);
2863 results_display.set_headers_clickable (false);
2864 results_display.set_reorderable (false);
2866 Gtk::ScrolledWindow list_scroller;
2869 Gtk::HBox dhbox; // the hbox for the image and text
2870 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2871 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2873 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2877 %1 - number of files removed
2878 %2 - location of "dead_sounds"
2879 %3 - size of files affected
2880 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2883 const char* bprefix;
2884 float space_adjusted;
2886 if (rep.space < 1000000.0f) {
2887 bprefix = X_("kilo");
2888 space_adjusted = truncf((float)rep.space / 1000.0f);
2889 } else if (rep.space < (1000000.0f * 1000)) {
2890 bprefix = X_("mega");
2891 space_adjusted = truncf((float)rep.space / (1000000.0f));
2893 bprefix = X_("giga");
2894 space_adjusted = truncf((float)rep.space / (1000000.0f * 1000));
2898 txt.set_text (string_compose (plural_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2900 txt.set_text (string_compose (singular_msg, removed, session->path() + "dead_sounds", space_adjusted, bprefix));
2903 dhbox.pack_start (*dimage, true, false, 5);
2904 dhbox.pack_start (txt, true, false, 5);
2906 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2907 TreeModel::Row row = *(results_model->append());
2908 row[results_columns.visible_name] = *i;
2909 row[results_columns.fullpath] = *i;
2912 list_scroller.add (results_display);
2913 list_scroller.set_size_request (-1, 150);
2914 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2916 dvbox.pack_start (dhbox, true, false, 5);
2917 dvbox.pack_start (list_scroller, true, false, 5);
2918 ddhbox.pack_start (dvbox, true, false, 5);
2920 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2921 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2922 results.set_default_response (RESPONSE_CLOSE);
2923 results.set_position (Gtk::WIN_POS_MOUSE);
2924 results.show_all_children ();
2925 results.set_resizable (false);
2932 ARDOUR_UI::cleanup ()
2935 /* shouldn't happen: menu item is insensitive */
2940 MessageDialog checker (_("Are you sure you want to cleanup?"),
2942 Gtk::MESSAGE_QUESTION,
2943 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2945 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2946 ALL undo/redo information will be lost if you cleanup.\n\
2947 After cleanup, unused audio files will be moved to a \
2948 \"dead sounds\" location."));
2950 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2951 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2952 checker.set_default_response (RESPONSE_CANCEL);
2954 checker.set_name (_("CleanupDialog"));
2955 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2956 checker.set_position (Gtk::WIN_POS_MOUSE);
2958 switch (checker.run()) {
2959 case RESPONSE_ACCEPT:
2965 Session::cleanup_report rep;
2967 editor->prepare_for_cleanup ();
2969 /* do not allow flush until a session is reloaded */
2971 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2973 act->set_sensitive (false);
2976 if (session->cleanup_sources (rep)) {
2977 editor->finish_cleanup ();
2981 editor->finish_cleanup ();
2984 display_cleanup_results (rep,
2987 The following %1 files were not in use and \n\
2988 have been moved to:\n\
2990 Flushing the wastebasket will \n\
2991 release an additional\n\
2992 %3 %4bytes of disk space.\n"),
2994 The following file was not in use and \n \
2995 has been moved to:\n \
2997 Flushing the wastebasket will \n\
2998 release an additional\n\
2999 %3 %4bytes of disk space.\n"
3005 ARDOUR_UI::flush_trash ()
3008 /* shouldn't happen: menu item is insensitive */
3012 Session::cleanup_report rep;
3014 if (session->cleanup_trash_sources (rep)) {
3018 display_cleanup_results (rep,
3020 _("The following %1 files were deleted from\n\
3022 releasing %3 %4bytes of disk space"),
3023 _("The following file was deleted from\n\
3025 releasing %3 %4bytes of disk space"));
3029 ARDOUR_UI::add_route (Gtk::Window* float_window)
3037 if (add_route_dialog == 0) {
3038 add_route_dialog = new AddRouteDialog;
3040 add_route_dialog->set_transient_for (*float_window);
3044 if (add_route_dialog->is_visible()) {
3045 /* we're already doing this */
3049 ResponseType r = (ResponseType) add_route_dialog->run ();
3051 add_route_dialog->hide();
3054 case RESPONSE_ACCEPT:
3061 if ((count = add_route_dialog->count()) <= 0) {
3065 string template_path = add_route_dialog->track_template();
3067 if (!template_path.empty()) {
3068 session->new_route_from_template (count, template_path);
3072 uint32_t input_chan = add_route_dialog->channels ();
3073 uint32_t output_chan;
3074 string name_template = add_route_dialog->name_template ();
3075 bool track = add_route_dialog->track ();
3077 AutoConnectOption oac = Config->get_output_auto_connect();
3079 if (oac & AutoConnectMaster) {
3080 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3082 output_chan = input_chan;
3085 /* XXX do something with name template */
3088 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
3090 session_add_audio_bus (input_chan, output_chan, count);
3095 ARDOUR_UI::mixer_settings () const
3100 node = session->instant_xml(X_("Mixer"), session->path());
3102 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
3106 node = new XMLNode (X_("Mixer"));
3113 ARDOUR_UI::editor_settings () const
3118 node = session->instant_xml(X_("Editor"), session->path());
3120 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
3124 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3125 node = Config->instant_xml(X_("Editor"), getenv("ARDOUR_INSTANT_XML_PATH"));
3130 node = new XMLNode (X_("Editor"));
3136 ARDOUR_UI::keyboard_settings () const
3140 node = Config->extra_xml(X_("Keyboard"));
3143 node = new XMLNode (X_("Keyboard"));
3149 ARDOUR_UI::create_xrun_marker(nframes_t where)
3151 editor->mouse_add_new_marker (where, false, true);
3155 ARDOUR_UI::halt_on_xrun_message ()
3157 MessageDialog msg (*editor,
3158 _("Recording was stopped because your system could not keep up."));
3163 ARDOUR_UI::xrun_handler(nframes_t where)
3169 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
3171 if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
3172 create_xrun_marker(where);
3175 if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
3176 halt_on_xrun_message ();
3181 ARDOUR_UI::preset_file_exists_handler ()
3183 /* if driven from another thread, say "do not overwrite" and show the user nothing.
3186 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { \
3190 HBox* hbox = new HBox();
3191 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3192 Gtk::Dialog dialog (_("Preset Exists"), true, false);
3194 A preset with this name already exists for this plugin.\n\
3196 What you would like to do?\n"));
3197 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3198 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3199 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3200 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3201 dialog.add_button (_("Overwrite the existing preset"), RESPONSE_ACCEPT);
3202 dialog.add_button (_("Leave the existing preset alone"), RESPONSE_REJECT);
3203 dialog.set_default_response (RESPONSE_ACCEPT);
3204 dialog.set_position (WIN_POS_MOUSE);
3205 dialog.set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY); // need to make it float above the preset name dialog
3211 switch (dialog.run ()) {
3212 case RESPONSE_ACCEPT:
3220 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
3225 while (disk_buffer_stats.size() > 60) {
3226 disk_buffer_stats.pop_front ();
3229 disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
3233 ARDOUR_UI::write_buffer_stats ()
3238 char path[PATH_MAX+1]; int fd;
3240 strcpy (path, "ardourBufferingXXXXXX");
3242 if ((fd = mkstemp (path )) < 0) {
3243 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3251 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
3255 for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3256 localtime_r (&(*i).when, &tm);
3257 strftime (buf, sizeof (buf), "%T", &tm);
3258 fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
3261 disk_buffer_stats.clear ();
3265 cerr << "Ardour buffering statistics can be found in: " << path << endl;
3269 ARDOUR_UI::disk_overrun_handler ()
3272 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3274 write_buffer_stats ();
3276 if (!have_disk_speed_dialog_displayed) {
3277 have_disk_speed_dialog_displayed = true;
3278 MessageDialog* msg = new MessageDialog (*editor, _("\
3279 The disk system on your computer\n\
3280 was not able to keep up with Ardour.\n\
3282 Specifically, it failed to write data to disk\n\
3283 quickly enough to keep up with recording.\n"));
3284 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3290 ARDOUR_UI::disk_underrun_handler ()
3293 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3295 write_buffer_stats ();
3297 if (!have_disk_speed_dialog_displayed) {
3298 have_disk_speed_dialog_displayed = true;
3299 MessageDialog* msg = new MessageDialog (*editor,
3300 _("The disk system on your computer\n\
3301 was not able to keep up with Ardour.\n\
3303 Specifically, it failed to read data from disk\n\
3304 quickly enough to keep up with playback.\n"));
3305 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3311 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3313 have_disk_speed_dialog_displayed = false;
3318 ARDOUR_UI::session_dialog (std::string msg)
3320 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3325 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3327 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3336 ARDOUR_UI::pending_state_dialog ()
3338 HBox* hbox = new HBox();
3339 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3340 ArdourDialog dialog (_("Crash Recovery"), true);
3342 This session appears to have been in\n\
3343 middle of recording when ardour or\n\
3344 the computer was shutdown.\n\
3346 Ardour can recover any captured audio for\n\
3347 you, or it can ignore it. Please decide\n\
3348 what you would like to do.\n"));
3349 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3350 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3351 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3352 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3353 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3354 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3355 dialog.set_default_response (RESPONSE_ACCEPT);
3356 dialog.set_position (WIN_POS_CENTER);
3363 switch (dialog.run ()) {
3364 case RESPONSE_ACCEPT:
3372 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3374 HBox* hbox = new HBox();
3375 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3376 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3377 Label message (string_compose (_("\
3378 This session was created with a sample rate of %1 Hz\n\
3380 The audioengine is currently running at %2 Hz\n"), desired, actual));
3382 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3383 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3384 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3385 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3386 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3387 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3388 dialog.set_default_response (RESPONSE_ACCEPT);
3389 dialog.set_position (WIN_POS_CENTER);
3394 switch (dialog.run ()) {
3395 case RESPONSE_ACCEPT:
3404 ARDOUR_UI::disconnect_from_jack ()
3407 if( engine->disconnect_from_jack ()) {
3408 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3412 update_sample_rate (0);
3417 ARDOUR_UI::reconnect_to_jack ()
3420 if (engine->reconnect_to_jack ()) {
3421 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3425 update_sample_rate (0);
3430 ARDOUR_UI::use_config ()
3432 Glib::RefPtr<Action> act;
3434 switch (Config->get_native_file_data_format ()) {
3436 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3439 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3442 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3447 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3448 ract->set_active ();
3451 switch (Config->get_native_file_header_format ()) {
3453 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3456 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3459 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3462 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3465 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3468 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3471 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3476 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3477 ract->set_active ();
3480 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3482 set_transport_controllable_state (*node);
3487 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3489 if (Config->get_primary_clock_delta_edit_cursor()) {
3490 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3492 primary_clock.set (pos, 0, true);
3495 if (Config->get_secondary_clock_delta_edit_cursor()) {
3496 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3498 secondary_clock.set (pos);
3501 if (big_clock_window) {
3502 big_clock.set (pos);
3507 ARDOUR_UI::record_state_changed ()
3509 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3511 if (!session || !big_clock_window) {
3512 /* why bother - the clock isn't visible */
3516 switch (session->record_status()) {
3517 case Session::Recording:
3518 big_clock.set_widget_name ("BigClockRecording");
3521 big_clock.set_widget_name ("BigClockNonRecording");
3527 ARDOUR_UI::first_idle ()
3530 session->allow_auto_play (true);
3534 editor->first_idle();
3537 Keyboard::set_can_save_keybindings (true);
3542 ARDOUR_UI::store_clock_modes ()
3544 XMLNode* node = new XMLNode(X_("ClockModes"));
3546 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3547 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3550 session->add_extra_xml (*node);
3551 session->set_dirty ();
3556 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3557 : Controllable (name), ui (u), type(tp)
3563 ARDOUR_UI::TransportControllable::set_value (float val)
3565 if (type == ShuttleControl) {
3572 fract = -((0.5f - val)/0.5f);
3574 fract = ((val - 0.5f)/0.5f);
3578 ui.set_shuttle_fract (fract);
3583 /* do nothing: these are radio-style actions */
3587 const char *action = 0;
3591 action = X_("Roll");
3594 action = X_("Stop");
3597 action = X_("Goto Start");
3600 action = X_("Goto End");
3603 action = X_("Loop");
3606 action = X_("Play Selection");
3609 action = X_("Record");
3619 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3627 ARDOUR_UI::TransportControllable::get_value (void) const
3646 case ShuttleControl:
3656 ARDOUR_UI::TransportControllable::set_id (const string& str)
3662 ARDOUR_UI::setup_profile ()
3664 if (gdk_screen_width() < 1200) {
3665 Profile->set_small_screen ();
3668 if (getenv ("ARDOUR_SAE")) {
3669 Profile->set_sae ();
3670 Profile->set_single_package ();