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.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/basename.h>
37 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/audiofilesource.h>
63 #include <ardour/recent_sessions.h>
64 #include <ardour/port.h>
65 #include <ardour/audio_track.h>
68 #include "ardour_ui.h"
69 #include "public_editor.h"
70 #include "audio_clock.h"
75 #include "add_route_dialog.h"
76 #include "new_session_dialog.h"
80 #include "gui_thread.h"
81 #include "theme_manager.h"
82 #include "engine_dialog.h"
86 using namespace ARDOUR;
88 using namespace Gtkmm2ext;
92 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
93 UIConfiguration *ARDOUR_UI::ui_config = 0;
95 sigc::signal<void,bool> ARDOUR_UI::Blink;
96 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
97 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
98 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
100 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
102 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
104 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
105 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
106 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
107 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
111 adjuster_table (3, 3),
115 preroll_button (_("pre\nroll")),
116 postroll_button (_("post\nroll")),
120 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
124 roll_controllable ("transport roll", *this, TransportControllable::Roll),
125 stop_controllable ("transport stop", *this, TransportControllable::Stop),
126 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
127 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
128 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
129 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
130 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
131 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
132 shuttle_controller_binding_proxy (shuttle_controllable),
134 roll_button (roll_controllable),
135 stop_button (stop_controllable),
136 goto_start_button (goto_start_controllable),
137 goto_end_button (goto_end_controllable),
138 auto_loop_button (auto_loop_controllable),
139 play_selection_button (play_selection_controllable),
140 rec_button (rec_controllable),
142 shuttle_units_button (_("% ")),
144 punch_in_button (_("Punch In")),
145 punch_out_button (_("Punch Out")),
146 auto_return_button (_("Auto Return")),
147 auto_play_button (_("Auto Play")),
148 auto_input_button (_("Auto Input")),
149 click_button (_("Click")),
150 time_master_button (_("time\nmaster")),
152 auditioning_alert_button (_("AUDITION")),
153 solo_alert_button (_("SOLO")),
155 error_log_button (_("Errors"))
157 using namespace Gtk::Menu_Helpers;
162 _auto_display_errors = false;
168 if (ARDOUR_COMMAND_LINE::session_name.length()) {
169 /* only show this if we're not going to post the new session dialog */
173 if (theArdourUI == 0) {
177 ui_config = new UIConfiguration();
178 theme_manager = new ThemeManager();
184 _session_is_new = false;
185 big_clock_window = 0;
186 session_selector_window = 0;
187 new_session_dialog = 0;
188 last_key_press_time = 0;
189 connection_editor = 0;
190 add_route_dialog = 0;
195 open_session_selector = 0;
196 have_configure_timeout = false;
197 have_disk_speed_dialog_displayed = false;
198 _will_create_new_session_automatically = false;
199 session_loaded = false;
200 last_speed_displayed = -1.0f;
201 ignore_dual_punch = false;
203 last_configure_time.tv_sec = 0;
204 last_configure_time.tv_usec = 0;
206 shuttle_grabbed = false;
208 shuttle_max_speed = 8.0f;
210 shuttle_style_menu = 0;
211 shuttle_unit_menu = 0;
213 gettimeofday (&last_peak_grab, 0);
214 gettimeofday (&last_shuttle_request, 0);
216 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
217 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
219 /* handle pending state with a dialog */
221 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
223 /* handle sr mismatch with a dialog */
225 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
227 /* lets get this party started */
230 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
231 throw failed_constructor ();
234 setup_gtk_ardour_enums ();
235 Config->set_current_owner (ConfigVariableBase::Interface);
238 } catch (failed_constructor& err) {
239 error << _("could not initialize Ardour.") << endmsg;
244 /* we like keyboards */
246 keyboard = new Keyboard;
250 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
251 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
257 ARDOUR_UI::create_engine ()
259 // this gets called every time by new_session()
265 loading_message (_("Starting audio engine"));
268 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
275 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
276 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
277 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
278 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
286 ARDOUR_UI::post_engine ()
288 /* Things to be done once we create the AudioEngine
291 check_memory_locking();
293 ActionManager::init ();
296 if (setup_windows ()) {
297 throw failed_constructor ();
300 /* this is the first point at which all the keybindings are available */
302 if (ARDOUR_COMMAND_LINE::show_key_actions) {
303 vector<string> names;
304 vector<string> paths;
306 vector<AccelKey> bindings;
308 ActionManager::get_all_actions (names, paths, keys, bindings);
310 vector<string>::iterator n;
311 vector<string>::iterator k;
312 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
313 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
319 blink_timeout_tag = -1;
321 /* the global configuration object is now valid */
325 /* this being a GUI and all, we want peakfiles */
327 AudioFileSource::set_build_peakfiles (true);
328 AudioFileSource::set_build_missing_peakfiles (true);
330 /* set default clock modes */
332 if (Profile->get_sae()) {
333 primary_clock.set_mode (AudioClock::MinSec);
335 primary_clock.set_mode (AudioClock::SMPTE);
337 secondary_clock.set_mode (AudioClock::BBT);
339 /* start the time-of-day-clock */
342 /* OS X provides an always visible wallclock, so don't be stupid */
343 update_wall_clock ();
344 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
347 update_disk_space ();
349 update_sample_rate (engine->frame_rate());
351 platform_specific ();
353 /* now start and maybe save state */
355 if (do_engine_start () == 0) {
356 if (session && _session_is_new) {
357 /* we need to retain initial visual
358 settings for a new session
360 session->save_state ("");
365 ARDOUR_UI::~ARDOUR_UI ()
367 save_ardour_state ();
381 if (add_route_dialog) {
382 delete add_route_dialog;
385 if (new_session_dialog) {
386 delete new_session_dialog;
391 ARDOUR_UI::pop_back_splash ()
393 if (Splash::instance()) {
394 // Splash::instance()->pop_back();
395 Splash::instance()->hide ();
400 ARDOUR_UI::configure_timeout ()
405 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
406 /* no configure events yet */
410 gettimeofday (&now, 0);
411 timersub (&now, &last_configure_time, &diff);
413 /* force a gap of 0.5 seconds since the last configure event
416 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
419 have_configure_timeout = false;
420 save_ardour_state ();
426 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
428 if (have_configure_timeout) {
429 gettimeofday (&last_configure_time, 0);
431 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
432 have_configure_timeout = true;
439 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
441 const XMLProperty* prop;
443 if ((prop = node.property ("roll")) != 0) {
444 roll_controllable.set_id (prop->value());
446 if ((prop = node.property ("stop")) != 0) {
447 stop_controllable.set_id (prop->value());
449 if ((prop = node.property ("goto_start")) != 0) {
450 goto_start_controllable.set_id (prop->value());
452 if ((prop = node.property ("goto_end")) != 0) {
453 goto_end_controllable.set_id (prop->value());
455 if ((prop = node.property ("auto_loop")) != 0) {
456 auto_loop_controllable.set_id (prop->value());
458 if ((prop = node.property ("play_selection")) != 0) {
459 play_selection_controllable.set_id (prop->value());
461 if ((prop = node.property ("rec")) != 0) {
462 rec_controllable.set_id (prop->value());
464 if ((prop = node.property ("shuttle")) != 0) {
465 shuttle_controllable.set_id (prop->value());
470 ARDOUR_UI::get_transport_controllable_state ()
472 XMLNode* node = new XMLNode(X_("TransportControllables"));
475 roll_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("roll"), buf);
477 stop_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("stop"), buf);
479 goto_start_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("goto_start"), buf);
481 goto_end_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("goto_end"), buf);
483 auto_loop_controllable.id().print (buf, sizeof (buf));
484 node->add_property (X_("auto_loop"), buf);
485 play_selection_controllable.id().print (buf, sizeof (buf));
486 node->add_property (X_("play_selection"), buf);
487 rec_controllable.id().print (buf, sizeof (buf));
488 node->add_property (X_("rec"), buf);
489 shuttle_controllable.id().print (buf, sizeof (buf));
490 node->add_property (X_("shuttle"), buf);
496 ARDOUR_UI::save_ardour_state ()
498 if (!keyboard || !mixer || !editor) {
502 /* XXX this is all a bit dubious. add_extra_xml() uses
503 a different lifetime model from add_instant_xml().
506 XMLNode* node = new XMLNode (keyboard->get_state());
507 Config->add_extra_xml (*node);
508 Config->add_extra_xml (get_transport_controllable_state());
509 if (new_session_dialog) {
510 if (new_session_dialog->engine_control.was_used()) {
511 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
514 Config->save_state();
515 ui_config->save_state ();
517 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
518 XMLNode mnode(mixer->get_state());
521 session->add_instant_xml (enode, session->path());
522 session->add_instant_xml (mnode, session->path());
524 Config->add_instant_xml (enode, get_user_ardour_path());
525 Config->add_instant_xml (mnode, get_user_ardour_path());
528 Keyboard::save_keybindings ();
532 ARDOUR_UI::autosave_session ()
534 if (!Config->get_periodic_safety_backups())
538 session->maybe_write_autosave();
545 ARDOUR_UI::update_autosave ()
547 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
549 if (session->dirty()) {
550 if (_autosave_connection.connected()) {
551 _autosave_connection.disconnect();
554 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
555 Config->get_periodic_safety_backup_interval() * 1000);
558 if (_autosave_connection.connected()) {
559 _autosave_connection.disconnect();
565 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
569 title = _("Ardour could not start JACK");
571 title = _("Ardour could not connect to JACK.");
574 MessageDialog win (title,
580 win.set_secondary_text(_("There are several possible reasons:\n\
582 1) You requested audio parameters that are not supported..\n\
583 2) JACK is running as another user.\n\
585 Please consider the possibilities, and perhaps try different parameters."));
587 win.set_secondary_text(_("There are several possible reasons:\n\
589 1) JACK is not running.\n\
590 2) JACK is running as another user, perhaps root.\n\
591 3) There is already another client called \"ardour\".\n\
593 Please consider the possibilities, and perhaps (re)start JACK."));
597 win.set_transient_for (*toplevel);
601 win.add_button (Stock::OK, RESPONSE_CLOSE);
603 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
606 win.set_default_response (RESPONSE_CLOSE);
609 win.set_position (Gtk::WIN_POS_CENTER);
612 /* we just don't care about the result, but we want to block */
618 ARDOUR_UI::startup ()
622 new_session_dialog = new NewSessionDialog();
624 bool backend_audio_is_running = EngineControl::engine_running();
625 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
628 new_session_dialog->engine_control.set_state (*audio_setup);
631 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
635 BootMessage (_("Ardour is ready for use"));
640 ARDOUR_UI::no_memory_warning ()
642 XMLNode node (X_("no-memory-warning"));
643 Config->add_instant_xml (node, get_user_ardour_path());
647 ARDOUR_UI::check_memory_locking ()
650 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
654 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
656 if (engine->is_realtime() && memory_warning_node == 0) {
658 struct rlimit limits;
660 long pages, page_size;
662 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
665 ram = (int64_t) pages * (int64_t) page_size;
668 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
672 if (limits.rlim_cur != RLIM_INFINITY) {
674 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
677 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
678 "This might cause Ardour to run out of memory before your system "
679 "runs out of memory. \n\n"
680 "You can view the memory limit with 'ulimit -l', "
681 "and it is normally controlled by /etc/security/limits.conf"));
683 VBox* vbox = msg.get_vbox();
685 CheckButton cb (_("Do not show this window again"));
687 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
689 hbox.pack_start (cb, true, false);
690 vbox->pack_start (hbox);
708 if (session->transport_rolling()) {
709 session->request_stop ();
713 if (session->dirty()) {
714 switch (ask_about_saving_session(_("quit"))) {
719 /* use the default name */
720 if (save_state_canfail ("")) {
721 /* failed - don't quit */
722 MessageDialog msg (*editor,
724 Ardour was unable to save your session.\n\n\
725 If you still wish to quit, please use the\n\n\
726 \"Just quit\" option."));
737 session->set_deletion_in_progress ();
741 save_ardour_state ();
746 ARDOUR_UI::ask_about_saving_session (const string & what)
748 ArdourDialog window (_("ardour: save session?"));
749 Gtk::HBox dhbox; // the hbox for the image and text
750 Gtk::Label prompt_label;
751 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
755 msg = string_compose(_("Don't %1"), what);
756 window.add_button (msg, RESPONSE_REJECT);
757 msg = string_compose(_("Just %1"), what);
758 window.add_button (msg, RESPONSE_APPLY);
759 msg = string_compose(_("Save and %1"), what);
760 window.add_button (msg, RESPONSE_ACCEPT);
762 window.set_default_response (RESPONSE_ACCEPT);
764 Gtk::Button noquit_button (msg);
765 noquit_button.set_name ("EditorGTKButton");
770 if (session->snap_name() == session->name()) {
773 type = _("snapshot");
775 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?"),
776 type, session->snap_name());
778 prompt_label.set_text (prompt);
779 prompt_label.set_name (X_("PrompterLabel"));
780 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
782 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
784 dhbox.set_homogeneous (false);
785 dhbox.pack_start (*dimage, false, false, 5);
786 dhbox.pack_start (prompt_label, true, false, 5);
787 window.get_vbox()->pack_start (dhbox);
789 window.set_name (_("Prompter"));
790 window.set_position (Gtk::WIN_POS_MOUSE);
791 window.set_modal (true);
792 window.set_resizable (false);
795 save_the_session = 0;
797 window.set_keep_above (true);
800 ResponseType r = (ResponseType) window.run();
805 case RESPONSE_ACCEPT: // save and get out of here
807 case RESPONSE_APPLY: // get out of here
817 ARDOUR_UI::every_second ()
820 update_buffer_load ();
821 update_disk_space ();
826 ARDOUR_UI::every_point_one_seconds ()
828 update_speed_display ();
829 RapidScreenUpdate(); /* EMIT_SIGNAL */
834 ARDOUR_UI::every_point_zero_one_seconds ()
836 // august 2007: actual update frequency: 40Hz, not 100Hz
838 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
843 ARDOUR_UI::update_sample_rate (nframes_t ignored)
847 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
849 if (!engine->connected()) {
851 snprintf (buf, sizeof (buf), _("disconnected"));
855 nframes_t rate = engine->frame_rate();
857 if (fmod (rate, 1000.0) != 0.0) {
858 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
859 (float) rate/1000.0f,
860 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
862 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
864 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
868 sample_rate_label.set_text (buf);
872 ARDOUR_UI::update_cpu_load ()
875 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
876 cpu_load_label.set_text (buf);
880 ARDOUR_UI::update_buffer_load ()
885 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
886 session->playback_load(), session->capture_load());
887 buffer_load_label.set_text (buf);
889 buffer_load_label.set_text ("");
894 ARDOUR_UI::count_recenabled_streams (Route& route)
896 Track* track = dynamic_cast<Track*>(&route);
897 if (track && track->diskstream()->record_enabled()) {
898 rec_enabled_streams += track->n_inputs();
903 ARDOUR_UI::update_disk_space()
909 nframes_t frames = session->available_capture_duration();
912 if (frames == max_frames) {
913 strcpy (buf, _("Disk: 24hrs+"));
918 nframes_t fr = session->frame_rate();
920 rec_enabled_streams = 0;
921 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
923 if (rec_enabled_streams) {
924 frames /= rec_enabled_streams;
927 hrs = frames / (fr * 3600);
928 frames -= hrs * fr * 3600;
929 mins = frames / (fr * 60);
930 frames -= mins * fr * 60;
933 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
936 disk_space_label.set_text (buf);
940 ARDOUR_UI::update_wall_clock ()
947 tm_now = localtime (&now);
949 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
950 wall_clock_label.set_text (buf);
956 ARDOUR_UI::session_menu (GdkEventButton *ev)
958 session_popup_menu->popup (0, 0);
963 ARDOUR_UI::redisplay_recent_sessions ()
965 vector<string *> *sessions;
966 vector<string *>::iterator i;
967 RecentSessionsSorter cmp;
969 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
970 recent_session_model->clear ();
973 ARDOUR::read_recent_sessions (rs);
976 recent_session_display.set_model (recent_session_model);
980 /* sort them alphabetically */
981 sort (rs.begin(), rs.end(), cmp);
982 sessions = new vector<string*>;
984 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
985 sessions->push_back (new string ((*i).second));
988 for (i = sessions->begin(); i != sessions->end(); ++i) {
990 vector<string*>* states;
991 vector<const gchar*> item;
992 string fullpath = *(*i);
994 /* remove any trailing / */
996 if (fullpath[fullpath.length()-1] == '/') {
997 fullpath = fullpath.substr (0, fullpath.length()-1);
1000 /* check whether session still exists */
1001 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1002 /* session doesn't exist */
1003 cerr << "skipping non-existent session " << fullpath << endl;
1007 /* now get available states for this session */
1009 if ((states = Session::possible_states (fullpath)) == 0) {
1010 /* no state file? */
1014 TreeModel::Row row = *(recent_session_model->append());
1016 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1017 row[recent_session_columns.fullpath] = fullpath;
1019 if (states->size() > 1) {
1021 /* add the children */
1023 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1025 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1027 child_row[recent_session_columns.visible_name] = **i2;
1028 child_row[recent_session_columns.fullpath] = fullpath;
1037 recent_session_display.set_model (recent_session_model);
1042 ARDOUR_UI::build_session_selector ()
1044 session_selector_window = new ArdourDialog ("session selector");
1046 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1048 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1049 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1050 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1051 recent_session_model = TreeStore::create (recent_session_columns);
1052 recent_session_display.set_model (recent_session_model);
1053 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1054 recent_session_display.set_headers_visible (false);
1055 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1056 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1058 scroller->add (recent_session_display);
1059 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1061 session_selector_window->set_name ("SessionSelectorWindow");
1062 session_selector_window->set_size_request (200, 400);
1063 session_selector_window->get_vbox()->pack_start (*scroller);
1064 session_selector_window->show_all_children();
1068 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1070 session_selector_window->response (RESPONSE_ACCEPT);
1074 ARDOUR_UI::open_recent_session ()
1076 bool can_return = (session != 0);
1078 if (session_selector_window == 0) {
1079 build_session_selector ();
1082 redisplay_recent_sessions ();
1086 session_selector_window->set_position (WIN_POS_MOUSE);
1088 ResponseType r = (ResponseType) session_selector_window->run ();
1091 case RESPONSE_ACCEPT:
1095 session_selector_window->hide();
1102 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1106 session_selector_window->hide();
1108 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1110 if (i == recent_session_model->children().end()) {
1114 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1115 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1117 _session_is_new = false;
1119 if (load_session (path, state) == 0) {
1128 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1130 struct stat statbuf;
1132 if (stat (info.filename.c_str(), &statbuf) != 0) {
1136 if (!S_ISDIR(statbuf.st_mode)) {
1142 string session_file = info.filename;
1143 session_file += '/';
1144 session_file += Glib::path_get_basename (info.filename);
1145 session_file += ".ardour";
1147 if (stat (session_file.c_str(), &statbuf) != 0) {
1151 return S_ISREG (statbuf.st_mode);
1155 ARDOUR_UI::check_audioengine ()
1158 if (!engine->connected()) {
1159 MessageDialog msg (_("Ardour is not connected to JACK\n"
1160 "You cannot open or close sessions in this condition"));
1172 ARDOUR_UI::open_session ()
1174 if (!check_audioengine()) {
1178 /* popup selector window */
1180 if (open_session_selector == 0) {
1182 /* ardour sessions are folders */
1184 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1185 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1186 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1187 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1189 FileFilter session_filter;
1190 session_filter.add_pattern ("*.ardour");
1191 session_filter.set_name (_("Ardour sessions"));
1192 open_session_selector->add_filter (session_filter);
1193 open_session_selector->set_filter (session_filter);
1196 int response = open_session_selector->run();
1197 open_session_selector->hide ();
1200 case RESPONSE_ACCEPT:
1203 open_session_selector->hide();
1207 open_session_selector->hide();
1208 string session_path = open_session_selector->get_filename();
1212 if (session_path.length() > 0) {
1213 if (Session::find_session (session_path, path, name, isnew) == 0) {
1214 _session_is_new = isnew;
1215 load_session (path, name);
1222 ARDOUR_UI::session_add_midi_track ()
1224 cerr << _("Patience is a virtue.\n");
1228 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1230 list<boost::shared_ptr<AudioTrack> > tracks;
1231 Session::RouteList routes;
1234 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1240 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1242 if (tracks.size() != how_many) {
1243 if (how_many == 1) {
1244 error << _("could not create a new audio track") << endmsg;
1246 error << string_compose (_("could only create %1 of %2 new audio %3"),
1247 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1253 routes = session->new_audio_route (input_channels, output_channels, how_many);
1255 if (routes.size() != how_many) {
1256 if (how_many == 1) {
1257 error << _("could not create a new audio track") << endmsg;
1259 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1265 if (need_control_room_outs) {
1271 route->set_stereo_control_outs (control_lr_channels);
1272 route->control_outs()->set_stereo_pan (pans, this);
1274 #endif /* CONTROLOUTS */
1278 MessageDialog msg (*editor,
1279 _("There are insufficient JACK ports available\n\
1280 to create a new track or bus.\n\
1281 You should save Ardour, exit and\n\
1282 restart JACK with more ports."));
1289 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1291 nframes_t _preroll = 0;
1294 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1295 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1297 if (new_position > _preroll) {
1298 new_position -= _preroll;
1303 session->request_locate (new_position);
1308 ARDOUR_UI::transport_goto_start ()
1311 session->goto_start();
1314 /* force displayed area in editor to start no matter
1315 what "follow playhead" setting is.
1319 editor->reset_x_origin (session->current_start_frame());
1325 ARDOUR_UI::transport_goto_zero ()
1328 session->request_locate (0);
1331 /* force displayed area in editor to start no matter
1332 what "follow playhead" setting is.
1336 editor->reset_x_origin (0);
1342 ARDOUR_UI::transport_goto_end ()
1345 nframes_t frame = session->current_end_frame();
1346 session->request_locate (frame);
1348 /* force displayed area in editor to start no matter
1349 what "follow playhead" setting is.
1353 editor->reset_x_origin (frame);
1359 ARDOUR_UI::transport_stop ()
1365 if (session->is_auditioning()) {
1366 session->cancel_audition ();
1370 if (session->get_play_loop ()) {
1371 session->request_play_loop (false);
1374 session->request_stop ();
1378 ARDOUR_UI::transport_stop_and_forget_capture ()
1381 session->request_stop (true);
1386 ARDOUR_UI::remove_last_capture()
1389 editor->remove_last_capture();
1394 ARDOUR_UI::transport_record (bool roll)
1397 switch (session->record_status()) {
1398 case Session::Disabled:
1399 if (session->ntracks() == 0) {
1400 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1404 session->maybe_enable_record ();
1409 case Session::Recording:
1411 session->request_stop();
1413 session->disable_record (false, true);
1417 case Session::Enabled:
1418 session->disable_record (false, true);
1424 ARDOUR_UI::transport_roll ()
1432 rolling = session->transport_rolling ();
1434 if (session->get_play_loop()) {
1435 session->request_play_loop (false);
1436 auto_loop_button.set_visual_state (1);
1437 roll_button.set_visual_state (1);
1438 } else if (session->get_play_range ()) {
1439 session->request_play_range (false);
1440 play_selection_button.set_visual_state (0);
1441 } else if (rolling) {
1442 session->request_locate (session->last_transport_start(), true);
1445 session->request_transport_speed (1.0f);
1449 ARDOUR_UI::transport_loop()
1452 if (session->get_play_loop()) {
1453 if (session->transport_rolling()) {
1454 Location * looploc = session->locations()->auto_loop_location();
1456 session->request_locate (looploc->start(), true);
1461 session->request_play_loop (true);
1467 ARDOUR_UI::transport_play_selection ()
1473 if (!session->get_play_range()) {
1474 session->request_stop ();
1477 editor->play_selection ();
1481 ARDOUR_UI::transport_rewind (int option)
1483 float current_transport_speed;
1486 current_transport_speed = session->transport_speed();
1488 if (current_transport_speed >= 0.0f) {
1491 session->request_transport_speed (-1.0f);
1494 session->request_transport_speed (-4.0f);
1497 session->request_transport_speed (-0.5f);
1502 session->request_transport_speed (current_transport_speed * 1.5f);
1508 ARDOUR_UI::transport_forward (int option)
1510 float current_transport_speed;
1513 current_transport_speed = session->transport_speed();
1515 if (current_transport_speed <= 0.0f) {
1518 session->request_transport_speed (1.0f);
1521 session->request_transport_speed (4.0f);
1524 session->request_transport_speed (0.5f);
1529 session->request_transport_speed (current_transport_speed * 1.5f);
1535 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1541 boost::shared_ptr<Route> r;
1543 if ((r = session->route_by_remote_id (dstream)) != 0) {
1547 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1548 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1557 ARDOUR_UI::queue_transport_change ()
1559 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1563 ARDOUR_UI::map_transport_state ()
1565 float sp = session->transport_speed();
1568 transport_rolling ();
1569 } else if (sp < 0.0f) {
1570 transport_rewinding ();
1571 } else if (sp > 0.0f) {
1572 transport_forwarding ();
1574 transport_stopped ();
1579 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1581 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1582 (int) adj.get_value()].c_str());
1586 ARDOUR_UI::engine_stopped ()
1588 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1589 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1590 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1594 ARDOUR_UI::engine_running ()
1596 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1597 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1598 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1600 Glib::RefPtr<Action> action;
1601 const char* action_name = 0;
1603 switch (engine->frames_per_cycle()) {
1605 action_name = X_("JACKLatency32");
1608 action_name = X_("JACKLatency64");
1611 action_name = X_("JACKLatency128");
1614 action_name = X_("JACKLatency512");
1617 action_name = X_("JACKLatency1024");
1620 action_name = X_("JACKLatency2048");
1623 action_name = X_("JACKLatency4096");
1626 action_name = X_("JACKLatency8192");
1629 /* XXX can we do anything useful ? */
1635 action = ActionManager::get_action (X_("JACK"), action_name);
1638 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1639 ract->set_active ();
1645 ARDOUR_UI::engine_halted ()
1647 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1649 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1650 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1652 update_sample_rate (0);
1654 MessageDialog msg (*editor,
1656 JACK has either been shutdown or it\n\
1657 disconnected Ardour because Ardour\n\
1658 was not fast enough. You can save the\n\
1659 session and/or try to reconnect to JACK ."));
1665 ARDOUR_UI::do_engine_start ()
1673 error << _("Unable to start the session running")
1683 ARDOUR_UI::setup_theme ()
1685 theme_manager->setup_theme();
1689 ARDOUR_UI::update_clocks ()
1691 if (!editor || !editor->dragging_playhead()) {
1692 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1697 ARDOUR_UI::start_clocking ()
1699 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1703 ARDOUR_UI::stop_clocking ()
1705 clock_signal_connection.disconnect ();
1709 ARDOUR_UI::toggle_clocking ()
1712 if (clock_button.get_active()) {
1721 ARDOUR_UI::_blink (void *arg)
1724 ((ARDOUR_UI *) arg)->blink ();
1731 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1735 ARDOUR_UI::start_blinking ()
1737 /* Start the blink signal. Everybody with a blinking widget
1738 uses Blink to drive the widget's state.
1741 if (blink_timeout_tag < 0) {
1743 blink_timeout_tag = g_timeout_add (240, _blink, this);
1748 ARDOUR_UI::stop_blinking ()
1750 if (blink_timeout_tag >= 0) {
1751 g_source_remove (blink_timeout_tag);
1752 blink_timeout_tag = -1;
1757 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1763 if (io.n_inputs() == 0) {
1768 /* XXX we're not handling multiple ports yet. */
1770 const char **connections = io.input(0)->get_connections();
1772 if (connections == 0 || connections[0] == '\0') {
1775 buf = connections[0];
1782 if (io.n_outputs() == 0) {
1787 /* XXX we're not handling multiple ports yet. */
1789 const char **connections = io.output(0)->get_connections();
1791 if (connections == 0 || connections[0] == '\0') {
1794 buf = connections[0];
1801 /** Ask the user for the name of a new shapshot and then take it.
1804 ARDOUR_UI::snapshot_session ()
1806 ArdourPrompter prompter (true);
1810 struct tm local_time;
1813 localtime_r (&n, &local_time);
1814 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1816 prompter.set_name ("Prompter");
1817 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1818 prompter.set_prompt (_("Name of New Snapshot"));
1819 prompter.set_initial_text (timebuf);
1821 switch (prompter.run()) {
1822 case RESPONSE_ACCEPT:
1823 prompter.get_result (snapname);
1824 if (snapname.length()){
1825 save_state (snapname);
1835 ARDOUR_UI::save_state (const string & name)
1837 (void) save_state_canfail (name);
1841 ARDOUR_UI::save_state_canfail (string name)
1846 if (name.length() == 0) {
1847 name = session->snap_name();
1850 if ((ret = session->save_state (name)) != 0) {
1854 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1859 ARDOUR_UI::restore_state (string name)
1862 if (name.length() == 0) {
1863 name = session->name();
1865 session->restore_state (name);
1870 ARDOUR_UI::primary_clock_value_changed ()
1873 session->request_locate (primary_clock.current_time ());
1878 ARDOUR_UI::big_clock_value_changed ()
1881 session->request_locate (big_clock.current_time ());
1886 ARDOUR_UI::secondary_clock_value_changed ()
1889 session->request_locate (secondary_clock.current_time ());
1894 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1896 if (session && dstream && dstream->record_enabled()) {
1898 Session::RecordState rs;
1900 rs = session->record_status ();
1903 case Session::Disabled:
1904 case Session::Enabled:
1905 if (w->get_state() != STATE_SELECTED) {
1906 w->set_state (STATE_SELECTED);
1910 case Session::Recording:
1911 if (w->get_state() != STATE_ACTIVE) {
1912 w->set_state (STATE_ACTIVE);
1918 if (w->get_state() != STATE_NORMAL) {
1919 w->set_state (STATE_NORMAL);
1925 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1931 switch (session->record_status()) {
1932 case Session::Enabled:
1934 rec_button.set_visual_state (2);
1936 rec_button.set_visual_state (0);
1940 case Session::Recording:
1941 rec_button.set_visual_state (1);
1945 rec_button.set_visual_state (0);
1951 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1959 ARDOUR_UI::save_template ()
1962 ArdourPrompter prompter (true);
1965 if (!check_audioengine()) {
1969 prompter.set_name (X_("Prompter"));
1970 prompter.set_prompt (_("Name for mix template:"));
1971 prompter.set_initial_text(session->name() + _("-template"));
1972 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1974 switch (prompter.run()) {
1975 case RESPONSE_ACCEPT:
1976 prompter.get_result (name);
1978 if (name.length()) {
1979 session->save_template (name);
1989 ARDOUR_UI::fontconfig_dialog ()
1992 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1993 may not and it can take a while to build it. Warn them.
1996 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1998 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1999 MessageDialog msg (*new_session_dialog,
2000 _("Welcome to Ardour.\n\n"
2001 "The program will take a bit longer to start up\n"
2002 "while the system fonts are checked.\n\n"
2003 "This will only be done once, and you will\n"
2004 "not see this message again\n"),
2017 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2019 existing_session = false;
2021 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2022 session_path = cmdline_path;
2023 existing_session = true;
2024 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2025 session_path = Glib::path_get_dirname (string (cmdline_path));
2026 existing_session = true;
2028 /* it doesn't exist, assume the best */
2029 session_path = Glib::path_get_dirname (string (cmdline_path));
2032 session_name = basename_nosuffix (string (cmdline_path));
2036 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2038 /* when this is called, the backend audio system must be running */
2040 /* the main idea here is to deal with the fact that a cmdline argument for the session
2041 can be interpreted in different ways - it could be a directory or a file, and before
2042 we load, we need to know both the session directory and the snapshot (statefile) within it
2043 that we are supposed to use.
2046 if (session_name.length() == 0 || session_path.length() == 0) {
2050 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2052 Glib::ustring predicted_session_file;
2054 predicted_session_file = session_path;
2055 predicted_session_file += '/';
2056 predicted_session_file += session_name;
2057 predicted_session_file += Session::statefile_suffix();
2059 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2060 existing_session = true;
2063 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2065 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2066 /* existing .ardour file */
2067 existing_session = true;
2071 existing_session = false;
2074 /* lets just try to load it */
2076 if (create_engine ()) {
2077 backend_audio_error (false, new_session_dialog);
2081 return load_session (session_path, session_name);
2085 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2087 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2089 MessageDialog msg (str,
2091 Gtk::MESSAGE_WARNING,
2092 Gtk::BUTTONS_YES_NO,
2096 msg.set_name (X_("CleanupDialog"));
2097 msg.set_wmclass (X_("existing_session"), "Ardour");
2098 msg.set_position (Gtk::WIN_POS_MOUSE);
2101 switch (msg.run()) {
2110 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2115 AutoConnectOption iconnect;
2116 AutoConnectOption oconnect;
2120 if (Profile->get_sae()) {
2124 iconnect = AutoConnectPhysical;
2125 oconnect = AutoConnectMaster;
2126 nphysin = 0; // use all available
2127 nphysout = 0; // use all available
2131 /* get settings from advanced section of NSD */
2133 if (new_session_dialog->create_control_bus()) {
2134 cchns = (uint32_t) new_session_dialog->control_channel_count();
2139 if (new_session_dialog->create_master_bus()) {
2140 mchns = (uint32_t) new_session_dialog->master_channel_count();
2145 if (new_session_dialog->connect_inputs()) {
2146 iconnect = AutoConnectPhysical;
2148 iconnect = AutoConnectOption (0);
2151 /// @todo some minor tweaks.
2153 if (new_session_dialog->connect_outs_to_master()) {
2154 oconnect = AutoConnectMaster;
2155 } else if (new_session_dialog->connect_outs_to_physical()) {
2156 oconnect = AutoConnectPhysical;
2158 oconnect = AutoConnectOption (0);
2161 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2162 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2165 if (build_session (session_path,
2173 engine->frame_rate() * 60 * 5)) {
2182 ARDOUR_UI::end_loading_messages ()
2188 ARDOUR_UI::loading_message (const std::string& msg)
2191 splash->message (msg);
2196 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2198 bool existing_session = false;
2199 Glib::ustring session_name;
2200 Glib::ustring session_path;
2201 Glib::ustring template_name;
2203 int response = Gtk::RESPONSE_NONE;
2205 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2207 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2209 /* don't ever reuse this */
2211 ARDOUR_COMMAND_LINE::session_name = string();
2213 if (existing_session && backend_audio_is_running) {
2215 /* just load the thing already */
2217 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2222 /* make the NSD use whatever information we have */
2224 new_session_dialog->set_session_name (session_name);
2225 new_session_dialog->set_session_folder (session_path);
2228 /* loading failed, or we need the NSD for something */
2230 new_session_dialog->set_modal (false);
2231 new_session_dialog->set_position (WIN_POS_CENTER);
2232 new_session_dialog->set_current_page (0);
2233 new_session_dialog->set_existing_session (existing_session);
2234 new_session_dialog->reset_recent();
2237 new_session_dialog->set_have_engine (backend_audio_is_running);
2238 new_session_dialog->present ();
2239 response = new_session_dialog->run ();
2241 _session_is_new = false;
2243 /* handle possible negative responses */
2246 case Gtk::RESPONSE_CANCEL:
2247 case Gtk::RESPONSE_DELETE_EVENT:
2251 new_session_dialog->hide ();
2254 case Gtk::RESPONSE_NONE:
2255 /* "Clear" was pressed */
2259 fontconfig_dialog();
2261 if (!backend_audio_is_running) {
2262 if (new_session_dialog->engine_control.setup_engine ()) {
2263 new_session_dialog->hide ();
2268 if (create_engine ()) {
2270 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2273 new_session_dialog->set_existing_session (false);
2274 new_session_dialog->set_current_page (2);
2276 response = Gtk::RESPONSE_NONE;
2280 backend_audio_is_running = true;
2282 if (response == Gtk::RESPONSE_OK) {
2284 session_name = new_session_dialog->session_name();
2286 if (session_name.empty()) {
2287 response = Gtk::RESPONSE_NONE;
2291 /* if the user mistakenly typed path information into the session filename entry,
2292 convert what they typed into a path & a name
2295 if (session_name[0] == '/' ||
2296 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2297 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2299 session_path = Glib::path_get_dirname (session_name);
2300 session_name = Glib::path_get_basename (session_name);
2304 session_path = new_session_dialog->session_folder();
2307 template_name = Glib::ustring();
2308 switch (new_session_dialog->which_page()) {
2310 case NewSessionDialog::OpenPage:
2311 case NewSessionDialog::EnginePage:
2315 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2317 should_be_new = true;
2319 //XXX This is needed because session constructor wants a
2320 //non-existant path. hopefully this will be fixed at some point.
2322 session_path = Glib::build_filename (session_path, session_name);
2324 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2326 if (ask_about_loading_existing_session (session_path)) {
2329 response = RESPONSE_NONE;
2334 _session_is_new = true;
2336 if (new_session_dialog->use_session_template()) {
2338 template_name = new_session_dialog->session_template_name();
2342 if (build_session_from_nsd (session_path, session_name)) {
2343 response = RESPONSE_NONE;
2355 new_session_dialog->hide ();
2357 if (load_session (session_path, session_name, template_name)) {
2359 response = Gtk::RESPONSE_NONE;
2363 if (response == Gtk::RESPONSE_NONE) {
2364 new_session_dialog->set_existing_session (false);
2365 new_session_dialog->reset ();
2369 } while (response == Gtk::RESPONSE_NONE);
2373 new_session_dialog->hide();
2374 new_session_dialog->reset();
2375 goto_editor_window ();
2380 ARDOUR_UI::close_session ()
2382 if (!check_audioengine()) {
2386 unload_session (true);
2388 get_session_parameters (true, false);
2392 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2394 Session *new_session;
2398 session_loaded = false;
2400 if (!check_audioengine()) {
2404 unload_status = unload_session ();
2406 if (unload_status < 0) {
2408 } else if (unload_status > 0) {
2413 /* if it already exists, we must have write access */
2415 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2416 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2417 "This prevents the session from being loaded."));
2423 loading_message (_("Please wait while Ardour loads your session"));
2424 disable_screen_updates ();
2427 new_session = new Session (*engine, path, snap_name, mix_template);
2430 /* this one is special */
2432 catch (AudioEngine::PortRegistrationFailure& err) {
2434 MessageDialog msg (err.what(),
2437 Gtk::BUTTONS_OK_CANCEL);
2439 msg.set_title (_("Loading Error"));
2440 msg.set_secondary_text (_("Click the OK button to try again."));
2441 msg.set_position (Gtk::WIN_POS_CENTER);
2445 int response = msg.run ();
2450 case RESPONSE_CANCEL:
2460 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2463 Gtk::BUTTONS_OK_CANCEL);
2465 msg.set_title (_("Loading Error"));
2466 msg.set_secondary_text (_("Click the OK button to try again."));
2467 msg.set_position (Gtk::WIN_POS_CENTER);
2471 int response = msg.run ();
2476 case RESPONSE_CANCEL:
2484 connect_to_session (new_session);
2486 Config->set_current_owner (ConfigVariableBase::Interface);
2488 session_loaded = true;
2490 goto_editor_window ();
2493 session->set_clean ();
2496 enable_screen_updates ();
2505 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2506 uint32_t control_channels,
2507 uint32_t master_channels,
2508 AutoConnectOption input_connect,
2509 AutoConnectOption output_connect,
2512 nframes_t initial_length)
2514 Session *new_session;
2517 if (!check_audioengine()) {
2521 session_loaded = false;
2523 x = unload_session ();
2531 _session_is_new = true;
2534 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2535 control_channels, master_channels, nphysin, nphysout, initial_length);
2540 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2546 connect_to_session (new_session);
2548 session_loaded = true;
2556 editor->show_window ();
2567 ARDOUR_UI::show_about ()
2571 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2578 ARDOUR_UI::hide_about ()
2581 about->get_window()->set_cursor ();
2587 ARDOUR_UI::about_signal_response(int response)
2593 ARDOUR_UI::show_splash ()
2597 splash = new Splash;
2605 splash->queue_draw ();
2606 splash->get_window()->process_updates (true);
2611 ARDOUR_UI::hide_splash ()
2619 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2623 removed = rep.paths.size();
2626 MessageDialog msgd (*editor,
2627 _("No audio files were ready for cleanup"),
2630 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2631 msgd.set_secondary_text (_("If this seems suprising, \n\
2632 check for any existing snapshots.\n\
2633 These may still include regions that\n\
2634 require some unused files to continue to exist."));
2640 ArdourDialog results (_("ardour: cleanup"), true, false);
2642 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2643 CleanupResultsModelColumns() {
2647 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2648 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2652 CleanupResultsModelColumns results_columns;
2653 Glib::RefPtr<Gtk::ListStore> results_model;
2654 Gtk::TreeView results_display;
2656 results_model = ListStore::create (results_columns);
2657 results_display.set_model (results_model);
2658 results_display.append_column (list_title, results_columns.visible_name);
2660 results_display.set_name ("CleanupResultsList");
2661 results_display.set_headers_visible (true);
2662 results_display.set_headers_clickable (false);
2663 results_display.set_reorderable (false);
2665 Gtk::ScrolledWindow list_scroller;
2668 Gtk::HBox dhbox; // the hbox for the image and text
2669 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2670 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2672 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2674 if (rep.space < 1048576.0f) {
2676 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2678 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2682 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2684 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2688 dhbox.pack_start (*dimage, true, false, 5);
2689 dhbox.pack_start (txt, true, false, 5);
2691 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2692 TreeModel::Row row = *(results_model->append());
2693 row[results_columns.visible_name] = *i;
2694 row[results_columns.fullpath] = *i;
2697 list_scroller.add (results_display);
2698 list_scroller.set_size_request (-1, 150);
2699 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2701 dvbox.pack_start (dhbox, true, false, 5);
2702 dvbox.pack_start (list_scroller, true, false, 5);
2703 ddhbox.pack_start (dvbox, true, false, 5);
2705 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2706 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2707 results.set_default_response (RESPONSE_CLOSE);
2708 results.set_position (Gtk::WIN_POS_MOUSE);
2709 results.show_all_children ();
2710 results.set_resizable (false);
2717 ARDOUR_UI::cleanup ()
2720 /* shouldn't happen: menu item is insensitive */
2725 MessageDialog checker (_("Are you sure you want to cleanup?"),
2727 Gtk::MESSAGE_QUESTION,
2728 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2730 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2731 ALL undo/redo information will be lost if you cleanup.\n\
2732 After cleanup, unused audio files will be moved to a \
2733 \"dead sounds\" location."));
2735 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2736 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2737 checker.set_default_response (RESPONSE_CANCEL);
2739 checker.set_name (_("CleanupDialog"));
2740 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2741 checker.set_position (Gtk::WIN_POS_MOUSE);
2743 switch (checker.run()) {
2744 case RESPONSE_ACCEPT:
2750 Session::cleanup_report rep;
2752 editor->prepare_for_cleanup ();
2754 /* do not allow flush until a session is reloaded */
2756 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2758 act->set_sensitive (false);
2761 if (session->cleanup_sources (rep)) {
2766 display_cleanup_results (rep,
2769 The following %1 %2 not in use and \n\
2770 have been moved to:\n\
2772 Flushing the wastebasket will \n\
2773 release an additional\n\
2774 %4 %5bytes of disk space.\n"
2782 ARDOUR_UI::flush_trash ()
2785 /* shouldn't happen: menu item is insensitive */
2789 Session::cleanup_report rep;
2791 if (session->cleanup_trash_sources (rep)) {
2795 display_cleanup_results (rep,
2797 _("The following %1 %2 deleted from\n\
2799 releasing %4 %5bytes of disk space"));
2803 ARDOUR_UI::add_route (Gtk::Window* float_window)
2811 if (add_route_dialog == 0) {
2812 add_route_dialog = new AddRouteDialog;
2814 add_route_dialog->set_transient_for (*float_window);
2818 if (add_route_dialog->is_visible()) {
2819 /* we're already doing this */
2823 ResponseType r = (ResponseType) add_route_dialog->run ();
2825 add_route_dialog->hide();
2828 case RESPONSE_ACCEPT:
2835 if ((count = add_route_dialog->count()) <= 0) {
2839 uint32_t input_chan = add_route_dialog->channels ();
2840 uint32_t output_chan;
2841 string name_template = add_route_dialog->name_template ();
2842 bool track = add_route_dialog->track ();
2844 AutoConnectOption oac = Config->get_output_auto_connect();
2846 if (oac & AutoConnectMaster) {
2847 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2849 output_chan = input_chan;
2852 /* XXX do something with name template */
2854 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2857 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2859 session_add_audio_bus (input_chan, output_chan, count);
2864 ARDOUR_UI::mixer_settings () const
2869 node = session->instant_xml(X_("Mixer"), session->path());
2871 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2875 node = new XMLNode (X_("Mixer"));
2882 ARDOUR_UI::editor_settings () const
2887 node = session->instant_xml(X_("Editor"), session->path());
2889 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2893 node = new XMLNode (X_("Editor"));
2899 ARDOUR_UI::keyboard_settings () const
2903 node = Config->extra_xml(X_("Keyboard"));
2906 node = new XMLNode (X_("Keyboard"));
2912 ARDOUR_UI::create_xrun_marker(nframes_t where)
2914 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
2915 editor->mouse_add_new_marker (where, false, true);
2919 ARDOUR_UI::halt_on_xrun_message ()
2921 MessageDialog msg (*editor,
2922 _("Recording was stopped because your system could not keep up."));
2927 ARDOUR_UI::xrun_handler(nframes_t where)
2929 if (Config->get_create_xrun_marker() && session->actively_recording()) {
2930 create_xrun_marker(where);
2933 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2934 halt_on_xrun_message ();
2939 ARDOUR_UI::disk_overrun_handler ()
2941 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2943 if (!have_disk_speed_dialog_displayed) {
2944 have_disk_speed_dialog_displayed = true;
2945 MessageDialog* msg = new MessageDialog (*editor, _("\
2946 The disk system on your computer\n\
2947 was not able to keep up with Ardour.\n\
2949 Specifically, it failed to write data to disk\n\
2950 quickly enough to keep up with recording.\n"));
2951 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2957 ARDOUR_UI::disk_underrun_handler ()
2959 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2961 if (!have_disk_speed_dialog_displayed) {
2962 have_disk_speed_dialog_displayed = true;
2963 MessageDialog* msg = new MessageDialog (*editor,
2964 _("The disk system on your computer\n\
2965 was not able to keep up with Ardour.\n\
2967 Specifically, it failed to read data from disk\n\
2968 quickly enough to keep up with playback.\n"));
2969 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2975 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2977 have_disk_speed_dialog_displayed = false;
2982 ARDOUR_UI::pending_state_dialog ()
2984 HBox* hbox = new HBox();
2985 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2986 ArdourDialog dialog (_("Crash Recovery"), true);
2988 This session appears to have been in\n\
2989 middle of recording when ardour or\n\
2990 the computer was shutdown.\n\
2992 Ardour can recover any captured audio for\n\
2993 you, or it can ignore it. Please decide\n\
2994 what you would like to do.\n"));
2995 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2996 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2997 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2998 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2999 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3000 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3001 dialog.set_default_response (RESPONSE_ACCEPT);
3002 dialog.set_position (WIN_POS_CENTER);
3007 switch (dialog.run ()) {
3008 case RESPONSE_ACCEPT:
3016 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3018 HBox* hbox = new HBox();
3019 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3020 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3021 Label message (string_compose (_("\
3022 This session was created with a sample rate of %1 Hz\n\
3024 The audioengine is currently running at %2 Hz\n"), desired, actual));
3026 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3027 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3028 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3029 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3030 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3031 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3032 dialog.set_default_response (RESPONSE_ACCEPT);
3033 dialog.set_position (WIN_POS_CENTER);
3038 switch (dialog.run ()) {
3039 case RESPONSE_ACCEPT:
3048 ARDOUR_UI::disconnect_from_jack ()
3051 if( engine->disconnect_from_jack ()) {
3052 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3056 update_sample_rate (0);
3061 ARDOUR_UI::reconnect_to_jack ()
3064 if (engine->reconnect_to_jack ()) {
3065 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3069 update_sample_rate (0);
3074 ARDOUR_UI::use_config ()
3076 Glib::RefPtr<Action> act;
3078 switch (Config->get_native_file_data_format ()) {
3080 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3083 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3086 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3091 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3092 ract->set_active ();
3095 switch (Config->get_native_file_header_format ()) {
3097 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3100 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3103 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3106 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3109 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3112 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3115 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3120 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3121 ract->set_active ();
3124 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3126 set_transport_controllable_state (*node);
3131 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3133 if (Config->get_primary_clock_delta_edit_cursor()) {
3134 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3136 primary_clock.set (pos, 0, true);
3139 if (Config->get_secondary_clock_delta_edit_cursor()) {
3140 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3142 secondary_clock.set (pos);
3145 if (big_clock_window) {
3146 big_clock.set (pos);
3151 ARDOUR_UI::record_state_changed ()
3153 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3155 if (!session || !big_clock_window) {
3156 /* why bother - the clock isn't visible */
3160 switch (session->record_status()) {
3161 case Session::Recording:
3162 big_clock.set_widget_name ("BigClockRecording");
3165 big_clock.set_widget_name ("BigClockNonRecording");
3171 ARDOUR_UI::first_idle ()
3174 session->allow_auto_play (true);
3178 editor->first_idle();
3181 Keyboard::set_can_save_keybindings (true);
3186 ARDOUR_UI::store_clock_modes ()
3188 XMLNode* node = new XMLNode(X_("ClockModes"));
3190 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3191 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3194 session->add_extra_xml (*node);
3195 session->set_dirty ();
3200 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3201 : Controllable (name), ui (u), type(tp)
3207 ARDOUR_UI::TransportControllable::set_value (float val)
3209 if (type == ShuttleControl) {
3216 fract = -((0.5f - val)/0.5f);
3218 fract = ((val - 0.5f)/0.5f);
3222 ui.set_shuttle_fract (fract);
3227 /* do nothing: these are radio-style actions */
3231 const char *action = 0;
3235 action = X_("Roll");
3238 action = X_("Stop");
3241 action = X_("Goto Start");
3244 action = X_("Goto End");
3247 action = X_("Loop");
3250 action = X_("Play Selection");
3253 action = X_("Record");
3263 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3271 ARDOUR_UI::TransportControllable::get_value (void) const
3290 case ShuttleControl:
3300 ARDOUR_UI::TransportControllable::set_id (const string& str)
3306 ARDOUR_UI::setup_profile ()
3308 if (gdk_screen_width() < 1200) {
3309 Profile->set_small_screen ();
3312 if (getenv ("ARDOUR_SAE")) {
3313 Profile->set_sae ();
3314 Profile->set_single_package ();