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.
20 #define __STDC_FORMAT_MACROS 1
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
40 #include <pbd/compose.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/memento_command.h>
44 #include <pbd/file_utils.h>
46 #include <gtkmm2ext/gtk_ui.h>
47 #include <gtkmm2ext/utils.h>
48 #include <gtkmm2ext/click_box.h>
49 #include <gtkmm2ext/fastmeter.h>
50 #include <gtkmm2ext/stop_signal.h>
51 #include <gtkmm2ext/popup.h>
52 #include <gtkmm2ext/window_title.h>
54 #include <midi++/manager.h>
56 #include <ardour/ardour.h>
57 #include <ardour/profile.h>
58 #include <ardour/session_directory.h>
59 #include <ardour/session_route.h>
60 #include <ardour/session_state_utils.h>
61 #include <ardour/session_utils.h>
62 #include <ardour/port.h>
63 #include <ardour/audioengine.h>
64 #include <ardour/playlist.h>
65 #include <ardour/utils.h>
66 #include <ardour/audio_diskstream.h>
67 #include <ardour/audiofilesource.h>
68 #include <ardour/recent_sessions.h>
69 #include <ardour/port.h>
70 #include <ardour/audio_track.h>
71 #include <ardour/midi_track.h>
72 #include <ardour/filesystem_paths.h>
75 #include "ardour_ui.h"
76 #include "public_editor.h"
77 #include "audio_clock.h"
82 #include "add_route_dialog.h"
83 #include "new_session_dialog.h"
86 #include "gui_thread.h"
87 #include "theme_manager.h"
92 using namespace ARDOUR;
94 using namespace Gtkmm2ext;
98 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
99 UIConfiguration *ARDOUR_UI::ui_config = 0;
101 sigc::signal<void,bool> ARDOUR_UI::Blink;
102 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
103 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
104 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
106 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
108 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
110 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
111 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
112 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
113 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
117 adjuster_table (3, 3),
121 preroll_button (_("pre\nroll")),
122 postroll_button (_("post\nroll")),
126 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
130 roll_controllable ("transport roll", *this, TransportControllable::Roll),
131 stop_controllable ("transport stop", *this, TransportControllable::Stop),
132 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
133 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
134 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
135 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
136 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
137 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
138 shuttle_controller_binding_proxy (shuttle_controllable),
140 roll_button (roll_controllable),
141 stop_button (stop_controllable),
142 goto_start_button (goto_start_controllable),
143 goto_end_button (goto_end_controllable),
144 auto_loop_button (auto_loop_controllable),
145 play_selection_button (play_selection_controllable),
146 rec_button (rec_controllable),
148 shuttle_units_button (_("% ")),
150 punch_in_button (_("Punch In")),
151 punch_out_button (_("Punch Out")),
152 auto_return_button (_("Auto Return")),
153 auto_play_button (_("Auto Play")),
154 auto_input_button (_("Auto Input")),
155 click_button (_("Click")),
156 time_master_button (_("time\nmaster")),
158 auditioning_alert_button (_("AUDITION")),
159 solo_alert_button (_("SOLO")),
161 error_log_button (_("Errors"))
164 using namespace Gtk::Menu_Helpers;
170 _auto_display_errors = false;
174 if (theArdourUI == 0) {
178 ui_config = new UIConfiguration();
179 theme_manager = new ThemeManager();
184 _session_is_new = false;
185 big_clock_window = 0;
186 session_selector_window = 0;
187 last_key_press_time = 0;
188 connection_editor = 0;
189 _will_create_new_session_automatically = false;
190 new_session_dialog = 0;
192 add_route_dialog = 0;
196 open_session_selector = 0;
197 have_configure_timeout = false;
198 have_disk_speed_dialog_displayed = false;
199 session_loaded = false;
200 last_speed_displayed = -1.0f;
203 sys::path key_bindings_file;
205 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
206 "ardour.bindings", key_bindings_file);
208 keybindings_path = key_bindings_file.to_string();
210 /* store all bindings changes in per-user file, no matter where they were loaded from */
211 user_keybindings_path = user_config_directory().to_string ();
212 user_keybindings_path += '/';
213 user_keybindings_path += "ardour.bindings";
215 can_save_keybindings = false;
217 last_configure_time.tv_sec = 0;
218 last_configure_time.tv_usec = 0;
220 shuttle_grabbed = false;
222 shuttle_max_speed = 8.0f;
224 shuttle_style_menu = 0;
225 shuttle_unit_menu = 0;
227 gettimeofday (&last_peak_grab, 0);
228 gettimeofday (&last_shuttle_request, 0);
230 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
231 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
233 /* handle pending state with a dialog */
235 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
237 /* lets get this party started */
240 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
241 setup_gtk_ardour_enums ();
242 Config->set_current_owner (ConfigVariableBase::Interface);
245 } catch (failed_constructor& err) {
246 error << _("could not initialize Ardour.") << endmsg;
251 /* we like keyboards */
253 keyboard = new Keyboard;
255 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
256 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
258 platform_specific ();
262 ARDOUR_UI::create_engine ()
264 // this gets called every time by new_session()
271 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
278 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
279 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
280 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
281 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
289 ARDOUR_UI::post_engine ()
291 extern int setup_midi ();
293 /* Things to be done once we create the AudioEngine
296 MIDI::Manager::instance()->set_api_data (engine->jack());
299 ActionManager::init ();
302 if (setup_windows ()) {
303 throw failed_constructor ();
306 check_memory_locking();
308 /* this is the first point at which all the keybindings are available */
310 if (ARDOUR_COMMAND_LINE::show_key_actions) {
311 vector<string> names;
312 vector<string> paths;
314 vector<AccelKey> bindings;
316 ActionManager::get_all_actions (names, paths, keys, bindings);
318 vector<string>::iterator n;
319 vector<string>::iterator k;
320 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
321 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
327 blink_timeout_tag = -1;
329 /* the global configuration object is now valid */
333 /* this being a GUI and all, we want peakfiles */
335 AudioFileSource::set_build_peakfiles (true);
336 AudioFileSource::set_build_missing_peakfiles (true);
338 /* set default clock modes */
340 primary_clock.set_mode (AudioClock::SMPTE);
341 secondary_clock.set_mode (AudioClock::BBT);
343 /* start the time-of-day-clock */
346 /* OS X provides an always visible wallclock, so don't be stupid */
347 update_wall_clock ();
348 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
351 update_disk_space ();
353 update_sample_rate (engine->frame_rate());
355 /* now start and maybe save state */
357 if (do_engine_start () == 0) {
358 if (session && _session_is_new) {
359 /* we need to retain initial visual
360 settings for a new session
362 session->save_state ("");
367 ARDOUR_UI::~ARDOUR_UI ()
369 save_ardour_state ();
383 if (add_route_dialog) {
384 delete add_route_dialog;
388 if (new_session_dialog) {
389 delete new_session_dialog;
394 ARDOUR_UI::configure_timeout ()
399 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
400 /* no configure events yet */
404 gettimeofday (&now, 0);
405 timersub (&now, &last_configure_time, &diff);
407 /* force a gap of 0.5 seconds since the last configure event
410 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
413 have_configure_timeout = false;
414 save_ardour_state ();
420 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
422 if (have_configure_timeout) {
423 gettimeofday (&last_configure_time, 0);
425 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
426 have_configure_timeout = true;
433 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
435 const XMLProperty* prop;
437 if ((prop = node.property ("roll")) != 0) {
438 roll_controllable.set_id (prop->value());
440 if ((prop = node.property ("stop")) != 0) {
441 stop_controllable.set_id (prop->value());
443 if ((prop = node.property ("goto_start")) != 0) {
444 goto_start_controllable.set_id (prop->value());
446 if ((prop = node.property ("goto_end")) != 0) {
447 goto_end_controllable.set_id (prop->value());
449 if ((prop = node.property ("auto_loop")) != 0) {
450 auto_loop_controllable.set_id (prop->value());
452 if ((prop = node.property ("play_selection")) != 0) {
453 play_selection_controllable.set_id (prop->value());
455 if ((prop = node.property ("rec")) != 0) {
456 rec_controllable.set_id (prop->value());
458 if ((prop = node.property ("shuttle")) != 0) {
459 shuttle_controllable.set_id (prop->value());
464 ARDOUR_UI::get_transport_controllable_state ()
466 XMLNode* node = new XMLNode(X_("TransportControllables"));
469 roll_controllable.id().print (buf, sizeof (buf));
470 node->add_property (X_("roll"), buf);
471 stop_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("stop"), buf);
473 goto_start_controllable.id().print (buf, sizeof (buf));
474 node->add_property (X_("goto_start"), buf);
475 goto_end_controllable.id().print (buf, sizeof (buf));
476 node->add_property (X_("goto_end"), buf);
477 auto_loop_controllable.id().print (buf, sizeof (buf));
478 node->add_property (X_("auto_loop"), buf);
479 play_selection_controllable.id().print (buf, sizeof (buf));
480 node->add_property (X_("play_selection"), buf);
481 rec_controllable.id().print (buf, sizeof (buf));
482 node->add_property (X_("rec"), buf);
483 shuttle_controllable.id().print (buf, sizeof (buf));
484 node->add_property (X_("shuttle"), buf);
490 ARDOUR_UI::save_ardour_state ()
492 if (!keyboard || !mixer || !editor) {
496 /* XXX this is all a bit dubious. add_extra_xml() uses
497 a different lifetime model from add_instant_xml().
500 XMLNode* node = new XMLNode (keyboard->get_state());
501 Config->add_extra_xml (*node);
502 Config->add_extra_xml (get_transport_controllable_state());
503 Config->save_state();
505 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
506 XMLNode mnode(mixer->get_state());
509 session->add_instant_xml (enode);
510 session->add_instant_xml (mnode);
512 Config->add_instant_xml (enode);
513 Config->add_instant_xml (mnode);
520 ARDOUR_UI::autosave_session ()
522 if (!Config->get_periodic_safety_backups())
526 session->maybe_write_autosave();
533 ARDOUR_UI::update_autosave ()
535 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
537 if (session->dirty()) {
538 if (_autosave_connection.connected()) {
539 _autosave_connection.disconnect();
542 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
543 Config->get_periodic_safety_backup_interval() * 1000);
546 if (_autosave_connection.connected()) {
547 _autosave_connection.disconnect();
553 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
557 title = _("Ardour could not start JACK");
559 title = _("Ardour could not connect to JACK.");
562 MessageDialog win (title,
568 win.set_secondary_text(_("There are several possible reasons:\n\
570 1) You requested audio parameters that are not supported..\n\
571 2) JACK is running as another user.\n\
573 Please consider the possibilities, and perhaps try different parameters."));
575 win.set_secondary_text(_("There are several possible reasons:\n\
577 1) JACK is not running.\n\
578 2) JACK is running as another user, perhaps root.\n\
579 3) There is already another client called \"ardour\".\n\
581 Please consider the possibilities, and perhaps (re)start JACK."));
585 win.set_transient_for (*toplevel);
589 win.add_button (Stock::OK, RESPONSE_CLOSE);
591 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
594 win.set_default_response (RESPONSE_CLOSE);
597 win.set_position (Gtk::WIN_POS_CENTER);
599 if (!ARDOUR_COMMAND_LINE::no_splash) {
603 /* we just don't care about the result, but we want to block */
609 ARDOUR_UI::startup ()
614 new_session_dialog = new NewSessionDialog();
616 /* If no session name is given: we're not loading a session yet, nor creating a new one */
618 if (ARDOUR_COMMAND_LINE::session_name.length()) {
620 /* Load session or start the new session dialog */
622 if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
623 error << string_compose(_("could not load command line session \"%1\""),
624 ARDOUR_COMMAND_LINE::session_name) << endmsg;
628 if (!ARDOUR_COMMAND_LINE::new_session) {
630 /* Supposed to be loading an existing session, but the session doesn't exist */
633 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
634 "To create it from the command line, start ardour as \"ardour --new %1"), path)
640 new_session_dialog->set_session_name (name);
641 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
642 _session_is_new = isnew;
647 bool have_backend = EngineControl::engine_running();
649 bool load_needed = false;
653 /* backend audio is working */
655 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
656 /* need NSD to get session name and other info */
664 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
667 new_session_dialog->engine_control.set_state (*audio_setup);
670 /* no backend audio, must bring up NSD to check configuration */
677 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
683 if (create_engine ()) {
684 backend_audio_error (false);
692 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
701 ARDOUR_UI::no_memory_warning ()
703 XMLNode node (X_("no-memory-warning"));
704 Config->add_instant_xml (node);
708 ARDOUR_UI::check_memory_locking ()
711 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
715 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
717 if (engine->is_realtime() && memory_warning_node == 0) {
719 struct rlimit limits;
721 long pages, page_size;
723 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
726 ram = (int64_t) pages * (int64_t) page_size;
729 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
733 if (limits.rlim_cur != RLIM_INFINITY) {
735 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
738 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
739 "This might cause Ardour to run out of memory before your system "
740 "runs out of memory. \n\n"
741 "You can view the memory limit with 'ulimit -l', "
742 "and it is normally controlled by /etc/security/limits.conf"));
744 VBox* vbox = msg.get_vbox();
746 CheckButton cb (_("Do not show this window again"));
748 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
750 hbox.pack_start (cb, true, false);
751 vbox->pack_start (hbox);
756 editor->ensure_float (msg);
768 if (session && session->dirty()) {
769 switch (ask_about_saving_session(_("quit"))) {
774 /* use the default name */
775 if (save_state_canfail ("")) {
776 /* failed - don't quit */
777 MessageDialog msg (*editor,
779 Ardour was unable to save your session.\n\n\
780 If you still wish to quit, please use the\n\n\
781 \"Just quit\" option."));
792 session->set_deletion_in_progress ();
795 Config->save_state();
796 ARDOUR_UI::config()->save_state();
801 ARDOUR_UI::ask_about_saving_session (const string & what)
803 ArdourDialog window (_("ardour: save session?"));
804 Gtk::HBox dhbox; // the hbox for the image and text
805 Gtk::Label prompt_label;
806 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
810 msg = string_compose(_("Don't %1"), what);
811 window.add_button (msg, RESPONSE_REJECT);
812 msg = string_compose(_("Just %1"), what);
813 window.add_button (msg, RESPONSE_APPLY);
814 msg = string_compose(_("Save and %1"), what);
815 window.add_button (msg, RESPONSE_ACCEPT);
817 window.set_default_response (RESPONSE_ACCEPT);
819 Gtk::Button noquit_button (msg);
820 noquit_button.set_name ("EditorGTKButton");
825 if (session->snap_name() == session->name()) {
828 type = _("snapshot");
830 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?"),
831 type, session->snap_name());
833 prompt_label.set_text (prompt);
834 prompt_label.set_name (X_("PrompterLabel"));
835 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
837 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
839 dhbox.set_homogeneous (false);
840 dhbox.pack_start (*dimage, false, false, 5);
841 dhbox.pack_start (prompt_label, true, false, 5);
842 window.get_vbox()->pack_start (dhbox);
844 window.set_name (_("Prompter"));
845 window.set_position (Gtk::WIN_POS_MOUSE);
846 window.set_modal (true);
847 window.set_resizable (false);
854 save_the_session = 0;
856 window.set_keep_above (true);
859 ResponseType r = (ResponseType) window.run();
864 case RESPONSE_ACCEPT: // save and get out of here
866 case RESPONSE_APPLY: // get out of here
876 ARDOUR_UI::every_second ()
879 update_buffer_load ();
880 update_disk_space ();
885 ARDOUR_UI::every_point_one_seconds ()
887 update_speed_display ();
888 RapidScreenUpdate(); /* EMIT_SIGNAL */
893 ARDOUR_UI::every_point_zero_one_seconds ()
895 // august 2007: actual update frequency: 40Hz, not 100Hz
897 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
902 ARDOUR_UI::update_sample_rate (nframes_t ignored)
906 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
908 if (!engine->connected()) {
910 snprintf (buf, sizeof (buf), _("disconnected"));
914 nframes_t rate = engine->frame_rate();
916 if (fmod (rate, 1000.0) != 0.0) {
917 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
918 (float) rate/1000.0f,
919 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
921 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
923 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
927 sample_rate_label.set_text (buf);
931 ARDOUR_UI::update_cpu_load ()
934 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
935 cpu_load_label.set_text (buf);
939 ARDOUR_UI::update_buffer_load ()
944 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
945 session->playback_load(), session->capture_load());
946 buffer_load_label.set_text (buf);
948 buffer_load_label.set_text ("");
953 ARDOUR_UI::count_recenabled_streams (Route& route)
955 Track* track = dynamic_cast<Track*>(&route);
956 if (track && track->diskstream()->record_enabled()) {
957 rec_enabled_streams += track->n_inputs().n_total();
962 ARDOUR_UI::update_disk_space()
968 nframes_t frames = session->available_capture_duration();
971 if (frames == max_frames) {
972 strcpy (buf, _("Disk: 24hrs+"));
977 nframes_t fr = session->frame_rate();
979 rec_enabled_streams = 0;
980 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
982 if (rec_enabled_streams) {
983 frames /= rec_enabled_streams;
986 hrs = frames / (fr * 3600);
987 frames -= hrs * fr * 3600;
988 mins = frames / (fr * 60);
989 frames -= mins * fr * 60;
992 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
995 disk_space_label.set_text (buf);
999 ARDOUR_UI::update_wall_clock ()
1006 tm_now = localtime (&now);
1008 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1009 wall_clock_label.set_text (buf);
1015 ARDOUR_UI::session_menu (GdkEventButton *ev)
1017 session_popup_menu->popup (0, 0);
1022 ARDOUR_UI::redisplay_recent_sessions ()
1024 std::vector<sys::path> session_directories;
1025 RecentSessionsSorter cmp;
1027 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1028 recent_session_model->clear ();
1030 ARDOUR::RecentSessions rs;
1031 ARDOUR::read_recent_sessions (rs);
1034 recent_session_display.set_model (recent_session_model);
1038 // sort them alphabetically
1039 sort (rs.begin(), rs.end(), cmp);
1041 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1042 session_directories.push_back ((*i).second);
1045 for (vector<sys::path>::const_iterator i = session_directories.begin();
1046 i != session_directories.end(); ++i)
1048 std::vector<sys::path> state_file_paths;
1050 // now get available states for this session
1052 get_state_files_in_directory (*i, state_file_paths);
1054 if (state_file_paths.empty()) {
1059 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1061 Gtk::TreeModel::Row row = *(recent_session_model->append());
1063 const string fullpath = (*i).to_string();
1065 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1066 row[recent_session_columns.fullpath] = fullpath;
1068 if (state_file_names.size() > 1) {
1072 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1073 i2 != state_file_names.end(); ++i2)
1076 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1078 child_row[recent_session_columns.visible_name] = *i2;
1079 child_row[recent_session_columns.fullpath] = fullpath;
1084 recent_session_display.set_model (recent_session_model);
1088 ARDOUR_UI::build_session_selector ()
1090 session_selector_window = new ArdourDialog ("session selector");
1092 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1094 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1095 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1096 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1097 recent_session_model = TreeStore::create (recent_session_columns);
1098 recent_session_display.set_model (recent_session_model);
1099 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1100 recent_session_display.set_headers_visible (false);
1101 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1103 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1105 scroller->add (recent_session_display);
1106 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1108 session_selector_window->set_name ("SessionSelectorWindow");
1109 session_selector_window->set_size_request (200, 400);
1110 session_selector_window->get_vbox()->pack_start (*scroller);
1112 recent_session_display.show();
1114 //session_selector_window->get_vbox()->show();
1118 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1120 session_selector_window->response (RESPONSE_ACCEPT);
1124 ARDOUR_UI::open_recent_session ()
1126 /* popup selector window */
1128 if (session_selector_window == 0) {
1129 build_session_selector ();
1132 redisplay_recent_sessions ();
1134 ResponseType r = (ResponseType) session_selector_window->run ();
1136 session_selector_window->hide();
1139 case RESPONSE_ACCEPT:
1145 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1147 if (i == recent_session_model->children().end()) {
1151 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1152 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1154 _session_is_new = false;
1156 load_session (path, state);
1160 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1162 struct stat statbuf;
1164 if (stat (info.filename.c_str(), &statbuf) != 0) {
1168 if (!S_ISDIR(statbuf.st_mode)) {
1174 string session_file = info.filename;
1175 session_file += '/';
1176 session_file += Glib::path_get_basename (info.filename);
1177 session_file += ".ardour";
1179 if (stat (session_file.c_str(), &statbuf) != 0) {
1183 return S_ISREG (statbuf.st_mode);
1187 ARDOUR_UI::check_audioengine ()
1190 if (!engine->connected()) {
1191 MessageDialog msg (_("Ardour is not connected to JACK\n"
1192 "You cannot open or close sessions in this condition"));
1203 ARDOUR_UI::open_session ()
1205 if (!check_audioengine()) {
1210 /* popup selector window */
1212 if (open_session_selector == 0) {
1214 /* ardour sessions are folders */
1216 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1217 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1218 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1219 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1221 FileFilter session_filter;
1222 session_filter.add_pattern ("*.ardour");
1223 session_filter.set_name (_("Ardour sessions"));
1224 open_session_selector->add_filter (session_filter);
1225 open_session_selector->set_filter (session_filter);
1228 int response = open_session_selector->run();
1229 open_session_selector->hide ();
1232 case RESPONSE_ACCEPT:
1235 open_session_selector->hide();
1239 open_session_selector->hide();
1240 string session_path = open_session_selector->get_filename();
1244 if (session_path.length() > 0) {
1245 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1246 _session_is_new = isnew;
1247 load_session (path, name);
1254 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1256 list<boost::shared_ptr<MidiTrack> > tracks;
1259 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1266 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1268 if (tracks.size() != how_many) {
1269 if (how_many == 1) {
1270 error << _("could not create a new midi track") << endmsg;
1272 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1276 if ((route = session->new_midi_route ()) == 0) {
1277 error << _("could not create new midi bus") << endmsg;
1283 MessageDialog msg (*editor,
1284 _("There are insufficient JACK ports available\n\
1285 to create a new track or bus.\n\
1286 You should save Ardour, exit and\n\
1287 restart JACK with more ports."));
1294 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1296 list<boost::shared_ptr<AudioTrack> > tracks;
1297 Session::RouteList routes;
1300 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1306 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1308 if (tracks.size() != how_many) {
1309 if (how_many == 1) {
1310 error << _("could not create a new audio track") << endmsg;
1312 error << string_compose (_("could only create %1 of %2 new audio %3"),
1313 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1319 routes = session->new_audio_route (input_channels, output_channels, how_many);
1321 if (routes.size() != how_many) {
1322 if (how_many == 1) {
1323 error << _("could not create a new audio track") << endmsg;
1325 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1331 if (need_control_room_outs) {
1337 route->set_stereo_control_outs (control_lr_channels);
1338 route->control_outs()->set_stereo_pan (pans, this);
1340 #endif /* CONTROLOUTS */
1344 cerr << "About to complain about JACK\n";
1345 MessageDialog msg (*editor,
1346 _("There are insufficient JACK ports available\n\
1347 to create a new track or bus.\n\
1348 You should save Ardour, exit and\n\
1349 restart JACK with more ports."));
1355 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1357 nframes_t _preroll = 0;
1360 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1361 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1363 if (new_position > _preroll) {
1364 new_position -= _preroll;
1369 session->request_locate (new_position);
1374 ARDOUR_UI::transport_goto_start ()
1377 session->goto_start();
1380 /* force displayed area in editor to start no matter
1381 what "follow playhead" setting is.
1385 editor->reset_x_origin (session->current_start_frame());
1391 ARDOUR_UI::transport_goto_zero ()
1394 session->request_locate (0);
1397 /* force displayed area in editor to start no matter
1398 what "follow playhead" setting is.
1402 editor->reset_x_origin (0);
1408 ARDOUR_UI::transport_goto_end ()
1411 nframes_t frame = session->current_end_frame();
1412 session->request_locate (frame);
1414 /* force displayed area in editor to start no matter
1415 what "follow playhead" setting is.
1419 editor->reset_x_origin (frame);
1425 ARDOUR_UI::transport_stop ()
1431 if (session->is_auditioning()) {
1432 session->cancel_audition ();
1436 if (session->get_play_loop ()) {
1437 session->request_play_loop (false);
1440 session->request_stop ();
1444 ARDOUR_UI::transport_stop_and_forget_capture ()
1447 session->request_stop (true);
1452 ARDOUR_UI::remove_last_capture()
1455 editor->remove_last_capture();
1460 ARDOUR_UI::transport_record ()
1463 switch (session->record_status()) {
1464 case Session::Disabled:
1465 if (session->ntracks() == 0) {
1466 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1470 session->maybe_enable_record ();
1472 case Session::Recording:
1473 case Session::Enabled:
1474 session->disable_record (false, true);
1480 ARDOUR_UI::transport_roll ()
1488 rolling = session->transport_rolling ();
1490 if (session->get_play_loop()) {
1491 session->request_play_loop (false);
1492 auto_loop_button.set_visual_state (1);
1493 roll_button.set_visual_state (1);
1494 } else if (session->get_play_range ()) {
1495 session->request_play_range (false);
1496 play_selection_button.set_visual_state (0);
1497 } else if (rolling) {
1498 session->request_locate (session->last_transport_start(), true);
1501 session->request_transport_speed (1.0f);
1505 ARDOUR_UI::transport_loop()
1508 if (session->get_play_loop()) {
1509 if (session->transport_rolling()) {
1510 Location * looploc = session->locations()->auto_loop_location();
1512 session->request_locate (looploc->start(), true);
1517 session->request_play_loop (true);
1523 ARDOUR_UI::transport_play_selection ()
1529 if (!session->get_play_range()) {
1530 session->request_stop ();
1533 editor->play_selection ();
1537 ARDOUR_UI::transport_rewind (int option)
1539 float current_transport_speed;
1542 current_transport_speed = session->transport_speed();
1544 if (current_transport_speed >= 0.0f) {
1547 session->request_transport_speed (-1.0f);
1550 session->request_transport_speed (-4.0f);
1553 session->request_transport_speed (-0.5f);
1558 session->request_transport_speed (current_transport_speed * 1.5f);
1564 ARDOUR_UI::transport_forward (int option)
1566 float current_transport_speed;
1569 current_transport_speed = session->transport_speed();
1571 if (current_transport_speed <= 0.0f) {
1574 session->request_transport_speed (1.0f);
1577 session->request_transport_speed (4.0f);
1580 session->request_transport_speed (0.5f);
1585 session->request_transport_speed (current_transport_speed * 1.5f);
1591 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1597 boost::shared_ptr<Route> r;
1599 if ((r = session->route_by_remote_id (dstream)) != 0) {
1603 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1604 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1613 ARDOUR_UI::queue_transport_change ()
1615 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1619 ARDOUR_UI::map_transport_state ()
1621 float sp = session->transport_speed();
1624 transport_rolling ();
1625 } else if (sp < 0.0f) {
1626 transport_rewinding ();
1627 } else if (sp > 0.0f) {
1628 transport_forwarding ();
1630 transport_stopped ();
1635 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1637 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1638 (int) adj.get_value()].c_str());
1642 ARDOUR_UI::engine_stopped ()
1644 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1645 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1646 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1650 ARDOUR_UI::engine_running ()
1652 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1653 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1654 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1656 Glib::RefPtr<Action> action;
1657 const char* action_name = 0;
1659 switch (engine->frames_per_cycle()) {
1661 action_name = X_("JACKLatency32");
1664 action_name = X_("JACKLatency64");
1667 action_name = X_("JACKLatency128");
1670 action_name = X_("JACKLatency512");
1673 action_name = X_("JACKLatency1024");
1676 action_name = X_("JACKLatency2048");
1679 action_name = X_("JACKLatency4096");
1682 action_name = X_("JACKLatency8192");
1685 /* XXX can we do anything useful ? */
1691 action = ActionManager::get_action (X_("JACK"), action_name);
1694 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1695 ract->set_active ();
1701 ARDOUR_UI::engine_halted ()
1703 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1705 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1706 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1708 update_sample_rate (0);
1710 MessageDialog msg (*editor,
1712 JACK has either been shutdown or it\n\
1713 disconnected Ardour because Ardour\n\
1714 was not fast enough. You can save the\n\
1715 session and/or try to reconnect to JACK ."));
1720 ARDOUR_UI::do_engine_start ()
1728 error << _("Unable to start the session running")
1738 ARDOUR_UI::setup_theme ()
1740 theme_manager->setup_theme();
1744 ARDOUR_UI::update_clocks ()
1746 if (!editor || !editor->dragging_playhead()) {
1747 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1752 ARDOUR_UI::start_clocking ()
1754 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1758 ARDOUR_UI::stop_clocking ()
1760 clock_signal_connection.disconnect ();
1764 ARDOUR_UI::toggle_clocking ()
1767 if (clock_button.get_active()) {
1776 ARDOUR_UI::_blink (void *arg)
1779 ((ARDOUR_UI *) arg)->blink ();
1786 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1790 ARDOUR_UI::start_blinking ()
1792 /* Start the blink signal. Everybody with a blinking widget
1793 uses Blink to drive the widget's state.
1796 if (blink_timeout_tag < 0) {
1798 blink_timeout_tag = g_timeout_add (240, _blink, this);
1803 ARDOUR_UI::stop_blinking ()
1805 if (blink_timeout_tag >= 0) {
1806 g_source_remove (blink_timeout_tag);
1807 blink_timeout_tag = -1;
1812 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1818 if (io.n_inputs().n_total() == 0) {
1823 /* XXX we're not handling multiple ports yet. */
1825 const char **connections = io.input(0)->get_connections();
1827 if (connections == 0 || connections[0] == '\0') {
1830 buf = connections[0];
1837 if (io.n_outputs().n_total() == 0) {
1842 /* XXX we're not handling multiple ports yet. */
1844 const char **connections = io.output(0)->get_connections();
1846 if (connections == 0 || connections[0] == '\0') {
1849 buf = connections[0];
1856 /** Ask the user for the name of a new shapshot and then take it.
1859 ARDOUR_UI::snapshot_session ()
1861 ArdourPrompter prompter (true);
1865 struct tm local_time;
1868 localtime_r (&n, &local_time);
1869 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1871 prompter.set_name ("Prompter");
1872 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1873 prompter.set_prompt (_("Name of New Snapshot"));
1874 prompter.set_initial_text (timebuf);
1876 switch (prompter.run()) {
1877 case RESPONSE_ACCEPT:
1878 prompter.get_result (snapname);
1879 if (snapname.length()){
1880 save_state (snapname);
1890 ARDOUR_UI::save_state (const string & name)
1892 (void) save_state_canfail (name);
1896 ARDOUR_UI::save_state_canfail (string name)
1901 if (name.length() == 0) {
1902 name = session->snap_name();
1905 if ((ret = session->save_state (name)) != 0) {
1909 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1914 ARDOUR_UI::restore_state (string name)
1917 if (name.length() == 0) {
1918 name = session->name();
1920 session->restore_state (name);
1925 ARDOUR_UI::primary_clock_value_changed ()
1928 session->request_locate (primary_clock.current_time ());
1933 ARDOUR_UI::secondary_clock_value_changed ()
1936 session->request_locate (secondary_clock.current_time ());
1941 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1943 if (session && dstream && dstream->record_enabled()) {
1945 Session::RecordState rs;
1947 rs = session->record_status ();
1950 case Session::Disabled:
1951 case Session::Enabled:
1952 if (w->get_state() != STATE_SELECTED) {
1953 w->set_state (STATE_SELECTED);
1957 case Session::Recording:
1958 if (w->get_state() != STATE_ACTIVE) {
1959 w->set_state (STATE_ACTIVE);
1965 if (w->get_state() != STATE_NORMAL) {
1966 w->set_state (STATE_NORMAL);
1972 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1978 switch (session->record_status()) {
1979 case Session::Enabled:
1981 rec_button.set_visual_state (2);
1983 rec_button.set_visual_state (0);
1987 case Session::Recording:
1988 rec_button.set_visual_state (1);
1992 rec_button.set_visual_state (0);
1998 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2006 ARDOUR_UI::save_template ()
2009 ArdourPrompter prompter (true);
2012 if (!check_audioengine()) {
2016 prompter.set_name (X_("Prompter"));
2017 prompter.set_prompt (_("Name for mix template:"));
2018 prompter.set_initial_text(session->name() + _("-template"));
2019 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2021 switch (prompter.run()) {
2022 case RESPONSE_ACCEPT:
2023 prompter.get_result (name);
2025 if (name.length()) {
2026 session->save_template (name);
2036 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2038 string session_name;
2039 string session_path;
2040 string template_name;
2042 if (!loading_dialog) {
2043 loading_dialog = new MessageDialog (*new_session_dialog,
2050 int response = Gtk::RESPONSE_NONE;
2052 new_session_dialog->set_modal(true);
2053 new_session_dialog->set_name (predetermined_path);
2054 new_session_dialog->reset_recent();
2055 new_session_dialog->set_position (WIN_POS_CENTER);
2056 new_session_dialog->set_current_page (0);
2059 new_session_dialog->set_have_engine (have_engine);
2061 new_session_dialog->show();
2062 new_session_dialog->present ();
2063 response = new_session_dialog->run ();
2065 _session_is_new = false;
2067 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2072 new_session_dialog->hide ();
2075 } else if (response == Gtk::RESPONSE_NONE) {
2077 /* Clear was pressed */
2078 new_session_dialog->reset();
2082 /* first things first ... if we're here to help set up audio parameters
2083 this is where want to do that.
2087 if (new_session_dialog->engine_control.setup_engine ()) {
2088 new_session_dialog->hide ();
2094 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2095 may not and it can take a while to build it. Warn them.
2098 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2100 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2101 MessageDialog msg (*new_session_dialog,
2102 _("Welcome to Ardour.\n\n"
2103 "The program will take a bit longer to start up\n"
2104 "while the system fonts are checked.\n\n"
2105 "This will only be done once, and you will\n"
2106 "not see this message again\n"),
2115 loading_dialog->set_message (_("Starting audio engine"));
2116 loading_dialog->show_all ();
2119 if (create_engine ()) {
2120 backend_audio_error (!have_engine, new_session_dialog);
2121 loading_dialog->hide ();
2123 /* audio setup page */
2124 new_session_dialog->set_current_page (2);
2126 response = Gtk::RESPONSE_NONE;
2132 /* now handle possible affirmative responses */
2134 if (response == Gtk::RESPONSE_YES) {
2136 /* YES == OPEN from the session selector */
2138 session_name = new_session_dialog->session_name();
2140 if (session_name.empty()) {
2141 response = Gtk::RESPONSE_NONE;
2145 if (session_name[0] == '/' ||
2146 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2147 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2148 load_session (Glib::path_get_dirname (session_name), session_name);
2150 session_path = new_session_dialog->session_folder();
2151 load_session (session_path, session_name);
2154 } else if (response == Gtk::RESPONSE_OK) {
2156 /* OK == OPEN button */
2158 session_name = new_session_dialog->session_name();
2160 if (session_name.empty()) {
2161 response = Gtk::RESPONSE_NONE;
2165 switch (new_session_dialog->get_current_page()) {
2166 case 1: /* recent session selector */
2167 case 2: /* audio engine control */
2169 if (session_name[0] == '/' ||
2170 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2171 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2172 load_session (Glib::path_get_dirname (session_name), session_name);
2174 session_path = new_session_dialog->session_folder();
2175 load_session (session_path, session_name);
2179 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2181 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2182 should_be_new = true;
2185 /* handle what appear to be paths rather than just a name */
2187 if (session_name[0] == '/' ||
2188 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2189 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2191 session_path = Glib::path_get_dirname (session_name);
2192 session_name = Glib::path_get_basename (session_name);
2196 session_path = new_session_dialog->session_folder();
2200 //XXX This is needed because session constructor wants a
2201 //non-existant path. hopefully this will be fixed at some point.
2203 session_path = Glib::build_filename (session_path, session_name);
2205 if (!should_be_new) {
2207 load_session (session_path, session_name);
2208 continue; /* leaves while() loop because response != NONE */
2210 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2212 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2214 MessageDialog msg (str,
2216 Gtk::MESSAGE_WARNING,
2217 Gtk::BUTTONS_YES_NO,
2221 msg.set_name (X_("CleanupDialog"));
2222 msg.set_wmclass (X_("existing_session"), "Ardour");
2223 msg.set_position (Gtk::WIN_POS_MOUSE);
2225 switch (msg.run()) {
2227 new_session_dialog->hide ();
2228 goto_editor_window ();
2230 load_session (session_path, session_name);
2234 response = RESPONSE_NONE;
2235 new_session_dialog->reset ();
2240 _session_is_new = true;
2242 if (new_session_dialog->use_session_template()) {
2244 template_name = new_session_dialog->session_template_name();
2246 new_session_dialog->hide ();
2247 goto_editor_window ();
2250 load_session (session_path, session_name, &template_name);
2256 AutoConnectOption iconnect;
2257 AutoConnectOption oconnect;
2261 if (Profile->get_sae()) {
2265 iconnect = AutoConnectPhysical;
2266 oconnect = AutoConnectMaster;
2267 nphysin = 0; // use all available
2268 nphysout = 0; // use all available
2272 /* get settings from advanced section of NSD */
2274 if (new_session_dialog->create_control_bus()) {
2275 cchns = (uint32_t) new_session_dialog->control_channel_count();
2280 if (new_session_dialog->create_master_bus()) {
2281 mchns = (uint32_t) new_session_dialog->master_channel_count();
2286 if (new_session_dialog->connect_inputs()) {
2287 iconnect = AutoConnectPhysical;
2289 iconnect = AutoConnectOption (0);
2292 /// @todo some minor tweaks.
2294 if (new_session_dialog->connect_outs_to_master()) {
2295 oconnect = AutoConnectMaster;
2296 } else if (new_session_dialog->connect_outs_to_physical()) {
2297 oconnect = AutoConnectPhysical;
2299 oconnect = AutoConnectOption (0);
2302 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2303 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2306 new_session_dialog->hide ();
2307 goto_editor_window ();
2310 if (build_session (session_path,
2318 engine->frame_rate() * 60 * 5)) {
2320 response = Gtk::RESPONSE_NONE;
2321 new_session_dialog->reset ();
2332 } while (response == Gtk::RESPONSE_NONE);
2336 loading_dialog->hide ();
2337 new_session_dialog->hide();
2342 ARDOUR_UI::close_session()
2344 if (!check_audioengine()) {
2348 unload_session (true);
2350 get_session_parameters ("", true, false);
2354 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2356 Session *new_session;
2360 session_loaded = false;
2362 if (!check_audioengine()) {
2366 unload_status = unload_session ();
2368 if (unload_status < 0) {
2370 } else if (unload_status > 0) {
2375 /* if it already exists, we must have write access */
2377 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2378 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2379 "This prevents the session from being loaded."));
2384 if (loading_dialog) {
2385 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2389 disable_screen_updates ();
2392 new_session = new Session (*engine, path, snap_name, mix_template);
2396 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2400 connect_to_session (new_session);
2402 Config->set_current_owner (ConfigVariableBase::Interface);
2404 session_loaded = true;
2406 goto_editor_window ();
2409 session->set_clean ();
2412 editor->edit_cursor_position (true);
2413 enable_screen_updates ();
2422 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2423 uint32_t control_channels,
2424 uint32_t master_channels,
2425 AutoConnectOption input_connect,
2426 AutoConnectOption output_connect,
2429 nframes_t initial_length)
2431 Session *new_session;
2434 if (!check_audioengine()) {
2438 session_loaded = false;
2440 x = unload_session ();
2448 _session_is_new = true;
2451 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2452 control_channels, master_channels, nphysin, nphysout, initial_length);
2457 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2462 connect_to_session (new_session);
2464 session_loaded = true;
2472 editor->show_window ();
2483 ARDOUR_UI::show_splash ()
2486 about = new About();
2487 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2494 ARDOUR_UI::about_signal_response(int response)
2500 ARDOUR_UI::hide_splash ()
2503 about->get_window()->set_cursor ();
2509 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2513 removed = rep.paths.size();
2516 MessageDialog msgd (*editor,
2517 _("No audio files were ready for cleanup"),
2520 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2521 msgd.set_secondary_text (_("If this seems suprising, \n\
2522 check for any existing snapshots.\n\
2523 These may still include regions that\n\
2524 require some unused files to continue to exist."));
2530 ArdourDialog results (_("ardour: cleanup"), true, false);
2532 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2533 CleanupResultsModelColumns() {
2537 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2538 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2542 CleanupResultsModelColumns results_columns;
2543 Glib::RefPtr<Gtk::ListStore> results_model;
2544 Gtk::TreeView results_display;
2546 results_model = ListStore::create (results_columns);
2547 results_display.set_model (results_model);
2548 results_display.append_column (list_title, results_columns.visible_name);
2550 results_display.set_name ("CleanupResultsList");
2551 results_display.set_headers_visible (true);
2552 results_display.set_headers_clickable (false);
2553 results_display.set_reorderable (false);
2555 Gtk::ScrolledWindow list_scroller;
2558 Gtk::HBox dhbox; // the hbox for the image and text
2559 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2560 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2562 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2564 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2566 if (rep.space < 1048576.0f) {
2568 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2570 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2574 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2576 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2580 dhbox.pack_start (*dimage, true, false, 5);
2581 dhbox.pack_start (txt, true, false, 5);
2583 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2584 TreeModel::Row row = *(results_model->append());
2585 row[results_columns.visible_name] = *i;
2586 row[results_columns.fullpath] = *i;
2589 list_scroller.add (results_display);
2590 list_scroller.set_size_request (-1, 150);
2591 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2593 dvbox.pack_start (dhbox, true, false, 5);
2594 dvbox.pack_start (list_scroller, true, false, 5);
2595 ddhbox.pack_start (dvbox, true, false, 5);
2597 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2598 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2599 results.set_default_response (RESPONSE_CLOSE);
2600 results.set_position (Gtk::WIN_POS_MOUSE);
2602 results_display.show();
2603 list_scroller.show();
2610 //results.get_vbox()->show();
2611 results.set_resizable (false);
2618 ARDOUR_UI::cleanup ()
2621 /* shouldn't happen: menu item is insensitive */
2626 MessageDialog checker (_("Are you sure you want to cleanup?"),
2628 Gtk::MESSAGE_QUESTION,
2629 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2631 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2632 ALL undo/redo information will be lost if you cleanup.\n\
2633 After cleanup, unused audio files will be moved to a \
2634 \"dead sounds\" location."));
2636 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2637 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2638 checker.set_default_response (RESPONSE_CANCEL);
2640 checker.set_name (_("CleanupDialog"));
2641 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2642 checker.set_position (Gtk::WIN_POS_MOUSE);
2644 switch (checker.run()) {
2645 case RESPONSE_ACCEPT:
2651 Session::cleanup_report rep;
2653 editor->prepare_for_cleanup ();
2655 /* do not allow flush until a session is reloaded */
2657 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2659 act->set_sensitive (false);
2662 if (session->cleanup_sources (rep)) {
2667 display_cleanup_results (rep,
2670 The following %1 %2 not in use and \n\
2671 have been moved to:\n\
2673 Flushing the wastebasket will \n\
2674 release an additional\n\
2675 %4 %5bytes of disk space.\n"
2683 ARDOUR_UI::flush_trash ()
2686 /* shouldn't happen: menu item is insensitive */
2690 Session::cleanup_report rep;
2692 if (session->cleanup_trash_sources (rep)) {
2696 display_cleanup_results (rep,
2698 _("The following %1 %2 deleted from\n\
2700 releasing %4 %5bytes of disk space"));
2704 ARDOUR_UI::add_route (Gtk::Window* float_window)
2712 if (add_route_dialog == 0) {
2713 add_route_dialog = new AddRouteDialog;
2715 add_route_dialog->set_transient_for (*float_window);
2719 if (add_route_dialog->is_visible()) {
2720 /* we're already doing this */
2724 ResponseType r = (ResponseType) add_route_dialog->run ();
2726 add_route_dialog->hide();
2729 case RESPONSE_ACCEPT:
2736 if ((count = add_route_dialog->count()) <= 0) {
2740 uint32_t input_chan = add_route_dialog->channels ();
2741 uint32_t output_chan;
2742 string name_template = add_route_dialog->name_template ();
2743 bool track = add_route_dialog->track ();
2745 AutoConnectOption oac = Config->get_output_auto_connect();
2747 if (oac & AutoConnectMaster) {
2748 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2750 output_chan = input_chan;
2753 /* XXX do something with name template */
2755 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2757 session_add_midi_track(count);
2759 MessageDialog msg (*editor,
2760 _("Sorry, MIDI Busses are not supported at this time."));
2762 //session_add_midi_bus();
2766 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2768 session_add_audio_bus (input_chan, output_chan, count);
2774 ARDOUR_UI::mixer_settings () const
2779 node = session->instant_xml(X_("Mixer"));
2781 node = Config->instant_xml(X_("Mixer"));
2785 node = new XMLNode (X_("Mixer"));
2792 ARDOUR_UI::editor_settings () const
2797 node = session->instant_xml(X_("Editor"));
2799 node = Config->instant_xml(X_("Editor"));
2803 node = new XMLNode (X_("Editor"));
2809 ARDOUR_UI::keyboard_settings () const
2813 node = Config->extra_xml(X_("Keyboard"));
2816 node = new XMLNode (X_("Keyboard"));
2822 ARDOUR_UI::halt_on_xrun_message ()
2824 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2826 MessageDialog msg (*editor,
2827 _("Recording was stopped because your system could not keep up."));
2832 ARDOUR_UI::disk_overrun_handler ()
2834 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2836 if (!have_disk_speed_dialog_displayed) {
2837 have_disk_speed_dialog_displayed = true;
2838 MessageDialog* msg = new MessageDialog (*editor, _("\
2839 The disk system on your computer\n\
2840 was not able to keep up with Ardour.\n\
2842 Specifically, it failed to write data to disk\n\
2843 quickly enough to keep up with recording.\n"));
2844 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2850 ARDOUR_UI::disk_underrun_handler ()
2852 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2854 if (!have_disk_speed_dialog_displayed) {
2855 have_disk_speed_dialog_displayed = true;
2856 MessageDialog* msg = new MessageDialog (*editor,
2857 _("The disk system on your computer\n\
2858 was not able to keep up with Ardour.\n\
2860 Specifically, it failed to read data from disk\n\
2861 quickly enough to keep up with playback.\n"));
2862 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2868 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2870 have_disk_speed_dialog_displayed = false;
2875 ARDOUR_UI::pending_state_dialog ()
2877 ArdourDialog dialog ("pending state dialog");
2879 This session appears to have been in\n\
2880 middle of recording when ardour or\n\
2881 the computer was shutdown.\n\
2883 Ardour can recover any captured audio for\n\
2884 you, or it can ignore it. Please decide\n\
2885 what you would like to do.\n"));
2887 dialog.get_vbox()->pack_start (message);
2888 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2889 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2891 dialog.set_position (WIN_POS_CENTER);
2893 //dialog.get_vbox()->show();
2895 switch (dialog.run ()) {
2896 case RESPONSE_ACCEPT:
2904 ARDOUR_UI::disconnect_from_jack ()
2907 if( engine->disconnect_from_jack ()) {
2908 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2912 update_sample_rate (0);
2917 ARDOUR_UI::reconnect_to_jack ()
2920 if (engine->reconnect_to_jack ()) {
2921 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2925 update_sample_rate (0);
2930 ARDOUR_UI::cmdline_new_session (string path)
2932 if (path[0] != '/') {
2933 char buf[PATH_MAX+1];
2936 getcwd (buf, sizeof (buf));
2943 get_session_parameters (path, false, true);
2945 _will_create_new_session_automatically = false; /* done it */
2947 return FALSE; /* don't call it again */
2951 ARDOUR_UI::use_config ()
2953 Glib::RefPtr<Action> act;
2955 switch (Config->get_native_file_data_format ()) {
2957 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2960 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2963 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2968 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2969 ract->set_active ();
2972 switch (Config->get_native_file_header_format ()) {
2974 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2977 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2980 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2983 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2986 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2989 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2992 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2997 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2998 ract->set_active ();
3001 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3003 set_transport_controllable_state (*node);
3008 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3010 if (Config->get_primary_clock_delta_edit_cursor()) {
3011 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
3013 primary_clock.set (pos, 0, true);
3016 if (Config->get_secondary_clock_delta_edit_cursor()) {
3017 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
3019 secondary_clock.set (pos);
3022 if (big_clock_window) {
3023 big_clock.set (pos);
3028 ARDOUR_UI::record_state_changed ()
3030 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3032 if (!session || !big_clock_window) {
3033 /* why bother - the clock isn't visible */
3037 switch (session->record_status()) {
3038 case Session::Recording:
3039 big_clock.set_widget_name ("BigClockRecording");
3042 big_clock.set_widget_name ("BigClockNonRecording");
3048 ARDOUR_UI::set_keybindings_path (string path)
3050 keybindings_path = path;
3054 ARDOUR_UI::save_keybindings ()
3056 if (can_save_keybindings) {
3057 AccelMap::save (user_keybindings_path);
3062 ARDOUR_UI::first_idle ()
3065 session->allow_auto_play (true);
3067 can_save_keybindings = true;
3072 ARDOUR_UI::store_clock_modes ()
3074 XMLNode* node = new XMLNode(X_("ClockModes"));
3076 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3077 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3080 session->add_extra_xml (*node);
3081 session->set_dirty ();
3086 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3087 : Controllable (name), ui (u), type(tp)
3093 ARDOUR_UI::TransportControllable::set_value (float val)
3095 if (type == ShuttleControl) {
3102 fract = -((0.5f - val)/0.5f);
3104 fract = ((val - 0.5f)/0.5f);
3108 ui.set_shuttle_fract (fract);
3113 /* do nothing: these are radio-style actions */
3117 const char *action = 0;
3121 action = X_("Roll");
3124 action = X_("Stop");
3127 action = X_("Goto Start");
3130 action = X_("Goto End");
3133 action = X_("Loop");
3136 action = X_("Play Selection");
3139 action = X_("Record");
3149 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3157 ARDOUR_UI::TransportControllable::get_value (void) const
3176 case ShuttleControl:
3186 ARDOUR_UI::TransportControllable::set_id (const string& str)
3192 ARDOUR_UI::setup_profile ()
3194 if (gdk_screen_width() < 1200) {
3195 Profile->set_small_screen ();
3199 if (getenv ("ARDOUR_SAE")) {
3200 Profile->set_sae ();
3201 Profile->set_single_package ();
3206 ARDOUR_UI::disable_all_plugins ()
3212 // session->begin_reversible_command (_("Disable all plugins"));
3214 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3216 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3217 // XMLNode& before = (*i)->get_redirect_state ();
3218 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
3219 (*i)->disable_plugins ();
3220 // XMLNode& after = (*i)->get_redirect_state ();
3221 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
3225 // session->commit_reversible_command ();
3229 ARDOUR_UI::ab_all_plugins ()
3235 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3237 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3238 (*i)->ab_plugins (ab_direction);
3241 ab_direction = !ab_direction;