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();
493 ui_config->save_state ();
495 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
496 XMLNode mnode(mixer->get_state());
499 session->add_instant_xml (enode, session->path());
500 session->add_instant_xml (mnode, session->path());
502 Config->add_instant_xml (enode, get_user_ardour_path());
503 Config->add_instant_xml (mnode, get_user_ardour_path());
510 ARDOUR_UI::autosave_session ()
512 if (!Config->get_periodic_safety_backups())
516 session->maybe_write_autosave();
523 ARDOUR_UI::update_autosave ()
525 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
527 if (session->dirty()) {
528 if (_autosave_connection.connected()) {
529 _autosave_connection.disconnect();
532 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
533 Config->get_periodic_safety_backup_interval() * 1000);
536 if (_autosave_connection.connected()) {
537 _autosave_connection.disconnect();
543 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
547 title = _("Ardour could not start JACK");
549 title = _("Ardour could not connect to JACK.");
552 MessageDialog win (title,
558 win.set_secondary_text(_("There are several possible reasons:\n\
560 1) You requested audio parameters that are not supported..\n\
561 2) JACK is running as another user.\n\
563 Please consider the possibilities, and perhaps try different parameters."));
565 win.set_secondary_text(_("There are several possible reasons:\n\
567 1) JACK is not running.\n\
568 2) JACK is running as another user, perhaps root.\n\
569 3) There is already another client called \"ardour\".\n\
571 Please consider the possibilities, and perhaps (re)start JACK."));
575 win.set_transient_for (*toplevel);
579 win.add_button (Stock::OK, RESPONSE_CLOSE);
581 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
584 win.set_default_response (RESPONSE_CLOSE);
587 win.set_position (Gtk::WIN_POS_CENTER);
589 if (!ARDOUR_COMMAND_LINE::no_splash) {
593 /* we just don't care about the result, but we want to block */
599 ARDOUR_UI::startup ()
604 new_session_dialog = new NewSessionDialog();
606 /* If no session name is given: we're not loading a session yet, nor creating a new one */
608 if (ARDOUR_COMMAND_LINE::session_name.length()) {
610 /* Load session or start the new session dialog */
612 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
613 error << string_compose(_("could not load command line session \"%1\""),
614 ARDOUR_COMMAND_LINE::session_name) << endmsg;
618 if (!ARDOUR_COMMAND_LINE::new_session) {
620 /* Supposed to be loading an existing session, but the session doesn't exist */
623 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
624 "To create it from the command line, start ardour as \"ardour --new %1"), path)
630 new_session_dialog->set_session_name (name);
631 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
632 _session_is_new = isnew;
637 bool have_backend = EngineControl::engine_running();
639 bool load_needed = false;
643 /* backend audio is working */
645 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
646 /* need NSD to get session name and other info */
654 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
657 new_session_dialog->engine_control.set_state (*audio_setup);
660 /* no backend audio, must bring up NSD to check configuration */
667 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
673 if (create_engine ()) {
674 backend_audio_error (false);
682 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
691 ARDOUR_UI::no_memory_warning ()
693 XMLNode node (X_("no-memory-warning"));
694 Config->add_instant_xml (node, get_user_ardour_path());
698 ARDOUR_UI::check_memory_locking ()
701 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
705 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
707 if (engine->is_realtime() && memory_warning_node == 0) {
709 struct rlimit limits;
711 long pages, page_size;
713 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
716 ram = (int64_t) pages * (int64_t) page_size;
719 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
723 if (limits.rlim_cur != RLIM_INFINITY) {
725 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
728 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
729 "This might cause Ardour to run out of memory before your system "
730 "runs out of memory. \n\n"
731 "You can view the memory limit with 'ulimit -l', "
732 "and it is normally controlled by /etc/security/limits.conf"));
734 VBox* vbox = msg.get_vbox();
736 CheckButton cb (_("Do not show this window again"));
738 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
740 hbox.pack_start (cb, true, false);
741 vbox->pack_start (hbox);
755 if (session && session->dirty()) {
756 switch (ask_about_saving_session(_("quit"))) {
761 /* use the default name */
762 if (save_state_canfail ("")) {
763 /* failed - don't quit */
764 MessageDialog msg (*editor,
766 Ardour was unable to save your session.\n\n\
767 If you still wish to quit, please use the\n\n\
768 \"Just quit\" option."));
779 session->set_deletion_in_progress ();
782 save_ardour_state ();
787 ARDOUR_UI::ask_about_saving_session (const string & what)
789 ArdourDialog window (_("ardour: save session?"));
790 Gtk::HBox dhbox; // the hbox for the image and text
791 Gtk::Label prompt_label;
792 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
796 msg = string_compose(_("Don't %1"), what);
797 window.add_button (msg, RESPONSE_REJECT);
798 msg = string_compose(_("Just %1"), what);
799 window.add_button (msg, RESPONSE_APPLY);
800 msg = string_compose(_("Save and %1"), what);
801 window.add_button (msg, RESPONSE_ACCEPT);
803 window.set_default_response (RESPONSE_ACCEPT);
805 Gtk::Button noquit_button (msg);
806 noquit_button.set_name ("EditorGTKButton");
811 if (session->snap_name() == session->name()) {
814 type = _("snapshot");
816 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?"),
817 type, session->snap_name());
819 prompt_label.set_text (prompt);
820 prompt_label.set_name (X_("PrompterLabel"));
821 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
823 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
825 dhbox.set_homogeneous (false);
826 dhbox.pack_start (*dimage, false, false, 5);
827 dhbox.pack_start (prompt_label, true, false, 5);
828 window.get_vbox()->pack_start (dhbox);
830 window.set_name (_("Prompter"));
831 window.set_position (Gtk::WIN_POS_MOUSE);
832 window.set_modal (true);
833 window.set_resizable (false);
836 save_the_session = 0;
838 window.set_keep_above (true);
841 ResponseType r = (ResponseType) window.run();
846 case RESPONSE_ACCEPT: // save and get out of here
848 case RESPONSE_APPLY: // get out of here
858 ARDOUR_UI::every_second ()
861 update_buffer_load ();
862 update_disk_space ();
867 ARDOUR_UI::every_point_one_seconds ()
869 update_speed_display ();
870 RapidScreenUpdate(); /* EMIT_SIGNAL */
875 ARDOUR_UI::every_point_zero_one_seconds ()
877 // august 2007: actual update frequency: 40Hz, not 100Hz
879 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
884 ARDOUR_UI::update_sample_rate (nframes_t ignored)
888 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
890 if (!engine->connected()) {
892 snprintf (buf, sizeof (buf), _("disconnected"));
896 nframes_t rate = engine->frame_rate();
898 if (fmod (rate, 1000.0) != 0.0) {
899 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
900 (float) rate/1000.0f,
901 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
903 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
905 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
909 sample_rate_label.set_text (buf);
913 ARDOUR_UI::update_cpu_load ()
916 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
917 cpu_load_label.set_text (buf);
921 ARDOUR_UI::update_buffer_load ()
926 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
927 session->playback_load(), session->capture_load());
928 buffer_load_label.set_text (buf);
930 buffer_load_label.set_text ("");
935 ARDOUR_UI::count_recenabled_streams (Route& route)
937 Track* track = dynamic_cast<Track*>(&route);
938 if (track && track->diskstream()->record_enabled()) {
939 rec_enabled_streams += track->n_inputs();
944 ARDOUR_UI::update_disk_space()
950 nframes_t frames = session->available_capture_duration();
953 if (frames == max_frames) {
954 strcpy (buf, _("Disk: 24hrs+"));
959 nframes_t fr = session->frame_rate();
961 rec_enabled_streams = 0;
962 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
964 if (rec_enabled_streams) {
965 frames /= rec_enabled_streams;
968 hrs = frames / (fr * 3600);
969 frames -= hrs * fr * 3600;
970 mins = frames / (fr * 60);
971 frames -= mins * fr * 60;
974 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
977 disk_space_label.set_text (buf);
981 ARDOUR_UI::update_wall_clock ()
988 tm_now = localtime (&now);
990 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
991 wall_clock_label.set_text (buf);
997 ARDOUR_UI::session_menu (GdkEventButton *ev)
999 session_popup_menu->popup (0, 0);
1004 ARDOUR_UI::redisplay_recent_sessions ()
1006 vector<string *> *sessions;
1007 vector<string *>::iterator i;
1008 RecentSessionsSorter cmp;
1010 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1011 recent_session_model->clear ();
1014 ARDOUR::read_recent_sessions (rs);
1017 recent_session_display.set_model (recent_session_model);
1021 /* sort them alphabetically */
1022 sort (rs.begin(), rs.end(), cmp);
1023 sessions = new vector<string*>;
1025 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1026 sessions->push_back (new string ((*i).second));
1029 for (i = sessions->begin(); i != sessions->end(); ++i) {
1031 vector<string*>* states;
1032 vector<const gchar*> item;
1033 string fullpath = *(*i);
1035 /* remove any trailing / */
1037 if (fullpath[fullpath.length()-1] == '/') {
1038 fullpath = fullpath.substr (0, fullpath.length()-1);
1041 /* now get available states for this session */
1043 if ((states = Session::possible_states (fullpath)) == 0) {
1044 /* no state file? */
1048 TreeModel::Row row = *(recent_session_model->append());
1050 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1051 row[recent_session_columns.fullpath] = fullpath;
1053 if (states->size() > 1) {
1055 /* add the children */
1057 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1059 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1061 child_row[recent_session_columns.visible_name] = **i2;
1062 child_row[recent_session_columns.fullpath] = fullpath;
1071 recent_session_display.set_model (recent_session_model);
1076 ARDOUR_UI::build_session_selector ()
1078 session_selector_window = new ArdourDialog ("session selector");
1080 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1082 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1083 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1084 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1085 recent_session_model = TreeStore::create (recent_session_columns);
1086 recent_session_display.set_model (recent_session_model);
1087 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1088 recent_session_display.set_headers_visible (false);
1089 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1091 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1093 scroller->add (recent_session_display);
1094 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1096 session_selector_window->set_name ("SessionSelectorWindow");
1097 session_selector_window->set_size_request (200, 400);
1098 session_selector_window->get_vbox()->pack_start (*scroller);
1099 session_selector_window->show_all_children();
1103 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1105 session_selector_window->response (RESPONSE_ACCEPT);
1109 ARDOUR_UI::open_recent_session ()
1111 /* popup selector window */
1113 if (session_selector_window == 0) {
1114 build_session_selector ();
1117 redisplay_recent_sessions ();
1119 ResponseType r = (ResponseType) session_selector_window->run ();
1121 session_selector_window->hide();
1124 case RESPONSE_ACCEPT:
1130 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1132 if (i == recent_session_model->children().end()) {
1136 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1137 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1139 _session_is_new = false;
1141 load_session (path, state);
1145 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1147 struct stat statbuf;
1149 if (stat (info.filename.c_str(), &statbuf) != 0) {
1153 if (!S_ISDIR(statbuf.st_mode)) {
1159 string session_file = info.filename;
1160 session_file += '/';
1161 session_file += Glib::path_get_basename (info.filename);
1162 session_file += ".ardour";
1164 if (stat (session_file.c_str(), &statbuf) != 0) {
1168 return S_ISREG (statbuf.st_mode);
1172 ARDOUR_UI::check_audioengine ()
1175 if (!engine->connected()) {
1176 MessageDialog msg (_("Ardour is not connected to JACK\n"
1177 "You cannot open or close sessions in this condition"));
1188 ARDOUR_UI::open_session ()
1190 if (!check_audioengine()) {
1194 /* popup selector window */
1196 if (open_session_selector == 0) {
1198 /* ardour sessions are folders */
1200 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1201 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1202 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1203 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1205 FileFilter session_filter;
1206 session_filter.add_pattern ("*.ardour");
1207 session_filter.set_name (_("Ardour sessions"));
1208 open_session_selector->add_filter (session_filter);
1209 open_session_selector->set_filter (session_filter);
1212 int response = open_session_selector->run();
1213 open_session_selector->hide ();
1216 case RESPONSE_ACCEPT:
1219 open_session_selector->hide();
1223 open_session_selector->hide();
1224 string session_path = open_session_selector->get_filename();
1228 if (session_path.length() > 0) {
1229 if (Session::find_session (session_path, path, name, isnew) == 0) {
1230 _session_is_new = isnew;
1231 load_session (path, name);
1238 ARDOUR_UI::session_add_midi_track ()
1240 cerr << _("Patience is a virtue.\n");
1244 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1246 list<boost::shared_ptr<AudioTrack> > tracks;
1247 Session::RouteList routes;
1250 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1256 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1258 if (tracks.size() != how_many) {
1259 if (how_many == 1) {
1260 error << _("could not create a new audio track") << endmsg;
1262 error << string_compose (_("could only create %1 of %2 new audio %3"),
1263 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1269 routes = session->new_audio_route (input_channels, output_channels, how_many);
1271 if (routes.size() != how_many) {
1272 if (how_many == 1) {
1273 error << _("could not create a new audio track") << endmsg;
1275 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1281 if (need_control_room_outs) {
1287 route->set_stereo_control_outs (control_lr_channels);
1288 route->control_outs()->set_stereo_pan (pans, this);
1290 #endif /* CONTROLOUTS */
1294 cerr << "About to complain about JACK\n";
1295 MessageDialog msg (*editor,
1296 _("There are insufficient JACK ports available\n\
1297 to create a new track or bus.\n\
1298 You should save Ardour, exit and\n\
1299 restart JACK with more ports."));
1305 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1307 nframes_t _preroll = 0;
1310 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1311 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1313 if (new_position > _preroll) {
1314 new_position -= _preroll;
1319 session->request_locate (new_position);
1324 ARDOUR_UI::transport_goto_start ()
1327 session->goto_start();
1330 /* force displayed area in editor to start no matter
1331 what "follow playhead" setting is.
1335 editor->reset_x_origin (session->current_start_frame());
1341 ARDOUR_UI::transport_goto_zero ()
1344 session->request_locate (0);
1347 /* force displayed area in editor to start no matter
1348 what "follow playhead" setting is.
1352 editor->reset_x_origin (0);
1358 ARDOUR_UI::transport_goto_end ()
1361 nframes_t frame = session->current_end_frame();
1362 session->request_locate (frame);
1364 /* force displayed area in editor to start no matter
1365 what "follow playhead" setting is.
1369 editor->reset_x_origin (frame);
1375 ARDOUR_UI::transport_stop ()
1381 if (session->is_auditioning()) {
1382 session->cancel_audition ();
1386 if (session->get_play_loop ()) {
1387 session->request_play_loop (false);
1390 session->request_stop ();
1394 ARDOUR_UI::transport_stop_and_forget_capture ()
1397 session->request_stop (true);
1402 ARDOUR_UI::remove_last_capture()
1405 editor->remove_last_capture();
1410 ARDOUR_UI::transport_record (bool roll)
1413 switch (session->record_status()) {
1414 case Session::Disabled:
1415 if (session->ntracks() == 0) {
1416 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1420 session->maybe_enable_record ();
1425 case Session::Recording:
1427 session->request_stop();
1429 session->disable_record (false, true);
1433 case Session::Enabled:
1434 session->disable_record (false, true);
1440 ARDOUR_UI::transport_roll ()
1448 rolling = session->transport_rolling ();
1450 if (session->get_play_loop()) {
1451 session->request_play_loop (false);
1452 auto_loop_button.set_visual_state (1);
1453 roll_button.set_visual_state (1);
1454 } else if (session->get_play_range ()) {
1455 session->request_play_range (false);
1456 play_selection_button.set_visual_state (0);
1457 } else if (rolling) {
1458 session->request_locate (session->last_transport_start(), true);
1461 session->request_transport_speed (1.0f);
1465 ARDOUR_UI::transport_loop()
1468 if (session->get_play_loop()) {
1469 if (session->transport_rolling()) {
1470 Location * looploc = session->locations()->auto_loop_location();
1472 session->request_locate (looploc->start(), true);
1477 session->request_play_loop (true);
1483 ARDOUR_UI::transport_play_selection ()
1489 if (!session->get_play_range()) {
1490 session->request_stop ();
1493 editor->play_selection ();
1497 ARDOUR_UI::transport_rewind (int option)
1499 float current_transport_speed;
1502 current_transport_speed = session->transport_speed();
1504 if (current_transport_speed >= 0.0f) {
1507 session->request_transport_speed (-1.0f);
1510 session->request_transport_speed (-4.0f);
1513 session->request_transport_speed (-0.5f);
1518 session->request_transport_speed (current_transport_speed * 1.5f);
1524 ARDOUR_UI::transport_forward (int option)
1526 float current_transport_speed;
1529 current_transport_speed = session->transport_speed();
1531 if (current_transport_speed <= 0.0f) {
1534 session->request_transport_speed (1.0f);
1537 session->request_transport_speed (4.0f);
1540 session->request_transport_speed (0.5f);
1545 session->request_transport_speed (current_transport_speed * 1.5f);
1551 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1557 boost::shared_ptr<Route> r;
1559 if ((r = session->route_by_remote_id (dstream)) != 0) {
1563 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1564 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1573 ARDOUR_UI::queue_transport_change ()
1575 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1579 ARDOUR_UI::map_transport_state ()
1581 float sp = session->transport_speed();
1584 transport_rolling ();
1585 } else if (sp < 0.0f) {
1586 transport_rewinding ();
1587 } else if (sp > 0.0f) {
1588 transport_forwarding ();
1590 transport_stopped ();
1595 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1597 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1598 (int) adj.get_value()].c_str());
1602 ARDOUR_UI::engine_stopped ()
1604 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1605 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1606 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1610 ARDOUR_UI::engine_running ()
1612 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1613 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1614 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1616 Glib::RefPtr<Action> action;
1617 char* action_name = 0;
1619 switch (engine->frames_per_cycle()) {
1621 action_name = X_("JACKLatency32");
1624 action_name = X_("JACKLatency64");
1627 action_name = X_("JACKLatency128");
1630 action_name = X_("JACKLatency512");
1633 action_name = X_("JACKLatency1024");
1636 action_name = X_("JACKLatency2048");
1639 action_name = X_("JACKLatency4096");
1642 action_name = X_("JACKLatency8192");
1645 /* XXX can we do anything useful ? */
1651 action = ActionManager::get_action (X_("JACK"), action_name);
1654 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1655 ract->set_active ();
1661 ARDOUR_UI::engine_halted ()
1663 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1665 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1666 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1668 update_sample_rate (0);
1670 MessageDialog msg (*editor,
1672 JACK has either been shutdown or it\n\
1673 disconnected Ardour because Ardour\n\
1674 was not fast enough. You can save the\n\
1675 session and/or try to reconnect to JACK ."));
1680 ARDOUR_UI::do_engine_start ()
1688 error << _("Unable to start the session running")
1698 ARDOUR_UI::setup_theme ()
1700 theme_manager->setup_theme();
1704 ARDOUR_UI::update_clocks ()
1706 if (!editor || !editor->dragging_playhead()) {
1707 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1712 ARDOUR_UI::start_clocking ()
1714 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1718 ARDOUR_UI::stop_clocking ()
1720 clock_signal_connection.disconnect ();
1724 ARDOUR_UI::toggle_clocking ()
1727 if (clock_button.get_active()) {
1736 ARDOUR_UI::_blink (void *arg)
1739 ((ARDOUR_UI *) arg)->blink ();
1746 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1750 ARDOUR_UI::start_blinking ()
1752 /* Start the blink signal. Everybody with a blinking widget
1753 uses Blink to drive the widget's state.
1756 if (blink_timeout_tag < 0) {
1758 blink_timeout_tag = g_timeout_add (240, _blink, this);
1763 ARDOUR_UI::stop_blinking ()
1765 if (blink_timeout_tag >= 0) {
1766 g_source_remove (blink_timeout_tag);
1767 blink_timeout_tag = -1;
1772 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1778 if (io.n_inputs() == 0) {
1783 /* XXX we're not handling multiple ports yet. */
1785 const char **connections = io.input(0)->get_connections();
1787 if (connections == 0 || connections[0] == '\0') {
1790 buf = connections[0];
1797 if (io.n_outputs() == 0) {
1802 /* XXX we're not handling multiple ports yet. */
1804 const char **connections = io.output(0)->get_connections();
1806 if (connections == 0 || connections[0] == '\0') {
1809 buf = connections[0];
1816 /** Ask the user for the name of a new shapshot and then take it.
1819 ARDOUR_UI::snapshot_session ()
1821 ArdourPrompter prompter (true);
1825 struct tm local_time;
1828 localtime_r (&n, &local_time);
1829 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1831 prompter.set_name ("Prompter");
1832 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1833 prompter.set_prompt (_("Name of New Snapshot"));
1834 prompter.set_initial_text (timebuf);
1836 switch (prompter.run()) {
1837 case RESPONSE_ACCEPT:
1838 prompter.get_result (snapname);
1839 if (snapname.length()){
1840 save_state (snapname);
1850 ARDOUR_UI::save_state (const string & name)
1852 (void) save_state_canfail (name);
1856 ARDOUR_UI::save_state_canfail (string name)
1861 if (name.length() == 0) {
1862 name = session->snap_name();
1865 if ((ret = session->save_state (name)) != 0) {
1869 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1874 ARDOUR_UI::restore_state (string name)
1877 if (name.length() == 0) {
1878 name = session->name();
1880 session->restore_state (name);
1885 ARDOUR_UI::primary_clock_value_changed ()
1888 session->request_locate (primary_clock.current_time ());
1893 ARDOUR_UI::big_clock_value_changed ()
1896 session->request_locate (big_clock.current_time ());
1901 ARDOUR_UI::secondary_clock_value_changed ()
1904 session->request_locate (secondary_clock.current_time ());
1909 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1911 if (session && dstream && dstream->record_enabled()) {
1913 Session::RecordState rs;
1915 rs = session->record_status ();
1918 case Session::Disabled:
1919 case Session::Enabled:
1920 if (w->get_state() != STATE_SELECTED) {
1921 w->set_state (STATE_SELECTED);
1925 case Session::Recording:
1926 if (w->get_state() != STATE_ACTIVE) {
1927 w->set_state (STATE_ACTIVE);
1933 if (w->get_state() != STATE_NORMAL) {
1934 w->set_state (STATE_NORMAL);
1940 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1946 switch (session->record_status()) {
1947 case Session::Enabled:
1949 rec_button.set_visual_state (2);
1951 rec_button.set_visual_state (0);
1955 case Session::Recording:
1956 rec_button.set_visual_state (1);
1960 rec_button.set_visual_state (0);
1966 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1974 ARDOUR_UI::save_template ()
1977 ArdourPrompter prompter (true);
1980 if (!check_audioengine()) {
1984 prompter.set_name (X_("Prompter"));
1985 prompter.set_prompt (_("Name for mix template:"));
1986 prompter.set_initial_text(session->name() + _("-template"));
1987 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1989 switch (prompter.run()) {
1990 case RESPONSE_ACCEPT:
1991 prompter.get_result (name);
1993 if (name.length()) {
1994 session->save_template (name);
2004 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2006 string session_name;
2007 string session_path;
2008 string template_name;
2010 if (!loading_dialog) {
2011 loading_dialog = new MessageDialog (*new_session_dialog,
2018 int response = Gtk::RESPONSE_NONE;
2020 new_session_dialog->set_modal(true);
2021 new_session_dialog->set_name (predetermined_path);
2022 new_session_dialog->reset_recent();
2023 new_session_dialog->set_position (WIN_POS_CENTER);
2024 new_session_dialog->set_current_page (0);
2027 new_session_dialog->set_have_engine (have_engine);
2029 new_session_dialog->show();
2030 new_session_dialog->present ();
2031 response = new_session_dialog->run ();
2033 loading_dialog->hide ();
2035 _session_is_new = false;
2037 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2042 new_session_dialog->hide ();
2045 } else if (response == Gtk::RESPONSE_NONE) {
2047 /* Clear was pressed */
2048 new_session_dialog->reset();
2052 /* first things first ... if we're here to help set up audio parameters
2053 this is where want to do that.
2057 if (new_session_dialog->engine_control.setup_engine ()) {
2058 new_session_dialog->hide ();
2064 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2065 may not and it can take a while to build it. Warn them.
2068 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2070 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2071 MessageDialog msg (*new_session_dialog,
2072 _("Welcome to Ardour.\n\n"
2073 "The program will take a bit longer to start up\n"
2074 "while the system fonts are checked.\n\n"
2075 "This will only be done once, and you will\n"
2076 "not see this message again\n"),
2085 loading_dialog->set_message (_("Starting audio engine"));
2086 loading_dialog->show_all ();
2089 if (create_engine ()) {
2090 backend_audio_error (!have_engine, new_session_dialog);
2091 loading_dialog->hide ();
2093 /* audio setup page */
2094 new_session_dialog->set_current_page (2);
2096 response = Gtk::RESPONSE_NONE;
2102 /* now handle possible affirmative responses */
2104 if (response == Gtk::RESPONSE_YES) {
2106 /* YES == OPEN from the session selector */
2108 session_name = new_session_dialog->session_name();
2110 if (session_name.empty()) {
2111 response = Gtk::RESPONSE_NONE;
2115 if (session_name[0] == '/' ||
2116 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2117 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2118 load_session (Glib::path_get_dirname (session_name), session_name);
2120 session_path = new_session_dialog->session_folder();
2121 load_session (session_path, session_name);
2124 } else if (response == Gtk::RESPONSE_OK) {
2126 /* OK == OPEN button */
2128 session_name = new_session_dialog->session_name();
2130 if (session_name.empty()) {
2131 response = Gtk::RESPONSE_NONE;
2135 switch (new_session_dialog->get_current_page()) {
2136 case 1: /* recent session selector */
2137 case 2: /* audio engine control */
2139 if (session_name[0] == '/' ||
2140 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2141 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2142 load_session (Glib::path_get_dirname (session_name), session_name);
2144 session_path = new_session_dialog->session_folder();
2145 load_session (session_path, session_name);
2149 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2151 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2152 should_be_new = true;
2155 /* handle what appear to be paths rather than just a name */
2157 if (session_name[0] == '/' ||
2158 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2159 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2161 session_path = Glib::path_get_dirname (session_name);
2162 session_name = Glib::path_get_basename (session_name);
2166 session_path = new_session_dialog->session_folder();
2170 //XXX This is needed because session constructor wants a
2171 //non-existant path. hopefully this will be fixed at some point.
2173 session_path = Glib::build_filename (session_path, session_name);
2175 if (!should_be_new) {
2177 load_session (session_path, session_name);
2178 continue; /* leaves while() loop because response != NONE */
2180 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2182 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2184 MessageDialog msg (str,
2186 Gtk::MESSAGE_WARNING,
2187 Gtk::BUTTONS_YES_NO,
2191 msg.set_name (X_("CleanupDialog"));
2192 msg.set_wmclass (X_("existing_session"), "Ardour");
2193 msg.set_position (Gtk::WIN_POS_MOUSE);
2195 switch (msg.run()) {
2197 new_session_dialog->hide ();
2198 goto_editor_window ();
2200 load_session (session_path, session_name);
2204 response = RESPONSE_NONE;
2205 new_session_dialog->reset ();
2210 _session_is_new = true;
2212 if (new_session_dialog->use_session_template()) {
2214 template_name = new_session_dialog->session_template_name();
2216 new_session_dialog->hide ();
2217 goto_editor_window ();
2220 load_session (session_path, session_name, &template_name);
2226 AutoConnectOption iconnect;
2227 AutoConnectOption oconnect;
2231 if (Profile->get_sae()) {
2235 iconnect = AutoConnectPhysical;
2236 oconnect = AutoConnectMaster;
2237 nphysin = 0; // use all available
2238 nphysout = 0; // use all available
2242 /* get settings from advanced section of NSD */
2244 if (new_session_dialog->create_control_bus()) {
2245 cchns = (uint32_t) new_session_dialog->control_channel_count();
2250 if (new_session_dialog->create_master_bus()) {
2251 mchns = (uint32_t) new_session_dialog->master_channel_count();
2256 if (new_session_dialog->connect_inputs()) {
2257 iconnect = AutoConnectPhysical;
2259 iconnect = AutoConnectOption (0);
2262 /// @todo some minor tweaks.
2264 if (new_session_dialog->connect_outs_to_master()) {
2265 oconnect = AutoConnectMaster;
2266 } else if (new_session_dialog->connect_outs_to_physical()) {
2267 oconnect = AutoConnectPhysical;
2269 oconnect = AutoConnectOption (0);
2272 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2273 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2276 new_session_dialog->hide ();
2277 goto_editor_window ();
2280 if (build_session (session_path,
2288 engine->frame_rate() * 60 * 5)) {
2290 response = Gtk::RESPONSE_NONE;
2291 new_session_dialog->reset ();
2302 } while (response == Gtk::RESPONSE_NONE);
2306 loading_dialog->hide ();
2307 new_session_dialog->hide();
2312 ARDOUR_UI::close_session ()
2314 if (!check_audioengine()) {
2318 unload_session (true);
2320 get_session_parameters ("", true, false);
2324 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2326 Session *new_session;
2330 session_loaded = false;
2332 if (!check_audioengine()) {
2336 unload_status = unload_session ();
2338 if (unload_status < 0) {
2340 } else if (unload_status > 0) {
2345 /* if it already exists, we must have write access */
2347 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2348 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2349 "This prevents the session from being loaded."));
2354 if (loading_dialog) {
2355 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2359 disable_screen_updates ();
2362 new_session = new Session (*engine, path, snap_name, mix_template);
2366 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2370 connect_to_session (new_session);
2372 Config->set_current_owner (ConfigVariableBase::Interface);
2374 session_loaded = true;
2376 goto_editor_window ();
2379 session->set_clean ();
2382 enable_screen_updates ();
2391 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2392 uint32_t control_channels,
2393 uint32_t master_channels,
2394 AutoConnectOption input_connect,
2395 AutoConnectOption output_connect,
2398 nframes_t initial_length)
2400 Session *new_session;
2403 if (!check_audioengine()) {
2407 session_loaded = false;
2409 x = unload_session ();
2417 _session_is_new = true;
2420 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2421 control_channels, master_channels, nphysin, nphysout, initial_length);
2426 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2431 connect_to_session (new_session);
2433 session_loaded = true;
2441 editor->show_window ();
2452 ARDOUR_UI::show_splash ()
2455 about = new About();
2456 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2463 ARDOUR_UI::about_signal_response(int response)
2469 ARDOUR_UI::hide_splash ()
2472 about->get_window()->set_cursor ();
2478 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2482 removed = rep.paths.size();
2485 MessageDialog msgd (*editor,
2486 _("No audio files were ready for cleanup"),
2489 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2490 msgd.set_secondary_text (_("If this seems suprising, \n\
2491 check for any existing snapshots.\n\
2492 These may still include regions that\n\
2493 require some unused files to continue to exist."));
2499 ArdourDialog results (_("ardour: cleanup"), true, false);
2501 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2502 CleanupResultsModelColumns() {
2506 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2507 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2511 CleanupResultsModelColumns results_columns;
2512 Glib::RefPtr<Gtk::ListStore> results_model;
2513 Gtk::TreeView results_display;
2515 results_model = ListStore::create (results_columns);
2516 results_display.set_model (results_model);
2517 results_display.append_column (list_title, results_columns.visible_name);
2519 results_display.set_name ("CleanupResultsList");
2520 results_display.set_headers_visible (true);
2521 results_display.set_headers_clickable (false);
2522 results_display.set_reorderable (false);
2524 Gtk::ScrolledWindow list_scroller;
2527 Gtk::HBox dhbox; // the hbox for the image and text
2528 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2529 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2531 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2533 if (rep.space < 1048576.0f) {
2535 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2537 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2541 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2543 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2547 dhbox.pack_start (*dimage, true, false, 5);
2548 dhbox.pack_start (txt, true, false, 5);
2550 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2551 TreeModel::Row row = *(results_model->append());
2552 row[results_columns.visible_name] = *i;
2553 row[results_columns.fullpath] = *i;
2556 list_scroller.add (results_display);
2557 list_scroller.set_size_request (-1, 150);
2558 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2560 dvbox.pack_start (dhbox, true, false, 5);
2561 dvbox.pack_start (list_scroller, true, false, 5);
2562 ddhbox.pack_start (dvbox, true, false, 5);
2564 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2565 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2566 results.set_default_response (RESPONSE_CLOSE);
2567 results.set_position (Gtk::WIN_POS_MOUSE);
2568 results.show_all_children ();
2569 results.set_resizable (false);
2576 ARDOUR_UI::cleanup ()
2579 /* shouldn't happen: menu item is insensitive */
2584 MessageDialog checker (_("Are you sure you want to cleanup?"),
2586 Gtk::MESSAGE_QUESTION,
2587 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2589 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2590 ALL undo/redo information will be lost if you cleanup.\n\
2591 After cleanup, unused audio files will be moved to a \
2592 \"dead sounds\" location."));
2594 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2595 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2596 checker.set_default_response (RESPONSE_CANCEL);
2598 checker.set_name (_("CleanupDialog"));
2599 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2600 checker.set_position (Gtk::WIN_POS_MOUSE);
2602 switch (checker.run()) {
2603 case RESPONSE_ACCEPT:
2609 Session::cleanup_report rep;
2611 editor->prepare_for_cleanup ();
2613 /* do not allow flush until a session is reloaded */
2615 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2617 act->set_sensitive (false);
2620 if (session->cleanup_sources (rep)) {
2625 display_cleanup_results (rep,
2628 The following %1 %2 not in use and \n\
2629 have been moved to:\n\
2631 Flushing the wastebasket will \n\
2632 release an additional\n\
2633 %4 %5bytes of disk space.\n"
2641 ARDOUR_UI::flush_trash ()
2644 /* shouldn't happen: menu item is insensitive */
2648 Session::cleanup_report rep;
2650 if (session->cleanup_trash_sources (rep)) {
2654 display_cleanup_results (rep,
2656 _("The following %1 %2 deleted from\n\
2658 releasing %4 %5bytes of disk space"));
2662 ARDOUR_UI::add_route (Gtk::Window* float_window)
2670 if (add_route_dialog == 0) {
2671 add_route_dialog = new AddRouteDialog;
2673 add_route_dialog->set_transient_for (*float_window);
2677 if (add_route_dialog->is_visible()) {
2678 /* we're already doing this */
2682 ResponseType r = (ResponseType) add_route_dialog->run ();
2684 add_route_dialog->hide();
2687 case RESPONSE_ACCEPT:
2694 if ((count = add_route_dialog->count()) <= 0) {
2698 uint32_t input_chan = add_route_dialog->channels ();
2699 uint32_t output_chan;
2700 string name_template = add_route_dialog->name_template ();
2701 bool track = add_route_dialog->track ();
2703 AutoConnectOption oac = Config->get_output_auto_connect();
2705 if (oac & AutoConnectMaster) {
2706 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2708 output_chan = input_chan;
2711 /* XXX do something with name template */
2714 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2716 session_add_audio_bus (input_chan, output_chan, count);
2721 ARDOUR_UI::mixer_settings () const
2726 node = session->instant_xml(X_("Mixer"), session->path());
2728 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2732 node = new XMLNode (X_("Mixer"));
2739 ARDOUR_UI::editor_settings () const
2744 node = session->instant_xml(X_("Editor"), session->path());
2746 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2750 node = new XMLNode (X_("Editor"));
2756 ARDOUR_UI::keyboard_settings () const
2760 node = Config->extra_xml(X_("Keyboard"));
2763 node = new XMLNode (X_("Keyboard"));
2769 ARDOUR_UI::halt_on_xrun_message ()
2771 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2773 MessageDialog msg (*editor,
2774 _("Recording was stopped because your system could not keep up."));
2779 ARDOUR_UI::disk_overrun_handler ()
2781 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2783 if (!have_disk_speed_dialog_displayed) {
2784 have_disk_speed_dialog_displayed = true;
2785 MessageDialog* msg = new MessageDialog (*editor, _("\
2786 The disk system on your computer\n\
2787 was not able to keep up with Ardour.\n\
2789 Specifically, it failed to write data to disk\n\
2790 quickly enough to keep up with recording.\n"));
2791 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2797 ARDOUR_UI::disk_underrun_handler ()
2799 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2801 if (!have_disk_speed_dialog_displayed) {
2802 have_disk_speed_dialog_displayed = true;
2803 MessageDialog* msg = new MessageDialog (*editor,
2804 _("The disk system on your computer\n\
2805 was not able to keep up with Ardour.\n\
2807 Specifically, it failed to read data from disk\n\
2808 quickly enough to keep up with playback.\n"));
2809 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2815 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2817 have_disk_speed_dialog_displayed = false;
2822 ARDOUR_UI::pending_state_dialog ()
2824 ArdourDialog dialog ("pending state dialog");
2826 This session appears to have been in\n\
2827 middle of recording when ardour or\n\
2828 the computer was shutdown.\n\
2830 Ardour can recover any captured audio for\n\
2831 you, or it can ignore it. Please decide\n\
2832 what you would like to do.\n"));
2834 dialog.get_vbox()->pack_start (message);
2835 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2836 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2838 dialog.set_position (WIN_POS_CENTER);
2841 switch (dialog.run ()) {
2842 case RESPONSE_ACCEPT:
2850 ARDOUR_UI::disconnect_from_jack ()
2853 if( engine->disconnect_from_jack ()) {
2854 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2858 update_sample_rate (0);
2863 ARDOUR_UI::reconnect_to_jack ()
2866 if (engine->reconnect_to_jack ()) {
2867 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2871 update_sample_rate (0);
2876 ARDOUR_UI::cmdline_new_session (string path)
2878 if (path[0] != '/') {
2879 char buf[PATH_MAX+1];
2882 getcwd (buf, sizeof (buf));
2889 get_session_parameters (path, false, true);
2891 _will_create_new_session_automatically = false; /* done it */
2892 return FALSE; /* don't call it again */
2896 ARDOUR_UI::use_config ()
2898 Glib::RefPtr<Action> act;
2900 switch (Config->get_native_file_data_format ()) {
2902 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2905 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2908 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2913 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2914 ract->set_active ();
2917 switch (Config->get_native_file_header_format ()) {
2919 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2922 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2925 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2928 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2931 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2934 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2937 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2942 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2943 ract->set_active ();
2946 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2948 set_transport_controllable_state (*node);
2953 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2955 if (Config->get_primary_clock_delta_edit_cursor()) {
2956 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
2958 primary_clock.set (pos, 0, true);
2961 if (Config->get_secondary_clock_delta_edit_cursor()) {
2962 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
2964 secondary_clock.set (pos);
2967 if (big_clock_window) {
2968 big_clock.set (pos);
2973 ARDOUR_UI::record_state_changed ()
2975 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2977 if (!session || !big_clock_window) {
2978 /* why bother - the clock isn't visible */
2982 switch (session->record_status()) {
2983 case Session::Recording:
2984 big_clock.set_widget_name ("BigClockRecording");
2987 big_clock.set_widget_name ("BigClockNonRecording");
2993 ARDOUR_UI::set_keybindings_path (string path)
2995 keybindings_path = path;
2999 ARDOUR_UI::save_keybindings ()
3001 if (can_save_keybindings) {
3002 AccelMap::save (user_keybindings_path);
3007 ARDOUR_UI::first_idle ()
3010 session->allow_auto_play (true);
3012 can_save_keybindings = true;
3017 ARDOUR_UI::store_clock_modes ()
3019 XMLNode* node = new XMLNode(X_("ClockModes"));
3021 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3022 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3025 session->add_extra_xml (*node);
3026 session->set_dirty ();
3031 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3032 : Controllable (name), ui (u), type(tp)
3038 ARDOUR_UI::TransportControllable::set_value (float val)
3040 if (type == ShuttleControl) {
3047 fract = -((0.5f - val)/0.5f);
3049 fract = ((val - 0.5f)/0.5f);
3053 ui.set_shuttle_fract (fract);
3058 /* do nothing: these are radio-style actions */
3066 action = X_("Roll");
3069 action = X_("Stop");
3072 action = X_("Goto Start");
3075 action = X_("Goto End");
3078 action = X_("Loop");
3081 action = X_("Play Selection");
3084 action = X_("Record");
3094 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3102 ARDOUR_UI::TransportControllable::get_value (void) const
3121 case ShuttleControl:
3131 ARDOUR_UI::TransportControllable::set_id (const string& str)
3137 ARDOUR_UI::setup_profile ()
3139 if (gdk_screen_width() < 1200) {
3140 Profile->set_small_screen ();
3143 if (getenv ("ARDOUR_SAE")) {
3144 Profile->set_sae ();
3145 Profile->set_single_package ();