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;
202 last_configure_time.tv_sec = 0;
203 last_configure_time.tv_usec = 0;
205 shuttle_grabbed = false;
207 shuttle_max_speed = 8.0f;
209 shuttle_style_menu = 0;
210 shuttle_unit_menu = 0;
212 gettimeofday (&last_peak_grab, 0);
213 gettimeofday (&last_shuttle_request, 0);
215 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
216 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
218 /* handle pending state with a dialog */
220 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
222 /* handle sr mismatch with a dialog */
224 ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
226 /* lets get this party started */
229 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
230 throw failed_constructor ();
233 setup_gtk_ardour_enums ();
234 Config->set_current_owner (ConfigVariableBase::Interface);
237 } catch (failed_constructor& err) {
238 error << _("could not initialize Ardour.") << endmsg;
243 /* we like keyboards */
245 keyboard = new Keyboard;
247 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
248 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
254 ARDOUR_UI::create_engine ()
256 // this gets called every time by new_session()
262 loading_message (_("Starting audio engine"));
265 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
272 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
273 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
274 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
275 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
283 ARDOUR_UI::post_engine ()
285 /* Things to be done once we create the AudioEngine
288 check_memory_locking();
290 ActionManager::init ();
293 if (setup_windows ()) {
294 throw failed_constructor ();
297 /* this is the first point at which all the keybindings are available */
299 if (ARDOUR_COMMAND_LINE::show_key_actions) {
300 vector<string> names;
301 vector<string> paths;
303 vector<AccelKey> bindings;
305 ActionManager::get_all_actions (names, paths, keys, bindings);
307 vector<string>::iterator n;
308 vector<string>::iterator k;
309 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
310 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
316 blink_timeout_tag = -1;
318 /* the global configuration object is now valid */
322 /* this being a GUI and all, we want peakfiles */
324 AudioFileSource::set_build_peakfiles (true);
325 AudioFileSource::set_build_missing_peakfiles (true);
327 /* set default clock modes */
329 if (Profile->get_sae()) {
330 primary_clock.set_mode (AudioClock::MinSec);
332 primary_clock.set_mode (AudioClock::SMPTE);
334 secondary_clock.set_mode (AudioClock::BBT);
336 /* start the time-of-day-clock */
339 /* OS X provides an always visible wallclock, so don't be stupid */
340 update_wall_clock ();
341 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
344 update_disk_space ();
346 update_sample_rate (engine->frame_rate());
348 platform_specific ();
350 /* now start and maybe save state */
352 if (do_engine_start () == 0) {
353 if (session && _session_is_new) {
354 /* we need to retain initial visual
355 settings for a new session
357 session->save_state ("");
362 ARDOUR_UI::~ARDOUR_UI ()
364 save_ardour_state ();
378 if (add_route_dialog) {
379 delete add_route_dialog;
382 if (new_session_dialog) {
383 delete new_session_dialog;
388 ARDOUR_UI::pop_back_splash ()
390 if (Splash::instance()) {
391 // Splash::instance()->pop_back();
392 Splash::instance()->hide ();
397 ARDOUR_UI::configure_timeout ()
402 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
403 /* no configure events yet */
407 gettimeofday (&now, 0);
408 timersub (&now, &last_configure_time, &diff);
410 /* force a gap of 0.5 seconds since the last configure event
413 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
416 have_configure_timeout = false;
417 save_ardour_state ();
423 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
425 if (have_configure_timeout) {
426 gettimeofday (&last_configure_time, 0);
428 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
429 have_configure_timeout = true;
436 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
438 const XMLProperty* prop;
440 if ((prop = node.property ("roll")) != 0) {
441 roll_controllable.set_id (prop->value());
443 if ((prop = node.property ("stop")) != 0) {
444 stop_controllable.set_id (prop->value());
446 if ((prop = node.property ("goto_start")) != 0) {
447 goto_start_controllable.set_id (prop->value());
449 if ((prop = node.property ("goto_end")) != 0) {
450 goto_end_controllable.set_id (prop->value());
452 if ((prop = node.property ("auto_loop")) != 0) {
453 auto_loop_controllable.set_id (prop->value());
455 if ((prop = node.property ("play_selection")) != 0) {
456 play_selection_controllable.set_id (prop->value());
458 if ((prop = node.property ("rec")) != 0) {
459 rec_controllable.set_id (prop->value());
461 if ((prop = node.property ("shuttle")) != 0) {
462 shuttle_controllable.set_id (prop->value());
467 ARDOUR_UI::get_transport_controllable_state ()
469 XMLNode* node = new XMLNode(X_("TransportControllables"));
472 roll_controllable.id().print (buf, sizeof (buf));
473 node->add_property (X_("roll"), buf);
474 stop_controllable.id().print (buf, sizeof (buf));
475 node->add_property (X_("stop"), buf);
476 goto_start_controllable.id().print (buf, sizeof (buf));
477 node->add_property (X_("goto_start"), buf);
478 goto_end_controllable.id().print (buf, sizeof (buf));
479 node->add_property (X_("goto_end"), buf);
480 auto_loop_controllable.id().print (buf, sizeof (buf));
481 node->add_property (X_("auto_loop"), buf);
482 play_selection_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("play_selection"), buf);
484 rec_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("rec"), buf);
486 shuttle_controllable.id().print (buf, sizeof (buf));
487 node->add_property (X_("shuttle"), buf);
493 ARDOUR_UI::save_ardour_state ()
495 if (!keyboard || !mixer || !editor) {
499 /* XXX this is all a bit dubious. add_extra_xml() uses
500 a different lifetime model from add_instant_xml().
503 XMLNode* node = new XMLNode (keyboard->get_state());
504 Config->add_extra_xml (*node);
505 Config->add_extra_xml (get_transport_controllable_state());
506 if (new_session_dialog) {
507 if (new_session_dialog->engine_control.was_used()) {
508 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
511 Config->save_state();
512 ui_config->save_state ();
514 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
515 XMLNode mnode(mixer->get_state());
518 session->add_instant_xml (enode, session->path());
519 session->add_instant_xml (mnode, session->path());
521 Config->add_instant_xml (enode, get_user_ardour_path());
522 Config->add_instant_xml (mnode, get_user_ardour_path());
525 Keyboard::save_keybindings ();
529 ARDOUR_UI::autosave_session ()
531 if (!Config->get_periodic_safety_backups())
535 session->maybe_write_autosave();
542 ARDOUR_UI::update_autosave ()
544 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
546 if (session->dirty()) {
547 if (_autosave_connection.connected()) {
548 _autosave_connection.disconnect();
551 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
552 Config->get_periodic_safety_backup_interval() * 1000);
555 if (_autosave_connection.connected()) {
556 _autosave_connection.disconnect();
562 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
566 title = _("Ardour could not start JACK");
568 title = _("Ardour could not connect to JACK.");
571 MessageDialog win (title,
577 win.set_secondary_text(_("There are several possible reasons:\n\
579 1) You requested audio parameters that are not supported..\n\
580 2) JACK is running as another user.\n\
582 Please consider the possibilities, and perhaps try different parameters."));
584 win.set_secondary_text(_("There are several possible reasons:\n\
586 1) JACK is not running.\n\
587 2) JACK is running as another user, perhaps root.\n\
588 3) There is already another client called \"ardour\".\n\
590 Please consider the possibilities, and perhaps (re)start JACK."));
594 win.set_transient_for (*toplevel);
598 win.add_button (Stock::OK, RESPONSE_CLOSE);
600 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
603 win.set_default_response (RESPONSE_CLOSE);
606 win.set_position (Gtk::WIN_POS_CENTER);
609 /* we just don't care about the result, but we want to block */
615 ARDOUR_UI::startup ()
619 new_session_dialog = new NewSessionDialog();
621 bool backend_audio_is_running = EngineControl::engine_running();
622 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
625 new_session_dialog->engine_control.set_state (*audio_setup);
628 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
632 BootMessage (_("Ardour is ready for use"));
638 ARDOUR_UI::no_memory_warning ()
640 XMLNode node (X_("no-memory-warning"));
641 Config->add_instant_xml (node, get_user_ardour_path());
645 ARDOUR_UI::check_memory_locking ()
648 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
652 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
654 if (engine->is_realtime() && memory_warning_node == 0) {
656 struct rlimit limits;
658 long pages, page_size;
660 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
663 ram = (int64_t) pages * (int64_t) page_size;
666 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
670 if (limits.rlim_cur != RLIM_INFINITY) {
672 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
675 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
676 "This might cause Ardour to run out of memory before your system "
677 "runs out of memory. \n\n"
678 "You can view the memory limit with 'ulimit -l', "
679 "and it is normally controlled by /etc/security/limits.conf"));
681 VBox* vbox = msg.get_vbox();
683 CheckButton cb (_("Do not show this window again"));
685 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
687 hbox.pack_start (cb, true, false);
688 vbox->pack_start (hbox);
706 if (session->transport_rolling()) {
707 session->request_stop ();
711 if (session->dirty()) {
712 switch (ask_about_saving_session(_("quit"))) {
717 /* use the default name */
718 if (save_state_canfail ("")) {
719 /* failed - don't quit */
720 MessageDialog msg (*editor,
722 Ardour was unable to save your session.\n\n\
723 If you still wish to quit, please use the\n\n\
724 \"Just quit\" option."));
735 session->set_deletion_in_progress ();
739 save_ardour_state ();
744 ARDOUR_UI::ask_about_saving_session (const string & what)
746 ArdourDialog window (_("ardour: save session?"));
747 Gtk::HBox dhbox; // the hbox for the image and text
748 Gtk::Label prompt_label;
749 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
753 msg = string_compose(_("Don't %1"), what);
754 window.add_button (msg, RESPONSE_REJECT);
755 msg = string_compose(_("Just %1"), what);
756 window.add_button (msg, RESPONSE_APPLY);
757 msg = string_compose(_("Save and %1"), what);
758 window.add_button (msg, RESPONSE_ACCEPT);
760 window.set_default_response (RESPONSE_ACCEPT);
762 Gtk::Button noquit_button (msg);
763 noquit_button.set_name ("EditorGTKButton");
768 if (session->snap_name() == session->name()) {
771 type = _("snapshot");
773 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?"),
774 type, session->snap_name());
776 prompt_label.set_text (prompt);
777 prompt_label.set_name (X_("PrompterLabel"));
778 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
780 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
782 dhbox.set_homogeneous (false);
783 dhbox.pack_start (*dimage, false, false, 5);
784 dhbox.pack_start (prompt_label, true, false, 5);
785 window.get_vbox()->pack_start (dhbox);
787 window.set_name (_("Prompter"));
788 window.set_position (Gtk::WIN_POS_MOUSE);
789 window.set_modal (true);
790 window.set_resizable (false);
793 save_the_session = 0;
795 window.set_keep_above (true);
798 ResponseType r = (ResponseType) window.run();
803 case RESPONSE_ACCEPT: // save and get out of here
805 case RESPONSE_APPLY: // get out of here
815 ARDOUR_UI::every_second ()
818 update_buffer_load ();
819 update_disk_space ();
824 ARDOUR_UI::every_point_one_seconds ()
826 update_speed_display ();
827 RapidScreenUpdate(); /* EMIT_SIGNAL */
832 ARDOUR_UI::every_point_zero_one_seconds ()
834 // august 2007: actual update frequency: 40Hz, not 100Hz
836 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
841 ARDOUR_UI::update_sample_rate (nframes_t ignored)
845 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
847 if (!engine->connected()) {
849 snprintf (buf, sizeof (buf), _("disconnected"));
853 nframes_t rate = engine->frame_rate();
855 if (fmod (rate, 1000.0) != 0.0) {
856 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
857 (float) rate/1000.0f,
858 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
860 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
862 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
866 sample_rate_label.set_text (buf);
870 ARDOUR_UI::update_cpu_load ()
873 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
874 cpu_load_label.set_text (buf);
878 ARDOUR_UI::update_buffer_load ()
883 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
884 session->playback_load(), session->capture_load());
885 buffer_load_label.set_text (buf);
887 buffer_load_label.set_text ("");
892 ARDOUR_UI::count_recenabled_streams (Route& route)
894 Track* track = dynamic_cast<Track*>(&route);
895 if (track && track->diskstream()->record_enabled()) {
896 rec_enabled_streams += track->n_inputs();
901 ARDOUR_UI::update_disk_space()
907 nframes_t frames = session->available_capture_duration();
910 if (frames == max_frames) {
911 strcpy (buf, _("Disk: 24hrs+"));
916 nframes_t fr = session->frame_rate();
918 rec_enabled_streams = 0;
919 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
921 if (rec_enabled_streams) {
922 frames /= rec_enabled_streams;
925 hrs = frames / (fr * 3600);
926 frames -= hrs * fr * 3600;
927 mins = frames / (fr * 60);
928 frames -= mins * fr * 60;
931 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
934 disk_space_label.set_text (buf);
938 ARDOUR_UI::update_wall_clock ()
945 tm_now = localtime (&now);
947 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
948 wall_clock_label.set_text (buf);
954 ARDOUR_UI::session_menu (GdkEventButton *ev)
956 session_popup_menu->popup (0, 0);
961 ARDOUR_UI::redisplay_recent_sessions ()
963 vector<string *> *sessions;
964 vector<string *>::iterator i;
965 RecentSessionsSorter cmp;
967 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
968 recent_session_model->clear ();
971 ARDOUR::read_recent_sessions (rs);
974 recent_session_display.set_model (recent_session_model);
978 /* sort them alphabetically */
979 sort (rs.begin(), rs.end(), cmp);
980 sessions = new vector<string*>;
982 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
983 sessions->push_back (new string ((*i).second));
986 for (i = sessions->begin(); i != sessions->end(); ++i) {
988 vector<string*>* states;
989 vector<const gchar*> item;
990 string fullpath = *(*i);
992 /* remove any trailing / */
994 if (fullpath[fullpath.length()-1] == '/') {
995 fullpath = fullpath.substr (0, fullpath.length()-1);
998 /* check whether session still exists */
999 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1000 /* session doesn't exist */
1001 cerr << "skipping non-existent session " << fullpath << endl;
1005 /* now get available states for this session */
1007 if ((states = Session::possible_states (fullpath)) == 0) {
1008 /* no state file? */
1012 TreeModel::Row row = *(recent_session_model->append());
1014 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1015 row[recent_session_columns.fullpath] = fullpath;
1017 if (states->size() > 1) {
1019 /* add the children */
1021 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1023 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1025 child_row[recent_session_columns.visible_name] = **i2;
1026 child_row[recent_session_columns.fullpath] = fullpath;
1035 recent_session_display.set_model (recent_session_model);
1040 ARDOUR_UI::build_session_selector ()
1042 session_selector_window = new ArdourDialog ("session selector");
1044 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1046 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1047 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1048 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1049 recent_session_model = TreeStore::create (recent_session_columns);
1050 recent_session_display.set_model (recent_session_model);
1051 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1052 recent_session_display.set_headers_visible (false);
1053 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1054 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1056 scroller->add (recent_session_display);
1057 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1059 session_selector_window->set_name ("SessionSelectorWindow");
1060 session_selector_window->set_size_request (200, 400);
1061 session_selector_window->get_vbox()->pack_start (*scroller);
1062 session_selector_window->show_all_children();
1066 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1068 session_selector_window->response (RESPONSE_ACCEPT);
1072 ARDOUR_UI::open_recent_session ()
1074 bool can_return = (session != 0);
1076 if (session_selector_window == 0) {
1077 build_session_selector ();
1080 redisplay_recent_sessions ();
1084 session_selector_window->set_position (WIN_POS_MOUSE);
1086 ResponseType r = (ResponseType) session_selector_window->run ();
1089 case RESPONSE_ACCEPT:
1093 session_selector_window->hide();
1100 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1104 session_selector_window->hide();
1106 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1108 if (i == recent_session_model->children().end()) {
1112 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1113 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1115 _session_is_new = false;
1117 if (load_session (path, state) == 0) {
1126 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1128 struct stat statbuf;
1130 if (stat (info.filename.c_str(), &statbuf) != 0) {
1134 if (!S_ISDIR(statbuf.st_mode)) {
1140 string session_file = info.filename;
1141 session_file += '/';
1142 session_file += Glib::path_get_basename (info.filename);
1143 session_file += ".ardour";
1145 if (stat (session_file.c_str(), &statbuf) != 0) {
1149 return S_ISREG (statbuf.st_mode);
1153 ARDOUR_UI::check_audioengine ()
1156 if (!engine->connected()) {
1157 MessageDialog msg (_("Ardour is not connected to JACK\n"
1158 "You cannot open or close sessions in this condition"));
1170 ARDOUR_UI::open_session ()
1172 if (!check_audioengine()) {
1176 /* popup selector window */
1178 if (open_session_selector == 0) {
1180 /* ardour sessions are folders */
1182 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1183 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1184 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1185 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1187 FileFilter session_filter;
1188 session_filter.add_pattern ("*.ardour");
1189 session_filter.set_name (_("Ardour sessions"));
1190 open_session_selector->add_filter (session_filter);
1191 open_session_selector->set_filter (session_filter);
1194 int response = open_session_selector->run();
1195 open_session_selector->hide ();
1198 case RESPONSE_ACCEPT:
1201 open_session_selector->hide();
1205 open_session_selector->hide();
1206 string session_path = open_session_selector->get_filename();
1210 if (session_path.length() > 0) {
1211 if (Session::find_session (session_path, path, name, isnew) == 0) {
1212 _session_is_new = isnew;
1213 load_session (path, name);
1220 ARDOUR_UI::session_add_midi_track ()
1222 cerr << _("Patience is a virtue.\n");
1226 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1228 list<boost::shared_ptr<AudioTrack> > tracks;
1229 Session::RouteList routes;
1232 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1238 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1240 if (tracks.size() != how_many) {
1241 if (how_many == 1) {
1242 error << _("could not create a new audio track") << endmsg;
1244 error << string_compose (_("could only create %1 of %2 new audio %3"),
1245 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1251 routes = session->new_audio_route (input_channels, output_channels, how_many);
1253 if (routes.size() != how_many) {
1254 if (how_many == 1) {
1255 error << _("could not create a new audio track") << endmsg;
1257 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1263 if (need_control_room_outs) {
1269 route->set_stereo_control_outs (control_lr_channels);
1270 route->control_outs()->set_stereo_pan (pans, this);
1272 #endif /* CONTROLOUTS */
1276 MessageDialog msg (*editor,
1277 _("There are insufficient JACK ports available\n\
1278 to create a new track or bus.\n\
1279 You should save Ardour, exit and\n\
1280 restart JACK with more ports."));
1287 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1289 nframes_t _preroll = 0;
1292 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1293 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1295 if (new_position > _preroll) {
1296 new_position -= _preroll;
1301 session->request_locate (new_position);
1306 ARDOUR_UI::transport_goto_start ()
1309 session->goto_start();
1312 /* force displayed area in editor to start no matter
1313 what "follow playhead" setting is.
1317 editor->reset_x_origin (session->current_start_frame());
1323 ARDOUR_UI::transport_goto_zero ()
1326 session->request_locate (0);
1329 /* force displayed area in editor to start no matter
1330 what "follow playhead" setting is.
1334 editor->reset_x_origin (0);
1340 ARDOUR_UI::transport_goto_end ()
1343 nframes_t frame = session->current_end_frame();
1344 session->request_locate (frame);
1346 /* force displayed area in editor to start no matter
1347 what "follow playhead" setting is.
1351 editor->reset_x_origin (frame);
1357 ARDOUR_UI::transport_stop ()
1363 if (session->is_auditioning()) {
1364 session->cancel_audition ();
1368 if (session->get_play_loop ()) {
1369 session->request_play_loop (false);
1372 session->request_stop ();
1376 ARDOUR_UI::transport_stop_and_forget_capture ()
1379 session->request_stop (true);
1384 ARDOUR_UI::remove_last_capture()
1387 editor->remove_last_capture();
1392 ARDOUR_UI::transport_record (bool roll)
1395 switch (session->record_status()) {
1396 case Session::Disabled:
1397 if (session->ntracks() == 0) {
1398 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1402 session->maybe_enable_record ();
1407 case Session::Recording:
1409 session->request_stop();
1411 session->disable_record (false, true);
1415 case Session::Enabled:
1416 session->disable_record (false, true);
1422 ARDOUR_UI::transport_roll ()
1430 rolling = session->transport_rolling ();
1432 if (session->get_play_loop()) {
1433 session->request_play_loop (false);
1434 auto_loop_button.set_visual_state (1);
1435 roll_button.set_visual_state (1);
1436 } else if (session->get_play_range ()) {
1437 session->request_play_range (false);
1438 play_selection_button.set_visual_state (0);
1439 } else if (rolling) {
1440 session->request_locate (session->last_transport_start(), true);
1443 session->request_transport_speed (1.0f);
1447 ARDOUR_UI::transport_loop()
1450 if (session->get_play_loop()) {
1451 if (session->transport_rolling()) {
1452 Location * looploc = session->locations()->auto_loop_location();
1454 session->request_locate (looploc->start(), true);
1459 session->request_play_loop (true);
1465 ARDOUR_UI::transport_play_selection ()
1471 if (!session->get_play_range()) {
1472 session->request_stop ();
1475 editor->play_selection ();
1479 ARDOUR_UI::transport_rewind (int option)
1481 float current_transport_speed;
1484 current_transport_speed = session->transport_speed();
1486 if (current_transport_speed >= 0.0f) {
1489 session->request_transport_speed (-1.0f);
1492 session->request_transport_speed (-4.0f);
1495 session->request_transport_speed (-0.5f);
1500 session->request_transport_speed (current_transport_speed * 1.5f);
1506 ARDOUR_UI::transport_forward (int option)
1508 float current_transport_speed;
1511 current_transport_speed = session->transport_speed();
1513 if (current_transport_speed <= 0.0f) {
1516 session->request_transport_speed (1.0f);
1519 session->request_transport_speed (4.0f);
1522 session->request_transport_speed (0.5f);
1527 session->request_transport_speed (current_transport_speed * 1.5f);
1533 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1539 boost::shared_ptr<Route> r;
1541 if ((r = session->route_by_remote_id (dstream)) != 0) {
1545 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1546 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1555 ARDOUR_UI::queue_transport_change ()
1557 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1561 ARDOUR_UI::map_transport_state ()
1563 float sp = session->transport_speed();
1566 transport_rolling ();
1567 } else if (sp < 0.0f) {
1568 transport_rewinding ();
1569 } else if (sp > 0.0f) {
1570 transport_forwarding ();
1572 transport_stopped ();
1577 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1579 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1580 (int) adj.get_value()].c_str());
1584 ARDOUR_UI::engine_stopped ()
1586 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1587 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1588 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1592 ARDOUR_UI::engine_running ()
1594 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1595 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1596 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1598 Glib::RefPtr<Action> action;
1599 char* action_name = 0;
1601 switch (engine->frames_per_cycle()) {
1603 action_name = X_("JACKLatency32");
1606 action_name = X_("JACKLatency64");
1609 action_name = X_("JACKLatency128");
1612 action_name = X_("JACKLatency512");
1615 action_name = X_("JACKLatency1024");
1618 action_name = X_("JACKLatency2048");
1621 action_name = X_("JACKLatency4096");
1624 action_name = X_("JACKLatency8192");
1627 /* XXX can we do anything useful ? */
1633 action = ActionManager::get_action (X_("JACK"), action_name);
1636 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1637 ract->set_active ();
1643 ARDOUR_UI::engine_halted ()
1645 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1647 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1648 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1650 update_sample_rate (0);
1652 MessageDialog msg (*editor,
1654 JACK has either been shutdown or it\n\
1655 disconnected Ardour because Ardour\n\
1656 was not fast enough. You can save the\n\
1657 session and/or try to reconnect to JACK ."));
1663 ARDOUR_UI::do_engine_start ()
1671 error << _("Unable to start the session running")
1681 ARDOUR_UI::setup_theme ()
1683 theme_manager->setup_theme();
1687 ARDOUR_UI::update_clocks ()
1689 if (!editor || !editor->dragging_playhead()) {
1690 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1695 ARDOUR_UI::start_clocking ()
1697 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1701 ARDOUR_UI::stop_clocking ()
1703 clock_signal_connection.disconnect ();
1707 ARDOUR_UI::toggle_clocking ()
1710 if (clock_button.get_active()) {
1719 ARDOUR_UI::_blink (void *arg)
1722 ((ARDOUR_UI *) arg)->blink ();
1729 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1733 ARDOUR_UI::start_blinking ()
1735 /* Start the blink signal. Everybody with a blinking widget
1736 uses Blink to drive the widget's state.
1739 if (blink_timeout_tag < 0) {
1741 blink_timeout_tag = g_timeout_add (240, _blink, this);
1746 ARDOUR_UI::stop_blinking ()
1748 if (blink_timeout_tag >= 0) {
1749 g_source_remove (blink_timeout_tag);
1750 blink_timeout_tag = -1;
1755 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1761 if (io.n_inputs() == 0) {
1766 /* XXX we're not handling multiple ports yet. */
1768 const char **connections = io.input(0)->get_connections();
1770 if (connections == 0 || connections[0] == '\0') {
1773 buf = connections[0];
1780 if (io.n_outputs() == 0) {
1785 /* XXX we're not handling multiple ports yet. */
1787 const char **connections = io.output(0)->get_connections();
1789 if (connections == 0 || connections[0] == '\0') {
1792 buf = connections[0];
1799 /** Ask the user for the name of a new shapshot and then take it.
1802 ARDOUR_UI::snapshot_session ()
1804 ArdourPrompter prompter (true);
1808 struct tm local_time;
1811 localtime_r (&n, &local_time);
1812 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1814 prompter.set_name ("Prompter");
1815 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1816 prompter.set_prompt (_("Name of New Snapshot"));
1817 prompter.set_initial_text (timebuf);
1819 switch (prompter.run()) {
1820 case RESPONSE_ACCEPT:
1821 prompter.get_result (snapname);
1822 if (snapname.length()){
1823 save_state (snapname);
1833 ARDOUR_UI::save_state (const string & name)
1835 (void) save_state_canfail (name);
1839 ARDOUR_UI::save_state_canfail (string name)
1844 if (name.length() == 0) {
1845 name = session->snap_name();
1848 if ((ret = session->save_state (name)) != 0) {
1852 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1857 ARDOUR_UI::restore_state (string name)
1860 if (name.length() == 0) {
1861 name = session->name();
1863 session->restore_state (name);
1868 ARDOUR_UI::primary_clock_value_changed ()
1871 session->request_locate (primary_clock.current_time ());
1876 ARDOUR_UI::big_clock_value_changed ()
1879 session->request_locate (big_clock.current_time ());
1884 ARDOUR_UI::secondary_clock_value_changed ()
1887 session->request_locate (secondary_clock.current_time ());
1892 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1894 if (session && dstream && dstream->record_enabled()) {
1896 Session::RecordState rs;
1898 rs = session->record_status ();
1901 case Session::Disabled:
1902 case Session::Enabled:
1903 if (w->get_state() != STATE_SELECTED) {
1904 w->set_state (STATE_SELECTED);
1908 case Session::Recording:
1909 if (w->get_state() != STATE_ACTIVE) {
1910 w->set_state (STATE_ACTIVE);
1916 if (w->get_state() != STATE_NORMAL) {
1917 w->set_state (STATE_NORMAL);
1923 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1929 switch (session->record_status()) {
1930 case Session::Enabled:
1932 rec_button.set_visual_state (2);
1934 rec_button.set_visual_state (0);
1938 case Session::Recording:
1939 rec_button.set_visual_state (1);
1943 rec_button.set_visual_state (0);
1949 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1957 ARDOUR_UI::save_template ()
1960 ArdourPrompter prompter (true);
1963 if (!check_audioengine()) {
1967 prompter.set_name (X_("Prompter"));
1968 prompter.set_prompt (_("Name for mix template:"));
1969 prompter.set_initial_text(session->name() + _("-template"));
1970 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1972 switch (prompter.run()) {
1973 case RESPONSE_ACCEPT:
1974 prompter.get_result (name);
1976 if (name.length()) {
1977 session->save_template (name);
1987 ARDOUR_UI::fontconfig_dialog ()
1990 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1991 may not and it can take a while to build it. Warn them.
1994 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1996 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1997 MessageDialog msg (*new_session_dialog,
1998 _("Welcome to Ardour.\n\n"
1999 "The program will take a bit longer to start up\n"
2000 "while the system fonts are checked.\n\n"
2001 "This will only be done once, and you will\n"
2002 "not see this message again\n"),
2015 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2017 existing_session = false;
2019 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2020 session_path = cmdline_path;
2021 existing_session = true;
2022 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2023 session_path = Glib::path_get_dirname (string (cmdline_path));
2024 existing_session = true;
2026 /* it doesn't exist, assume the best */
2027 session_path = Glib::path_get_dirname (string (cmdline_path));
2030 session_name = basename_nosuffix (string (cmdline_path));
2034 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2036 /* when this is called, the backend audio system must be running */
2038 /* the main idea here is to deal with the fact that a cmdline argument for the session
2039 can be interpreted in different ways - it could be a directory or a file, and before
2040 we load, we need to know both the session directory and the snapshot (statefile) within it
2041 that we are supposed to use.
2044 if (session_name.length() == 0 || session_path.length() == 0) {
2048 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2050 Glib::ustring predicted_session_file;
2052 predicted_session_file = session_path;
2053 predicted_session_file += '/';
2054 predicted_session_file += session_name;
2055 predicted_session_file += Session::statefile_suffix();
2057 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2058 existing_session = true;
2061 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2063 if (session_path.find (Session::statefile_suffix()) == session_path.length() - 7) {
2064 /* existing .ardour file */
2065 existing_session = true;
2069 existing_session = false;
2072 /* lets just try to load it */
2074 if (create_engine ()) {
2075 backend_audio_error (false, new_session_dialog);
2079 return load_session (session_path, session_name);
2083 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2085 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2087 MessageDialog msg (str,
2089 Gtk::MESSAGE_WARNING,
2090 Gtk::BUTTONS_YES_NO,
2094 msg.set_name (X_("CleanupDialog"));
2095 msg.set_wmclass (X_("existing_session"), "Ardour");
2096 msg.set_position (Gtk::WIN_POS_MOUSE);
2099 switch (msg.run()) {
2108 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2113 AutoConnectOption iconnect;
2114 AutoConnectOption oconnect;
2118 if (Profile->get_sae()) {
2122 iconnect = AutoConnectPhysical;
2123 oconnect = AutoConnectMaster;
2124 nphysin = 0; // use all available
2125 nphysout = 0; // use all available
2129 /* get settings from advanced section of NSD */
2131 if (new_session_dialog->create_control_bus()) {
2132 cchns = (uint32_t) new_session_dialog->control_channel_count();
2137 if (new_session_dialog->create_master_bus()) {
2138 mchns = (uint32_t) new_session_dialog->master_channel_count();
2143 if (new_session_dialog->connect_inputs()) {
2144 iconnect = AutoConnectPhysical;
2146 iconnect = AutoConnectOption (0);
2149 /// @todo some minor tweaks.
2151 if (new_session_dialog->connect_outs_to_master()) {
2152 oconnect = AutoConnectMaster;
2153 } else if (new_session_dialog->connect_outs_to_physical()) {
2154 oconnect = AutoConnectPhysical;
2156 oconnect = AutoConnectOption (0);
2159 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2160 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2163 if (build_session (session_path,
2171 engine->frame_rate() * 60 * 5)) {
2180 ARDOUR_UI::end_loading_messages ()
2186 ARDOUR_UI::loading_message (const std::string& msg)
2189 splash->message (msg);
2194 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2196 bool existing_session = false;
2197 Glib::ustring session_name;
2198 Glib::ustring session_path;
2199 Glib::ustring template_name;
2201 int response = Gtk::RESPONSE_NONE;
2203 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2205 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2207 /* don't ever reuse this */
2209 ARDOUR_COMMAND_LINE::session_name = string();
2211 if (existing_session && backend_audio_is_running) {
2213 /* just load the thing already */
2215 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2220 /* make the NSD use whatever information we have */
2222 new_session_dialog->set_session_name (session_name);
2223 new_session_dialog->set_session_folder (session_path);
2226 /* loading failed, or we need the NSD for something */
2228 new_session_dialog->set_modal (false);
2229 new_session_dialog->set_position (WIN_POS_CENTER);
2230 new_session_dialog->set_current_page (0);
2231 new_session_dialog->set_existing_session (existing_session);
2232 new_session_dialog->reset_recent();
2235 new_session_dialog->set_have_engine (backend_audio_is_running);
2236 new_session_dialog->present ();
2237 response = new_session_dialog->run ();
2239 _session_is_new = false;
2241 /* handle possible negative responses */
2244 case Gtk::RESPONSE_CANCEL:
2245 case Gtk::RESPONSE_DELETE_EVENT:
2249 new_session_dialog->hide ();
2252 case Gtk::RESPONSE_NONE:
2253 /* "Clear" was pressed */
2257 fontconfig_dialog();
2259 if (!backend_audio_is_running) {
2260 if (new_session_dialog->engine_control.setup_engine ()) {
2261 new_session_dialog->hide ();
2266 if (create_engine ()) {
2268 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2271 new_session_dialog->set_existing_session (false);
2272 new_session_dialog->set_current_page (2);
2274 response = Gtk::RESPONSE_NONE;
2278 backend_audio_is_running = true;
2280 if (response == Gtk::RESPONSE_OK) {
2282 session_name = new_session_dialog->session_name();
2284 if (session_name.empty()) {
2285 response = Gtk::RESPONSE_NONE;
2289 /* if the user mistakenly typed path information into the session filename entry,
2290 convert what they typed into a path & a name
2293 if (session_name[0] == '/' ||
2294 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2295 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2297 session_path = Glib::path_get_dirname (session_name);
2298 session_name = Glib::path_get_basename (session_name);
2302 session_path = new_session_dialog->session_folder();
2305 template_name = Glib::ustring();
2306 switch (new_session_dialog->which_page()) {
2308 case NewSessionDialog::OpenPage:
2309 case NewSessionDialog::EnginePage:
2313 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2315 should_be_new = true;
2317 //XXX This is needed because session constructor wants a
2318 //non-existant path. hopefully this will be fixed at some point.
2320 session_path = Glib::build_filename (session_path, session_name);
2322 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2324 if (ask_about_loading_existing_session (session_path)) {
2327 response = RESPONSE_NONE;
2332 _session_is_new = true;
2334 if (new_session_dialog->use_session_template()) {
2336 template_name = new_session_dialog->session_template_name();
2340 if (build_session_from_nsd (session_path, session_name)) {
2341 response = RESPONSE_NONE;
2353 new_session_dialog->hide ();
2355 if (load_session (session_path, session_name, template_name)) {
2357 response = Gtk::RESPONSE_NONE;
2361 if (response == Gtk::RESPONSE_NONE) {
2362 new_session_dialog->set_existing_session (false);
2363 new_session_dialog->reset ();
2367 } while (response == Gtk::RESPONSE_NONE);
2371 new_session_dialog->hide();
2372 new_session_dialog->reset();
2373 goto_editor_window ();
2378 ARDOUR_UI::close_session ()
2380 if (!check_audioengine()) {
2384 unload_session (true);
2386 get_session_parameters (true, false);
2390 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2392 Session *new_session;
2396 session_loaded = false;
2398 if (!check_audioengine()) {
2402 unload_status = unload_session ();
2404 if (unload_status < 0) {
2406 } else if (unload_status > 0) {
2411 /* if it already exists, we must have write access */
2413 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2414 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2415 "This prevents the session from being loaded."));
2421 loading_message (_("Please wait while Ardour loads your session"));
2422 disable_screen_updates ();
2425 new_session = new Session (*engine, path, snap_name, mix_template);
2428 /* this one is special */
2430 catch (AudioEngine::PortRegistrationFailure& err) {
2432 MessageDialog msg (err.what(),
2435 Gtk::BUTTONS_OK_CANCEL);
2437 msg.set_title (_("Loading Error"));
2438 msg.set_secondary_text (_("Click the OK button to try again."));
2439 msg.set_position (Gtk::WIN_POS_CENTER);
2443 int response = msg.run ();
2448 case RESPONSE_CANCEL:
2458 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2461 Gtk::BUTTONS_OK_CANCEL);
2463 msg.set_title (_("Loading Error"));
2464 msg.set_secondary_text (_("Click the OK button to try again."));
2465 msg.set_position (Gtk::WIN_POS_CENTER);
2469 int response = msg.run ();
2474 case RESPONSE_CANCEL:
2482 connect_to_session (new_session);
2484 Config->set_current_owner (ConfigVariableBase::Interface);
2486 session_loaded = true;
2488 goto_editor_window ();
2491 session->set_clean ();
2494 enable_screen_updates ();
2503 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2504 uint32_t control_channels,
2505 uint32_t master_channels,
2506 AutoConnectOption input_connect,
2507 AutoConnectOption output_connect,
2510 nframes_t initial_length)
2512 Session *new_session;
2515 if (!check_audioengine()) {
2519 session_loaded = false;
2521 x = unload_session ();
2529 _session_is_new = true;
2532 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2533 control_channels, master_channels, nphysin, nphysout, initial_length);
2538 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2544 connect_to_session (new_session);
2546 session_loaded = true;
2554 editor->show_window ();
2565 ARDOUR_UI::show_about ()
2569 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2576 ARDOUR_UI::hide_about ()
2579 about->get_window()->set_cursor ();
2585 ARDOUR_UI::about_signal_response(int response)
2591 ARDOUR_UI::show_splash ()
2595 splash = new Splash;
2603 splash->queue_draw ();
2604 splash->get_window()->process_updates (true);
2609 ARDOUR_UI::hide_splash ()
2617 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2621 removed = rep.paths.size();
2624 MessageDialog msgd (*editor,
2625 _("No audio files were ready for cleanup"),
2628 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2629 msgd.set_secondary_text (_("If this seems suprising, \n\
2630 check for any existing snapshots.\n\
2631 These may still include regions that\n\
2632 require some unused files to continue to exist."));
2638 ArdourDialog results (_("ardour: cleanup"), true, false);
2640 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2641 CleanupResultsModelColumns() {
2645 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2646 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2650 CleanupResultsModelColumns results_columns;
2651 Glib::RefPtr<Gtk::ListStore> results_model;
2652 Gtk::TreeView results_display;
2654 results_model = ListStore::create (results_columns);
2655 results_display.set_model (results_model);
2656 results_display.append_column (list_title, results_columns.visible_name);
2658 results_display.set_name ("CleanupResultsList");
2659 results_display.set_headers_visible (true);
2660 results_display.set_headers_clickable (false);
2661 results_display.set_reorderable (false);
2663 Gtk::ScrolledWindow list_scroller;
2666 Gtk::HBox dhbox; // the hbox for the image and text
2667 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2668 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2670 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2672 if (rep.space < 1048576.0f) {
2674 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2676 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2680 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2682 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2686 dhbox.pack_start (*dimage, true, false, 5);
2687 dhbox.pack_start (txt, true, false, 5);
2689 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2690 TreeModel::Row row = *(results_model->append());
2691 row[results_columns.visible_name] = *i;
2692 row[results_columns.fullpath] = *i;
2695 list_scroller.add (results_display);
2696 list_scroller.set_size_request (-1, 150);
2697 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2699 dvbox.pack_start (dhbox, true, false, 5);
2700 dvbox.pack_start (list_scroller, true, false, 5);
2701 ddhbox.pack_start (dvbox, true, false, 5);
2703 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2704 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2705 results.set_default_response (RESPONSE_CLOSE);
2706 results.set_position (Gtk::WIN_POS_MOUSE);
2707 results.show_all_children ();
2708 results.set_resizable (false);
2715 ARDOUR_UI::cleanup ()
2718 /* shouldn't happen: menu item is insensitive */
2723 MessageDialog checker (_("Are you sure you want to cleanup?"),
2725 Gtk::MESSAGE_QUESTION,
2726 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2728 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2729 ALL undo/redo information will be lost if you cleanup.\n\
2730 After cleanup, unused audio files will be moved to a \
2731 \"dead sounds\" location."));
2733 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2734 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2735 checker.set_default_response (RESPONSE_CANCEL);
2737 checker.set_name (_("CleanupDialog"));
2738 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2739 checker.set_position (Gtk::WIN_POS_MOUSE);
2741 switch (checker.run()) {
2742 case RESPONSE_ACCEPT:
2748 Session::cleanup_report rep;
2750 editor->prepare_for_cleanup ();
2752 /* do not allow flush until a session is reloaded */
2754 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2756 act->set_sensitive (false);
2759 if (session->cleanup_sources (rep)) {
2764 display_cleanup_results (rep,
2767 The following %1 %2 not in use and \n\
2768 have been moved to:\n\
2770 Flushing the wastebasket will \n\
2771 release an additional\n\
2772 %4 %5bytes of disk space.\n"
2780 ARDOUR_UI::flush_trash ()
2783 /* shouldn't happen: menu item is insensitive */
2787 Session::cleanup_report rep;
2789 if (session->cleanup_trash_sources (rep)) {
2793 display_cleanup_results (rep,
2795 _("The following %1 %2 deleted from\n\
2797 releasing %4 %5bytes of disk space"));
2801 ARDOUR_UI::add_route (Gtk::Window* float_window)
2809 if (add_route_dialog == 0) {
2810 add_route_dialog = new AddRouteDialog;
2812 add_route_dialog->set_transient_for (*float_window);
2816 if (add_route_dialog->is_visible()) {
2817 /* we're already doing this */
2821 ResponseType r = (ResponseType) add_route_dialog->run ();
2823 add_route_dialog->hide();
2826 case RESPONSE_ACCEPT:
2833 if ((count = add_route_dialog->count()) <= 0) {
2837 uint32_t input_chan = add_route_dialog->channels ();
2838 uint32_t output_chan;
2839 string name_template = add_route_dialog->name_template ();
2840 bool track = add_route_dialog->track ();
2842 AutoConnectOption oac = Config->get_output_auto_connect();
2844 if (oac & AutoConnectMaster) {
2845 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2847 output_chan = input_chan;
2850 /* XXX do something with name template */
2852 cerr << "Adding with " << input_chan << " in and " << output_chan << "out\n";
2855 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2857 session_add_audio_bus (input_chan, output_chan, count);
2862 ARDOUR_UI::mixer_settings () const
2867 node = session->instant_xml(X_("Mixer"), session->path());
2869 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2873 node = new XMLNode (X_("Mixer"));
2880 ARDOUR_UI::editor_settings () const
2885 node = session->instant_xml(X_("Editor"), session->path());
2887 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2891 node = new XMLNode (X_("Editor"));
2897 ARDOUR_UI::keyboard_settings () const
2901 node = Config->extra_xml(X_("Keyboard"));
2904 node = new XMLNode (X_("Keyboard"));
2910 ARDOUR_UI::create_xrun_marker(nframes_t where)
2912 ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::create_xrun_marker), where));
2913 editor->mouse_add_new_marker (where, false, true);
2917 ARDOUR_UI::halt_on_xrun_message ()
2919 MessageDialog msg (*editor,
2920 _("Recording was stopped because your system could not keep up."));
2925 ARDOUR_UI::xrun_handler(nframes_t where)
2927 if (Config->get_create_xrun_marker() && session->actively_recording()) {
2928 create_xrun_marker(where);
2931 if (Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2932 halt_on_xrun_message ();
2937 ARDOUR_UI::disk_overrun_handler ()
2939 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2941 if (!have_disk_speed_dialog_displayed) {
2942 have_disk_speed_dialog_displayed = true;
2943 MessageDialog* msg = new MessageDialog (*editor, _("\
2944 The disk system on your computer\n\
2945 was not able to keep up with Ardour.\n\
2947 Specifically, it failed to write data to disk\n\
2948 quickly enough to keep up with recording.\n"));
2949 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2955 ARDOUR_UI::disk_underrun_handler ()
2957 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2959 if (!have_disk_speed_dialog_displayed) {
2960 have_disk_speed_dialog_displayed = true;
2961 MessageDialog* msg = new MessageDialog (*editor,
2962 _("The disk system on your computer\n\
2963 was not able to keep up with Ardour.\n\
2965 Specifically, it failed to read data from disk\n\
2966 quickly enough to keep up with playback.\n"));
2967 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2973 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2975 have_disk_speed_dialog_displayed = false;
2980 ARDOUR_UI::pending_state_dialog ()
2982 HBox* hbox = new HBox();
2983 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2984 ArdourDialog dialog (_("Crash Recovery"), true);
2986 This session appears to have been in\n\
2987 middle of recording when ardour or\n\
2988 the computer was shutdown.\n\
2990 Ardour can recover any captured audio for\n\
2991 you, or it can ignore it. Please decide\n\
2992 what you would like to do.\n"));
2993 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2994 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2995 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2996 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2997 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2998 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2999 dialog.set_default_response (RESPONSE_ACCEPT);
3000 dialog.set_position (WIN_POS_CENTER);
3005 switch (dialog.run ()) {
3006 case RESPONSE_ACCEPT:
3014 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3016 HBox* hbox = new HBox();
3017 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3018 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3019 Label message (string_compose (_("\
3020 This session was created with a sample rate of %1 Hz\n\
3022 The audioengine is currently running at %2 Hz\n"), desired, actual));
3024 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3025 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3026 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3027 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3028 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3029 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3030 dialog.set_default_response (RESPONSE_ACCEPT);
3031 dialog.set_position (WIN_POS_CENTER);
3036 switch (dialog.run ()) {
3037 case RESPONSE_ACCEPT:
3046 ARDOUR_UI::disconnect_from_jack ()
3049 if( engine->disconnect_from_jack ()) {
3050 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3054 update_sample_rate (0);
3059 ARDOUR_UI::reconnect_to_jack ()
3062 if (engine->reconnect_to_jack ()) {
3063 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3067 update_sample_rate (0);
3072 ARDOUR_UI::use_config ()
3074 Glib::RefPtr<Action> act;
3076 switch (Config->get_native_file_data_format ()) {
3078 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3081 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3084 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3089 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3090 ract->set_active ();
3093 switch (Config->get_native_file_header_format ()) {
3095 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3098 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3101 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3104 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3107 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3110 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3113 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3118 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3119 ract->set_active ();
3122 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3124 set_transport_controllable_state (*node);
3129 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3131 if (Config->get_primary_clock_delta_edit_cursor()) {
3132 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3134 primary_clock.set (pos, 0, true);
3137 if (Config->get_secondary_clock_delta_edit_cursor()) {
3138 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3140 secondary_clock.set (pos);
3143 if (big_clock_window) {
3144 big_clock.set (pos);
3149 ARDOUR_UI::record_state_changed ()
3151 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3153 if (!session || !big_clock_window) {
3154 /* why bother - the clock isn't visible */
3158 switch (session->record_status()) {
3159 case Session::Recording:
3160 big_clock.set_widget_name ("BigClockRecording");
3163 big_clock.set_widget_name ("BigClockNonRecording");
3169 ARDOUR_UI::first_idle ()
3172 session->allow_auto_play (true);
3174 Keyboard::set_can_save_keybindings (true);
3179 ARDOUR_UI::store_clock_modes ()
3181 XMLNode* node = new XMLNode(X_("ClockModes"));
3183 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3184 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3187 session->add_extra_xml (*node);
3188 session->set_dirty ();
3193 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3194 : Controllable (name), ui (u), type(tp)
3200 ARDOUR_UI::TransportControllable::set_value (float val)
3202 if (type == ShuttleControl) {
3209 fract = -((0.5f - val)/0.5f);
3211 fract = ((val - 0.5f)/0.5f);
3215 ui.set_shuttle_fract (fract);
3220 /* do nothing: these are radio-style actions */
3228 action = X_("Roll");
3231 action = X_("Stop");
3234 action = X_("Goto Start");
3237 action = X_("Goto End");
3240 action = X_("Loop");
3243 action = X_("Play Selection");
3246 action = X_("Record");
3256 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3264 ARDOUR_UI::TransportControllable::get_value (void) const
3283 case ShuttleControl:
3293 ARDOUR_UI::TransportControllable::set_id (const string& str)
3299 ARDOUR_UI::setup_profile ()
3301 if (gdk_screen_width() < 1200) {
3302 Profile->set_small_screen ();
3305 if (getenv ("ARDOUR_SAE")) {
3306 Profile->set_sae ();
3307 Profile->set_single_package ();