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"
88 #include "bundle_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();
185 _session_is_new = false;
186 big_clock_window = 0;
187 session_selector_window = 0;
188 last_key_press_time = 0;
189 connection_editor = 0;
190 _will_create_new_session_automatically = false;
191 new_session_dialog = 0;
193 add_route_dialog = 0;
197 open_session_selector = 0;
198 have_configure_timeout = false;
199 have_disk_speed_dialog_displayed = false;
200 session_loaded = false;
201 last_speed_displayed = -1.0f;
204 sys::path key_bindings_file;
206 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
207 "ardour.bindings", key_bindings_file);
209 keybindings_path = key_bindings_file.to_string();
211 /* store all bindings changes in per-user file, no matter where they were loaded from */
212 user_keybindings_path = user_config_directory().to_string ();
213 user_keybindings_path += '/';
214 user_keybindings_path += "ardour.bindings";
216 can_save_keybindings = false;
218 last_configure_time.tv_sec = 0;
219 last_configure_time.tv_usec = 0;
221 shuttle_grabbed = false;
223 shuttle_max_speed = 8.0f;
225 shuttle_style_menu = 0;
226 shuttle_unit_menu = 0;
228 gettimeofday (&last_peak_grab, 0);
229 gettimeofday (&last_shuttle_request, 0);
231 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
232 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
234 /* handle pending state with a dialog */
236 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
238 /* lets get this party started */
241 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
242 setup_gtk_ardour_enums ();
243 Config->set_current_owner (ConfigVariableBase::Interface);
246 } catch (failed_constructor& err) {
247 error << _("could not initialize Ardour.") << endmsg;
252 /* we like keyboards */
254 keyboard = new Keyboard;
256 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
257 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
259 platform_specific ();
263 ARDOUR_UI::create_engine ()
265 // this gets called every time by new_session()
272 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
279 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
280 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
281 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
282 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
290 ARDOUR_UI::post_engine ()
292 extern int setup_midi ();
294 /* Things to be done once we create the AudioEngine
297 MIDI::Manager::instance()->set_api_data (engine->jack());
300 ActionManager::init ();
303 if (setup_windows ()) {
304 throw failed_constructor ();
307 check_memory_locking();
309 /* this is the first point at which all the keybindings are available */
311 if (ARDOUR_COMMAND_LINE::show_key_actions) {
312 vector<string> names;
313 vector<string> paths;
315 vector<AccelKey> bindings;
317 ActionManager::get_all_actions (names, paths, keys, bindings);
319 vector<string>::iterator n;
320 vector<string>::iterator k;
321 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
322 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
328 blink_timeout_tag = -1;
330 /* the global configuration object is now valid */
334 /* this being a GUI and all, we want peakfiles */
336 AudioFileSource::set_build_peakfiles (true);
337 AudioFileSource::set_build_missing_peakfiles (true);
339 /* set default clock modes */
341 primary_clock.set_mode (AudioClock::SMPTE);
342 secondary_clock.set_mode (AudioClock::BBT);
344 /* start the time-of-day-clock */
347 /* OS X provides an always visible wallclock, so don't be stupid */
348 update_wall_clock ();
349 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
352 update_disk_space ();
354 update_sample_rate (engine->frame_rate());
356 /* now start and maybe save state */
358 if (do_engine_start () == 0) {
359 if (session && _session_is_new) {
360 /* we need to retain initial visual
361 settings for a new session
363 session->save_state ("");
368 ARDOUR_UI::~ARDOUR_UI ()
370 save_ardour_state ();
384 if (add_route_dialog) {
385 delete add_route_dialog;
389 if (new_session_dialog) {
390 delete new_session_dialog;
395 ARDOUR_UI::configure_timeout ()
400 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
401 /* no configure events yet */
405 gettimeofday (&now, 0);
406 timersub (&now, &last_configure_time, &diff);
408 /* force a gap of 0.5 seconds since the last configure event
411 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
414 have_configure_timeout = false;
415 save_ardour_state ();
421 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
423 if (have_configure_timeout) {
424 gettimeofday (&last_configure_time, 0);
426 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
427 have_configure_timeout = true;
434 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
436 const XMLProperty* prop;
438 if ((prop = node.property ("roll")) != 0) {
439 roll_controllable.set_id (prop->value());
441 if ((prop = node.property ("stop")) != 0) {
442 stop_controllable.set_id (prop->value());
444 if ((prop = node.property ("goto_start")) != 0) {
445 goto_start_controllable.set_id (prop->value());
447 if ((prop = node.property ("goto_end")) != 0) {
448 goto_end_controllable.set_id (prop->value());
450 if ((prop = node.property ("auto_loop")) != 0) {
451 auto_loop_controllable.set_id (prop->value());
453 if ((prop = node.property ("play_selection")) != 0) {
454 play_selection_controllable.set_id (prop->value());
456 if ((prop = node.property ("rec")) != 0) {
457 rec_controllable.set_id (prop->value());
459 if ((prop = node.property ("shuttle")) != 0) {
460 shuttle_controllable.set_id (prop->value());
465 ARDOUR_UI::get_transport_controllable_state ()
467 XMLNode* node = new XMLNode(X_("TransportControllables"));
470 roll_controllable.id().print (buf, sizeof (buf));
471 node->add_property (X_("roll"), buf);
472 stop_controllable.id().print (buf, sizeof (buf));
473 node->add_property (X_("stop"), buf);
474 goto_start_controllable.id().print (buf, sizeof (buf));
475 node->add_property (X_("goto_start"), buf);
476 goto_end_controllable.id().print (buf, sizeof (buf));
477 node->add_property (X_("goto_end"), buf);
478 auto_loop_controllable.id().print (buf, sizeof (buf));
479 node->add_property (X_("auto_loop"), buf);
480 play_selection_controllable.id().print (buf, sizeof (buf));
481 node->add_property (X_("play_selection"), buf);
482 rec_controllable.id().print (buf, sizeof (buf));
483 node->add_property (X_("rec"), buf);
484 shuttle_controllable.id().print (buf, sizeof (buf));
485 node->add_property (X_("shuttle"), buf);
491 ARDOUR_UI::save_ardour_state ()
493 if (!keyboard || !mixer || !editor) {
497 /* XXX this is all a bit dubious. add_extra_xml() uses
498 a different lifetime model from add_instant_xml().
501 XMLNode* node = new XMLNode (keyboard->get_state());
502 Config->add_extra_xml (*node);
503 Config->add_extra_xml (get_transport_controllable_state());
504 Config->save_state();
506 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
507 XMLNode mnode(mixer->get_state());
510 session->add_instant_xml (enode);
511 session->add_instant_xml (mnode);
513 Config->add_instant_xml (enode);
514 Config->add_instant_xml (mnode);
521 ARDOUR_UI::autosave_session ()
523 if (!Config->get_periodic_safety_backups())
527 session->maybe_write_autosave();
534 ARDOUR_UI::update_autosave ()
536 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
538 if (session->dirty()) {
539 if (_autosave_connection.connected()) {
540 _autosave_connection.disconnect();
543 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
544 Config->get_periodic_safety_backup_interval() * 1000);
547 if (_autosave_connection.connected()) {
548 _autosave_connection.disconnect();
554 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
558 title = _("Ardour could not start JACK");
560 title = _("Ardour could not connect to JACK.");
563 MessageDialog win (title,
569 win.set_secondary_text(_("There are several possible reasons:\n\
571 1) You requested audio parameters that are not supported..\n\
572 2) JACK is running as another user.\n\
574 Please consider the possibilities, and perhaps try different parameters."));
576 win.set_secondary_text(_("There are several possible reasons:\n\
578 1) JACK is not running.\n\
579 2) JACK is running as another user, perhaps root.\n\
580 3) There is already another client called \"ardour\".\n\
582 Please consider the possibilities, and perhaps (re)start JACK."));
586 win.set_transient_for (*toplevel);
590 win.add_button (Stock::OK, RESPONSE_CLOSE);
592 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
595 win.set_default_response (RESPONSE_CLOSE);
598 win.set_position (Gtk::WIN_POS_CENTER);
600 if (!ARDOUR_COMMAND_LINE::no_splash) {
604 /* we just don't care about the result, but we want to block */
610 ARDOUR_UI::startup ()
615 new_session_dialog = new NewSessionDialog();
617 /* If no session name is given: we're not loading a session yet, nor creating a new one */
619 if (ARDOUR_COMMAND_LINE::session_name.length()) {
621 /* Load session or start the new session dialog */
623 if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
624 error << string_compose(_("could not load command line session \"%1\""),
625 ARDOUR_COMMAND_LINE::session_name) << endmsg;
629 if (!ARDOUR_COMMAND_LINE::new_session) {
631 /* Supposed to be loading an existing session, but the session doesn't exist */
634 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
635 "To create it from the command line, start ardour as \"ardour --new %1"), path)
641 new_session_dialog->set_session_name (name);
642 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
643 _session_is_new = isnew;
648 bool have_backend = EngineControl::engine_running();
650 bool load_needed = false;
654 /* backend audio is working */
656 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
657 /* need NSD to get session name and other info */
665 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
668 new_session_dialog->engine_control.set_state (*audio_setup);
671 /* no backend audio, must bring up NSD to check configuration */
678 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
684 if (create_engine ()) {
685 backend_audio_error (false);
693 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
702 ARDOUR_UI::no_memory_warning ()
704 XMLNode node (X_("no-memory-warning"));
705 Config->add_instant_xml (node);
709 ARDOUR_UI::check_memory_locking ()
712 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
716 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
718 if (engine->is_realtime() && memory_warning_node == 0) {
720 struct rlimit limits;
722 long pages, page_size;
724 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
727 ram = (int64_t) pages * (int64_t) page_size;
730 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
734 if (limits.rlim_cur != RLIM_INFINITY) {
736 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
739 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
740 "This might cause Ardour to run out of memory before your system "
741 "runs out of memory. \n\n"
742 "You can view the memory limit with 'ulimit -l', "
743 "and it is normally controlled by /etc/security/limits.conf"));
745 VBox* vbox = msg.get_vbox();
747 CheckButton cb (_("Do not show this window again"));
749 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
751 hbox.pack_start (cb, true, false);
752 vbox->pack_start (hbox);
757 editor->ensure_float (msg);
769 if (session && session->dirty()) {
770 switch (ask_about_saving_session(_("quit"))) {
775 /* use the default name */
776 if (save_state_canfail ("")) {
777 /* failed - don't quit */
778 MessageDialog msg (*editor,
780 Ardour was unable to save your session.\n\n\
781 If you still wish to quit, please use the\n\n\
782 \"Just quit\" option."));
793 session->set_deletion_in_progress ();
796 Config->save_state();
797 ARDOUR_UI::config()->save_state();
802 ARDOUR_UI::ask_about_saving_session (const string & what)
804 ArdourDialog window (_("ardour: save session?"));
805 Gtk::HBox dhbox; // the hbox for the image and text
806 Gtk::Label prompt_label;
807 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
811 msg = string_compose(_("Don't %1"), what);
812 window.add_button (msg, RESPONSE_REJECT);
813 msg = string_compose(_("Just %1"), what);
814 window.add_button (msg, RESPONSE_APPLY);
815 msg = string_compose(_("Save and %1"), what);
816 window.add_button (msg, RESPONSE_ACCEPT);
818 window.set_default_response (RESPONSE_ACCEPT);
820 Gtk::Button noquit_button (msg);
821 noquit_button.set_name ("EditorGTKButton");
826 if (session->snap_name() == session->name()) {
829 type = _("snapshot");
831 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?"),
832 type, session->snap_name());
834 prompt_label.set_text (prompt);
835 prompt_label.set_name (X_("PrompterLabel"));
836 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
838 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
840 dhbox.set_homogeneous (false);
841 dhbox.pack_start (*dimage, false, false, 5);
842 dhbox.pack_start (prompt_label, true, false, 5);
843 window.get_vbox()->pack_start (dhbox);
845 window.set_name (_("Prompter"));
846 window.set_position (Gtk::WIN_POS_MOUSE);
847 window.set_modal (true);
848 window.set_resizable (false);
855 save_the_session = 0;
857 window.set_keep_above (true);
860 ResponseType r = (ResponseType) window.run();
865 case RESPONSE_ACCEPT: // save and get out of here
867 case RESPONSE_APPLY: // get out of here
877 ARDOUR_UI::every_second ()
880 update_buffer_load ();
881 update_disk_space ();
886 ARDOUR_UI::every_point_one_seconds ()
888 update_speed_display ();
889 RapidScreenUpdate(); /* EMIT_SIGNAL */
894 ARDOUR_UI::every_point_zero_one_seconds ()
896 // august 2007: actual update frequency: 40Hz, not 100Hz
898 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
903 ARDOUR_UI::update_sample_rate (nframes_t ignored)
907 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
909 if (!engine->connected()) {
911 snprintf (buf, sizeof (buf), _("disconnected"));
915 nframes_t rate = engine->frame_rate();
917 if (fmod (rate, 1000.0) != 0.0) {
918 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
919 (float) rate/1000.0f,
920 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
922 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
924 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
928 sample_rate_label.set_text (buf);
932 ARDOUR_UI::update_cpu_load ()
935 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
936 cpu_load_label.set_text (buf);
940 ARDOUR_UI::update_buffer_load ()
945 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
946 session->playback_load(), session->capture_load());
947 buffer_load_label.set_text (buf);
949 buffer_load_label.set_text ("");
954 ARDOUR_UI::count_recenabled_streams (Route& route)
956 Track* track = dynamic_cast<Track*>(&route);
957 if (track && track->diskstream()->record_enabled()) {
958 rec_enabled_streams += track->n_inputs().n_total();
963 ARDOUR_UI::update_disk_space()
969 nframes_t frames = session->available_capture_duration();
972 if (frames == max_frames) {
973 strcpy (buf, _("Disk: 24hrs+"));
978 nframes_t fr = session->frame_rate();
980 rec_enabled_streams = 0;
981 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
983 if (rec_enabled_streams) {
984 frames /= rec_enabled_streams;
987 hrs = frames / (fr * 3600);
988 frames -= hrs * fr * 3600;
989 mins = frames / (fr * 60);
990 frames -= mins * fr * 60;
993 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
996 disk_space_label.set_text (buf);
1000 ARDOUR_UI::update_wall_clock ()
1007 tm_now = localtime (&now);
1009 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1010 wall_clock_label.set_text (buf);
1016 ARDOUR_UI::session_menu (GdkEventButton *ev)
1018 session_popup_menu->popup (0, 0);
1023 ARDOUR_UI::redisplay_recent_sessions ()
1025 std::vector<sys::path> session_directories;
1026 RecentSessionsSorter cmp;
1028 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1029 recent_session_model->clear ();
1031 ARDOUR::RecentSessions rs;
1032 ARDOUR::read_recent_sessions (rs);
1035 recent_session_display.set_model (recent_session_model);
1039 // sort them alphabetically
1040 sort (rs.begin(), rs.end(), cmp);
1042 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1043 session_directories.push_back ((*i).second);
1046 for (vector<sys::path>::const_iterator i = session_directories.begin();
1047 i != session_directories.end(); ++i)
1049 std::vector<sys::path> state_file_paths;
1051 // now get available states for this session
1053 get_state_files_in_directory (*i, state_file_paths);
1055 if (state_file_paths.empty()) {
1060 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1062 Gtk::TreeModel::Row row = *(recent_session_model->append());
1064 const string fullpath = (*i).to_string();
1066 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1067 row[recent_session_columns.fullpath] = fullpath;
1069 if (state_file_names.size() > 1) {
1073 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1074 i2 != state_file_names.end(); ++i2)
1077 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1079 child_row[recent_session_columns.visible_name] = *i2;
1080 child_row[recent_session_columns.fullpath] = fullpath;
1085 recent_session_display.set_model (recent_session_model);
1089 ARDOUR_UI::build_session_selector ()
1091 session_selector_window = new ArdourDialog ("session selector");
1093 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1095 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1096 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1097 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1098 recent_session_model = TreeStore::create (recent_session_columns);
1099 recent_session_display.set_model (recent_session_model);
1100 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1101 recent_session_display.set_headers_visible (false);
1102 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1104 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1106 scroller->add (recent_session_display);
1107 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1109 session_selector_window->set_name ("SessionSelectorWindow");
1110 session_selector_window->set_size_request (200, 400);
1111 session_selector_window->get_vbox()->pack_start (*scroller);
1113 recent_session_display.show();
1115 //session_selector_window->get_vbox()->show();
1119 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1121 session_selector_window->response (RESPONSE_ACCEPT);
1125 ARDOUR_UI::open_recent_session ()
1127 /* popup selector window */
1129 if (session_selector_window == 0) {
1130 build_session_selector ();
1133 redisplay_recent_sessions ();
1135 ResponseType r = (ResponseType) session_selector_window->run ();
1137 session_selector_window->hide();
1140 case RESPONSE_ACCEPT:
1146 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1148 if (i == recent_session_model->children().end()) {
1152 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1153 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1155 _session_is_new = false;
1157 load_session (path, state);
1161 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1163 struct stat statbuf;
1165 if (stat (info.filename.c_str(), &statbuf) != 0) {
1169 if (!S_ISDIR(statbuf.st_mode)) {
1175 string session_file = info.filename;
1176 session_file += '/';
1177 session_file += Glib::path_get_basename (info.filename);
1178 session_file += ".ardour";
1180 if (stat (session_file.c_str(), &statbuf) != 0) {
1184 return S_ISREG (statbuf.st_mode);
1188 ARDOUR_UI::check_audioengine ()
1191 if (!engine->connected()) {
1192 MessageDialog msg (_("Ardour is not connected to JACK\n"
1193 "You cannot open or close sessions in this condition"));
1204 ARDOUR_UI::open_session ()
1206 if (!check_audioengine()) {
1211 /* popup selector window */
1213 if (open_session_selector == 0) {
1215 /* ardour sessions are folders */
1217 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1218 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1219 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1220 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1222 FileFilter session_filter;
1223 session_filter.add_pattern ("*.ardour");
1224 session_filter.set_name (_("Ardour sessions"));
1225 open_session_selector->add_filter (session_filter);
1226 open_session_selector->set_filter (session_filter);
1229 int response = open_session_selector->run();
1230 open_session_selector->hide ();
1233 case RESPONSE_ACCEPT:
1236 open_session_selector->hide();
1240 open_session_selector->hide();
1241 string session_path = open_session_selector->get_filename();
1245 if (session_path.length() > 0) {
1246 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1247 _session_is_new = isnew;
1248 load_session (path, name);
1255 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1257 list<boost::shared_ptr<MidiTrack> > tracks;
1260 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1267 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1269 if (tracks.size() != how_many) {
1270 if (how_many == 1) {
1271 error << _("could not create a new midi track") << endmsg;
1273 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1277 if ((route = session->new_midi_route ()) == 0) {
1278 error << _("could not create new midi bus") << endmsg;
1284 MessageDialog msg (*editor,
1285 _("There are insufficient JACK ports available\n\
1286 to create a new track or bus.\n\
1287 You should save Ardour, exit and\n\
1288 restart JACK with more ports."));
1295 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1297 list<boost::shared_ptr<AudioTrack> > tracks;
1298 Session::RouteList routes;
1301 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1307 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1309 if (tracks.size() != how_many) {
1310 if (how_many == 1) {
1311 error << _("could not create a new audio track") << endmsg;
1313 error << string_compose (_("could only create %1 of %2 new audio %3"),
1314 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1320 routes = session->new_audio_route (input_channels, output_channels, how_many);
1322 if (routes.size() != how_many) {
1323 if (how_many == 1) {
1324 error << _("could not create a new audio track") << endmsg;
1326 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1332 if (need_control_room_outs) {
1338 route->set_stereo_control_outs (control_lr_channels);
1339 route->control_outs()->set_stereo_pan (pans, this);
1341 #endif /* CONTROLOUTS */
1345 cerr << "About to complain about JACK\n";
1346 MessageDialog msg (*editor,
1347 _("There are insufficient JACK ports available\n\
1348 to create a new track or bus.\n\
1349 You should save Ardour, exit and\n\
1350 restart JACK with more ports."));
1356 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1358 nframes_t _preroll = 0;
1361 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1362 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1364 if (new_position > _preroll) {
1365 new_position -= _preroll;
1370 session->request_locate (new_position);
1375 ARDOUR_UI::transport_goto_start ()
1378 session->goto_start();
1381 /* force displayed area in editor to start no matter
1382 what "follow playhead" setting is.
1386 editor->reset_x_origin (session->current_start_frame());
1392 ARDOUR_UI::transport_goto_zero ()
1395 session->request_locate (0);
1398 /* force displayed area in editor to start no matter
1399 what "follow playhead" setting is.
1403 editor->reset_x_origin (0);
1409 ARDOUR_UI::transport_goto_end ()
1412 nframes_t frame = session->current_end_frame();
1413 session->request_locate (frame);
1415 /* force displayed area in editor to start no matter
1416 what "follow playhead" setting is.
1420 editor->reset_x_origin (frame);
1426 ARDOUR_UI::transport_stop ()
1432 if (session->is_auditioning()) {
1433 session->cancel_audition ();
1437 if (session->get_play_loop ()) {
1438 session->request_play_loop (false);
1441 session->request_stop ();
1445 ARDOUR_UI::transport_stop_and_forget_capture ()
1448 session->request_stop (true);
1453 ARDOUR_UI::remove_last_capture()
1456 editor->remove_last_capture();
1461 ARDOUR_UI::transport_record ()
1464 switch (session->record_status()) {
1465 case Session::Disabled:
1466 if (session->ntracks() == 0) {
1467 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1471 session->maybe_enable_record ();
1473 case Session::Recording:
1474 case Session::Enabled:
1475 session->disable_record (false, true);
1481 ARDOUR_UI::transport_roll ()
1489 rolling = session->transport_rolling ();
1491 if (session->get_play_loop()) {
1492 session->request_play_loop (false);
1493 auto_loop_button.set_visual_state (1);
1494 roll_button.set_visual_state (1);
1495 } else if (session->get_play_range ()) {
1496 session->request_play_range (false);
1497 play_selection_button.set_visual_state (0);
1498 } else if (rolling) {
1499 session->request_locate (session->last_transport_start(), true);
1502 session->request_transport_speed (1.0f);
1506 ARDOUR_UI::transport_loop()
1509 if (session->get_play_loop()) {
1510 if (session->transport_rolling()) {
1511 Location * looploc = session->locations()->auto_loop_location();
1513 session->request_locate (looploc->start(), true);
1518 session->request_play_loop (true);
1524 ARDOUR_UI::transport_play_selection ()
1530 if (!session->get_play_range()) {
1531 session->request_stop ();
1534 editor->play_selection ();
1538 ARDOUR_UI::transport_rewind (int option)
1540 float current_transport_speed;
1543 current_transport_speed = session->transport_speed();
1545 if (current_transport_speed >= 0.0f) {
1548 session->request_transport_speed (-1.0f);
1551 session->request_transport_speed (-4.0f);
1554 session->request_transport_speed (-0.5f);
1559 session->request_transport_speed (current_transport_speed * 1.5f);
1565 ARDOUR_UI::transport_forward (int option)
1567 float current_transport_speed;
1570 current_transport_speed = session->transport_speed();
1572 if (current_transport_speed <= 0.0f) {
1575 session->request_transport_speed (1.0f);
1578 session->request_transport_speed (4.0f);
1581 session->request_transport_speed (0.5f);
1586 session->request_transport_speed (current_transport_speed * 1.5f);
1592 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1598 boost::shared_ptr<Route> r;
1600 if ((r = session->route_by_remote_id (dstream)) != 0) {
1604 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1605 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1614 ARDOUR_UI::queue_transport_change ()
1616 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1620 ARDOUR_UI::map_transport_state ()
1622 float sp = session->transport_speed();
1625 transport_rolling ();
1626 } else if (sp < 0.0f) {
1627 transport_rewinding ();
1628 } else if (sp > 0.0f) {
1629 transport_forwarding ();
1631 transport_stopped ();
1636 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1638 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1639 (int) adj.get_value()].c_str());
1643 ARDOUR_UI::engine_stopped ()
1645 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1646 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1647 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1651 ARDOUR_UI::engine_running ()
1653 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1654 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1655 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1657 Glib::RefPtr<Action> action;
1658 const char* action_name = 0;
1660 switch (engine->frames_per_cycle()) {
1662 action_name = X_("JACKLatency32");
1665 action_name = X_("JACKLatency64");
1668 action_name = X_("JACKLatency128");
1671 action_name = X_("JACKLatency512");
1674 action_name = X_("JACKLatency1024");
1677 action_name = X_("JACKLatency2048");
1680 action_name = X_("JACKLatency4096");
1683 action_name = X_("JACKLatency8192");
1686 /* XXX can we do anything useful ? */
1692 action = ActionManager::get_action (X_("JACK"), action_name);
1695 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1696 ract->set_active ();
1702 ARDOUR_UI::engine_halted ()
1704 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1706 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1707 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1709 update_sample_rate (0);
1711 MessageDialog msg (*editor,
1713 JACK has either been shutdown or it\n\
1714 disconnected Ardour because Ardour\n\
1715 was not fast enough. You can save the\n\
1716 session and/or try to reconnect to JACK ."));
1721 ARDOUR_UI::do_engine_start ()
1729 error << _("Unable to start the session running")
1739 ARDOUR_UI::setup_theme ()
1741 theme_manager->setup_theme();
1745 ARDOUR_UI::update_clocks ()
1747 if (!editor || !editor->dragging_playhead()) {
1748 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1753 ARDOUR_UI::start_clocking ()
1755 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1759 ARDOUR_UI::stop_clocking ()
1761 clock_signal_connection.disconnect ();
1765 ARDOUR_UI::toggle_clocking ()
1768 if (clock_button.get_active()) {
1777 ARDOUR_UI::_blink (void *arg)
1780 ((ARDOUR_UI *) arg)->blink ();
1787 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1791 ARDOUR_UI::start_blinking ()
1793 /* Start the blink signal. Everybody with a blinking widget
1794 uses Blink to drive the widget's state.
1797 if (blink_timeout_tag < 0) {
1799 blink_timeout_tag = g_timeout_add (240, _blink, this);
1804 ARDOUR_UI::stop_blinking ()
1806 if (blink_timeout_tag >= 0) {
1807 g_source_remove (blink_timeout_tag);
1808 blink_timeout_tag = -1;
1813 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1818 vector<string> connections;
1821 if (io.n_inputs().n_total() == 0) {
1826 /* XXX we're not handling multiple ports yet. */
1828 if (io.input(0)->get_connections(connections) == 0) {
1831 buf = connections.front();
1836 if (io.n_outputs().n_total() == 0) {
1841 /* XXX we're not handling multiple ports yet. */
1843 if (io.output(0)->get_connections(connections) == 0) {
1846 buf = connections.front();
1851 /** Ask the user for the name of a new shapshot and then take it.
1854 ARDOUR_UI::snapshot_session ()
1856 ArdourPrompter prompter (true);
1860 struct tm local_time;
1863 localtime_r (&n, &local_time);
1864 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1866 prompter.set_name ("Prompter");
1867 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1868 prompter.set_prompt (_("Name of New Snapshot"));
1869 prompter.set_initial_text (timebuf);
1871 switch (prompter.run()) {
1872 case RESPONSE_ACCEPT:
1873 prompter.get_result (snapname);
1874 if (snapname.length()){
1875 save_state (snapname);
1885 ARDOUR_UI::save_state (const string & name)
1887 (void) save_state_canfail (name);
1891 ARDOUR_UI::save_state_canfail (string name)
1896 if (name.length() == 0) {
1897 name = session->snap_name();
1900 if ((ret = session->save_state (name)) != 0) {
1904 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1909 ARDOUR_UI::restore_state (string name)
1912 if (name.length() == 0) {
1913 name = session->name();
1915 session->restore_state (name);
1920 ARDOUR_UI::primary_clock_value_changed ()
1923 session->request_locate (primary_clock.current_time ());
1928 ARDOUR_UI::secondary_clock_value_changed ()
1931 session->request_locate (secondary_clock.current_time ());
1936 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1938 if (session && dstream && dstream->record_enabled()) {
1940 Session::RecordState rs;
1942 rs = session->record_status ();
1945 case Session::Disabled:
1946 case Session::Enabled:
1947 if (w->get_state() != STATE_SELECTED) {
1948 w->set_state (STATE_SELECTED);
1952 case Session::Recording:
1953 if (w->get_state() != STATE_ACTIVE) {
1954 w->set_state (STATE_ACTIVE);
1960 if (w->get_state() != STATE_NORMAL) {
1961 w->set_state (STATE_NORMAL);
1967 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1973 switch (session->record_status()) {
1974 case Session::Enabled:
1976 rec_button.set_visual_state (2);
1978 rec_button.set_visual_state (0);
1982 case Session::Recording:
1983 rec_button.set_visual_state (1);
1987 rec_button.set_visual_state (0);
1993 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2001 ARDOUR_UI::save_template ()
2004 ArdourPrompter prompter (true);
2007 if (!check_audioengine()) {
2011 prompter.set_name (X_("Prompter"));
2012 prompter.set_prompt (_("Name for mix template:"));
2013 prompter.set_initial_text(session->name() + _("-template"));
2014 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2016 switch (prompter.run()) {
2017 case RESPONSE_ACCEPT:
2018 prompter.get_result (name);
2020 if (name.length()) {
2021 session->save_template (name);
2031 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2033 string session_name;
2034 string session_path;
2035 string template_name;
2037 if (!loading_dialog) {
2038 loading_dialog = new MessageDialog (*new_session_dialog,
2045 int response = Gtk::RESPONSE_NONE;
2047 new_session_dialog->set_modal(true);
2048 new_session_dialog->set_name (predetermined_path);
2049 new_session_dialog->reset_recent();
2050 new_session_dialog->set_position (WIN_POS_CENTER);
2051 new_session_dialog->set_current_page (0);
2054 new_session_dialog->set_have_engine (have_engine);
2056 new_session_dialog->show();
2057 new_session_dialog->present ();
2058 response = new_session_dialog->run ();
2060 _session_is_new = false;
2062 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2067 new_session_dialog->hide ();
2070 } else if (response == Gtk::RESPONSE_NONE) {
2072 /* Clear was pressed */
2073 new_session_dialog->reset();
2077 /* first things first ... if we're here to help set up audio parameters
2078 this is where want to do that.
2082 if (new_session_dialog->engine_control.setup_engine ()) {
2083 new_session_dialog->hide ();
2089 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2090 may not and it can take a while to build it. Warn them.
2093 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2095 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2096 MessageDialog msg (*new_session_dialog,
2097 _("Welcome to Ardour.\n\n"
2098 "The program will take a bit longer to start up\n"
2099 "while the system fonts are checked.\n\n"
2100 "This will only be done once, and you will\n"
2101 "not see this message again\n"),
2110 loading_dialog->set_message (_("Starting audio engine"));
2111 loading_dialog->show_all ();
2114 if (create_engine ()) {
2115 backend_audio_error (!have_engine, new_session_dialog);
2116 loading_dialog->hide ();
2118 /* audio setup page */
2119 new_session_dialog->set_current_page (2);
2121 response = Gtk::RESPONSE_NONE;
2127 /* now handle possible affirmative responses */
2129 if (response == Gtk::RESPONSE_YES) {
2131 /* YES == OPEN from the session selector */
2133 session_name = new_session_dialog->session_name();
2135 if (session_name.empty()) {
2136 response = Gtk::RESPONSE_NONE;
2140 if (session_name[0] == '/' ||
2141 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2142 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2143 load_session (Glib::path_get_dirname (session_name), session_name);
2145 session_path = new_session_dialog->session_folder();
2146 load_session (session_path, session_name);
2149 } else if (response == Gtk::RESPONSE_OK) {
2151 /* OK == OPEN button */
2153 session_name = new_session_dialog->session_name();
2155 if (session_name.empty()) {
2156 response = Gtk::RESPONSE_NONE;
2160 switch (new_session_dialog->get_current_page()) {
2161 case 1: /* recent session selector */
2162 case 2: /* audio engine control */
2164 if (session_name[0] == '/' ||
2165 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2166 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2167 load_session (Glib::path_get_dirname (session_name), session_name);
2169 session_path = new_session_dialog->session_folder();
2170 load_session (session_path, session_name);
2174 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2176 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2177 should_be_new = true;
2180 /* handle what appear to be paths rather than just a name */
2182 if (session_name[0] == '/' ||
2183 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2184 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2186 session_path = Glib::path_get_dirname (session_name);
2187 session_name = Glib::path_get_basename (session_name);
2191 session_path = new_session_dialog->session_folder();
2195 //XXX This is needed because session constructor wants a
2196 //non-existant path. hopefully this will be fixed at some point.
2198 session_path = Glib::build_filename (session_path, session_name);
2200 if (!should_be_new) {
2202 load_session (session_path, session_name);
2203 continue; /* leaves while() loop because response != NONE */
2205 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2207 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2209 MessageDialog msg (str,
2211 Gtk::MESSAGE_WARNING,
2212 Gtk::BUTTONS_YES_NO,
2216 msg.set_name (X_("CleanupDialog"));
2217 msg.set_wmclass (X_("existing_session"), "Ardour");
2218 msg.set_position (Gtk::WIN_POS_MOUSE);
2220 switch (msg.run()) {
2222 new_session_dialog->hide ();
2223 goto_editor_window ();
2225 load_session (session_path, session_name);
2229 response = RESPONSE_NONE;
2230 new_session_dialog->reset ();
2235 _session_is_new = true;
2237 if (new_session_dialog->use_session_template()) {
2239 template_name = new_session_dialog->session_template_name();
2241 new_session_dialog->hide ();
2242 goto_editor_window ();
2245 load_session (session_path, session_name, &template_name);
2251 AutoConnectOption iconnect;
2252 AutoConnectOption oconnect;
2256 if (Profile->get_sae()) {
2260 iconnect = AutoConnectPhysical;
2261 oconnect = AutoConnectMaster;
2262 nphysin = 0; // use all available
2263 nphysout = 0; // use all available
2267 /* get settings from advanced section of NSD */
2269 if (new_session_dialog->create_control_bus()) {
2270 cchns = (uint32_t) new_session_dialog->control_channel_count();
2275 if (new_session_dialog->create_master_bus()) {
2276 mchns = (uint32_t) new_session_dialog->master_channel_count();
2281 if (new_session_dialog->connect_inputs()) {
2282 iconnect = AutoConnectPhysical;
2284 iconnect = AutoConnectOption (0);
2287 /// @todo some minor tweaks.
2289 if (new_session_dialog->connect_outs_to_master()) {
2290 oconnect = AutoConnectMaster;
2291 } else if (new_session_dialog->connect_outs_to_physical()) {
2292 oconnect = AutoConnectPhysical;
2294 oconnect = AutoConnectOption (0);
2297 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2298 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2301 new_session_dialog->hide ();
2302 goto_editor_window ();
2305 if (build_session (session_path,
2313 engine->frame_rate() * 60 * 5)) {
2315 response = Gtk::RESPONSE_NONE;
2316 new_session_dialog->reset ();
2327 } while (response == Gtk::RESPONSE_NONE);
2331 loading_dialog->hide ();
2332 new_session_dialog->hide();
2337 ARDOUR_UI::close_session()
2339 if (!check_audioengine()) {
2343 unload_session (true);
2345 get_session_parameters ("", true, false);
2349 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2351 Session *new_session;
2355 session_loaded = false;
2357 if (!check_audioengine()) {
2361 unload_status = unload_session ();
2363 if (unload_status < 0) {
2365 } else if (unload_status > 0) {
2370 /* if it already exists, we must have write access */
2372 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2373 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2374 "This prevents the session from being loaded."));
2379 if (loading_dialog) {
2380 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2384 disable_screen_updates ();
2387 new_session = new Session (*engine, path, snap_name, mix_template);
2391 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2395 connect_to_session (new_session);
2397 Config->set_current_owner (ConfigVariableBase::Interface);
2399 session_loaded = true;
2401 goto_editor_window ();
2404 session->set_clean ();
2407 editor->edit_cursor_position (true);
2408 enable_screen_updates ();
2417 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2418 uint32_t control_channels,
2419 uint32_t master_channels,
2420 AutoConnectOption input_connect,
2421 AutoConnectOption output_connect,
2424 nframes_t initial_length)
2426 Session *new_session;
2429 if (!check_audioengine()) {
2433 session_loaded = false;
2435 x = unload_session ();
2443 _session_is_new = true;
2446 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2447 control_channels, master_channels, nphysin, nphysout, initial_length);
2452 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2457 connect_to_session (new_session);
2459 session_loaded = true;
2467 editor->show_window ();
2478 ARDOUR_UI::show_splash ()
2481 about = new About();
2482 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2489 ARDOUR_UI::about_signal_response(int response)
2495 ARDOUR_UI::hide_splash ()
2498 about->get_window()->set_cursor ();
2504 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2508 removed = rep.paths.size();
2511 MessageDialog msgd (*editor,
2512 _("No audio files were ready for cleanup"),
2515 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2516 msgd.set_secondary_text (_("If this seems suprising, \n\
2517 check for any existing snapshots.\n\
2518 These may still include regions that\n\
2519 require some unused files to continue to exist."));
2525 ArdourDialog results (_("ardour: cleanup"), true, false);
2527 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2528 CleanupResultsModelColumns() {
2532 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2533 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2537 CleanupResultsModelColumns results_columns;
2538 Glib::RefPtr<Gtk::ListStore> results_model;
2539 Gtk::TreeView results_display;
2541 results_model = ListStore::create (results_columns);
2542 results_display.set_model (results_model);
2543 results_display.append_column (list_title, results_columns.visible_name);
2545 results_display.set_name ("CleanupResultsList");
2546 results_display.set_headers_visible (true);
2547 results_display.set_headers_clickable (false);
2548 results_display.set_reorderable (false);
2550 Gtk::ScrolledWindow list_scroller;
2553 Gtk::HBox dhbox; // the hbox for the image and text
2554 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2555 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2557 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2559 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2561 if (rep.space < 1048576.0f) {
2563 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2565 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2569 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2571 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2575 dhbox.pack_start (*dimage, true, false, 5);
2576 dhbox.pack_start (txt, true, false, 5);
2578 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2579 TreeModel::Row row = *(results_model->append());
2580 row[results_columns.visible_name] = *i;
2581 row[results_columns.fullpath] = *i;
2584 list_scroller.add (results_display);
2585 list_scroller.set_size_request (-1, 150);
2586 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2588 dvbox.pack_start (dhbox, true, false, 5);
2589 dvbox.pack_start (list_scroller, true, false, 5);
2590 ddhbox.pack_start (dvbox, true, false, 5);
2592 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2593 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2594 results.set_default_response (RESPONSE_CLOSE);
2595 results.set_position (Gtk::WIN_POS_MOUSE);
2597 results_display.show();
2598 list_scroller.show();
2605 //results.get_vbox()->show();
2606 results.set_resizable (false);
2613 ARDOUR_UI::cleanup ()
2616 /* shouldn't happen: menu item is insensitive */
2621 MessageDialog checker (_("Are you sure you want to cleanup?"),
2623 Gtk::MESSAGE_QUESTION,
2624 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2626 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2627 ALL undo/redo information will be lost if you cleanup.\n\
2628 After cleanup, unused audio files will be moved to a \
2629 \"dead sounds\" location."));
2631 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2632 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2633 checker.set_default_response (RESPONSE_CANCEL);
2635 checker.set_name (_("CleanupDialog"));
2636 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2637 checker.set_position (Gtk::WIN_POS_MOUSE);
2639 switch (checker.run()) {
2640 case RESPONSE_ACCEPT:
2646 Session::cleanup_report rep;
2648 editor->prepare_for_cleanup ();
2650 /* do not allow flush until a session is reloaded */
2652 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2654 act->set_sensitive (false);
2657 if (session->cleanup_sources (rep)) {
2662 display_cleanup_results (rep,
2665 The following %1 %2 not in use and \n\
2666 have been moved to:\n\
2668 Flushing the wastebasket will \n\
2669 release an additional\n\
2670 %4 %5bytes of disk space.\n"
2678 ARDOUR_UI::flush_trash ()
2681 /* shouldn't happen: menu item is insensitive */
2685 Session::cleanup_report rep;
2687 if (session->cleanup_trash_sources (rep)) {
2691 display_cleanup_results (rep,
2693 _("The following %1 %2 deleted from\n\
2695 releasing %4 %5bytes of disk space"));
2699 ARDOUR_UI::add_route (Gtk::Window* float_window)
2707 if (add_route_dialog == 0) {
2708 add_route_dialog = new AddRouteDialog;
2710 add_route_dialog->set_transient_for (*float_window);
2714 if (add_route_dialog->is_visible()) {
2715 /* we're already doing this */
2719 ResponseType r = (ResponseType) add_route_dialog->run ();
2721 add_route_dialog->hide();
2724 case RESPONSE_ACCEPT:
2731 if ((count = add_route_dialog->count()) <= 0) {
2735 uint32_t input_chan = add_route_dialog->channels ();
2736 uint32_t output_chan;
2737 string name_template = add_route_dialog->name_template ();
2738 bool track = add_route_dialog->track ();
2740 AutoConnectOption oac = Config->get_output_auto_connect();
2742 if (oac & AutoConnectMaster) {
2743 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2745 output_chan = input_chan;
2748 /* XXX do something with name template */
2750 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2752 session_add_midi_track(count);
2754 MessageDialog msg (*editor,
2755 _("Sorry, MIDI Busses are not supported at this time."));
2757 //session_add_midi_bus();
2761 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2763 session_add_audio_bus (input_chan, output_chan, count);
2769 ARDOUR_UI::mixer_settings () const
2774 node = session->instant_xml(X_("Mixer"));
2776 node = Config->instant_xml(X_("Mixer"));
2780 node = new XMLNode (X_("Mixer"));
2787 ARDOUR_UI::editor_settings () const
2792 node = session->instant_xml(X_("Editor"));
2794 node = Config->instant_xml(X_("Editor"));
2798 node = new XMLNode (X_("Editor"));
2804 ARDOUR_UI::keyboard_settings () const
2808 node = Config->extra_xml(X_("Keyboard"));
2811 node = new XMLNode (X_("Keyboard"));
2817 ARDOUR_UI::halt_on_xrun_message ()
2819 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2821 MessageDialog msg (*editor,
2822 _("Recording was stopped because your system could not keep up."));
2827 ARDOUR_UI::disk_overrun_handler ()
2829 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2831 if (!have_disk_speed_dialog_displayed) {
2832 have_disk_speed_dialog_displayed = true;
2833 MessageDialog* msg = new MessageDialog (*editor, _("\
2834 The disk system on your computer\n\
2835 was not able to keep up with Ardour.\n\
2837 Specifically, it failed to write data to disk\n\
2838 quickly enough to keep up with recording.\n"));
2839 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2845 ARDOUR_UI::disk_underrun_handler ()
2847 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2849 if (!have_disk_speed_dialog_displayed) {
2850 have_disk_speed_dialog_displayed = true;
2851 MessageDialog* msg = new MessageDialog (*editor,
2852 _("The disk system on your computer\n\
2853 was not able to keep up with Ardour.\n\
2855 Specifically, it failed to read data from disk\n\
2856 quickly enough to keep up with playback.\n"));
2857 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2863 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2865 have_disk_speed_dialog_displayed = false;
2870 ARDOUR_UI::pending_state_dialog ()
2872 HBox* hbox = new HBox();
2873 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2874 ArdourDialog dialog ("pending state dialog");
2876 This session appears to have been in\n\
2877 middle of recording when ardour or\n\
2878 the computer was shutdown.\n\
2880 Ardour can recover any captured audio for\n\
2881 you, or it can ignore it. Please decide\n\
2882 what you would like to do.\n"));
2884 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2885 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2886 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2887 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2888 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2889 dialog.set_default_response (RESPONSE_ACCEPT);
2890 dialog.set_position (WIN_POS_CENTER);
2894 //dialog.get_vbox()->show();
2896 switch (dialog.run ()) {
2897 case RESPONSE_ACCEPT:
2905 ARDOUR_UI::disconnect_from_jack ()
2908 if( engine->disconnect_from_jack ()) {
2909 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2913 update_sample_rate (0);
2918 ARDOUR_UI::reconnect_to_jack ()
2921 if (engine->reconnect_to_jack ()) {
2922 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2926 update_sample_rate (0);
2931 ARDOUR_UI::cmdline_new_session (string path)
2933 if (path[0] != '/') {
2934 char buf[PATH_MAX+1];
2937 getcwd (buf, sizeof (buf));
2944 get_session_parameters (path, false, true);
2946 _will_create_new_session_automatically = false; /* done it */
2948 return FALSE; /* don't call it again */
2952 ARDOUR_UI::use_config ()
2954 Glib::RefPtr<Action> act;
2956 switch (Config->get_native_file_data_format ()) {
2958 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2961 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2964 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2969 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2970 ract->set_active ();
2973 switch (Config->get_native_file_header_format ()) {
2975 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2978 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2981 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2984 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2987 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2990 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2993 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2998 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2999 ract->set_active ();
3002 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3004 set_transport_controllable_state (*node);
3009 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3011 if (Config->get_primary_clock_delta_edit_cursor()) {
3012 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
3014 primary_clock.set (pos, 0, true);
3017 if (Config->get_secondary_clock_delta_edit_cursor()) {
3018 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
3020 secondary_clock.set (pos);
3023 if (big_clock_window) {
3024 big_clock.set (pos);
3029 ARDOUR_UI::record_state_changed ()
3031 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3033 if (!session || !big_clock_window) {
3034 /* why bother - the clock isn't visible */
3038 switch (session->record_status()) {
3039 case Session::Recording:
3040 big_clock.set_widget_name ("BigClockRecording");
3043 big_clock.set_widget_name ("BigClockNonRecording");
3049 ARDOUR_UI::set_keybindings_path (string path)
3051 keybindings_path = path;
3055 ARDOUR_UI::save_keybindings ()
3057 if (can_save_keybindings) {
3058 AccelMap::save (user_keybindings_path);
3063 ARDOUR_UI::first_idle ()
3066 session->allow_auto_play (true);
3068 can_save_keybindings = true;
3073 ARDOUR_UI::store_clock_modes ()
3075 XMLNode* node = new XMLNode(X_("ClockModes"));
3077 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3078 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3081 session->add_extra_xml (*node);
3082 session->set_dirty ();
3087 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3088 : Controllable (name), ui (u), type(tp)
3094 ARDOUR_UI::TransportControllable::set_value (float val)
3096 if (type == ShuttleControl) {
3103 fract = -((0.5f - val)/0.5f);
3105 fract = ((val - 0.5f)/0.5f);
3109 ui.set_shuttle_fract (fract);
3114 /* do nothing: these are radio-style actions */
3118 const char *action = 0;
3122 action = X_("Roll");
3125 action = X_("Stop");
3128 action = X_("Goto Start");
3131 action = X_("Goto End");
3134 action = X_("Loop");
3137 action = X_("Play Selection");
3140 action = X_("Record");
3150 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3158 ARDOUR_UI::TransportControllable::get_value (void) const
3177 case ShuttleControl:
3187 ARDOUR_UI::TransportControllable::set_id (const string& str)
3193 ARDOUR_UI::setup_profile ()
3195 if (gdk_screen_width() < 1200) {
3196 Profile->set_small_screen ();
3200 if (getenv ("ARDOUR_SAE")) {
3201 Profile->set_sae ();
3202 Profile->set_single_package ();
3207 ARDOUR_UI::disable_all_plugins ()
3213 // session->begin_reversible_command (_("Disable all plugins"));
3215 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3217 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3218 // XMLNode& before = (*i)->get_redirect_state ();
3219 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
3220 (*i)->disable_plugins ();
3221 // XMLNode& after = (*i)->get_redirect_state ();
3222 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
3226 // session->commit_reversible_command ();
3230 ARDOUR_UI::ab_all_plugins ()
3236 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
3238 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
3239 (*i)->ab_plugins (ab_direction);
3242 ab_direction = !ab_direction;