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/compose.h>
38 #include <pbd/pathscanner.h>
39 #include <pbd/failed_constructor.h>
40 #include <pbd/enumwriter.h>
41 #include <pbd/stacktrace.h>
42 #include <gtkmm2ext/gtk_ui.h>
43 #include <gtkmm2ext/utils.h>
44 #include <gtkmm2ext/click_box.h>
45 #include <gtkmm2ext/fastmeter.h>
46 #include <gtkmm2ext/stop_signal.h>
47 #include <gtkmm2ext/popup.h>
48 #include <gtkmm2ext/window_title.h>
50 #include <midi++/port.h>
51 #include <midi++/mmc.h>
53 #include <ardour/ardour.h>
54 #include <ardour/profile.h>
55 #include <ardour/session_route.h>
56 #include <ardour/port.h>
57 #include <ardour/audioengine.h>
58 #include <ardour/playlist.h>
59 #include <ardour/utils.h>
60 #include <ardour/audio_diskstream.h>
61 #include <ardour/audiofilesource.h>
62 #include <ardour/recent_sessions.h>
63 #include <ardour/port.h>
64 #include <ardour/audio_track.h>
67 #include "ardour_ui.h"
68 #include "public_editor.h"
69 #include "audio_clock.h"
74 #include "add_route_dialog.h"
75 #include "new_session_dialog.h"
78 #include "gui_thread.h"
79 #include "theme_manager.h"
80 #include "engine_dialog.h"
84 using namespace ARDOUR;
86 using namespace Gtkmm2ext;
90 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
91 UIConfiguration *ARDOUR_UI::ui_config = 0;
93 sigc::signal<void,bool> ARDOUR_UI::Blink;
94 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
95 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
96 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
98 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
100 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
102 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
103 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
104 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
105 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
109 adjuster_table (3, 3),
113 preroll_button (_("pre\nroll")),
114 postroll_button (_("post\nroll")),
118 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, 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;
163 if (getenv ("ARDOUR_DEBUG_UPDATES")) {
164 gdk_window_set_debug_updates (true);
169 if (theArdourUI == 0) {
173 ui_config = new UIConfiguration();
174 theme_manager = new ThemeManager();
180 _session_is_new = false;
181 big_clock_window = 0;
182 session_selector_window = 0;
183 new_session_dialog = 0;
184 last_key_press_time = 0;
185 connection_editor = 0;
186 add_route_dialog = 0;
190 open_session_selector = 0;
191 have_configure_timeout = false;
192 have_disk_speed_dialog_displayed = false;
193 _will_create_new_session_automatically = false;
194 session_loaded = false;
196 last_speed_displayed = -1.0f;
198 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
199 /* all changes go to the user directory */
200 user_keybindings_path = get_user_ardour_path ();
201 user_keybindings_path += '/';
202 user_keybindings_path += "ardour.bindings";
204 can_save_keybindings = false;
206 last_configure_time.tv_sec = 0;
207 last_configure_time.tv_usec = 0;
209 shuttle_grabbed = false;
211 shuttle_max_speed = 8.0f;
213 shuttle_style_menu = 0;
214 shuttle_unit_menu = 0;
216 gettimeofday (&last_peak_grab, 0);
217 gettimeofday (&last_shuttle_request, 0);
219 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
220 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
222 /* handle pending state with a dialog */
224 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
226 /* lets get this party started */
229 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
230 setup_gtk_ardour_enums ();
231 Config->set_current_owner (ConfigVariableBase::Interface);
234 } catch (failed_constructor& err) {
235 error << _("could not initialize Ardour.") << endmsg;
240 /* we like keyboards */
242 keyboard = new Keyboard;
244 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
245 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
249 ARDOUR_UI::start_backend_audio ()
251 if (new_session_dialog->engine_control.start_engine ()) {
259 ARDOUR_UI::create_engine ()
261 // this gets called every time by new_session()
268 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
269 } catch (AudioEngine::NoBackendAvailable& err) {
270 backend_audio_error ();
271 error << string_compose (_("Could not connect to JACK server as \"%1\""), ARDOUR_COMMAND_LINE::jack_client_name) << endmsg;
275 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
276 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
277 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
278 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
284 ARDOUR_UI::post_engine ()
286 /* Things to be done once we create the AudioEngine
289 check_memory_locking();
291 ActionManager::init ();
294 if (setup_windows ()) {
295 throw failed_constructor ();
298 /* this is the first point at which all the keybindings are available */
300 if (ARDOUR_COMMAND_LINE::show_key_actions) {
301 vector<string> names;
302 vector<string> paths;
304 vector<AccelKey> bindings;
306 ActionManager::get_all_actions (names, paths, keys, bindings);
308 vector<string>::iterator n;
309 vector<string>::iterator k;
310 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
311 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
317 blink_timeout_tag = -1;
319 /* the global configuration object is now valid */
323 /* this being a GUI and all, we want peakfiles */
325 AudioFileSource::set_build_peakfiles (true);
326 AudioFileSource::set_build_missing_peakfiles (true);
328 /* set default clock modes */
330 primary_clock.set_mode (AudioClock::SMPTE);
331 secondary_clock.set_mode (AudioClock::BBT);
333 /* start the time-of-day-clock */
336 update_wall_clock ();
337 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
340 update_disk_space ();
342 update_sample_rate (engine->frame_rate());
344 /* now start and maybe save state */
346 if (do_engine_start () == 0) {
347 if (session && _session_is_new) {
348 /* we need to retain initial visual
349 settings for a new session
351 session->save_state ("");
356 ARDOUR_UI::~ARDOUR_UI ()
358 save_ardour_state ();
372 if (add_route_dialog) {
373 delete add_route_dialog;
376 if (new_session_dialog) {
377 delete new_session_dialog;
382 ARDOUR_UI::configure_timeout ()
387 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
388 /* no configure events yet */
392 gettimeofday (&now, 0);
393 timersub (&now, &last_configure_time, &diff);
395 /* force a gap of 0.5 seconds since the last configure event
398 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
401 have_configure_timeout = false;
402 save_ardour_state ();
408 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
410 if (have_configure_timeout) {
411 gettimeofday (&last_configure_time, 0);
413 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
414 have_configure_timeout = true;
421 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
423 const XMLProperty* prop;
425 if ((prop = node.property ("roll")) != 0) {
426 roll_controllable.set_id (prop->value());
428 if ((prop = node.property ("stop")) != 0) {
429 stop_controllable.set_id (prop->value());
431 if ((prop = node.property ("goto_start")) != 0) {
432 goto_start_controllable.set_id (prop->value());
434 if ((prop = node.property ("goto_end")) != 0) {
435 goto_end_controllable.set_id (prop->value());
437 if ((prop = node.property ("auto_loop")) != 0) {
438 auto_loop_controllable.set_id (prop->value());
440 if ((prop = node.property ("play_selection")) != 0) {
441 play_selection_controllable.set_id (prop->value());
443 if ((prop = node.property ("rec")) != 0) {
444 rec_controllable.set_id (prop->value());
446 if ((prop = node.property ("shuttle")) != 0) {
447 shuttle_controllable.set_id (prop->value());
452 ARDOUR_UI::get_transport_controllable_state ()
454 XMLNode* node = new XMLNode(X_("TransportControllables"));
457 roll_controllable.id().print (buf, sizeof (buf));
458 node->add_property (X_("roll"), buf);
459 stop_controllable.id().print (buf, sizeof (buf));
460 node->add_property (X_("stop"), buf);
461 goto_start_controllable.id().print (buf, sizeof (buf));
462 node->add_property (X_("goto_start"), buf);
463 goto_end_controllable.id().print (buf, sizeof (buf));
464 node->add_property (X_("goto_end"), buf);
465 auto_loop_controllable.id().print (buf, sizeof (buf));
466 node->add_property (X_("auto_loop"), buf);
467 play_selection_controllable.id().print (buf, sizeof (buf));
468 node->add_property (X_("play_selection"), buf);
469 rec_controllable.id().print (buf, sizeof (buf));
470 node->add_property (X_("rec"), buf);
471 shuttle_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("shuttle"), buf);
478 ARDOUR_UI::save_ardour_state ()
480 if (!keyboard || !mixer || !editor) {
484 /* XXX this is all a bit dubious. add_extra_xml() uses
485 a different lifetime model from add_instant_xml().
488 XMLNode* node = new XMLNode (keyboard->get_state());
489 Config->add_extra_xml (*node);
490 Config->add_extra_xml (get_transport_controllable_state());
491 if (new_session_dialog) {
492 if (new_session_dialog->engine_control.was_used()) {
493 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
496 Config->save_state();
498 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
499 XMLNode mnode(mixer->get_state());
502 session->add_instant_xml (enode, session->path());
503 session->add_instant_xml (mnode, session->path());
505 Config->add_instant_xml (enode, get_user_ardour_path());
506 Config->add_instant_xml (mnode, get_user_ardour_path());
513 ARDOUR_UI::autosave_session ()
515 if (!Config->get_periodic_safety_backups())
519 session->maybe_write_autosave();
526 ARDOUR_UI::update_autosave ()
528 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
530 if (session->dirty()) {
531 if (_autosave_connection.connected()) {
532 _autosave_connection.disconnect();
535 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
536 Config->get_periodic_safety_backup_interval() * 1000);
539 if (_autosave_connection.connected()) {
540 _autosave_connection.disconnect();
546 ARDOUR_UI::backend_audio_error ()
548 MessageDialog win (_("Ardour could not connect to JACK."),
551 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
552 win.set_secondary_text(_("There are several possible reasons:\n\
554 1) JACK is not running.\n\
555 2) JACK is running as another user, perhaps root.\n\
556 3) There is already another client called \"ardour\".\n\
558 Please consider the possibilities, and perhaps (re)start JACK."));
560 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
561 win.set_default_response (RESPONSE_CLOSE);
564 win.set_position (Gtk::WIN_POS_CENTER);
566 if (!ARDOUR_COMMAND_LINE::no_splash) {
570 /* we just don't care about the result, but we want to block */
576 ARDOUR_UI::startup ()
581 new_session_dialog = new NewSessionDialog();
583 /* If no session name is given: we're not loading a session yet, nor creating a new one */
585 if (ARDOUR_COMMAND_LINE::session_name.length()) {
587 /* Load session or start the new session dialog */
589 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
590 error << string_compose(_("could not load command line session \"%1\""),
591 ARDOUR_COMMAND_LINE::session_name) << endmsg;
595 if (!ARDOUR_COMMAND_LINE::new_session) {
597 /* Supposed to be loading an existing session, but the session doesn't exist */
600 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
601 "To create it from the command line, start ardour as \"ardour --new %1"), path)
607 new_session_dialog->set_session_name (name);
608 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
609 _session_is_new = isnew;
614 bool have_backend = EngineControl::engine_running();
616 bool load_needed = false;
620 /* backend audio is working */
622 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
623 /* need NSD to get session name and other info */
631 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
634 new_session_dialog->engine_control.set_state (*audio_setup);
637 /* no backend audio, must bring up NSD to check configuration */
644 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
656 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
665 ARDOUR_UI::no_memory_warning ()
667 XMLNode node (X_("no-memory-warning"));
668 Config->add_instant_xml (node, get_user_ardour_path());
672 ARDOUR_UI::check_memory_locking ()
675 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
679 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
681 if (engine->is_realtime() && memory_warning_node == 0) {
683 struct rlimit limits;
685 long pages, page_size;
687 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
690 ram = (int64_t) pages * (int64_t) page_size;
693 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
697 if (limits.rlim_cur != RLIM_INFINITY) {
699 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
702 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
703 "This might cause Ardour to run out of memory before your system "
704 "runs out of memory. \n\n"
705 "You can view the memory limit with 'ulimit -l', "
706 "and it is normally controlled by /etc/security/limits.conf"));
708 VBox* vbox = msg.get_vbox();
710 CheckButton cb (_("Do not show this window again"));
712 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
714 hbox.pack_start (cb, true, false);
715 vbox->pack_start (hbox);
729 if (session && session->dirty()) {
730 switch (ask_about_saving_session(_("quit"))) {
735 /* use the default name */
736 if (save_state_canfail ("")) {
737 /* failed - don't quit */
738 MessageDialog msg (*editor,
740 Ardour was unable to save your session.\n\n\
741 If you still wish to quit, please use the\n\n\
742 \"Just quit\" option."));
753 session->set_deletion_in_progress ();
756 save_ardour_state ();
761 ARDOUR_UI::ask_about_saving_session (const string & what)
763 ArdourDialog window (_("ardour: save session?"));
764 Gtk::HBox dhbox; // the hbox for the image and text
765 Gtk::Label prompt_label;
766 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
770 msg = string_compose(_("Don't %1"), what);
771 window.add_button (msg, RESPONSE_REJECT);
772 msg = string_compose(_("Just %1"), what);
773 window.add_button (msg, RESPONSE_APPLY);
774 msg = string_compose(_("Save and %1"), what);
775 window.add_button (msg, RESPONSE_ACCEPT);
777 window.set_default_response (RESPONSE_ACCEPT);
779 Gtk::Button noquit_button (msg);
780 noquit_button.set_name ("EditorGTKButton");
785 if (session->snap_name() == session->name()) {
788 type = _("snapshot");
790 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?"),
791 type, session->snap_name());
793 prompt_label.set_text (prompt);
794 prompt_label.set_name (X_("PrompterLabel"));
795 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
797 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
799 dhbox.set_homogeneous (false);
800 dhbox.pack_start (*dimage, false, false, 5);
801 dhbox.pack_start (prompt_label, true, false, 5);
802 window.get_vbox()->pack_start (dhbox);
804 window.set_name (_("Prompter"));
805 window.set_position (Gtk::WIN_POS_MOUSE);
806 window.set_modal (true);
807 window.set_resizable (false);
810 save_the_session = 0;
812 window.set_keep_above (true);
815 ResponseType r = (ResponseType) window.run();
820 case RESPONSE_ACCEPT: // save and get out of here
822 case RESPONSE_APPLY: // get out of here
832 ARDOUR_UI::every_second ()
835 update_buffer_load ();
836 update_disk_space ();
841 ARDOUR_UI::every_point_one_seconds ()
843 update_speed_display ();
844 RapidScreenUpdate(); /* EMIT_SIGNAL */
849 ARDOUR_UI::every_point_zero_one_seconds ()
851 // august 2007: actual update frequency: 40Hz, not 100Hz
853 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
858 ARDOUR_UI::update_sample_rate (nframes_t ignored)
862 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
864 if (!engine->connected()) {
866 snprintf (buf, sizeof (buf), _("disconnected"));
870 nframes_t rate = engine->frame_rate();
872 if (fmod (rate, 1000.0) != 0.0) {
873 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
874 (float) rate/1000.0f,
875 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
877 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
879 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
883 sample_rate_label.set_text (buf);
887 ARDOUR_UI::update_cpu_load ()
890 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
891 cpu_load_label.set_text (buf);
895 ARDOUR_UI::update_buffer_load ()
900 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
901 session->playback_load(), session->capture_load());
902 buffer_load_label.set_text (buf);
904 buffer_load_label.set_text ("");
909 ARDOUR_UI::count_recenabled_streams (Route& route)
911 Track* track = dynamic_cast<Track*>(&route);
912 if (track && track->diskstream()->record_enabled()) {
913 rec_enabled_streams += track->n_inputs();
918 ARDOUR_UI::update_disk_space()
924 nframes_t frames = session->available_capture_duration();
927 if (frames == max_frames) {
928 strcpy (buf, _("Disk: 24hrs+"));
933 nframes_t fr = session->frame_rate();
935 rec_enabled_streams = 0;
936 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
938 if (rec_enabled_streams) {
939 frames /= rec_enabled_streams;
942 hrs = frames / (fr * 3600);
943 frames -= hrs * fr * 3600;
944 mins = frames / (fr * 60);
945 frames -= mins * fr * 60;
948 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
951 disk_space_label.set_text (buf);
955 ARDOUR_UI::update_wall_clock ()
962 tm_now = localtime (&now);
964 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
965 wall_clock_label.set_text (buf);
971 ARDOUR_UI::session_menu (GdkEventButton *ev)
973 session_popup_menu->popup (0, 0);
978 ARDOUR_UI::redisplay_recent_sessions ()
980 vector<string *> *sessions;
981 vector<string *>::iterator i;
982 RecentSessionsSorter cmp;
984 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
985 recent_session_model->clear ();
988 ARDOUR::read_recent_sessions (rs);
991 recent_session_display.set_model (recent_session_model);
995 /* sort them alphabetically */
996 sort (rs.begin(), rs.end(), cmp);
997 sessions = new vector<string*>;
999 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1000 sessions->push_back (new string ((*i).second));
1003 for (i = sessions->begin(); i != sessions->end(); ++i) {
1005 vector<string*>* states;
1006 vector<const gchar*> item;
1007 string fullpath = *(*i);
1009 /* remove any trailing / */
1011 if (fullpath[fullpath.length()-1] == '/') {
1012 fullpath = fullpath.substr (0, fullpath.length()-1);
1015 /* now get available states for this session */
1017 if ((states = Session::possible_states (fullpath)) == 0) {
1018 /* no state file? */
1022 TreeModel::Row row = *(recent_session_model->append());
1024 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1025 row[recent_session_columns.fullpath] = fullpath;
1027 if (states->size() > 1) {
1029 /* add the children */
1031 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1033 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1035 child_row[recent_session_columns.visible_name] = **i2;
1036 child_row[recent_session_columns.fullpath] = fullpath;
1045 recent_session_display.set_model (recent_session_model);
1050 ARDOUR_UI::build_session_selector ()
1052 session_selector_window = new ArdourDialog ("session selector");
1054 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1056 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1057 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1058 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1059 recent_session_model = TreeStore::create (recent_session_columns);
1060 recent_session_display.set_model (recent_session_model);
1061 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1062 recent_session_display.set_headers_visible (false);
1063 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1065 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1067 scroller->add (recent_session_display);
1068 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1070 session_selector_window->set_name ("SessionSelectorWindow");
1071 session_selector_window->set_size_request (200, 400);
1072 session_selector_window->get_vbox()->pack_start (*scroller);
1073 session_selector_window->show_all_children();
1077 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1079 session_selector_window->response (RESPONSE_ACCEPT);
1083 ARDOUR_UI::open_recent_session ()
1085 /* popup selector window */
1087 if (session_selector_window == 0) {
1088 build_session_selector ();
1091 redisplay_recent_sessions ();
1093 ResponseType r = (ResponseType) session_selector_window->run ();
1095 session_selector_window->hide();
1098 case RESPONSE_ACCEPT:
1104 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1106 if (i == recent_session_model->children().end()) {
1110 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1111 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1113 _session_is_new = false;
1115 load_session (path, state);
1119 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1121 struct stat statbuf;
1123 if (stat (info.filename.c_str(), &statbuf) != 0) {
1127 if (!S_ISDIR(statbuf.st_mode)) {
1133 string session_file = info.filename;
1134 session_file += '/';
1135 session_file += Glib::path_get_basename (info.filename);
1136 session_file += ".ardour";
1138 if (stat (session_file.c_str(), &statbuf) != 0) {
1142 return S_ISREG (statbuf.st_mode);
1146 ARDOUR_UI::check_audioengine ()
1149 if (!engine->connected()) {
1150 MessageDialog msg (_("Ardour is not connected to JACK\n"
1151 "You cannot open or close sessions in this condition"));
1162 ARDOUR_UI::open_session ()
1164 if (!check_audioengine()) {
1168 /* popup selector window */
1170 if (open_session_selector == 0) {
1172 /* ardour sessions are folders */
1174 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1175 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1176 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1177 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1179 FileFilter session_filter;
1180 session_filter.add_pattern ("*.ardour");
1181 session_filter.set_name (_("Ardour sessions"));
1182 open_session_selector->add_filter (session_filter);
1183 open_session_selector->set_filter (session_filter);
1186 int response = open_session_selector->run();
1187 open_session_selector->hide ();
1190 case RESPONSE_ACCEPT:
1193 open_session_selector->hide();
1197 open_session_selector->hide();
1198 string session_path = open_session_selector->get_filename();
1202 if (session_path.length() > 0) {
1203 if (Session::find_session (session_path, path, name, isnew) == 0) {
1204 _session_is_new = isnew;
1205 load_session (path, name);
1212 ARDOUR_UI::session_add_midi_track ()
1214 cerr << _("Patience is a virtue.\n");
1218 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1220 list<boost::shared_ptr<AudioTrack> > tracks;
1221 Session::RouteList routes;
1224 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1230 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1232 if (tracks.size() != how_many) {
1233 if (how_many == 1) {
1234 error << _("could not create a new audio track") << endmsg;
1236 error << string_compose (_("could only create %1 of %2 new audio %3"),
1237 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1243 routes = session->new_audio_route (input_channels, output_channels, how_many);
1245 if (routes.size() != how_many) {
1246 if (how_many == 1) {
1247 error << _("could not create a new audio track") << endmsg;
1249 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1255 if (need_control_room_outs) {
1261 route->set_stereo_control_outs (control_lr_channels);
1262 route->control_outs()->set_stereo_pan (pans, this);
1264 #endif /* CONTROLOUTS */
1268 cerr << "About to complain about JACK\n";
1269 MessageDialog msg (*editor,
1270 _("There are insufficient JACK ports available\n\
1271 to create a new track or bus.\n\
1272 You should save Ardour, exit and\n\
1273 restart JACK with more ports."));
1279 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1281 nframes_t _preroll = 0;
1284 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1285 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1287 if (new_position > _preroll) {
1288 new_position -= _preroll;
1293 session->request_locate (new_position);
1298 ARDOUR_UI::transport_goto_start ()
1301 session->goto_start();
1304 /* force displayed area in editor to start no matter
1305 what "follow playhead" setting is.
1309 editor->reset_x_origin (session->current_start_frame());
1315 ARDOUR_UI::transport_goto_zero ()
1318 session->request_locate (0);
1321 /* force displayed area in editor to start no matter
1322 what "follow playhead" setting is.
1326 editor->reset_x_origin (0);
1332 ARDOUR_UI::transport_goto_end ()
1335 nframes_t frame = session->current_end_frame();
1336 session->request_locate (frame);
1338 /* force displayed area in editor to start no matter
1339 what "follow playhead" setting is.
1343 editor->reset_x_origin (frame);
1349 ARDOUR_UI::transport_stop ()
1355 if (session->is_auditioning()) {
1356 session->cancel_audition ();
1360 if (session->get_play_loop ()) {
1361 session->request_play_loop (false);
1364 session->request_stop ();
1368 ARDOUR_UI::transport_stop_and_forget_capture ()
1371 session->request_stop (true);
1376 ARDOUR_UI::remove_last_capture()
1379 editor->remove_last_capture();
1384 ARDOUR_UI::transport_record ()
1387 switch (session->record_status()) {
1388 case Session::Disabled:
1389 if (session->ntracks() == 0) {
1390 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1394 session->maybe_enable_record ();
1396 case Session::Recording:
1397 case Session::Enabled:
1398 session->disable_record (false, true);
1404 ARDOUR_UI::transport_roll ()
1412 rolling = session->transport_rolling ();
1414 if (session->get_play_loop()) {
1415 session->request_play_loop (false);
1416 auto_loop_button.set_visual_state (1);
1417 roll_button.set_visual_state (1);
1418 } else if (session->get_play_range ()) {
1419 session->request_play_range (false);
1420 play_selection_button.set_visual_state (0);
1421 } else if (rolling) {
1422 session->request_locate (session->last_transport_start(), true);
1425 session->request_transport_speed (1.0f);
1429 ARDOUR_UI::transport_loop()
1432 if (session->get_play_loop()) {
1433 if (session->transport_rolling()) {
1434 Location * looploc = session->locations()->auto_loop_location();
1436 session->request_locate (looploc->start(), true);
1441 session->request_play_loop (true);
1447 ARDOUR_UI::transport_play_selection ()
1453 if (!session->get_play_range()) {
1454 session->request_stop ();
1457 editor->play_selection ();
1461 ARDOUR_UI::transport_rewind (int option)
1463 float current_transport_speed;
1466 current_transport_speed = session->transport_speed();
1468 if (current_transport_speed >= 0.0f) {
1471 session->request_transport_speed (-1.0f);
1474 session->request_transport_speed (-4.0f);
1477 session->request_transport_speed (-0.5f);
1482 session->request_transport_speed (current_transport_speed * 1.5f);
1488 ARDOUR_UI::transport_forward (int option)
1490 float current_transport_speed;
1493 current_transport_speed = session->transport_speed();
1495 if (current_transport_speed <= 0.0f) {
1498 session->request_transport_speed (1.0f);
1501 session->request_transport_speed (4.0f);
1504 session->request_transport_speed (0.5f);
1509 session->request_transport_speed (current_transport_speed * 1.5f);
1515 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1521 boost::shared_ptr<Route> r;
1523 if ((r = session->route_by_remote_id (dstream)) != 0) {
1527 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1528 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1537 ARDOUR_UI::queue_transport_change ()
1539 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1543 ARDOUR_UI::map_transport_state ()
1545 float sp = session->transport_speed();
1548 transport_rolling ();
1549 } else if (sp < 0.0f) {
1550 transport_rewinding ();
1551 } else if (sp > 0.0f) {
1552 transport_forwarding ();
1554 transport_stopped ();
1559 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1561 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1562 (int) adj.get_value()].c_str());
1566 ARDOUR_UI::engine_stopped ()
1568 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1569 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1570 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1574 ARDOUR_UI::engine_running ()
1576 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1577 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1578 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1580 Glib::RefPtr<Action> action;
1581 char* action_name = 0;
1583 switch (engine->frames_per_cycle()) {
1585 action_name = X_("JACKLatency32");
1588 action_name = X_("JACKLatency64");
1591 action_name = X_("JACKLatency128");
1594 action_name = X_("JACKLatency512");
1597 action_name = X_("JACKLatency1024");
1600 action_name = X_("JACKLatency2048");
1603 action_name = X_("JACKLatency4096");
1606 action_name = X_("JACKLatency8192");
1609 /* XXX can we do anything useful ? */
1615 action = ActionManager::get_action (X_("JACK"), action_name);
1618 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1619 ract->set_active ();
1625 ARDOUR_UI::engine_halted ()
1627 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1629 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1630 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1632 update_sample_rate (0);
1634 MessageDialog msg (*editor,
1636 JACK has either been shutdown or it\n\
1637 disconnected Ardour because Ardour\n\
1638 was not fast enough. You can save the\n\
1639 session and/or try to reconnect to JACK ."));
1644 ARDOUR_UI::do_engine_start ()
1652 error << _("Unable to start the session running")
1662 ARDOUR_UI::setup_theme ()
1664 theme_manager->setup_theme();
1668 ARDOUR_UI::update_clocks ()
1670 if (!editor || !editor->dragging_playhead()) {
1671 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1676 ARDOUR_UI::start_clocking ()
1678 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1682 ARDOUR_UI::stop_clocking ()
1684 clock_signal_connection.disconnect ();
1688 ARDOUR_UI::toggle_clocking ()
1691 if (clock_button.get_active()) {
1700 ARDOUR_UI::_blink (void *arg)
1703 ((ARDOUR_UI *) arg)->blink ();
1710 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1714 ARDOUR_UI::start_blinking ()
1716 /* Start the blink signal. Everybody with a blinking widget
1717 uses Blink to drive the widget's state.
1720 if (blink_timeout_tag < 0) {
1722 blink_timeout_tag = g_timeout_add (240, _blink, this);
1727 ARDOUR_UI::stop_blinking ()
1729 if (blink_timeout_tag >= 0) {
1730 g_source_remove (blink_timeout_tag);
1731 blink_timeout_tag = -1;
1736 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1742 if (io.n_inputs() == 0) {
1747 /* XXX we're not handling multiple ports yet. */
1749 const char **connections = io.input(0)->get_connections();
1751 if (connections == 0 || connections[0] == '\0') {
1754 buf = connections[0];
1761 if (io.n_outputs() == 0) {
1766 /* XXX we're not handling multiple ports yet. */
1768 const char **connections = io.output(0)->get_connections();
1770 if (connections == 0 || connections[0] == '\0') {
1773 buf = connections[0];
1780 /** Ask the user for the name of a new shapshot and then take it.
1783 ARDOUR_UI::snapshot_session ()
1785 ArdourPrompter prompter (true);
1789 struct tm local_time;
1792 localtime_r (&n, &local_time);
1793 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1795 prompter.set_name ("Prompter");
1796 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1797 prompter.set_prompt (_("Name of New Snapshot"));
1798 prompter.set_initial_text (timebuf);
1800 switch (prompter.run()) {
1801 case RESPONSE_ACCEPT:
1802 prompter.get_result (snapname);
1803 if (snapname.length()){
1804 save_state (snapname);
1814 ARDOUR_UI::save_state (const string & name)
1816 (void) save_state_canfail (name);
1820 ARDOUR_UI::save_state_canfail (string name)
1825 if (name.length() == 0) {
1826 name = session->snap_name();
1829 if ((ret = session->save_state (name)) != 0) {
1833 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1838 ARDOUR_UI::restore_state (string name)
1841 if (name.length() == 0) {
1842 name = session->name();
1844 session->restore_state (name);
1849 ARDOUR_UI::primary_clock_value_changed ()
1852 session->request_locate (primary_clock.current_time ());
1857 ARDOUR_UI::secondary_clock_value_changed ()
1860 session->request_locate (secondary_clock.current_time ());
1865 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1867 if (session && dstream && dstream->record_enabled()) {
1869 Session::RecordState rs;
1871 rs = session->record_status ();
1874 case Session::Disabled:
1875 case Session::Enabled:
1876 if (w->get_state() != STATE_SELECTED) {
1877 w->set_state (STATE_SELECTED);
1881 case Session::Recording:
1882 if (w->get_state() != STATE_ACTIVE) {
1883 w->set_state (STATE_ACTIVE);
1889 if (w->get_state() != STATE_NORMAL) {
1890 w->set_state (STATE_NORMAL);
1896 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1902 switch (session->record_status()) {
1903 case Session::Enabled:
1905 rec_button.set_visual_state (2);
1907 rec_button.set_visual_state (0);
1911 case Session::Recording:
1912 rec_button.set_visual_state (1);
1916 rec_button.set_visual_state (0);
1922 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1930 ARDOUR_UI::save_template ()
1933 ArdourPrompter prompter (true);
1936 if (!check_audioengine()) {
1940 prompter.set_name (X_("Prompter"));
1941 prompter.set_prompt (_("Name for mix template:"));
1942 prompter.set_initial_text(session->name() + _("-template"));
1943 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1945 switch (prompter.run()) {
1946 case RESPONSE_ACCEPT:
1947 prompter.get_result (name);
1949 if (name.length()) {
1950 session->save_template (name);
1960 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
1962 string session_name;
1963 string session_path;
1964 string template_name;
1966 if (!loading_dialog) {
1967 loading_dialog = new MessageDialog (*new_session_dialog,
1968 _("Starting audio engine"),
1974 int response = Gtk::RESPONSE_NONE;
1976 new_session_dialog->set_modal(true);
1977 new_session_dialog->set_name (predetermined_path);
1978 new_session_dialog->reset_recent();
1979 new_session_dialog->set_position (WIN_POS_CENTER);
1980 new_session_dialog->show();
1981 new_session_dialog->present ();
1982 new_session_dialog->set_current_page (0);
1986 new_session_dialog->set_have_engine (have_engine);
1988 response = new_session_dialog->run ();
1990 _session_is_new = false;
1992 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1997 new_session_dialog->hide ();
2000 } else if (response == Gtk::RESPONSE_NONE) {
2002 /* Clear was pressed */
2003 new_session_dialog->reset();
2007 /* first things first ... we need an audio engine running */
2010 if (start_backend_audio ()) {
2011 new_session_dialog->hide ();
2017 loading_dialog->show_all ();
2022 /* now handle possible affirmative responses */
2024 if (response == Gtk::RESPONSE_YES) {
2026 /* YES == OPEN from the session selector */
2028 session_name = new_session_dialog->session_name();
2030 if (session_name.empty()) {
2031 response = Gtk::RESPONSE_NONE;
2035 if (session_name[0] == '/' ||
2036 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2037 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2038 load_session (Glib::path_get_dirname (session_name), session_name);
2040 session_path = new_session_dialog->session_folder();
2041 load_session (session_path, session_name);
2044 } else if (response == Gtk::RESPONSE_OK) {
2046 /* OK == OPEN button */
2048 session_name = new_session_dialog->session_name();
2050 if (session_name.empty()) {
2051 response = Gtk::RESPONSE_NONE;
2055 switch (new_session_dialog->get_current_page()) {
2056 case 1: /* recent session selector */
2057 case 2: /* audio engine control */
2059 if (session_name[0] == '/' ||
2060 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2061 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2062 load_session (Glib::path_get_dirname (session_name), session_name);
2064 session_path = new_session_dialog->session_folder();
2065 load_session (session_path, session_name);
2069 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2071 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2072 should_be_new = true;
2075 /* handle what appear to be paths rather than just a name */
2077 if (session_name[0] == '/' ||
2078 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2079 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2081 session_path = Glib::path_get_dirname (session_name);
2082 session_name = Glib::path_get_basename (session_name);
2086 session_path = new_session_dialog->session_folder();
2090 //XXX This is needed because session constructor wants a
2091 //non-existant path. hopefully this will be fixed at some point.
2093 session_path = Glib::build_filename (session_path, session_name);
2095 if (!should_be_new) {
2097 load_session (session_path, session_name);
2098 continue; /* leaves while() loop because response != NONE */
2100 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2102 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2104 MessageDialog msg (str,
2106 Gtk::MESSAGE_WARNING,
2107 Gtk::BUTTONS_YES_NO,
2111 msg.set_name (X_("CleanupDialog"));
2112 msg.set_wmclass (X_("existing_session"), "Ardour");
2113 msg.set_position (Gtk::WIN_POS_MOUSE);
2115 switch (msg.run()) {
2117 new_session_dialog->hide ();
2118 goto_editor_window ();
2120 load_session (session_path, session_name);
2124 response = RESPONSE_NONE;
2125 new_session_dialog->reset ();
2130 _session_is_new = true;
2132 if (new_session_dialog->use_session_template()) {
2134 template_name = new_session_dialog->session_template_name();
2136 new_session_dialog->hide ();
2137 goto_editor_window ();
2140 load_session (session_path, session_name, &template_name);
2146 AutoConnectOption iconnect;
2147 AutoConnectOption oconnect;
2151 if (Profile->get_sae()) {
2155 iconnect = AutoConnectPhysical;
2156 oconnect = AutoConnectMaster;
2157 nphysin = 0; // use all available
2158 nphysout = 0; // use all available
2162 /* get settings from advanced section of NSD */
2164 if (new_session_dialog->create_control_bus()) {
2165 cchns = (uint32_t) new_session_dialog->control_channel_count();
2170 if (new_session_dialog->create_master_bus()) {
2171 mchns = (uint32_t) new_session_dialog->master_channel_count();
2176 if (new_session_dialog->connect_inputs()) {
2177 iconnect = AutoConnectPhysical;
2179 iconnect = AutoConnectOption (0);
2182 /// @todo some minor tweaks.
2184 if (new_session_dialog->connect_outs_to_master()) {
2185 oconnect = AutoConnectMaster;
2186 } else if (new_session_dialog->connect_outs_to_physical()) {
2187 oconnect = AutoConnectPhysical;
2189 oconnect = AutoConnectOption (0);
2192 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2193 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2196 new_session_dialog->hide ();
2197 goto_editor_window ();
2200 if (build_session (session_path,
2208 engine->frame_rate() * 60 * 5)) {
2210 response = Gtk::RESPONSE_NONE;
2211 new_session_dialog->reset ();
2222 } while (response == Gtk::RESPONSE_NONE);
2226 loading_dialog->hide ();
2227 new_session_dialog->hide();
2232 ARDOUR_UI::close_session ()
2234 if (!check_audioengine()) {
2238 unload_session (true);
2240 get_session_parameters ("", true, false);
2244 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2246 Session *new_session;
2250 session_loaded = false;
2252 if (!check_audioengine()) {
2256 unload_status = unload_session ();
2258 if (unload_status < 0) {
2260 } else if (unload_status > 0) {
2265 /* if it already exists, we must have write access */
2267 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2268 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2269 "This prevents the session from being loaded."));
2274 if (loading_dialog) {
2275 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2279 disable_screen_updates ();
2282 new_session = new Session (*engine, path, snap_name, mix_template);
2286 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2290 connect_to_session (new_session);
2292 Config->set_current_owner (ConfigVariableBase::Interface);
2294 session_loaded = true;
2296 goto_editor_window ();
2299 session->set_clean ();
2302 editor->edit_cursor_position (true);
2303 enable_screen_updates ();
2312 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2313 uint32_t control_channels,
2314 uint32_t master_channels,
2315 AutoConnectOption input_connect,
2316 AutoConnectOption output_connect,
2319 nframes_t initial_length)
2321 Session *new_session;
2324 if (!check_audioengine()) {
2328 session_loaded = false;
2330 x = unload_session ();
2338 _session_is_new = true;
2341 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2342 control_channels, master_channels, nphysin, nphysout, initial_length);
2347 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2352 connect_to_session (new_session);
2354 session_loaded = true;
2362 editor->show_window ();
2373 ARDOUR_UI::show_splash ()
2376 about = new About();
2377 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2384 ARDOUR_UI::about_signal_response(int response)
2390 ARDOUR_UI::hide_splash ()
2393 about->get_window()->set_cursor ();
2399 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2403 removed = rep.paths.size();
2406 MessageDialog msgd (*editor,
2407 _("No audio files were ready for cleanup"),
2410 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2411 msgd.set_secondary_text (_("If this seems suprising, \n\
2412 check for any existing snapshots.\n\
2413 These may still include regions that\n\
2414 require some unused files to continue to exist."));
2420 ArdourDialog results (_("ardour: cleanup"), true, false);
2422 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2423 CleanupResultsModelColumns() {
2427 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2428 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2432 CleanupResultsModelColumns results_columns;
2433 Glib::RefPtr<Gtk::ListStore> results_model;
2434 Gtk::TreeView results_display;
2436 results_model = ListStore::create (results_columns);
2437 results_display.set_model (results_model);
2438 results_display.append_column (list_title, results_columns.visible_name);
2440 results_display.set_name ("CleanupResultsList");
2441 results_display.set_headers_visible (true);
2442 results_display.set_headers_clickable (false);
2443 results_display.set_reorderable (false);
2445 Gtk::ScrolledWindow list_scroller;
2448 Gtk::HBox dhbox; // the hbox for the image and text
2449 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2450 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2452 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2454 if (rep.space < 1048576.0f) {
2456 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2458 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2462 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2464 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2468 dhbox.pack_start (*dimage, true, false, 5);
2469 dhbox.pack_start (txt, true, false, 5);
2471 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2472 TreeModel::Row row = *(results_model->append());
2473 row[results_columns.visible_name] = *i;
2474 row[results_columns.fullpath] = *i;
2477 list_scroller.add (results_display);
2478 list_scroller.set_size_request (-1, 150);
2479 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2481 dvbox.pack_start (dhbox, true, false, 5);
2482 dvbox.pack_start (list_scroller, true, false, 5);
2483 ddhbox.pack_start (dvbox, true, false, 5);
2485 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2486 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2487 results.set_default_response (RESPONSE_CLOSE);
2488 results.set_position (Gtk::WIN_POS_MOUSE);
2489 results.show_all_children ();
2490 results.set_resizable (false);
2497 ARDOUR_UI::cleanup ()
2500 /* shouldn't happen: menu item is insensitive */
2505 MessageDialog checker (_("Are you sure you want to cleanup?"),
2507 Gtk::MESSAGE_QUESTION,
2508 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2510 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2511 ALL undo/redo information will be lost if you cleanup.\n\
2512 After cleanup, unused audio files will be moved to a \
2513 \"dead sounds\" location."));
2515 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2516 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2517 checker.set_default_response (RESPONSE_CANCEL);
2519 checker.set_name (_("CleanupDialog"));
2520 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2521 checker.set_position (Gtk::WIN_POS_MOUSE);
2523 switch (checker.run()) {
2524 case RESPONSE_ACCEPT:
2530 Session::cleanup_report rep;
2532 editor->prepare_for_cleanup ();
2534 /* do not allow flush until a session is reloaded */
2536 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2538 act->set_sensitive (false);
2541 if (session->cleanup_sources (rep)) {
2546 display_cleanup_results (rep,
2549 The following %1 %2 not in use and \n\
2550 have been moved to:\n\
2552 Flushing the wastebasket will \n\
2553 release an additional\n\
2554 %4 %5bytes of disk space.\n"
2562 ARDOUR_UI::flush_trash ()
2565 /* shouldn't happen: menu item is insensitive */
2569 Session::cleanup_report rep;
2571 if (session->cleanup_trash_sources (rep)) {
2575 display_cleanup_results (rep,
2577 _("The following %1 %2 deleted from\n\
2579 releasing %4 %5bytes of disk space"));
2583 ARDOUR_UI::add_route (Gtk::Window* float_window)
2591 if (add_route_dialog == 0) {
2592 add_route_dialog = new AddRouteDialog;
2594 add_route_dialog->set_transient_for (*float_window);
2598 if (add_route_dialog->is_visible()) {
2599 /* we're already doing this */
2603 ResponseType r = (ResponseType) add_route_dialog->run ();
2605 add_route_dialog->hide();
2608 case RESPONSE_ACCEPT:
2615 if ((count = add_route_dialog->count()) <= 0) {
2619 uint32_t input_chan = add_route_dialog->channels ();
2620 uint32_t output_chan;
2621 string name_template = add_route_dialog->name_template ();
2622 bool track = add_route_dialog->track ();
2624 AutoConnectOption oac = Config->get_output_auto_connect();
2626 if (oac & AutoConnectMaster) {
2627 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2629 output_chan = input_chan;
2632 /* XXX do something with name template */
2635 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2637 session_add_audio_bus (input_chan, output_chan, count);
2642 ARDOUR_UI::mixer_settings () const
2647 node = session->instant_xml(X_("Mixer"), session->path());
2649 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2653 node = new XMLNode (X_("Mixer"));
2660 ARDOUR_UI::editor_settings () const
2665 node = session->instant_xml(X_("Editor"), session->path());
2667 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2671 node = new XMLNode (X_("Editor"));
2677 ARDOUR_UI::keyboard_settings () const
2681 node = Config->extra_xml(X_("Keyboard"));
2684 node = new XMLNode (X_("Keyboard"));
2690 ARDOUR_UI::halt_on_xrun_message ()
2692 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2694 MessageDialog msg (*editor,
2695 _("Recording was stopped because your system could not keep up."));
2700 ARDOUR_UI::disk_overrun_handler ()
2702 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2704 if (!have_disk_speed_dialog_displayed) {
2705 have_disk_speed_dialog_displayed = true;
2706 MessageDialog* msg = new MessageDialog (*editor, _("\
2707 The disk system on your computer\n\
2708 was not able to keep up with Ardour.\n\
2710 Specifically, it failed to write data to disk\n\
2711 quickly enough to keep up with recording.\n"));
2712 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2718 ARDOUR_UI::disk_underrun_handler ()
2720 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2722 if (!have_disk_speed_dialog_displayed) {
2723 have_disk_speed_dialog_displayed = true;
2724 MessageDialog* msg = new MessageDialog (*editor,
2725 _("The disk system on your computer\n\
2726 was not able to keep up with Ardour.\n\
2728 Specifically, it failed to read data from disk\n\
2729 quickly enough to keep up with playback.\n"));
2730 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2736 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2738 have_disk_speed_dialog_displayed = false;
2743 ARDOUR_UI::pending_state_dialog ()
2745 ArdourDialog dialog ("pending state dialog");
2747 This session appears to have been in\n\
2748 middle of recording when ardour or\n\
2749 the computer was shutdown.\n\
2751 Ardour can recover any captured audio for\n\
2752 you, or it can ignore it. Please decide\n\
2753 what you would like to do.\n"));
2755 dialog.get_vbox()->pack_start (message);
2756 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2757 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2759 dialog.set_position (WIN_POS_CENTER);
2762 switch (dialog.run ()) {
2763 case RESPONSE_ACCEPT:
2771 ARDOUR_UI::disconnect_from_jack ()
2774 if( engine->disconnect_from_jack ()) {
2775 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2779 update_sample_rate (0);
2784 ARDOUR_UI::reconnect_to_jack ()
2787 if (engine->reconnect_to_jack ()) {
2788 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2792 update_sample_rate (0);
2797 ARDOUR_UI::cmdline_new_session (string path)
2799 if (path[0] != '/') {
2800 char buf[PATH_MAX+1];
2803 getcwd (buf, sizeof (buf));
2810 get_session_parameters (path, false, true);
2812 _will_create_new_session_automatically = false; /* done it */
2813 return FALSE; /* don't call it again */
2817 ARDOUR_UI::use_config ()
2819 Glib::RefPtr<Action> act;
2821 switch (Config->get_native_file_data_format ()) {
2823 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2826 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2829 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2834 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2835 ract->set_active ();
2838 switch (Config->get_native_file_header_format ()) {
2840 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2843 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2846 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2849 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2852 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2855 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2858 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2863 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2864 ract->set_active ();
2867 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2869 set_transport_controllable_state (*node);
2874 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2876 if (Config->get_primary_clock_delta_edit_cursor()) {
2877 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2879 primary_clock.set (pos, 0, true);
2882 if (Config->get_secondary_clock_delta_edit_cursor()) {
2883 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2885 secondary_clock.set (pos);
2888 if (big_clock_window) {
2889 big_clock.set (pos);
2894 ARDOUR_UI::record_state_changed ()
2896 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2898 if (!session || !big_clock_window) {
2899 /* why bother - the clock isn't visible */
2903 switch (session->record_status()) {
2904 case Session::Recording:
2905 big_clock.set_widget_name ("BigClockRecording");
2908 big_clock.set_widget_name ("BigClockNonRecording");
2914 ARDOUR_UI::set_keybindings_path (string path)
2916 keybindings_path = path;
2920 ARDOUR_UI::save_keybindings ()
2922 if (can_save_keybindings) {
2923 AccelMap::save (user_keybindings_path);
2928 ARDOUR_UI::first_idle ()
2931 session->allow_auto_play (true);
2933 can_save_keybindings = true;
2938 ARDOUR_UI::store_clock_modes ()
2940 XMLNode* node = new XMLNode(X_("ClockModes"));
2942 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2943 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2946 session->add_extra_xml (*node);
2947 session->set_dirty ();
2952 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2953 : Controllable (name), ui (u), type(tp)
2959 ARDOUR_UI::TransportControllable::set_value (float val)
2961 if (type == ShuttleControl) {
2968 fract = -((0.5f - val)/0.5f);
2970 fract = ((val - 0.5f)/0.5f);
2974 ui.set_shuttle_fract (fract);
2979 /* do nothing: these are radio-style actions */
2987 action = X_("Roll");
2990 action = X_("Stop");
2993 action = X_("Goto Start");
2996 action = X_("Goto End");
2999 action = X_("Loop");
3002 action = X_("Play Selection");
3005 action = X_("Record");
3015 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3023 ARDOUR_UI::TransportControllable::get_value (void) const
3042 case ShuttleControl:
3052 ARDOUR_UI::TransportControllable::set_id (const string& str)
3058 ARDOUR_UI::setup_profile ()
3060 if (gdk_screen_width() < 1200) {
3061 Profile->set_small_screen ();
3064 if (getenv ("ARDOUR_SAE")) {
3065 Profile->set_sae ();
3066 Profile->set_single_package ();
3071 ARDOUR_UI::audioengine_setup ()