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", true, false, true),
122 roll_controllable ("transport roll", *this, TransportControllable::Roll),
123 stop_controllable ("transport stop", *this, TransportControllable::Stop),
124 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
125 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
126 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
127 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
128 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
129 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
130 shuttle_controller_binding_proxy (shuttle_controllable),
132 roll_button (roll_controllable),
133 stop_button (stop_controllable),
134 goto_start_button (goto_start_controllable),
135 goto_end_button (goto_end_controllable),
136 auto_loop_button (auto_loop_controllable),
137 play_selection_button (play_selection_controllable),
138 rec_button (rec_controllable),
140 shuttle_units_button (_("% ")),
142 punch_in_button (_("Punch In")),
143 punch_out_button (_("Punch Out")),
144 auto_return_button (_("Auto Return")),
145 auto_play_button (_("Auto Play")),
146 auto_input_button (_("Auto Input")),
147 click_button (_("Click")),
148 time_master_button (_("time\nmaster")),
150 auditioning_alert_button (_("AUDITION")),
151 solo_alert_button (_("SOLO")),
153 error_log_button (_("Errors"))
155 using namespace Gtk::Menu_Helpers;
160 _auto_display_errors = false;
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;
191 open_session_selector = 0;
192 have_configure_timeout = false;
193 have_disk_speed_dialog_displayed = false;
194 _will_create_new_session_automatically = false;
195 session_loaded = false;
197 last_speed_displayed = -1.0f;
199 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
200 /* all changes go to the user directory */
201 user_keybindings_path = get_user_ardour_path ();
202 user_keybindings_path += '/';
203 user_keybindings_path += "ardour.bindings";
205 can_save_keybindings = false;
207 last_configure_time.tv_sec = 0;
208 last_configure_time.tv_usec = 0;
210 shuttle_grabbed = false;
212 shuttle_max_speed = 8.0f;
214 shuttle_style_menu = 0;
215 shuttle_unit_menu = 0;
217 gettimeofday (&last_peak_grab, 0);
218 gettimeofday (&last_shuttle_request, 0);
220 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
221 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
223 /* handle pending state with a dialog */
225 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
227 /* lets get this party started */
230 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
231 setup_gtk_ardour_enums ();
232 Config->set_current_owner (ConfigVariableBase::Interface);
235 } catch (failed_constructor& err) {
236 error << _("could not initialize Ardour.") << endmsg;
241 /* we like keyboards */
243 keyboard = new Keyboard;
245 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
246 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
250 ARDOUR_UI::create_engine ()
252 // this gets called every time by new_session()
259 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
266 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
267 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
268 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
269 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
277 ARDOUR_UI::post_engine ()
279 /* Things to be done once we create the AudioEngine
282 check_memory_locking();
284 ActionManager::init ();
287 if (setup_windows ()) {
288 throw failed_constructor ();
291 /* this is the first point at which all the keybindings are available */
293 if (ARDOUR_COMMAND_LINE::show_key_actions) {
294 vector<string> names;
295 vector<string> paths;
297 vector<AccelKey> bindings;
299 ActionManager::get_all_actions (names, paths, keys, bindings);
301 vector<string>::iterator n;
302 vector<string>::iterator k;
303 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
304 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
310 blink_timeout_tag = -1;
312 /* the global configuration object is now valid */
316 /* this being a GUI and all, we want peakfiles */
318 AudioFileSource::set_build_peakfiles (true);
319 AudioFileSource::set_build_missing_peakfiles (true);
321 /* set default clock modes */
323 primary_clock.set_mode (AudioClock::SMPTE);
324 secondary_clock.set_mode (AudioClock::BBT);
326 /* start the time-of-day-clock */
329 /* OS X provides an always visible wallclock, so don't be stupid */
330 update_wall_clock ();
331 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
334 update_disk_space ();
336 update_sample_rate (engine->frame_rate());
338 platform_specific ();
340 /* now start and maybe save state */
342 if (do_engine_start () == 0) {
343 if (session && _session_is_new) {
344 /* we need to retain initial visual
345 settings for a new session
347 session->save_state ("");
352 ARDOUR_UI::~ARDOUR_UI ()
354 save_ardour_state ();
368 if (add_route_dialog) {
369 delete add_route_dialog;
372 if (new_session_dialog) {
373 delete new_session_dialog;
378 ARDOUR_UI::configure_timeout ()
383 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
384 /* no configure events yet */
388 gettimeofday (&now, 0);
389 timersub (&now, &last_configure_time, &diff);
391 /* force a gap of 0.5 seconds since the last configure event
394 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
397 have_configure_timeout = false;
398 save_ardour_state ();
404 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
406 if (have_configure_timeout) {
407 gettimeofday (&last_configure_time, 0);
409 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
410 have_configure_timeout = true;
417 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
419 const XMLProperty* prop;
421 if ((prop = node.property ("roll")) != 0) {
422 roll_controllable.set_id (prop->value());
424 if ((prop = node.property ("stop")) != 0) {
425 stop_controllable.set_id (prop->value());
427 if ((prop = node.property ("goto_start")) != 0) {
428 goto_start_controllable.set_id (prop->value());
430 if ((prop = node.property ("goto_end")) != 0) {
431 goto_end_controllable.set_id (prop->value());
433 if ((prop = node.property ("auto_loop")) != 0) {
434 auto_loop_controllable.set_id (prop->value());
436 if ((prop = node.property ("play_selection")) != 0) {
437 play_selection_controllable.set_id (prop->value());
439 if ((prop = node.property ("rec")) != 0) {
440 rec_controllable.set_id (prop->value());
442 if ((prop = node.property ("shuttle")) != 0) {
443 shuttle_controllable.set_id (prop->value());
448 ARDOUR_UI::get_transport_controllable_state ()
450 XMLNode* node = new XMLNode(X_("TransportControllables"));
453 roll_controllable.id().print (buf, sizeof (buf));
454 node->add_property (X_("roll"), buf);
455 stop_controllable.id().print (buf, sizeof (buf));
456 node->add_property (X_("stop"), buf);
457 goto_start_controllable.id().print (buf, sizeof (buf));
458 node->add_property (X_("goto_start"), buf);
459 goto_end_controllable.id().print (buf, sizeof (buf));
460 node->add_property (X_("goto_end"), buf);
461 auto_loop_controllable.id().print (buf, sizeof (buf));
462 node->add_property (X_("auto_loop"), buf);
463 play_selection_controllable.id().print (buf, sizeof (buf));
464 node->add_property (X_("play_selection"), buf);
465 rec_controllable.id().print (buf, sizeof (buf));
466 node->add_property (X_("rec"), buf);
467 shuttle_controllable.id().print (buf, sizeof (buf));
468 node->add_property (X_("shuttle"), buf);
474 ARDOUR_UI::save_ardour_state ()
476 if (!keyboard || !mixer || !editor) {
480 /* XXX this is all a bit dubious. add_extra_xml() uses
481 a different lifetime model from add_instant_xml().
484 XMLNode* node = new XMLNode (keyboard->get_state());
485 Config->add_extra_xml (*node);
486 Config->add_extra_xml (get_transport_controllable_state());
487 if (new_session_dialog) {
488 if (new_session_dialog->engine_control.was_used()) {
489 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
492 Config->save_state();
494 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
495 XMLNode mnode(mixer->get_state());
498 session->add_instant_xml (enode, session->path());
499 session->add_instant_xml (mnode, session->path());
501 Config->add_instant_xml (enode, get_user_ardour_path());
502 Config->add_instant_xml (mnode, get_user_ardour_path());
509 ARDOUR_UI::autosave_session ()
511 if (!Config->get_periodic_safety_backups())
515 session->maybe_write_autosave();
522 ARDOUR_UI::update_autosave ()
524 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
526 if (session->dirty()) {
527 if (_autosave_connection.connected()) {
528 _autosave_connection.disconnect();
531 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
532 Config->get_periodic_safety_backup_interval() * 1000);
535 if (_autosave_connection.connected()) {
536 _autosave_connection.disconnect();
542 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
546 title = _("Ardour could not start JACK");
548 title = _("Ardour could not connect to JACK.");
551 MessageDialog win (title,
557 win.set_secondary_text(_("There are several possible reasons:\n\
559 1) You requested audio parameters that are not supported..\n\
560 2) JACK is running as another user.\n\
562 Please consider the possibilities, and perhaps try different parameters."));
564 win.set_secondary_text(_("There are several possible reasons:\n\
566 1) JACK is not running.\n\
567 2) JACK is running as another user, perhaps root.\n\
568 3) There is already another client called \"ardour\".\n\
570 Please consider the possibilities, and perhaps (re)start JACK."));
574 win.set_transient_for (*toplevel);
578 win.add_button (Stock::OK, RESPONSE_CLOSE);
580 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
583 win.set_default_response (RESPONSE_CLOSE);
586 win.set_position (Gtk::WIN_POS_CENTER);
588 if (!ARDOUR_COMMAND_LINE::no_splash) {
592 /* we just don't care about the result, but we want to block */
598 ARDOUR_UI::startup ()
603 new_session_dialog = new NewSessionDialog();
605 /* If no session name is given: we're not loading a session yet, nor creating a new one */
607 if (ARDOUR_COMMAND_LINE::session_name.length()) {
609 /* Load session or start the new session dialog */
611 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
612 error << string_compose(_("could not load command line session \"%1\""),
613 ARDOUR_COMMAND_LINE::session_name) << endmsg;
617 if (!ARDOUR_COMMAND_LINE::new_session) {
619 /* Supposed to be loading an existing session, but the session doesn't exist */
622 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
623 "To create it from the command line, start ardour as \"ardour --new %1"), path)
629 new_session_dialog->set_session_name (name);
630 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
631 _session_is_new = isnew;
636 bool have_backend = EngineControl::engine_running();
638 bool load_needed = false;
642 /* backend audio is working */
644 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
645 /* need NSD to get session name and other info */
653 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
656 new_session_dialog->engine_control.set_state (*audio_setup);
659 /* no backend audio, must bring up NSD to check configuration */
666 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
672 if (create_engine ()) {
673 backend_audio_error (false);
681 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
690 ARDOUR_UI::no_memory_warning ()
692 XMLNode node (X_("no-memory-warning"));
693 Config->add_instant_xml (node, get_user_ardour_path());
697 ARDOUR_UI::check_memory_locking ()
700 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
704 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
706 if (engine->is_realtime() && memory_warning_node == 0) {
708 struct rlimit limits;
710 long pages, page_size;
712 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
715 ram = (int64_t) pages * (int64_t) page_size;
718 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
722 if (limits.rlim_cur != RLIM_INFINITY) {
724 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
727 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
728 "This might cause Ardour to run out of memory before your system "
729 "runs out of memory. \n\n"
730 "You can view the memory limit with 'ulimit -l', "
731 "and it is normally controlled by /etc/security/limits.conf"));
733 VBox* vbox = msg.get_vbox();
735 CheckButton cb (_("Do not show this window again"));
737 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
739 hbox.pack_start (cb, true, false);
740 vbox->pack_start (hbox);
754 if (session && session->dirty()) {
755 switch (ask_about_saving_session(_("quit"))) {
760 /* use the default name */
761 if (save_state_canfail ("")) {
762 /* failed - don't quit */
763 MessageDialog msg (*editor,
765 Ardour was unable to save your session.\n\n\
766 If you still wish to quit, please use the\n\n\
767 \"Just quit\" option."));
778 session->set_deletion_in_progress ();
781 save_ardour_state ();
786 ARDOUR_UI::ask_about_saving_session (const string & what)
788 ArdourDialog window (_("ardour: save session?"));
789 Gtk::HBox dhbox; // the hbox for the image and text
790 Gtk::Label prompt_label;
791 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
795 msg = string_compose(_("Don't %1"), what);
796 window.add_button (msg, RESPONSE_REJECT);
797 msg = string_compose(_("Just %1"), what);
798 window.add_button (msg, RESPONSE_APPLY);
799 msg = string_compose(_("Save and %1"), what);
800 window.add_button (msg, RESPONSE_ACCEPT);
802 window.set_default_response (RESPONSE_ACCEPT);
804 Gtk::Button noquit_button (msg);
805 noquit_button.set_name ("EditorGTKButton");
810 if (session->snap_name() == session->name()) {
813 type = _("snapshot");
815 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?"),
816 type, session->snap_name());
818 prompt_label.set_text (prompt);
819 prompt_label.set_name (X_("PrompterLabel"));
820 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
822 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
824 dhbox.set_homogeneous (false);
825 dhbox.pack_start (*dimage, false, false, 5);
826 dhbox.pack_start (prompt_label, true, false, 5);
827 window.get_vbox()->pack_start (dhbox);
829 window.set_name (_("Prompter"));
830 window.set_position (Gtk::WIN_POS_MOUSE);
831 window.set_modal (true);
832 window.set_resizable (false);
835 save_the_session = 0;
837 window.set_keep_above (true);
840 ResponseType r = (ResponseType) window.run();
845 case RESPONSE_ACCEPT: // save and get out of here
847 case RESPONSE_APPLY: // get out of here
857 ARDOUR_UI::every_second ()
860 update_buffer_load ();
861 update_disk_space ();
866 ARDOUR_UI::every_point_one_seconds ()
868 update_speed_display ();
869 RapidScreenUpdate(); /* EMIT_SIGNAL */
874 ARDOUR_UI::every_point_zero_one_seconds ()
876 // august 2007: actual update frequency: 40Hz, not 100Hz
878 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
883 ARDOUR_UI::update_sample_rate (nframes_t ignored)
887 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
889 if (!engine->connected()) {
891 snprintf (buf, sizeof (buf), _("disconnected"));
895 nframes_t rate = engine->frame_rate();
897 if (fmod (rate, 1000.0) != 0.0) {
898 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
899 (float) rate/1000.0f,
900 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
902 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
904 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
908 sample_rate_label.set_text (buf);
912 ARDOUR_UI::update_cpu_load ()
915 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
916 cpu_load_label.set_text (buf);
920 ARDOUR_UI::update_buffer_load ()
925 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
926 session->playback_load(), session->capture_load());
927 buffer_load_label.set_text (buf);
929 buffer_load_label.set_text ("");
934 ARDOUR_UI::count_recenabled_streams (Route& route)
936 Track* track = dynamic_cast<Track*>(&route);
937 if (track && track->diskstream()->record_enabled()) {
938 rec_enabled_streams += track->n_inputs();
943 ARDOUR_UI::update_disk_space()
949 nframes_t frames = session->available_capture_duration();
952 if (frames == max_frames) {
953 strcpy (buf, _("Disk: 24hrs+"));
958 nframes_t fr = session->frame_rate();
960 rec_enabled_streams = 0;
961 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
963 if (rec_enabled_streams) {
964 frames /= rec_enabled_streams;
967 hrs = frames / (fr * 3600);
968 frames -= hrs * fr * 3600;
969 mins = frames / (fr * 60);
970 frames -= mins * fr * 60;
973 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
976 disk_space_label.set_text (buf);
980 ARDOUR_UI::update_wall_clock ()
987 tm_now = localtime (&now);
989 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
990 wall_clock_label.set_text (buf);
996 ARDOUR_UI::session_menu (GdkEventButton *ev)
998 session_popup_menu->popup (0, 0);
1003 ARDOUR_UI::redisplay_recent_sessions ()
1005 vector<string *> *sessions;
1006 vector<string *>::iterator i;
1007 RecentSessionsSorter cmp;
1009 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1010 recent_session_model->clear ();
1013 ARDOUR::read_recent_sessions (rs);
1016 recent_session_display.set_model (recent_session_model);
1020 /* sort them alphabetically */
1021 sort (rs.begin(), rs.end(), cmp);
1022 sessions = new vector<string*>;
1024 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1025 sessions->push_back (new string ((*i).second));
1028 for (i = sessions->begin(); i != sessions->end(); ++i) {
1030 vector<string*>* states;
1031 vector<const gchar*> item;
1032 string fullpath = *(*i);
1034 /* remove any trailing / */
1036 if (fullpath[fullpath.length()-1] == '/') {
1037 fullpath = fullpath.substr (0, fullpath.length()-1);
1040 /* now get available states for this session */
1042 if ((states = Session::possible_states (fullpath)) == 0) {
1043 /* no state file? */
1047 TreeModel::Row row = *(recent_session_model->append());
1049 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1050 row[recent_session_columns.fullpath] = fullpath;
1052 if (states->size() > 1) {
1054 /* add the children */
1056 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1058 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1060 child_row[recent_session_columns.visible_name] = **i2;
1061 child_row[recent_session_columns.fullpath] = fullpath;
1070 recent_session_display.set_model (recent_session_model);
1075 ARDOUR_UI::build_session_selector ()
1077 session_selector_window = new ArdourDialog ("session selector");
1079 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1081 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1082 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1083 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1084 recent_session_model = TreeStore::create (recent_session_columns);
1085 recent_session_display.set_model (recent_session_model);
1086 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1087 recent_session_display.set_headers_visible (false);
1088 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1090 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1092 scroller->add (recent_session_display);
1093 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1095 session_selector_window->set_name ("SessionSelectorWindow");
1096 session_selector_window->set_size_request (200, 400);
1097 session_selector_window->get_vbox()->pack_start (*scroller);
1098 session_selector_window->show_all_children();
1102 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1104 session_selector_window->response (RESPONSE_ACCEPT);
1108 ARDOUR_UI::open_recent_session ()
1110 /* popup selector window */
1112 if (session_selector_window == 0) {
1113 build_session_selector ();
1116 redisplay_recent_sessions ();
1118 ResponseType r = (ResponseType) session_selector_window->run ();
1120 session_selector_window->hide();
1123 case RESPONSE_ACCEPT:
1129 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1131 if (i == recent_session_model->children().end()) {
1135 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1136 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1138 _session_is_new = false;
1140 load_session (path, state);
1144 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1146 struct stat statbuf;
1148 if (stat (info.filename.c_str(), &statbuf) != 0) {
1152 if (!S_ISDIR(statbuf.st_mode)) {
1158 string session_file = info.filename;
1159 session_file += '/';
1160 session_file += Glib::path_get_basename (info.filename);
1161 session_file += ".ardour";
1163 if (stat (session_file.c_str(), &statbuf) != 0) {
1167 return S_ISREG (statbuf.st_mode);
1171 ARDOUR_UI::check_audioengine ()
1174 if (!engine->connected()) {
1175 MessageDialog msg (_("Ardour is not connected to JACK\n"
1176 "You cannot open or close sessions in this condition"));
1187 ARDOUR_UI::open_session ()
1189 if (!check_audioengine()) {
1193 /* popup selector window */
1195 if (open_session_selector == 0) {
1197 /* ardour sessions are folders */
1199 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1200 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1201 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1202 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1204 FileFilter session_filter;
1205 session_filter.add_pattern ("*.ardour");
1206 session_filter.set_name (_("Ardour sessions"));
1207 open_session_selector->add_filter (session_filter);
1208 open_session_selector->set_filter (session_filter);
1211 int response = open_session_selector->run();
1212 open_session_selector->hide ();
1215 case RESPONSE_ACCEPT:
1218 open_session_selector->hide();
1222 open_session_selector->hide();
1223 string session_path = open_session_selector->get_filename();
1227 if (session_path.length() > 0) {
1228 if (Session::find_session (session_path, path, name, isnew) == 0) {
1229 _session_is_new = isnew;
1230 load_session (path, name);
1237 ARDOUR_UI::session_add_midi_track ()
1239 cerr << _("Patience is a virtue.\n");
1243 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1245 list<boost::shared_ptr<AudioTrack> > tracks;
1246 Session::RouteList routes;
1249 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1255 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1257 if (tracks.size() != how_many) {
1258 if (how_many == 1) {
1259 error << _("could not create a new audio track") << endmsg;
1261 error << string_compose (_("could only create %1 of %2 new audio %3"),
1262 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1268 routes = session->new_audio_route (input_channels, output_channels, how_many);
1270 if (routes.size() != how_many) {
1271 if (how_many == 1) {
1272 error << _("could not create a new audio track") << endmsg;
1274 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1280 if (need_control_room_outs) {
1286 route->set_stereo_control_outs (control_lr_channels);
1287 route->control_outs()->set_stereo_pan (pans, this);
1289 #endif /* CONTROLOUTS */
1293 cerr << "About to complain about JACK\n";
1294 MessageDialog msg (*editor,
1295 _("There are insufficient JACK ports available\n\
1296 to create a new track or bus.\n\
1297 You should save Ardour, exit and\n\
1298 restart JACK with more ports."));
1304 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1306 nframes_t _preroll = 0;
1309 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1310 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1312 if (new_position > _preroll) {
1313 new_position -= _preroll;
1318 session->request_locate (new_position);
1323 ARDOUR_UI::transport_goto_start ()
1326 session->goto_start();
1329 /* force displayed area in editor to start no matter
1330 what "follow playhead" setting is.
1334 editor->reset_x_origin (session->current_start_frame());
1340 ARDOUR_UI::transport_goto_zero ()
1343 session->request_locate (0);
1346 /* force displayed area in editor to start no matter
1347 what "follow playhead" setting is.
1351 editor->reset_x_origin (0);
1357 ARDOUR_UI::transport_goto_end ()
1360 nframes_t frame = session->current_end_frame();
1361 session->request_locate (frame);
1363 /* force displayed area in editor to start no matter
1364 what "follow playhead" setting is.
1368 editor->reset_x_origin (frame);
1374 ARDOUR_UI::transport_stop ()
1380 if (session->is_auditioning()) {
1381 session->cancel_audition ();
1385 if (session->get_play_loop ()) {
1386 session->request_play_loop (false);
1389 session->request_stop ();
1393 ARDOUR_UI::transport_stop_and_forget_capture ()
1396 session->request_stop (true);
1401 ARDOUR_UI::remove_last_capture()
1404 editor->remove_last_capture();
1409 ARDOUR_UI::transport_record (bool roll)
1412 switch (session->record_status()) {
1413 case Session::Disabled:
1414 if (session->ntracks() == 0) {
1415 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1419 session->maybe_enable_record ();
1424 case Session::Recording:
1426 session->request_stop();
1428 session->disable_record (false, true);
1432 case Session::Enabled:
1433 session->disable_record (false, true);
1439 ARDOUR_UI::transport_roll ()
1447 rolling = session->transport_rolling ();
1449 if (session->get_play_loop()) {
1450 session->request_play_loop (false);
1451 auto_loop_button.set_visual_state (1);
1452 roll_button.set_visual_state (1);
1453 } else if (session->get_play_range ()) {
1454 session->request_play_range (false);
1455 play_selection_button.set_visual_state (0);
1456 } else if (rolling) {
1457 session->request_locate (session->last_transport_start(), true);
1460 session->request_transport_speed (1.0f);
1464 ARDOUR_UI::transport_loop()
1467 if (session->get_play_loop()) {
1468 if (session->transport_rolling()) {
1469 Location * looploc = session->locations()->auto_loop_location();
1471 session->request_locate (looploc->start(), true);
1476 session->request_play_loop (true);
1482 ARDOUR_UI::transport_play_selection ()
1488 if (!session->get_play_range()) {
1489 session->request_stop ();
1492 editor->play_selection ();
1496 ARDOUR_UI::transport_rewind (int option)
1498 float current_transport_speed;
1501 current_transport_speed = session->transport_speed();
1503 if (current_transport_speed >= 0.0f) {
1506 session->request_transport_speed (-1.0f);
1509 session->request_transport_speed (-4.0f);
1512 session->request_transport_speed (-0.5f);
1517 session->request_transport_speed (current_transport_speed * 1.5f);
1523 ARDOUR_UI::transport_forward (int option)
1525 float current_transport_speed;
1528 current_transport_speed = session->transport_speed();
1530 if (current_transport_speed <= 0.0f) {
1533 session->request_transport_speed (1.0f);
1536 session->request_transport_speed (4.0f);
1539 session->request_transport_speed (0.5f);
1544 session->request_transport_speed (current_transport_speed * 1.5f);
1550 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1556 boost::shared_ptr<Route> r;
1558 if ((r = session->route_by_remote_id (dstream)) != 0) {
1562 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1563 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1572 ARDOUR_UI::queue_transport_change ()
1574 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1578 ARDOUR_UI::map_transport_state ()
1580 float sp = session->transport_speed();
1583 transport_rolling ();
1584 } else if (sp < 0.0f) {
1585 transport_rewinding ();
1586 } else if (sp > 0.0f) {
1587 transport_forwarding ();
1589 transport_stopped ();
1594 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1596 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1597 (int) adj.get_value()].c_str());
1601 ARDOUR_UI::engine_stopped ()
1603 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1604 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1605 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1609 ARDOUR_UI::engine_running ()
1611 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1612 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1613 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1615 Glib::RefPtr<Action> action;
1616 char* action_name = 0;
1618 switch (engine->frames_per_cycle()) {
1620 action_name = X_("JACKLatency32");
1623 action_name = X_("JACKLatency64");
1626 action_name = X_("JACKLatency128");
1629 action_name = X_("JACKLatency512");
1632 action_name = X_("JACKLatency1024");
1635 action_name = X_("JACKLatency2048");
1638 action_name = X_("JACKLatency4096");
1641 action_name = X_("JACKLatency8192");
1644 /* XXX can we do anything useful ? */
1650 action = ActionManager::get_action (X_("JACK"), action_name);
1653 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1654 ract->set_active ();
1660 ARDOUR_UI::engine_halted ()
1662 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1664 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1665 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1667 update_sample_rate (0);
1669 MessageDialog msg (*editor,
1671 JACK has either been shutdown or it\n\
1672 disconnected Ardour because Ardour\n\
1673 was not fast enough. You can save the\n\
1674 session and/or try to reconnect to JACK ."));
1679 ARDOUR_UI::do_engine_start ()
1687 error << _("Unable to start the session running")
1697 ARDOUR_UI::setup_theme ()
1699 theme_manager->setup_theme();
1703 ARDOUR_UI::update_clocks ()
1705 if (!editor || !editor->dragging_playhead()) {
1706 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1711 ARDOUR_UI::start_clocking ()
1713 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1717 ARDOUR_UI::stop_clocking ()
1719 clock_signal_connection.disconnect ();
1723 ARDOUR_UI::toggle_clocking ()
1726 if (clock_button.get_active()) {
1735 ARDOUR_UI::_blink (void *arg)
1738 ((ARDOUR_UI *) arg)->blink ();
1745 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1749 ARDOUR_UI::start_blinking ()
1751 /* Start the blink signal. Everybody with a blinking widget
1752 uses Blink to drive the widget's state.
1755 if (blink_timeout_tag < 0) {
1757 blink_timeout_tag = g_timeout_add (240, _blink, this);
1762 ARDOUR_UI::stop_blinking ()
1764 if (blink_timeout_tag >= 0) {
1765 g_source_remove (blink_timeout_tag);
1766 blink_timeout_tag = -1;
1771 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1777 if (io.n_inputs() == 0) {
1782 /* XXX we're not handling multiple ports yet. */
1784 const char **connections = io.input(0)->get_connections();
1786 if (connections == 0 || connections[0] == '\0') {
1789 buf = connections[0];
1796 if (io.n_outputs() == 0) {
1801 /* XXX we're not handling multiple ports yet. */
1803 const char **connections = io.output(0)->get_connections();
1805 if (connections == 0 || connections[0] == '\0') {
1808 buf = connections[0];
1815 /** Ask the user for the name of a new shapshot and then take it.
1818 ARDOUR_UI::snapshot_session ()
1820 ArdourPrompter prompter (true);
1824 struct tm local_time;
1827 localtime_r (&n, &local_time);
1828 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1830 prompter.set_name ("Prompter");
1831 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1832 prompter.set_prompt (_("Name of New Snapshot"));
1833 prompter.set_initial_text (timebuf);
1835 switch (prompter.run()) {
1836 case RESPONSE_ACCEPT:
1837 prompter.get_result (snapname);
1838 if (snapname.length()){
1839 save_state (snapname);
1849 ARDOUR_UI::save_state (const string & name)
1851 (void) save_state_canfail (name);
1855 ARDOUR_UI::save_state_canfail (string name)
1860 if (name.length() == 0) {
1861 name = session->snap_name();
1864 if ((ret = session->save_state (name)) != 0) {
1868 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1873 ARDOUR_UI::restore_state (string name)
1876 if (name.length() == 0) {
1877 name = session->name();
1879 session->restore_state (name);
1884 ARDOUR_UI::primary_clock_value_changed ()
1887 session->request_locate (primary_clock.current_time ());
1892 ARDOUR_UI::big_clock_value_changed ()
1895 session->request_locate (big_clock.current_time ());
1900 ARDOUR_UI::secondary_clock_value_changed ()
1903 session->request_locate (secondary_clock.current_time ());
1908 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1910 if (session && dstream && dstream->record_enabled()) {
1912 Session::RecordState rs;
1914 rs = session->record_status ();
1917 case Session::Disabled:
1918 case Session::Enabled:
1919 if (w->get_state() != STATE_SELECTED) {
1920 w->set_state (STATE_SELECTED);
1924 case Session::Recording:
1925 if (w->get_state() != STATE_ACTIVE) {
1926 w->set_state (STATE_ACTIVE);
1932 if (w->get_state() != STATE_NORMAL) {
1933 w->set_state (STATE_NORMAL);
1939 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1945 switch (session->record_status()) {
1946 case Session::Enabled:
1948 rec_button.set_visual_state (2);
1950 rec_button.set_visual_state (0);
1954 case Session::Recording:
1955 rec_button.set_visual_state (1);
1959 rec_button.set_visual_state (0);
1965 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1973 ARDOUR_UI::save_template ()
1976 ArdourPrompter prompter (true);
1979 if (!check_audioengine()) {
1983 prompter.set_name (X_("Prompter"));
1984 prompter.set_prompt (_("Name for mix template:"));
1985 prompter.set_initial_text(session->name() + _("-template"));
1986 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1988 switch (prompter.run()) {
1989 case RESPONSE_ACCEPT:
1990 prompter.get_result (name);
1992 if (name.length()) {
1993 session->save_template (name);
2003 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2005 string session_name;
2006 string session_path;
2007 string template_name;
2009 if (!loading_dialog) {
2010 loading_dialog = new MessageDialog (*new_session_dialog,
2017 int response = Gtk::RESPONSE_NONE;
2019 new_session_dialog->set_modal(true);
2020 new_session_dialog->set_name (predetermined_path);
2021 new_session_dialog->reset_recent();
2022 new_session_dialog->set_position (WIN_POS_CENTER);
2023 new_session_dialog->set_current_page (0);
2026 new_session_dialog->set_have_engine (have_engine);
2028 new_session_dialog->show();
2029 new_session_dialog->present ();
2030 response = new_session_dialog->run ();
2032 _session_is_new = false;
2034 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2039 new_session_dialog->hide ();
2042 } else if (response == Gtk::RESPONSE_NONE) {
2044 /* Clear was pressed */
2045 new_session_dialog->reset();
2049 /* first things first ... if we're here to help set up audio parameters
2050 this is where want to do that.
2054 if (new_session_dialog->engine_control.setup_engine ()) {
2055 new_session_dialog->hide ();
2061 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2062 may not and it can take a while to build it. Warn them.
2065 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2067 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2068 MessageDialog msg (*new_session_dialog,
2069 _("Welcome to Ardour.\n\n"
2070 "The program will take a bit longer to start up\n"
2071 "while the system fonts are checked.\n\n"
2072 "This will only be done once, and you will\n"
2073 "not see this message again\n"),
2082 loading_dialog->set_message (_("Starting audio engine"));
2083 loading_dialog->show_all ();
2086 if (create_engine ()) {
2087 backend_audio_error (!have_engine, new_session_dialog);
2088 loading_dialog->hide ();
2090 /* audio setup page */
2091 new_session_dialog->set_current_page (2);
2093 response = Gtk::RESPONSE_NONE;
2099 /* now handle possible affirmative responses */
2101 if (response == Gtk::RESPONSE_YES) {
2103 /* YES == OPEN from the session selector */
2105 session_name = new_session_dialog->session_name();
2107 if (session_name.empty()) {
2108 response = Gtk::RESPONSE_NONE;
2112 if (session_name[0] == '/' ||
2113 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2114 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2115 load_session (Glib::path_get_dirname (session_name), session_name);
2117 session_path = new_session_dialog->session_folder();
2118 load_session (session_path, session_name);
2121 } else if (response == Gtk::RESPONSE_OK) {
2123 /* OK == OPEN button */
2125 session_name = new_session_dialog->session_name();
2127 if (session_name.empty()) {
2128 response = Gtk::RESPONSE_NONE;
2132 switch (new_session_dialog->get_current_page()) {
2133 case 1: /* recent session selector */
2134 case 2: /* audio engine control */
2136 if (session_name[0] == '/' ||
2137 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2138 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2139 load_session (Glib::path_get_dirname (session_name), session_name);
2141 session_path = new_session_dialog->session_folder();
2142 load_session (session_path, session_name);
2146 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2148 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2149 should_be_new = true;
2152 /* handle what appear to be paths rather than just a name */
2154 if (session_name[0] == '/' ||
2155 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2156 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2158 session_path = Glib::path_get_dirname (session_name);
2159 session_name = Glib::path_get_basename (session_name);
2163 session_path = new_session_dialog->session_folder();
2167 //XXX This is needed because session constructor wants a
2168 //non-existant path. hopefully this will be fixed at some point.
2170 session_path = Glib::build_filename (session_path, session_name);
2172 if (!should_be_new) {
2174 load_session (session_path, session_name);
2175 continue; /* leaves while() loop because response != NONE */
2177 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2179 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2181 MessageDialog msg (str,
2183 Gtk::MESSAGE_WARNING,
2184 Gtk::BUTTONS_YES_NO,
2188 msg.set_name (X_("CleanupDialog"));
2189 msg.set_wmclass (X_("existing_session"), "Ardour");
2190 msg.set_position (Gtk::WIN_POS_MOUSE);
2192 switch (msg.run()) {
2194 new_session_dialog->hide ();
2195 goto_editor_window ();
2197 load_session (session_path, session_name);
2201 response = RESPONSE_NONE;
2202 new_session_dialog->reset ();
2207 _session_is_new = true;
2209 if (new_session_dialog->use_session_template()) {
2211 template_name = new_session_dialog->session_template_name();
2213 new_session_dialog->hide ();
2214 goto_editor_window ();
2217 load_session (session_path, session_name, &template_name);
2223 AutoConnectOption iconnect;
2224 AutoConnectOption oconnect;
2228 if (Profile->get_sae()) {
2232 iconnect = AutoConnectPhysical;
2233 oconnect = AutoConnectMaster;
2234 nphysin = 0; // use all available
2235 nphysout = 0; // use all available
2239 /* get settings from advanced section of NSD */
2241 if (new_session_dialog->create_control_bus()) {
2242 cchns = (uint32_t) new_session_dialog->control_channel_count();
2247 if (new_session_dialog->create_master_bus()) {
2248 mchns = (uint32_t) new_session_dialog->master_channel_count();
2253 if (new_session_dialog->connect_inputs()) {
2254 iconnect = AutoConnectPhysical;
2256 iconnect = AutoConnectOption (0);
2259 /// @todo some minor tweaks.
2261 if (new_session_dialog->connect_outs_to_master()) {
2262 oconnect = AutoConnectMaster;
2263 } else if (new_session_dialog->connect_outs_to_physical()) {
2264 oconnect = AutoConnectPhysical;
2266 oconnect = AutoConnectOption (0);
2269 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2270 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2273 new_session_dialog->hide ();
2274 goto_editor_window ();
2277 if (build_session (session_path,
2285 engine->frame_rate() * 60 * 5)) {
2287 response = Gtk::RESPONSE_NONE;
2288 new_session_dialog->reset ();
2299 } while (response == Gtk::RESPONSE_NONE);
2303 loading_dialog->hide ();
2304 new_session_dialog->hide();
2309 ARDOUR_UI::close_session ()
2311 if (!check_audioengine()) {
2315 unload_session (true);
2317 get_session_parameters ("", true, false);
2321 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2323 Session *new_session;
2327 session_loaded = false;
2329 if (!check_audioengine()) {
2333 unload_status = unload_session ();
2335 if (unload_status < 0) {
2337 } else if (unload_status > 0) {
2342 /* if it already exists, we must have write access */
2344 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2345 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2346 "This prevents the session from being loaded."));
2351 if (loading_dialog) {
2352 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2356 disable_screen_updates ();
2359 new_session = new Session (*engine, path, snap_name, mix_template);
2363 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2367 connect_to_session (new_session);
2369 Config->set_current_owner (ConfigVariableBase::Interface);
2371 session_loaded = true;
2373 goto_editor_window ();
2376 session->set_clean ();
2379 enable_screen_updates ();
2388 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2389 uint32_t control_channels,
2390 uint32_t master_channels,
2391 AutoConnectOption input_connect,
2392 AutoConnectOption output_connect,
2395 nframes_t initial_length)
2397 Session *new_session;
2400 if (!check_audioengine()) {
2404 session_loaded = false;
2406 x = unload_session ();
2414 _session_is_new = true;
2417 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2418 control_channels, master_channels, nphysin, nphysout, initial_length);
2423 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2428 connect_to_session (new_session);
2430 session_loaded = true;
2438 editor->show_window ();
2449 ARDOUR_UI::show_splash ()
2452 about = new About();
2453 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2460 ARDOUR_UI::about_signal_response(int response)
2466 ARDOUR_UI::hide_splash ()
2469 about->get_window()->set_cursor ();
2475 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2479 removed = rep.paths.size();
2482 MessageDialog msgd (*editor,
2483 _("No audio files were ready for cleanup"),
2486 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2487 msgd.set_secondary_text (_("If this seems suprising, \n\
2488 check for any existing snapshots.\n\
2489 These may still include regions that\n\
2490 require some unused files to continue to exist."));
2496 ArdourDialog results (_("ardour: cleanup"), true, false);
2498 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2499 CleanupResultsModelColumns() {
2503 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2504 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2508 CleanupResultsModelColumns results_columns;
2509 Glib::RefPtr<Gtk::ListStore> results_model;
2510 Gtk::TreeView results_display;
2512 results_model = ListStore::create (results_columns);
2513 results_display.set_model (results_model);
2514 results_display.append_column (list_title, results_columns.visible_name);
2516 results_display.set_name ("CleanupResultsList");
2517 results_display.set_headers_visible (true);
2518 results_display.set_headers_clickable (false);
2519 results_display.set_reorderable (false);
2521 Gtk::ScrolledWindow list_scroller;
2524 Gtk::HBox dhbox; // the hbox for the image and text
2525 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2526 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2528 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2530 if (rep.space < 1048576.0f) {
2532 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2534 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2538 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2540 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2544 dhbox.pack_start (*dimage, true, false, 5);
2545 dhbox.pack_start (txt, true, false, 5);
2547 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2548 TreeModel::Row row = *(results_model->append());
2549 row[results_columns.visible_name] = *i;
2550 row[results_columns.fullpath] = *i;
2553 list_scroller.add (results_display);
2554 list_scroller.set_size_request (-1, 150);
2555 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2557 dvbox.pack_start (dhbox, true, false, 5);
2558 dvbox.pack_start (list_scroller, true, false, 5);
2559 ddhbox.pack_start (dvbox, true, false, 5);
2561 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2562 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2563 results.set_default_response (RESPONSE_CLOSE);
2564 results.set_position (Gtk::WIN_POS_MOUSE);
2565 results.show_all_children ();
2566 results.set_resizable (false);
2573 ARDOUR_UI::cleanup ()
2576 /* shouldn't happen: menu item is insensitive */
2581 MessageDialog checker (_("Are you sure you want to cleanup?"),
2583 Gtk::MESSAGE_QUESTION,
2584 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2586 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2587 ALL undo/redo information will be lost if you cleanup.\n\
2588 After cleanup, unused audio files will be moved to a \
2589 \"dead sounds\" location."));
2591 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2592 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2593 checker.set_default_response (RESPONSE_CANCEL);
2595 checker.set_name (_("CleanupDialog"));
2596 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2597 checker.set_position (Gtk::WIN_POS_MOUSE);
2599 switch (checker.run()) {
2600 case RESPONSE_ACCEPT:
2606 Session::cleanup_report rep;
2608 editor->prepare_for_cleanup ();
2610 /* do not allow flush until a session is reloaded */
2612 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2614 act->set_sensitive (false);
2617 if (session->cleanup_sources (rep)) {
2622 display_cleanup_results (rep,
2625 The following %1 %2 not in use and \n\
2626 have been moved to:\n\
2628 Flushing the wastebasket will \n\
2629 release an additional\n\
2630 %4 %5bytes of disk space.\n"
2638 ARDOUR_UI::flush_trash ()
2641 /* shouldn't happen: menu item is insensitive */
2645 Session::cleanup_report rep;
2647 if (session->cleanup_trash_sources (rep)) {
2651 display_cleanup_results (rep,
2653 _("The following %1 %2 deleted from\n\
2655 releasing %4 %5bytes of disk space"));
2659 ARDOUR_UI::add_route (Gtk::Window* float_window)
2667 if (add_route_dialog == 0) {
2668 add_route_dialog = new AddRouteDialog;
2670 add_route_dialog->set_transient_for (*float_window);
2674 if (add_route_dialog->is_visible()) {
2675 /* we're already doing this */
2679 ResponseType r = (ResponseType) add_route_dialog->run ();
2681 add_route_dialog->hide();
2684 case RESPONSE_ACCEPT:
2691 if ((count = add_route_dialog->count()) <= 0) {
2695 uint32_t input_chan = add_route_dialog->channels ();
2696 uint32_t output_chan;
2697 string name_template = add_route_dialog->name_template ();
2698 bool track = add_route_dialog->track ();
2700 AutoConnectOption oac = Config->get_output_auto_connect();
2702 if (oac & AutoConnectMaster) {
2703 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2705 output_chan = input_chan;
2708 /* XXX do something with name template */
2711 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2713 session_add_audio_bus (input_chan, output_chan, count);
2718 ARDOUR_UI::mixer_settings () const
2723 node = session->instant_xml(X_("Mixer"), session->path());
2725 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2729 node = new XMLNode (X_("Mixer"));
2736 ARDOUR_UI::editor_settings () const
2741 node = session->instant_xml(X_("Editor"), session->path());
2743 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2747 node = new XMLNode (X_("Editor"));
2753 ARDOUR_UI::keyboard_settings () const
2757 node = Config->extra_xml(X_("Keyboard"));
2760 node = new XMLNode (X_("Keyboard"));
2766 ARDOUR_UI::halt_on_xrun_message ()
2768 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2770 MessageDialog msg (*editor,
2771 _("Recording was stopped because your system could not keep up."));
2776 ARDOUR_UI::disk_overrun_handler ()
2778 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2780 if (!have_disk_speed_dialog_displayed) {
2781 have_disk_speed_dialog_displayed = true;
2782 MessageDialog* msg = new MessageDialog (*editor, _("\
2783 The disk system on your computer\n\
2784 was not able to keep up with Ardour.\n\
2786 Specifically, it failed to write data to disk\n\
2787 quickly enough to keep up with recording.\n"));
2788 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2794 ARDOUR_UI::disk_underrun_handler ()
2796 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2798 if (!have_disk_speed_dialog_displayed) {
2799 have_disk_speed_dialog_displayed = true;
2800 MessageDialog* msg = new MessageDialog (*editor,
2801 _("The disk system on your computer\n\
2802 was not able to keep up with Ardour.\n\
2804 Specifically, it failed to read data from disk\n\
2805 quickly enough to keep up with playback.\n"));
2806 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2812 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2814 have_disk_speed_dialog_displayed = false;
2819 ARDOUR_UI::pending_state_dialog ()
2821 ArdourDialog dialog ("pending state dialog");
2823 This session appears to have been in\n\
2824 middle of recording when ardour or\n\
2825 the computer was shutdown.\n\
2827 Ardour can recover any captured audio for\n\
2828 you, or it can ignore it. Please decide\n\
2829 what you would like to do.\n"));
2831 dialog.get_vbox()->pack_start (message);
2832 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2833 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2835 dialog.set_position (WIN_POS_CENTER);
2838 switch (dialog.run ()) {
2839 case RESPONSE_ACCEPT:
2847 ARDOUR_UI::disconnect_from_jack ()
2850 if( engine->disconnect_from_jack ()) {
2851 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2855 update_sample_rate (0);
2860 ARDOUR_UI::reconnect_to_jack ()
2863 if (engine->reconnect_to_jack ()) {
2864 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2868 update_sample_rate (0);
2873 ARDOUR_UI::cmdline_new_session (string path)
2875 if (path[0] != '/') {
2876 char buf[PATH_MAX+1];
2879 getcwd (buf, sizeof (buf));
2886 get_session_parameters (path, false, true);
2888 _will_create_new_session_automatically = false; /* done it */
2889 return FALSE; /* don't call it again */
2893 ARDOUR_UI::use_config ()
2895 Glib::RefPtr<Action> act;
2897 switch (Config->get_native_file_data_format ()) {
2899 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2902 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2905 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2910 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2911 ract->set_active ();
2914 switch (Config->get_native_file_header_format ()) {
2916 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2919 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2922 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2925 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2928 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2931 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2934 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2939 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2940 ract->set_active ();
2943 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2945 set_transport_controllable_state (*node);
2950 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2952 if (Config->get_primary_clock_delta_edit_cursor()) {
2953 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
2955 primary_clock.set (pos, 0, true);
2958 if (Config->get_secondary_clock_delta_edit_cursor()) {
2959 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
2961 secondary_clock.set (pos);
2964 if (big_clock_window) {
2965 big_clock.set (pos);
2970 ARDOUR_UI::record_state_changed ()
2972 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2974 if (!session || !big_clock_window) {
2975 /* why bother - the clock isn't visible */
2979 switch (session->record_status()) {
2980 case Session::Recording:
2981 big_clock.set_widget_name ("BigClockRecording");
2984 big_clock.set_widget_name ("BigClockNonRecording");
2990 ARDOUR_UI::set_keybindings_path (string path)
2992 keybindings_path = path;
2996 ARDOUR_UI::save_keybindings ()
2998 if (can_save_keybindings) {
2999 AccelMap::save (user_keybindings_path);
3004 ARDOUR_UI::first_idle ()
3007 session->allow_auto_play (true);
3009 can_save_keybindings = true;
3014 ARDOUR_UI::store_clock_modes ()
3016 XMLNode* node = new XMLNode(X_("ClockModes"));
3018 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3019 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3022 session->add_extra_xml (*node);
3023 session->set_dirty ();
3028 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3029 : Controllable (name), ui (u), type(tp)
3035 ARDOUR_UI::TransportControllable::set_value (float val)
3037 if (type == ShuttleControl) {
3044 fract = -((0.5f - val)/0.5f);
3046 fract = ((val - 0.5f)/0.5f);
3050 ui.set_shuttle_fract (fract);
3055 /* do nothing: these are radio-style actions */
3063 action = X_("Roll");
3066 action = X_("Stop");
3069 action = X_("Goto Start");
3072 action = X_("Goto End");
3075 action = X_("Loop");
3078 action = X_("Play Selection");
3081 action = X_("Record");
3091 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3099 ARDOUR_UI::TransportControllable::get_value (void) const
3118 case ShuttleControl:
3128 ARDOUR_UI::TransportControllable::set_id (const string& str)
3134 ARDOUR_UI::setup_profile ()
3136 if (gdk_screen_width() < 1200) {
3137 Profile->set_small_screen ();
3140 if (getenv ("ARDOUR_SAE")) {
3141 Profile->set_sae ();
3142 Profile->set_single_package ();