2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include <sys/resource.h>
33 #include <gtkmm/messagedialog.h>
34 #include <gtkmm/accelmap.h>
36 #include <pbd/error.h>
37 #include <pbd/basename.h>
38 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/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>
67 typedef uint64_t microseconds_t;
70 #include "ardour_ui.h"
71 #include "public_editor.h"
72 #include "audio_clock.h"
77 #include "add_route_dialog.h"
78 #include "new_session_dialog.h"
82 #include "gui_thread.h"
83 #include "theme_manager.h"
84 #include "engine_dialog.h"
88 using namespace ARDOUR;
90 using namespace Gtkmm2ext;
94 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
95 UIConfiguration *ARDOUR_UI::ui_config = 0;
97 sigc::signal<void,bool> ARDOUR_UI::Blink;
98 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
99 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
100 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
102 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
104 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
106 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
107 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
108 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
109 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
113 preroll_button (_("pre\nroll")),
114 postroll_button (_("post\nroll")),
118 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
122 roll_controllable ("transport roll", *this, TransportControllable::Roll),
123 stop_controllable ("transport stop", *this, TransportControllable::Stop),
124 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
125 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
126 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
127 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
128 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
129 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
130 shuttle_controller_binding_proxy (shuttle_controllable),
132 roll_button (roll_controllable),
133 stop_button (stop_controllable),
134 goto_start_button (goto_start_controllable),
135 goto_end_button (goto_end_controllable),
136 auto_loop_button (auto_loop_controllable),
137 play_selection_button (play_selection_controllable),
138 rec_button (rec_controllable),
140 shuttle_units_button (_("% ")),
142 punch_in_button (_("Punch In")),
143 punch_out_button (_("Punch Out")),
144 auto_return_button (_("Auto Return")),
145 auto_play_button (_("Auto Play")),
146 auto_input_button (_("Auto Input")),
147 click_button (_("Click")),
148 time_master_button (_("time\nmaster")),
150 auditioning_alert_button (_("AUDITION")),
151 solo_alert_button (_("SOLO")),
153 error_log_button (_("Errors"))
155 using namespace Gtk::Menu_Helpers;
160 _auto_display_errors = false;
166 if (ARDOUR_COMMAND_LINE::session_name.length()) {
167 /* only show this if we're not going to post the new session dialog */
171 if (theArdourUI == 0) {
175 ui_config = new UIConfiguration();
176 theme_manager = new ThemeManager();
182 _session_is_new = false;
183 big_clock_window = 0;
184 session_selector_window = 0;
185 new_session_dialog = 0;
186 last_key_press_time = 0;
187 connection_editor = 0;
188 add_route_dialog = 0;
193 open_session_selector = 0;
194 have_configure_timeout = false;
195 have_disk_speed_dialog_displayed = false;
196 _will_create_new_session_automatically = false;
197 session_loaded = false;
198 last_speed_displayed = -1.0f;
199 ignore_dual_punch = false;
201 last_configure_time= 0;
203 shuttle_grabbed = false;
205 shuttle_max_speed = 8.0f;
207 shuttle_style_menu = 0;
208 shuttle_unit_menu = 0;
210 // We do not have jack linked in yet so;
212 last_shuttle_request = last_peak_grab = 0; // get_microseconds();
214 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
215 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
217 /* handle dialog requests */
219 ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
221 /* handle pending state with a dialog */
223 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
225 /* handle sr mismatch with a dialog */
227 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
229 /* lets get this party started */
232 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
233 throw failed_constructor ();
236 setup_gtk_ardour_enums ();
237 Config->set_current_owner (ConfigVariableBase::Interface);
240 } catch (failed_constructor& err) {
241 error << _("could not initialize Ardour.") << endmsg;
246 /* we like keyboards */
248 keyboard = new Keyboard;
252 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
253 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
259 ARDOUR_UI::create_engine ()
261 // this gets called every time by new_session()
267 loading_message (_("Starting audio engine"));
270 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
277 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
278 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
279 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
280 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
288 ARDOUR_UI::post_engine ()
290 /* Things to be done once we create the AudioEngine
293 check_memory_locking();
295 ActionManager::init ();
298 if (setup_windows ()) {
299 throw failed_constructor ();
302 /* this is the first point at which all the keybindings are available */
304 if (ARDOUR_COMMAND_LINE::show_key_actions) {
305 vector<string> names;
306 vector<string> paths;
308 vector<AccelKey> bindings;
310 ActionManager::get_all_actions (names, paths, keys, bindings);
312 vector<string>::iterator n;
313 vector<string>::iterator k;
314 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
315 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
321 blink_timeout_tag = -1;
323 /* the global configuration object is now valid */
327 /* this being a GUI and all, we want peakfiles */
329 AudioFileSource::set_build_peakfiles (true);
330 AudioFileSource::set_build_missing_peakfiles (true);
332 /* set default clock modes */
334 if (Profile->get_sae()) {
335 primary_clock.set_mode (AudioClock::MinSec);
337 primary_clock.set_mode (AudioClock::SMPTE);
339 secondary_clock.set_mode (AudioClock::BBT);
341 /* start the time-of-day-clock */
344 /* OS X provides an always visible wallclock, so don't be stupid */
345 update_wall_clock ();
346 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
349 update_disk_space ();
351 update_sample_rate (engine->frame_rate());
353 platform_specific ();
355 /* now start and maybe save state */
357 if (do_engine_start () == 0) {
358 if (session && _session_is_new) {
359 /* we need to retain initial visual
360 settings for a new session
362 session->save_state ("");
367 ARDOUR_UI::~ARDOUR_UI ()
369 save_ardour_state ();
383 if (add_route_dialog) {
384 delete add_route_dialog;
387 if (new_session_dialog) {
388 delete new_session_dialog;
393 ARDOUR_UI::pop_back_splash ()
395 if (Splash::instance()) {
396 // Splash::instance()->pop_back();
397 Splash::instance()->hide ();
402 ARDOUR_UI::configure_timeout ()
404 if (last_configure_time == 0) {
405 /* no configure events yet */
409 /* force a gap of 0.5 seconds since the last configure event
412 if (get_microseconds() - last_configure_time < 500000) {
415 have_configure_timeout = false;
416 save_ardour_state ();
422 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
424 if (have_configure_timeout) {
425 last_configure_time = get_microseconds();
427 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
428 have_configure_timeout = true;
435 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
437 const XMLProperty* prop;
439 if ((prop = node.property ("roll")) != 0) {
440 roll_controllable.set_id (prop->value());
442 if ((prop = node.property ("stop")) != 0) {
443 stop_controllable.set_id (prop->value());
445 if ((prop = node.property ("goto_start")) != 0) {
446 goto_start_controllable.set_id (prop->value());
448 if ((prop = node.property ("goto_end")) != 0) {
449 goto_end_controllable.set_id (prop->value());
451 if ((prop = node.property ("auto_loop")) != 0) {
452 auto_loop_controllable.set_id (prop->value());
454 if ((prop = node.property ("play_selection")) != 0) {
455 play_selection_controllable.set_id (prop->value());
457 if ((prop = node.property ("rec")) != 0) {
458 rec_controllable.set_id (prop->value());
460 if ((prop = node.property ("shuttle")) != 0) {
461 shuttle_controllable.set_id (prop->value());
466 ARDOUR_UI::get_transport_controllable_state ()
468 XMLNode* node = new XMLNode(X_("TransportControllables"));
471 roll_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("roll"), buf);
473 stop_controllable.id().print (buf, sizeof (buf));
474 node->add_property (X_("stop"), buf);
475 goto_start_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("goto_start"), buf);
477 goto_end_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("goto_end"), buf);
479 auto_loop_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("auto_loop"), buf);
481 play_selection_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("play_selection"), buf);
483 rec_controllable.id().print (buf, sizeof (buf));
484 node->add_property (X_("rec"), buf);
485 shuttle_controllable.id().print (buf, sizeof (buf));
486 node->add_property (X_("shuttle"), buf);
492 ARDOUR_UI::save_ardour_state ()
494 if (!keyboard || !mixer || !editor) {
498 /* XXX this is all a bit dubious. add_extra_xml() uses
499 a different lifetime model from add_instant_xml().
502 XMLNode* node = new XMLNode (keyboard->get_state());
503 Config->add_extra_xml (*node);
504 Config->add_extra_xml (get_transport_controllable_state());
505 if (new_session_dialog) {
506 if (new_session_dialog->engine_control.was_used()) {
507 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
510 Config->save_state();
511 ui_config->save_state ();
513 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
514 XMLNode mnode(mixer->get_state());
517 session->add_instant_xml (enode, session->path());
518 session->add_instant_xml (mnode, session->path());
520 Config->add_instant_xml (enode, get_user_ardour_path());
521 Config->add_instant_xml (mnode, get_user_ardour_path());
524 Keyboard::save_keybindings ();
528 ARDOUR_UI::autosave_session ()
530 if (!Config->get_periodic_safety_backups())
534 session->maybe_write_autosave();
541 ARDOUR_UI::update_autosave ()
543 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
545 if (session->dirty()) {
546 if (_autosave_connection.connected()) {
547 _autosave_connection.disconnect();
550 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
551 Config->get_periodic_safety_backup_interval() * 1000);
554 if (_autosave_connection.connected()) {
555 _autosave_connection.disconnect();
561 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
565 title = _("Ardour could not start JACK");
567 title = _("Ardour could not connect to JACK.");
570 MessageDialog win (title,
576 win.set_secondary_text(_("There are several possible reasons:\n\
578 1) You requested audio parameters that are not supported..\n\
579 2) JACK is running as another user.\n\
581 Please consider the possibilities, and perhaps try different parameters."));
583 win.set_secondary_text(_("There are several possible reasons:\n\
585 1) JACK is not running.\n\
586 2) JACK is running as another user, perhaps root.\n\
587 3) There is already another client called \"ardour\".\n\
589 Please consider the possibilities, and perhaps (re)start JACK."));
593 win.set_transient_for (*toplevel);
597 win.add_button (Stock::OK, RESPONSE_CLOSE);
599 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
602 win.set_default_response (RESPONSE_CLOSE);
605 win.set_position (Gtk::WIN_POS_CENTER);
608 /* we just don't care about the result, but we want to block */
614 ARDOUR_UI::startup ()
618 new_session_dialog = new NewSessionDialog();
620 bool backend_audio_is_running = EngineControl::engine_running();
621 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
624 new_session_dialog->engine_control.set_state (*audio_setup);
627 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
631 BootMessage (_("Ardour is ready for use"));
636 ARDOUR_UI::no_memory_warning ()
638 XMLNode node (X_("no-memory-warning"));
639 Config->add_instant_xml (node, get_user_ardour_path());
643 ARDOUR_UI::check_memory_locking ()
646 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
650 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
652 if (engine->is_realtime() && memory_warning_node == 0) {
654 struct rlimit limits;
656 long pages, page_size;
658 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
661 ram = (int64_t) pages * (int64_t) page_size;
664 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
668 if (limits.rlim_cur != RLIM_INFINITY) {
670 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
673 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
674 "This might cause Ardour to run out of memory before your system "
675 "runs out of memory. \n\n"
676 "You can view the memory limit with 'ulimit -l', "
677 "and it is normally controlled by /etc/security/limits.conf"));
679 VBox* vbox = msg.get_vbox();
681 CheckButton cb (_("Do not show this window again"));
683 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
685 hbox.pack_start (cb, true, false);
686 vbox->pack_start (hbox);
704 if (session->transport_rolling()) {
705 session->request_stop ();
709 if (session->dirty()) {
710 switch (ask_about_saving_session(_("quit"))) {
715 /* use the default name */
716 if (save_state_canfail ("")) {
717 /* failed - don't quit */
718 MessageDialog msg (*editor,
720 Ardour was unable to save your session.\n\n\
721 If you still wish to quit, please use the\n\n\
722 \"Just quit\" option."));
733 session->set_deletion_in_progress ();
737 save_ardour_state ();
742 ARDOUR_UI::ask_about_saving_session (const string & what)
744 ArdourDialog window (_("ardour: save session?"));
745 Gtk::HBox dhbox; // the hbox for the image and text
746 Gtk::Label prompt_label;
747 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
751 msg = string_compose(_("Don't %1"), what);
752 window.add_button (msg, RESPONSE_REJECT);
753 msg = string_compose(_("Just %1"), what);
754 window.add_button (msg, RESPONSE_APPLY);
755 msg = string_compose(_("Save and %1"), what);
756 window.add_button (msg, RESPONSE_ACCEPT);
758 window.set_default_response (RESPONSE_ACCEPT);
760 Gtk::Button noquit_button (msg);
761 noquit_button.set_name ("EditorGTKButton");
766 if (session->snap_name() == session->name()) {
769 type = _("snapshot");
771 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?"),
772 type, session->snap_name());
774 prompt_label.set_text (prompt);
775 prompt_label.set_name (X_("PrompterLabel"));
776 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
778 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
780 dhbox.set_homogeneous (false);
781 dhbox.pack_start (*dimage, false, false, 5);
782 dhbox.pack_start (prompt_label, true, false, 5);
783 window.get_vbox()->pack_start (dhbox);
785 window.set_name (_("Prompter"));
786 window.set_position (Gtk::WIN_POS_MOUSE);
787 window.set_modal (true);
788 window.set_resizable (false);
791 window.set_keep_above (true);
794 ResponseType r = (ResponseType) window.run();
799 case RESPONSE_ACCEPT: // save and get out of here
801 case RESPONSE_APPLY: // get out of here
811 ARDOUR_UI::every_second ()
814 update_buffer_load ();
815 update_disk_space ();
820 ARDOUR_UI::every_point_one_seconds ()
822 update_speed_display ();
823 RapidScreenUpdate(); /* EMIT_SIGNAL */
828 ARDOUR_UI::every_point_zero_one_seconds ()
830 // august 2007: actual update frequency: 40Hz, not 100Hz
832 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
837 ARDOUR_UI::update_sample_rate (nframes_t ignored)
841 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
843 if (!engine->connected()) {
845 snprintf (buf, sizeof (buf), _("disconnected"));
849 nframes_t rate = engine->frame_rate();
851 if (fmod (rate, 1000.0) != 0.0) {
852 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
853 (float) rate/1000.0f,
854 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
856 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
858 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
862 sample_rate_label.set_text (buf);
866 ARDOUR_UI::update_cpu_load ()
869 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
870 cpu_load_label.set_text (buf);
874 ARDOUR_UI::update_buffer_load ()
879 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
880 session->playback_load(), session->capture_load());
881 buffer_load_label.set_text (buf);
883 buffer_load_label.set_text ("");
888 ARDOUR_UI::count_recenabled_streams (Route& route)
890 Track* track = dynamic_cast<Track*>(&route);
891 if (track && track->diskstream()->record_enabled()) {
892 rec_enabled_streams += track->n_inputs();
897 ARDOUR_UI::update_disk_space()
903 nframes_t frames = session->available_capture_duration();
906 if (frames == max_frames) {
907 strcpy (buf, _("Disk: 24hrs+"));
912 nframes_t fr = session->frame_rate();
914 rec_enabled_streams = 0;
915 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
917 if (rec_enabled_streams) {
918 frames /= rec_enabled_streams;
921 hrs = frames / (fr * 3600);
922 frames -= hrs * fr * 3600;
923 mins = frames / (fr * 60);
924 frames -= mins * fr * 60;
927 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
930 disk_space_label.set_text (buf);
934 ARDOUR_UI::update_wall_clock ()
941 tm_now = localtime (&now);
943 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
944 wall_clock_label.set_text (buf);
950 ARDOUR_UI::session_menu (GdkEventButton *ev)
952 session_popup_menu->popup (0, 0);
957 ARDOUR_UI::redisplay_recent_sessions ()
959 vector<string *> *sessions;
960 vector<string *>::iterator i;
961 RecentSessionsSorter cmp;
963 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
964 recent_session_model->clear ();
967 ARDOUR::read_recent_sessions (rs);
970 recent_session_display.set_model (recent_session_model);
974 /* sort them alphabetically */
975 sort (rs.begin(), rs.end(), cmp);
976 sessions = new vector<string*>;
978 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
979 sessions->push_back (new string ((*i).second));
982 for (i = sessions->begin(); i != sessions->end(); ++i) {
984 vector<string*>* states;
985 vector<const gchar*> item;
986 string fullpath = *(*i);
988 /* remove any trailing / */
990 if (fullpath[fullpath.length()-1] == '/') {
991 fullpath = fullpath.substr (0, fullpath.length()-1);
994 /* check whether session still exists */
995 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
996 /* session doesn't exist */
997 cerr << "skipping non-existent session " << fullpath << endl;
1001 /* now get available states for this session */
1003 if ((states = Session::possible_states (fullpath)) == 0) {
1004 /* no state file? */
1008 TreeModel::Row row = *(recent_session_model->append());
1010 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1011 row[recent_session_columns.fullpath] = fullpath;
1013 if (states->size() > 1) {
1015 /* add the children */
1017 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1019 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1021 child_row[recent_session_columns.visible_name] = **i2;
1022 child_row[recent_session_columns.fullpath] = fullpath;
1031 recent_session_display.set_model (recent_session_model);
1036 ARDOUR_UI::build_session_selector ()
1038 session_selector_window = new ArdourDialog ("session selector");
1040 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1042 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1043 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1044 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1045 recent_session_model = TreeStore::create (recent_session_columns);
1046 recent_session_display.set_model (recent_session_model);
1047 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1048 recent_session_display.set_headers_visible (false);
1049 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1050 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1052 scroller->add (recent_session_display);
1053 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1055 session_selector_window->set_name ("SessionSelectorWindow");
1056 session_selector_window->set_size_request (200, 400);
1057 session_selector_window->get_vbox()->pack_start (*scroller);
1058 session_selector_window->show_all_children();
1062 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1064 session_selector_window->response (RESPONSE_ACCEPT);
1068 ARDOUR_UI::open_recent_session ()
1070 bool can_return = (session != 0);
1072 if (session_selector_window == 0) {
1073 build_session_selector ();
1076 redisplay_recent_sessions ();
1080 session_selector_window->set_position (WIN_POS_MOUSE);
1082 ResponseType r = (ResponseType) session_selector_window->run ();
1085 case RESPONSE_ACCEPT:
1089 session_selector_window->hide();
1096 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1100 session_selector_window->hide();
1102 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1104 if (i == recent_session_model->children().end()) {
1108 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1109 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1111 _session_is_new = false;
1113 if (load_session (path, state) == 0) {
1122 ARDOUR_UI::check_audioengine ()
1125 if (!engine->connected()) {
1126 MessageDialog msg (_("Ardour is not connected to JACK\n"
1127 "You cannot open or close sessions in this condition"));
1139 ARDOUR_UI::open_session ()
1141 if (!check_audioengine()) {
1145 /* popup selector window */
1147 if (open_session_selector == 0) {
1149 /* ardour sessions are folders */
1151 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1152 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1153 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1154 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1156 FileFilter session_filter;
1157 session_filter.add_pattern ("*.ardour");
1158 session_filter.set_name (_("Ardour sessions"));
1159 open_session_selector->add_filter (session_filter);
1160 open_session_selector->set_filter (session_filter);
1163 int response = open_session_selector->run();
1164 open_session_selector->hide ();
1167 case RESPONSE_ACCEPT:
1170 open_session_selector->hide();
1174 open_session_selector->hide();
1175 string session_path = open_session_selector->get_filename();
1179 if (session_path.length() > 0) {
1180 if (Session::find_session (session_path, path, name, isnew) == 0) {
1181 _session_is_new = isnew;
1182 load_session (path, name);
1189 ARDOUR_UI::session_add_midi_track ()
1191 cerr << _("Patience is a virtue.\n");
1195 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1197 list<boost::shared_ptr<AudioTrack> > tracks;
1198 Session::RouteList routes;
1201 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1207 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1209 if (tracks.size() != how_many) {
1210 if (how_many == 1) {
1211 error << _("could not create a new audio track") << endmsg;
1213 error << string_compose (_("could only create %1 of %2 new audio %3"),
1214 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1220 routes = session->new_audio_route (input_channels, output_channels, how_many);
1222 if (routes.size() != how_many) {
1223 if (how_many == 1) {
1224 error << _("could not create a new audio track") << endmsg;
1226 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1232 if (need_control_room_outs) {
1238 route->set_stereo_control_outs (control_lr_channels);
1239 route->control_outs()->set_stereo_pan (pans, this);
1241 #endif /* CONTROLOUTS */
1245 MessageDialog msg (*editor,
1246 _("There are insufficient JACK ports available\n\
1247 to create a new track or bus.\n\
1248 You should save Ardour, exit and\n\
1249 restart JACK with more ports."));
1256 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1258 nframes_t _preroll = 0;
1261 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1262 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1264 if (new_position > _preroll) {
1265 new_position -= _preroll;
1270 session->request_locate (new_position);
1275 ARDOUR_UI::transport_goto_start ()
1278 session->goto_start();
1281 /* force displayed area in editor to start no matter
1282 what "follow playhead" setting is.
1286 editor->reset_x_origin (session->current_start_frame());
1292 ARDOUR_UI::transport_goto_zero ()
1295 session->request_locate (0);
1298 /* force displayed area in editor to start no matter
1299 what "follow playhead" setting is.
1303 editor->reset_x_origin (0);
1309 ARDOUR_UI::transport_goto_wallclock ()
1311 if (session && editor) {
1318 localtime_r (&now, &tmnow);
1320 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1321 frames += tmnow.tm_min * (60 * session->frame_rate());
1322 frames += tmnow.tm_sec * session->frame_rate();
1324 session->request_locate (frames);
1326 /* force displayed area in editor to start no matter
1327 what "follow playhead" setting is.
1331 editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1337 ARDOUR_UI::transport_goto_end ()
1340 nframes_t frame = session->current_end_frame();
1341 session->request_locate (frame);
1343 /* force displayed area in editor to start no matter
1344 what "follow playhead" setting is.
1348 editor->reset_x_origin (frame);
1354 ARDOUR_UI::transport_stop ()
1360 if (session->is_auditioning()) {
1361 session->cancel_audition ();
1365 if (session->get_play_loop ()) {
1366 session->request_play_loop (false);
1369 session->request_stop ();
1373 ARDOUR_UI::transport_stop_and_forget_capture ()
1376 session->request_stop (true);
1381 ARDOUR_UI::remove_last_capture()
1384 editor->remove_last_capture();
1389 ARDOUR_UI::transport_record (bool roll)
1393 switch (session->record_status()) {
1394 case Session::Disabled:
1395 if (session->ntracks() == 0) {
1396 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1400 session->maybe_enable_record ();
1405 case Session::Recording:
1407 session->request_stop();
1409 session->disable_record (false, true);
1413 case Session::Enabled:
1414 session->disable_record (false, true);
1417 //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1421 ARDOUR_UI::transport_roll ()
1429 rolling = session->transport_rolling ();
1431 //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1433 if (session->get_play_loop()) {
1434 session->request_play_loop (false);
1435 auto_loop_button.set_visual_state (1);
1436 roll_button.set_visual_state (1);
1437 } else if (session->get_play_range ()) {
1438 session->request_play_range (false);
1439 play_selection_button.set_visual_state (0);
1440 } else if (rolling) {
1441 session->request_locate (session->last_transport_start(), true);
1444 session->request_transport_speed (1.0f);
1448 ARDOUR_UI::transport_loop()
1451 if (session->get_play_loop()) {
1452 if (session->transport_rolling()) {
1453 Location * looploc = session->locations()->auto_loop_location();
1455 session->request_locate (looploc->start(), true);
1460 session->request_play_loop (true);
1466 ARDOUR_UI::transport_play_selection ()
1472 if (!session->get_play_range()) {
1473 session->request_stop ();
1476 editor->play_selection ();
1480 ARDOUR_UI::transport_rewind (int option)
1482 float current_transport_speed;
1485 current_transport_speed = session->transport_speed();
1487 if (current_transport_speed >= 0.0f) {
1490 session->request_transport_speed (-1.0f);
1493 session->request_transport_speed (-4.0f);
1496 session->request_transport_speed (-0.5f);
1501 session->request_transport_speed (current_transport_speed * 1.5f);
1507 ARDOUR_UI::transport_forward (int option)
1509 float current_transport_speed;
1512 current_transport_speed = session->transport_speed();
1514 if (current_transport_speed <= 0.0f) {
1517 session->request_transport_speed (1.0f);
1520 session->request_transport_speed (4.0f);
1523 session->request_transport_speed (0.5f);
1528 session->request_transport_speed (current_transport_speed * 1.5f);
1534 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1540 boost::shared_ptr<Route> r;
1542 if ((r = session->route_by_remote_id (dstream)) != 0) {
1546 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1547 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1556 ARDOUR_UI::queue_transport_change ()
1558 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1562 ARDOUR_UI::map_transport_state ()
1564 float sp = session->transport_speed();
1567 transport_rolling ();
1568 } else if (sp < 0.0f) {
1569 transport_rewinding ();
1570 } else if (sp > 0.0f) {
1571 transport_forwarding ();
1573 transport_stopped ();
1578 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1580 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1581 (int) adj.get_value()].c_str());
1585 ARDOUR_UI::engine_stopped ()
1587 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1588 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1589 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1593 ARDOUR_UI::engine_running ()
1595 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1596 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1597 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1599 Glib::RefPtr<Action> action;
1600 const char* action_name = 0;
1602 switch (engine->frames_per_cycle()) {
1604 action_name = X_("JACKLatency32");
1607 action_name = X_("JACKLatency64");
1610 action_name = X_("JACKLatency128");
1613 action_name = X_("JACKLatency512");
1616 action_name = X_("JACKLatency1024");
1619 action_name = X_("JACKLatency2048");
1622 action_name = X_("JACKLatency4096");
1625 action_name = X_("JACKLatency8192");
1628 /* XXX can we do anything useful ? */
1634 action = ActionManager::get_action (X_("JACK"), action_name);
1637 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1638 ract->set_active ();
1644 ARDOUR_UI::engine_halted ()
1646 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1648 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1649 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1651 update_sample_rate (0);
1653 MessageDialog msg (*editor,
1655 JACK has either been shutdown or it\n\
1656 disconnected Ardour because Ardour\n\
1657 was not fast enough. You can save the\n\
1658 session and/or try to reconnect to JACK ."));
1664 ARDOUR_UI::do_engine_start ()
1672 error << _("Unable to start the session running")
1682 ARDOUR_UI::setup_theme ()
1684 theme_manager->setup_theme();
1688 ARDOUR_UI::update_clocks ()
1690 if (!editor || !editor->dragging_playhead()) {
1691 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1696 ARDOUR_UI::start_clocking ()
1698 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1702 ARDOUR_UI::stop_clocking ()
1704 clock_signal_connection.disconnect ();
1708 ARDOUR_UI::toggle_clocking ()
1711 if (clock_button.get_active()) {
1720 ARDOUR_UI::_blink (void *arg)
1723 ((ARDOUR_UI *) arg)->blink ();
1730 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1734 ARDOUR_UI::start_blinking ()
1736 /* Start the blink signal. Everybody with a blinking widget
1737 uses Blink to drive the widget's state.
1740 if (blink_timeout_tag < 0) {
1742 blink_timeout_tag = g_timeout_add (240, _blink, this);
1747 ARDOUR_UI::stop_blinking ()
1749 if (blink_timeout_tag >= 0) {
1750 g_source_remove (blink_timeout_tag);
1751 blink_timeout_tag = -1;
1756 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1762 if (io.n_inputs() == 0) {
1767 /* XXX we're not handling multiple ports yet. */
1769 const char **connections = io.input(0)->get_connections();
1771 if (connections == 0 || connections[0] == '\0') {
1774 buf = connections[0];
1781 if (io.n_outputs() == 0) {
1786 /* XXX we're not handling multiple ports yet. */
1788 const char **connections = io.output(0)->get_connections();
1790 if (connections == 0 || connections[0] == '\0') {
1793 buf = connections[0];
1800 /** Ask the user for the name of a new shapshot and then take it.
1803 ARDOUR_UI::snapshot_session ()
1805 ArdourPrompter prompter (true);
1809 struct tm local_time;
1812 localtime_r (&n, &local_time);
1813 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1815 prompter.set_name ("Prompter");
1816 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1817 prompter.set_prompt (_("Name of New Snapshot"));
1818 prompter.set_initial_text (timebuf);
1820 switch (prompter.run()) {
1821 case RESPONSE_ACCEPT:
1822 prompter.get_result (snapname);
1823 if (snapname.length()){
1824 save_state (snapname);
1834 ARDOUR_UI::save_state (const string & name)
1836 (void) save_state_canfail (name);
1840 ARDOUR_UI::save_state_canfail (string name)
1845 if (name.length() == 0) {
1846 name = session->snap_name();
1849 if ((ret = session->save_state (name)) != 0) {
1853 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1858 ARDOUR_UI::primary_clock_value_changed ()
1861 session->request_locate (primary_clock.current_time ());
1866 ARDOUR_UI::big_clock_value_changed ()
1869 session->request_locate (big_clock.current_time ());
1874 ARDOUR_UI::secondary_clock_value_changed ()
1877 session->request_locate (secondary_clock.current_time ());
1882 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1888 switch (session->record_status()) {
1889 case Session::Enabled:
1891 rec_button.set_visual_state (2);
1893 rec_button.set_visual_state (0);
1897 case Session::Recording:
1898 rec_button.set_visual_state (1);
1902 rec_button.set_visual_state (0);
1908 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1916 ARDOUR_UI::save_template ()
1919 ArdourPrompter prompter (true);
1922 if (!check_audioengine()) {
1926 prompter.set_name (X_("Prompter"));
1927 prompter.set_prompt (_("Name for mix template:"));
1928 prompter.set_initial_text(session->name() + _("-template"));
1929 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1931 switch (prompter.run()) {
1932 case RESPONSE_ACCEPT:
1933 prompter.get_result (name);
1935 if (name.length()) {
1936 session->save_template (name);
1946 ARDOUR_UI::fontconfig_dialog ()
1949 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1950 may not and it can take a while to build it. Warn them.
1953 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1955 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1956 MessageDialog msg (*new_session_dialog,
1957 _("Welcome to Ardour.\n\n"
1958 "The program will take a bit longer to start up\n"
1959 "while the system fonts are checked.\n\n"
1960 "This will only be done once, and you will\n"
1961 "not see this message again\n"),
1974 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
1976 existing_session = false;
1978 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
1979 session_path = cmdline_path;
1980 existing_session = true;
1981 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
1982 session_path = Glib::path_get_dirname (string (cmdline_path));
1983 existing_session = true;
1985 /* it doesn't exist, assume the best */
1986 session_path = Glib::path_get_dirname (string (cmdline_path));
1989 session_name = basename_nosuffix (string (cmdline_path));
1993 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
1995 /* when this is called, the backend audio system must be running */
1997 /* the main idea here is to deal with the fact that a cmdline argument for the session
1998 can be interpreted in different ways - it could be a directory or a file, and before
1999 we load, we need to know both the session directory and the snapshot (statefile) within it
2000 that we are supposed to use.
2003 if (session_name.length() == 0 || session_path.length() == 0) {
2007 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2009 Glib::ustring predicted_session_file;
2011 predicted_session_file = session_path;
2012 predicted_session_file += '/';
2013 predicted_session_file += session_name;
2014 predicted_session_file += Session::statefile_suffix();
2016 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2017 existing_session = true;
2020 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2022 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2023 /* existing .ardour file */
2024 existing_session = true;
2028 existing_session = false;
2031 /* lets just try to load it */
2033 if (create_engine ()) {
2034 backend_audio_error (false, new_session_dialog);
2038 return load_session (session_path, session_name);
2042 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2044 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2046 MessageDialog msg (str,
2048 Gtk::MESSAGE_WARNING,
2049 Gtk::BUTTONS_YES_NO,
2053 msg.set_name (X_("CleanupDialog"));
2054 msg.set_wmclass (X_("existing_session"), "Ardour");
2055 msg.set_position (Gtk::WIN_POS_MOUSE);
2058 switch (msg.run()) {
2067 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2072 AutoConnectOption iconnect;
2073 AutoConnectOption oconnect;
2077 if (Profile->get_sae()) {
2081 iconnect = AutoConnectPhysical;
2082 oconnect = AutoConnectMaster;
2083 nphysin = 0; // use all available
2084 nphysout = 0; // use all available
2088 /* get settings from advanced section of NSD */
2090 if (new_session_dialog->create_control_bus()) {
2091 cchns = (uint32_t) new_session_dialog->control_channel_count();
2096 if (new_session_dialog->create_master_bus()) {
2097 mchns = (uint32_t) new_session_dialog->master_channel_count();
2102 if (new_session_dialog->connect_inputs()) {
2103 iconnect = AutoConnectPhysical;
2105 iconnect = AutoConnectOption (0);
2108 /// @todo some minor tweaks.
2110 if (new_session_dialog->connect_outs_to_master()) {
2111 oconnect = AutoConnectMaster;
2112 } else if (new_session_dialog->connect_outs_to_physical()) {
2113 oconnect = AutoConnectPhysical;
2115 oconnect = AutoConnectOption (0);
2118 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2119 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2122 if (build_session (session_path,
2130 engine->frame_rate() * 60 * 5)) {
2139 ARDOUR_UI::end_loading_messages ()
2145 ARDOUR_UI::loading_message (const std::string& msg)
2148 splash->message (msg);
2153 ARDOUR_UI::idle_load (const Glib::ustring& path)
2156 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2157 /* /path/to/foo => /path/to/foo, foo */
2158 load_session (path, basename_nosuffix (path));
2160 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2161 load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2164 ARDOUR_COMMAND_LINE::session_name = path;
2165 if (new_session_dialog) {
2166 /* make it break out of Dialog::run() and
2169 new_session_dialog->response (1);
2175 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2177 bool existing_session = false;
2178 Glib::ustring session_name;
2179 Glib::ustring session_path;
2180 Glib::ustring template_name;
2184 response = Gtk::RESPONSE_NONE;
2186 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2188 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2190 /* don't ever reuse this */
2192 ARDOUR_COMMAND_LINE::session_name = string();
2194 if (existing_session && backend_audio_is_running) {
2196 /* just load the thing already */
2198 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2203 /* make the NSD use whatever information we have */
2205 new_session_dialog->set_session_name (session_name);
2206 new_session_dialog->set_session_folder (session_path);
2209 /* loading failed, or we need the NSD for something */
2211 new_session_dialog->set_modal (false);
2212 new_session_dialog->set_position (WIN_POS_CENTER);
2213 new_session_dialog->set_current_page (0);
2214 new_session_dialog->set_existing_session (existing_session);
2215 new_session_dialog->reset_recent();
2218 new_session_dialog->set_have_engine (backend_audio_is_running);
2219 new_session_dialog->present ();
2220 response = new_session_dialog->run ();
2222 _session_is_new = false;
2224 /* handle possible negative responses */
2228 /* sent by idle_load, meaning restart the whole process again */
2229 new_session_dialog->hide();
2230 new_session_dialog->reset();
2234 case Gtk::RESPONSE_CANCEL:
2235 case Gtk::RESPONSE_DELETE_EVENT:
2239 new_session_dialog->hide ();
2242 case Gtk::RESPONSE_NONE:
2243 /* "Clear" was pressed */
2247 fontconfig_dialog();
2249 if (!backend_audio_is_running) {
2250 if (new_session_dialog->engine_control.setup_engine ()) {
2251 new_session_dialog->hide ();
2256 if (create_engine ()) {
2258 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2261 new_session_dialog->set_existing_session (false);
2262 new_session_dialog->set_current_page (2);
2264 response = Gtk::RESPONSE_NONE;
2268 backend_audio_is_running = true;
2270 if (response == Gtk::RESPONSE_OK) {
2272 session_name = new_session_dialog->session_name();
2274 if (session_name.empty()) {
2275 response = Gtk::RESPONSE_NONE;
2279 /* if the user mistakenly typed path information into the session filename entry,
2280 convert what they typed into a path & a name
2283 if (session_name[0] == '/' ||
2284 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2285 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2287 session_path = Glib::path_get_dirname (session_name);
2288 session_name = Glib::path_get_basename (session_name);
2292 session_path = new_session_dialog->session_folder();
2295 template_name = Glib::ustring();
2296 switch (new_session_dialog->which_page()) {
2298 case NewSessionDialog::OpenPage:
2299 case NewSessionDialog::EnginePage:
2303 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2305 should_be_new = true;
2307 //XXX This is needed because session constructor wants a
2308 //non-existant path. hopefully this will be fixed at some point.
2310 session_path = Glib::build_filename (session_path, session_name);
2312 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2314 if (ask_about_loading_existing_session (session_path)) {
2317 response = RESPONSE_NONE;
2322 _session_is_new = true;
2324 if (new_session_dialog->use_session_template()) {
2326 template_name = new_session_dialog->session_template_name();
2330 if (build_session_from_nsd (session_path, session_name)) {
2331 response = RESPONSE_NONE;
2343 new_session_dialog->hide ();
2345 if (load_session (session_path, session_name, template_name)) {
2347 response = Gtk::RESPONSE_NONE;
2351 if (response == Gtk::RESPONSE_NONE) {
2352 new_session_dialog->set_existing_session (false);
2353 new_session_dialog->reset ();
2357 } while (response == Gtk::RESPONSE_NONE);
2361 new_session_dialog->hide();
2362 new_session_dialog->reset();
2363 goto_editor_window ();
2368 ARDOUR_UI::close_session ()
2370 if (!check_audioengine()) {
2374 unload_session (true);
2376 get_session_parameters (true, false);
2380 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2382 Session *new_session;
2386 session_loaded = false;
2388 if (!check_audioengine()) {
2392 unload_status = unload_session ();
2394 if (unload_status < 0) {
2396 } else if (unload_status > 0) {
2401 /* if it already exists, we must have write access */
2403 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2404 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2405 "This prevents the session from being loaded."));
2411 loading_message (_("Please wait while Ardour loads your session"));
2414 new_session = new Session (*engine, path, snap_name, mix_template);
2417 /* this one is special */
2419 catch (AudioEngine::PortRegistrationFailure& err) {
2421 MessageDialog msg (err.what(),
2424 Gtk::BUTTONS_OK_CANCEL);
2426 msg.set_title (_("Loading Error"));
2427 msg.set_secondary_text (_("Click the OK button to try again."));
2428 msg.set_position (Gtk::WIN_POS_CENTER);
2432 int response = msg.run ();
2437 case RESPONSE_CANCEL:
2447 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2450 Gtk::BUTTONS_OK_CANCEL);
2452 msg.set_title (_("Loading Error"));
2453 msg.set_secondary_text (_("Click the OK button to try again."));
2454 msg.set_position (Gtk::WIN_POS_CENTER);
2458 int response = msg.run ();
2463 case RESPONSE_CANCEL:
2471 connect_to_session (new_session);
2473 Config->set_current_owner (ConfigVariableBase::Interface);
2475 session_loaded = true;
2477 goto_editor_window ();
2480 session->set_clean ();
2491 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2492 uint32_t control_channels,
2493 uint32_t master_channels,
2494 AutoConnectOption input_connect,
2495 AutoConnectOption output_connect,
2498 nframes_t initial_length)
2500 Session *new_session;
2503 if (!check_audioengine()) {
2507 session_loaded = false;
2509 x = unload_session ();
2517 _session_is_new = true;
2520 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2521 control_channels, master_channels, nphysin, nphysout, initial_length);
2526 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2532 connect_to_session (new_session);
2534 session_loaded = true;
2542 editor->show_window ();
2553 ARDOUR_UI::show_about ()
2557 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2564 ARDOUR_UI::hide_about ()
2567 about->get_window()->set_cursor ();
2573 ARDOUR_UI::about_signal_response(int response)
2579 ARDOUR_UI::show_splash ()
2583 splash = new Splash;
2591 splash->queue_draw ();
2592 splash->get_window()->process_updates (true);
2597 ARDOUR_UI::hide_splash ()
2605 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2609 removed = rep.paths.size();
2612 MessageDialog msgd (*editor,
2613 _("No audio files were ready for cleanup"),
2616 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2617 msgd.set_secondary_text (_("If this seems suprising, \n\
2618 check for any existing snapshots.\n\
2619 These may still include regions that\n\
2620 require some unused files to continue to exist."));
2626 ArdourDialog results (_("ardour: cleanup"), true, false);
2628 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2629 CleanupResultsModelColumns() {
2633 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2634 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2638 CleanupResultsModelColumns results_columns;
2639 Glib::RefPtr<Gtk::ListStore> results_model;
2640 Gtk::TreeView results_display;
2642 results_model = ListStore::create (results_columns);
2643 results_display.set_model (results_model);
2644 results_display.append_column (list_title, results_columns.visible_name);
2646 results_display.set_name ("CleanupResultsList");
2647 results_display.set_headers_visible (true);
2648 results_display.set_headers_clickable (false);
2649 results_display.set_reorderable (false);
2651 Gtk::ScrolledWindow list_scroller;
2654 Gtk::HBox dhbox; // the hbox for the image and text
2655 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2656 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2658 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2660 if (rep.space < 1048576.0f) {
2662 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2664 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2668 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2670 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2674 dhbox.pack_start (*dimage, true, false, 5);
2675 dhbox.pack_start (txt, true, false, 5);
2677 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2678 TreeModel::Row row = *(results_model->append());
2679 row[results_columns.visible_name] = *i;
2680 row[results_columns.fullpath] = *i;
2683 list_scroller.add (results_display);
2684 list_scroller.set_size_request (-1, 150);
2685 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2687 dvbox.pack_start (dhbox, true, false, 5);
2688 dvbox.pack_start (list_scroller, true, false, 5);
2689 ddhbox.pack_start (dvbox, true, false, 5);
2691 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2692 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2693 results.set_default_response (RESPONSE_CLOSE);
2694 results.set_position (Gtk::WIN_POS_MOUSE);
2695 results.show_all_children ();
2696 results.set_resizable (false);
2703 ARDOUR_UI::cleanup ()
2706 /* shouldn't happen: menu item is insensitive */
2711 MessageDialog checker (_("Are you sure you want to cleanup?"),
2713 Gtk::MESSAGE_QUESTION,
2714 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2716 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2717 ALL undo/redo information will be lost if you cleanup.\n\
2718 After cleanup, unused audio files will be moved to a \
2719 \"dead sounds\" location."));
2721 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2722 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2723 checker.set_default_response (RESPONSE_CANCEL);
2725 checker.set_name (_("CleanupDialog"));
2726 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2727 checker.set_position (Gtk::WIN_POS_MOUSE);
2729 switch (checker.run()) {
2730 case RESPONSE_ACCEPT:
2736 Session::cleanup_report rep;
2738 editor->prepare_for_cleanup ();
2740 /* do not allow flush until a session is reloaded */
2742 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2744 act->set_sensitive (false);
2747 if (session->cleanup_sources (rep)) {
2752 display_cleanup_results (rep,
2755 The following %1 %2 not in use and \n\
2756 have been moved to:\n\
2758 Flushing the wastebasket will \n\
2759 release an additional\n\
2760 %4 %5bytes of disk space.\n"
2768 ARDOUR_UI::flush_trash ()
2771 /* shouldn't happen: menu item is insensitive */
2775 Session::cleanup_report rep;
2777 if (session->cleanup_trash_sources (rep)) {
2781 display_cleanup_results (rep,
2783 _("The following %1 %2 deleted from\n\
2785 releasing %4 %5bytes of disk space"));
2789 ARDOUR_UI::add_route (Gtk::Window* float_window)
2797 if (add_route_dialog == 0) {
2798 add_route_dialog = new AddRouteDialog;
2800 add_route_dialog->set_transient_for (*float_window);
2804 if (add_route_dialog->is_visible()) {
2805 /* we're already doing this */
2809 ResponseType r = (ResponseType) add_route_dialog->run ();
2811 add_route_dialog->hide();
2814 case RESPONSE_ACCEPT:
2821 if ((count = add_route_dialog->count()) <= 0) {
2825 uint32_t input_chan = add_route_dialog->channels ();
2826 uint32_t output_chan;
2827 string name_template = add_route_dialog->name_template ();
2828 bool track = add_route_dialog->track ();
2830 AutoConnectOption oac = Config->get_output_auto_connect();
2832 if (oac & AutoConnectMaster) {
2833 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2835 output_chan = input_chan;
2838 /* XXX do something with name template */
2840 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2843 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2845 session_add_audio_bus (input_chan, output_chan, count);
2850 ARDOUR_UI::mixer_settings () const
2855 node = session->instant_xml(X_("Mixer"), session->path());
2857 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2861 node = new XMLNode (X_("Mixer"));
2868 ARDOUR_UI::editor_settings () const
2873 node = session->instant_xml(X_("Editor"), session->path());
2875 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2879 node = new XMLNode (X_("Editor"));
2885 ARDOUR_UI::keyboard_settings () const
2889 node = Config->extra_xml(X_("Keyboard"));
2892 node = new XMLNode (X_("Keyboard"));
2898 ARDOUR_UI::create_xrun_marker(nframes_t where)
2900 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
2901 editor->mouse_add_new_marker (where, false, true);
2905 ARDOUR_UI::halt_on_xrun_message ()
2907 MessageDialog msg (*editor,
2908 _("Recording was stopped because your system could not keep up."));
2913 ARDOUR_UI::xrun_handler(nframes_t where)
2915 if (Config->get_create_xrun_marker() && session->actively_recording()) {
2916 create_xrun_marker(where);
2919 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2920 halt_on_xrun_message ();
2925 ARDOUR_UI::disk_overrun_handler ()
2927 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2929 if (!have_disk_speed_dialog_displayed) {
2930 have_disk_speed_dialog_displayed = true;
2931 MessageDialog* msg = new MessageDialog (*editor, _("\
2932 The disk system on your computer\n\
2933 was not able to keep up with Ardour.\n\
2935 Specifically, it failed to write data to disk\n\
2936 quickly enough to keep up with recording.\n"));
2937 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2943 ARDOUR_UI::disk_underrun_handler ()
2945 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2947 if (!have_disk_speed_dialog_displayed) {
2948 have_disk_speed_dialog_displayed = true;
2949 MessageDialog* msg = new MessageDialog (*editor,
2950 _("The disk system on your computer\n\
2951 was not able to keep up with Ardour.\n\
2953 Specifically, it failed to read data from disk\n\
2954 quickly enough to keep up with playback.\n"));
2955 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2961 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2963 have_disk_speed_dialog_displayed = false;
2968 ARDOUR_UI::session_dialog (std::string msg)
2970 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
2975 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2977 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2986 ARDOUR_UI::pending_state_dialog ()
2988 HBox* hbox = new HBox();
2989 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2990 ArdourDialog dialog (_("Crash Recovery"), true);
2992 This session appears to have been in\n\
2993 middle of recording when ardour or\n\
2994 the computer was shutdown.\n\
2996 Ardour can recover any captured audio for\n\
2997 you, or it can ignore it. Please decide\n\
2998 what you would like to do.\n"));
2999 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3000 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3001 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3002 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3003 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3004 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3005 dialog.set_default_response (RESPONSE_ACCEPT);
3006 dialog.set_position (WIN_POS_CENTER);
3011 switch (dialog.run ()) {
3012 case RESPONSE_ACCEPT:
3020 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3022 HBox* hbox = new HBox();
3023 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3024 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3025 Label message (string_compose (_("\
3026 This session was created with a sample rate of %1 Hz\n\
3028 The audioengine is currently running at %2 Hz\n"), desired, actual));
3030 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3031 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3032 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3033 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3034 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3035 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3036 dialog.set_default_response (RESPONSE_ACCEPT);
3037 dialog.set_position (WIN_POS_CENTER);
3042 switch (dialog.run ()) {
3043 case RESPONSE_ACCEPT:
3052 ARDOUR_UI::disconnect_from_jack ()
3055 if( engine->disconnect_from_jack ()) {
3056 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3060 update_sample_rate (0);
3065 ARDOUR_UI::reconnect_to_jack ()
3068 if (engine->reconnect_to_jack ()) {
3069 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3073 update_sample_rate (0);
3078 ARDOUR_UI::use_config ()
3080 Glib::RefPtr<Action> act;
3082 switch (Config->get_native_file_data_format ()) {
3084 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3087 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3090 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3095 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3096 ract->set_active ();
3099 switch (Config->get_native_file_header_format ()) {
3101 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3104 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3107 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3110 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3113 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3116 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3119 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3124 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3125 ract->set_active ();
3128 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3130 set_transport_controllable_state (*node);
3135 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3137 if (Config->get_primary_clock_delta_edit_cursor()) {
3138 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3140 primary_clock.set (pos, 0, true);
3143 if (Config->get_secondary_clock_delta_edit_cursor()) {
3144 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3146 secondary_clock.set (pos);
3149 if (big_clock_window) {
3150 big_clock.set (pos);
3155 ARDOUR_UI::record_state_changed ()
3157 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3159 if (!session || !big_clock_window) {
3160 /* why bother - the clock isn't visible */
3164 switch (session->record_status()) {
3165 case Session::Recording:
3166 big_clock.set_widget_name ("BigClockRecording");
3169 big_clock.set_widget_name ("BigClockNonRecording");
3175 ARDOUR_UI::first_idle ()
3178 session->allow_auto_play (true);
3182 editor->first_idle();
3185 Keyboard::set_can_save_keybindings (true);
3190 ARDOUR_UI::store_clock_modes ()
3192 XMLNode* node = new XMLNode(X_("ClockModes"));
3194 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3195 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3198 session->add_extra_xml (*node);
3199 session->set_dirty ();
3204 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3205 : Controllable (name), ui (u), type(tp)
3211 ARDOUR_UI::TransportControllable::set_value (float val)
3213 if (type == ShuttleControl) {
3220 fract = -((0.5f - val)/0.5f);
3222 fract = ((val - 0.5f)/0.5f);
3226 ui.set_shuttle_fract (fract);
3231 /* do nothing: these are radio-style actions */
3235 const char *action = 0;
3239 action = X_("Roll");
3242 action = X_("Stop");
3245 action = X_("Goto Start");
3248 action = X_("Goto End");
3251 action = X_("Loop");
3254 action = X_("Play Selection");
3257 action = X_("Record");
3267 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3275 ARDOUR_UI::TransportControllable::get_value (void) const
3294 case ShuttleControl:
3304 ARDOUR_UI::TransportControllable::set_id (const string& str)
3310 ARDOUR_UI::setup_profile ()
3312 if (gdk_screen_width() < 1200) {
3313 Profile->set_small_screen ();
3316 if (getenv ("ARDOUR_SAE")) {
3317 Profile->set_sae ();
3318 Profile->set_single_package ();