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/basename.h>
41 #include <pbd/compose.h>
42 #include <pbd/failed_constructor.h>
43 #include <pbd/enumwriter.h>
44 #include <pbd/memento_command.h>
45 #include <pbd/file_utils.h>
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
55 #include <midi++/manager.h>
57 #include <ardour/ardour.h>
58 #include <ardour/profile.h>
59 #include <ardour/session_directory.h>
60 #include <ardour/session_route.h>
61 #include <ardour/session_state_utils.h>
62 #include <ardour/session_utils.h>
63 #include <ardour/port.h>
64 #include <ardour/audioengine.h>
65 #include <ardour/playlist.h>
66 #include <ardour/utils.h>
67 #include <ardour/audio_diskstream.h>
68 #include <ardour/audiofilesource.h>
69 #include <ardour/recent_sessions.h>
70 #include <ardour/port.h>
71 #include <ardour/audio_track.h>
72 #include <ardour/midi_track.h>
73 #include <ardour/filesystem_paths.h>
74 #include <ardour/filename_extensions.h>
77 #include "ardour_ui.h"
78 #include "public_editor.h"
79 #include "audio_clock.h"
84 #include "add_route_dialog.h"
85 #include "new_session_dialog.h"
89 #include "gui_thread.h"
90 #include "theme_manager.h"
91 #include "bundle_manager.h"
95 using namespace ARDOUR;
97 using namespace Gtkmm2ext;
101 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
102 UIConfiguration *ARDOUR_UI::ui_config = 0;
104 sigc::signal<void,bool> ARDOUR_UI::Blink;
105 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
106 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
107 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
109 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
111 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
113 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
114 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
115 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
116 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
120 adjuster_table (3, 3),
124 preroll_button (_("pre\nroll")),
125 postroll_button (_("post\nroll")),
129 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
133 roll_controllable ("transport roll", *this, TransportControllable::Roll),
134 stop_controllable ("transport stop", *this, TransportControllable::Stop),
135 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
136 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
137 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
138 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
139 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
140 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
141 shuttle_controller_binding_proxy (shuttle_controllable),
143 roll_button (roll_controllable),
144 stop_button (stop_controllable),
145 goto_start_button (goto_start_controllable),
146 goto_end_button (goto_end_controllable),
147 auto_loop_button (auto_loop_controllable),
148 play_selection_button (play_selection_controllable),
149 rec_button (rec_controllable),
151 shuttle_units_button (_("% ")),
153 punch_in_button (_("Punch In")),
154 punch_out_button (_("Punch Out")),
155 auto_return_button (_("Auto Return")),
156 auto_play_button (_("Auto Play")),
157 auto_input_button (_("Auto Input")),
158 click_button (_("Click")),
159 time_master_button (_("time\nmaster")),
161 auditioning_alert_button (_("AUDITION")),
162 solo_alert_button (_("SOLO")),
164 error_log_button (_("Errors"))
167 using namespace Gtk::Menu_Helpers;
173 _auto_display_errors = false;
178 if (ARDOUR_COMMAND_LINE::session_name.length()) {
179 /* only show this if we're not going to post the new session dialog */
183 if (theArdourUI == 0) {
187 ui_config = new UIConfiguration();
188 theme_manager = new ThemeManager();
194 _session_is_new = false;
195 big_clock_window = 0;
196 session_selector_window = 0;
197 last_key_press_time = 0;
198 connection_editor = 0;
199 _will_create_new_session_automatically = false;
200 new_session_dialog = 0;
202 add_route_dialog = 0;
206 open_session_selector = 0;
207 have_configure_timeout = false;
208 have_disk_speed_dialog_displayed = false;
209 session_loaded = false;
210 last_speed_displayed = -1.0f;
212 sys::path key_bindings_file;
214 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
215 "ardour.bindings", key_bindings_file);
217 keybindings_path = key_bindings_file.to_string();
219 /* store all bindings changes in per-user file, no matter where they were loaded from */
220 user_keybindings_path = user_config_directory().to_string ();
221 user_keybindings_path += '/';
222 user_keybindings_path += "ardour.bindings";
224 can_save_keybindings = false;
226 last_configure_time.tv_sec = 0;
227 last_configure_time.tv_usec = 0;
229 shuttle_grabbed = false;
231 shuttle_max_speed = 8.0f;
233 shuttle_style_menu = 0;
234 shuttle_unit_menu = 0;
236 gettimeofday (&last_peak_grab, 0);
237 gettimeofday (&last_shuttle_request, 0);
239 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
240 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
242 /* handle pending state with a dialog */
244 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
246 /* lets get this party started */
249 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
250 throw failed_constructor ();
253 setup_gtk_ardour_enums ();
254 Config->set_current_owner (ConfigVariableBase::Interface);
257 } catch (failed_constructor& err) {
258 error << _("could not initialize Ardour.") << endmsg;
263 /* we like keyboards */
265 keyboard = new Keyboard;
267 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
268 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
274 ARDOUR_UI::create_engine ()
276 // this gets called every time by new_session()
283 // OS X where everything is sllloooowwww
284 loading_dialog->set_message (_("Starting audio engine"));
285 loading_dialog->show_all ();
290 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
297 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
298 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
299 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
300 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
308 ARDOUR_UI::post_engine ()
310 extern int setup_midi ();
312 /* Things to be done once we create the AudioEngine
315 MIDI::Manager::instance()->set_api_data (engine->jack());
318 ActionManager::init ();
321 if (setup_windows ()) {
322 throw failed_constructor ();
325 check_memory_locking();
327 /* this is the first point at which all the keybindings are available */
329 if (ARDOUR_COMMAND_LINE::show_key_actions) {
330 vector<string> names;
331 vector<string> paths;
333 vector<AccelKey> bindings;
335 ActionManager::get_all_actions (names, paths, keys, bindings);
337 vector<string>::iterator n;
338 vector<string>::iterator k;
339 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
340 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
346 blink_timeout_tag = -1;
348 /* the global configuration object is now valid */
352 /* this being a GUI and all, we want peakfiles */
354 AudioFileSource::set_build_peakfiles (true);
355 AudioFileSource::set_build_missing_peakfiles (true);
357 /* set default clock modes */
359 primary_clock.set_mode (AudioClock::SMPTE);
360 secondary_clock.set_mode (AudioClock::BBT);
362 /* start the time-of-day-clock */
365 /* OS X provides an always visible wallclock, so don't be stupid */
366 update_wall_clock ();
367 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
370 update_disk_space ();
372 update_sample_rate (engine->frame_rate());
374 /* now start and maybe save state */
376 if (do_engine_start () == 0) {
377 if (session && _session_is_new) {
378 /* we need to retain initial visual
379 settings for a new session
381 session->save_state ("");
386 ARDOUR_UI::~ARDOUR_UI ()
388 save_ardour_state ();
402 if (add_route_dialog) {
403 delete add_route_dialog;
407 if (new_session_dialog) {
408 delete new_session_dialog;
413 ARDOUR_UI::configure_timeout ()
418 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
419 /* no configure events yet */
423 gettimeofday (&now, 0);
424 timersub (&now, &last_configure_time, &diff);
426 /* force a gap of 0.5 seconds since the last configure event
429 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
432 have_configure_timeout = false;
433 save_ardour_state ();
439 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
441 if (have_configure_timeout) {
442 gettimeofday (&last_configure_time, 0);
444 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
445 have_configure_timeout = true;
452 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
454 const XMLProperty* prop;
456 if ((prop = node.property ("roll")) != 0) {
457 roll_controllable.set_id (prop->value());
459 if ((prop = node.property ("stop")) != 0) {
460 stop_controllable.set_id (prop->value());
462 if ((prop = node.property ("goto_start")) != 0) {
463 goto_start_controllable.set_id (prop->value());
465 if ((prop = node.property ("goto_end")) != 0) {
466 goto_end_controllable.set_id (prop->value());
468 if ((prop = node.property ("auto_loop")) != 0) {
469 auto_loop_controllable.set_id (prop->value());
471 if ((prop = node.property ("play_selection")) != 0) {
472 play_selection_controllable.set_id (prop->value());
474 if ((prop = node.property ("rec")) != 0) {
475 rec_controllable.set_id (prop->value());
477 if ((prop = node.property ("shuttle")) != 0) {
478 shuttle_controllable.set_id (prop->value());
483 ARDOUR_UI::get_transport_controllable_state ()
485 XMLNode* node = new XMLNode(X_("TransportControllables"));
488 roll_controllable.id().print (buf, sizeof (buf));
489 node->add_property (X_("roll"), buf);
490 stop_controllable.id().print (buf, sizeof (buf));
491 node->add_property (X_("stop"), buf);
492 goto_start_controllable.id().print (buf, sizeof (buf));
493 node->add_property (X_("goto_start"), buf);
494 goto_end_controllable.id().print (buf, sizeof (buf));
495 node->add_property (X_("goto_end"), buf);
496 auto_loop_controllable.id().print (buf, sizeof (buf));
497 node->add_property (X_("auto_loop"), buf);
498 play_selection_controllable.id().print (buf, sizeof (buf));
499 node->add_property (X_("play_selection"), buf);
500 rec_controllable.id().print (buf, sizeof (buf));
501 node->add_property (X_("rec"), buf);
502 shuttle_controllable.id().print (buf, sizeof (buf));
503 node->add_property (X_("shuttle"), buf);
509 ARDOUR_UI::save_ardour_state ()
511 if (!keyboard || !mixer || !editor) {
515 /* XXX this is all a bit dubious. add_extra_xml() uses
516 a different lifetime model from add_instant_xml().
519 XMLNode* node = new XMLNode (keyboard->get_state());
520 Config->add_extra_xml (*node);
521 Config->add_extra_xml (get_transport_controllable_state());
522 Config->save_state();
523 ui_config->save_state ();
525 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
526 XMLNode mnode(mixer->get_state());
529 session->add_instant_xml (enode);
530 session->add_instant_xml (mnode);
532 Config->add_instant_xml (enode);
533 Config->add_instant_xml (mnode);
540 ARDOUR_UI::autosave_session ()
542 if (!Config->get_periodic_safety_backups())
546 session->maybe_write_autosave();
553 ARDOUR_UI::update_autosave ()
555 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
557 if (session->dirty()) {
558 if (_autosave_connection.connected()) {
559 _autosave_connection.disconnect();
562 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
563 Config->get_periodic_safety_backup_interval() * 1000);
566 if (_autosave_connection.connected()) {
567 _autosave_connection.disconnect();
573 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
577 title = _("Ardour could not start JACK");
579 title = _("Ardour could not connect to JACK.");
582 MessageDialog win (title,
588 win.set_secondary_text(_("There are several possible reasons:\n\
590 1) You requested audio parameters that are not supported..\n\
591 2) JACK is running as another user.\n\
593 Please consider the possibilities, and perhaps try different parameters."));
595 win.set_secondary_text(_("There are several possible reasons:\n\
597 1) JACK is not running.\n\
598 2) JACK is running as another user, perhaps root.\n\
599 3) There is already another client called \"ardour\".\n\
601 Please consider the possibilities, and perhaps (re)start JACK."));
605 win.set_transient_for (*toplevel);
609 win.add_button (Stock::OK, RESPONSE_CLOSE);
611 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
614 win.set_default_response (RESPONSE_CLOSE);
617 win.set_position (Gtk::WIN_POS_CENTER);
621 /* we just don't care about the result, but we want to block */
627 _hide_splash (gpointer arg)
629 ((ARDOUR_UI*)arg)->hide_splash();
634 ARDOUR_UI::startup ()
638 new_session_dialog = new NewSessionDialog();
640 // in 4 seconds, hide the splash screen
642 Glib::signal_timeout().connect (bind (sigc::ptr_fun (_hide_splash), this), 4000);
644 bool backend_audio_is_running = EngineControl::engine_running();
645 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
648 new_session_dialog->engine_control.set_state (*audio_setup);
651 if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
659 ARDOUR_UI::no_memory_warning ()
661 XMLNode node (X_("no-memory-warning"));
662 Config->add_instant_xml (node);
666 ARDOUR_UI::check_memory_locking ()
669 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
673 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
675 if (engine->is_realtime() && memory_warning_node == 0) {
677 struct rlimit limits;
679 long pages, page_size;
681 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
684 ram = (int64_t) pages * (int64_t) page_size;
687 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
691 if (limits.rlim_cur != RLIM_INFINITY) {
693 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
696 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
697 "This might cause Ardour to run out of memory before your system "
698 "runs out of memory. \n\n"
699 "You can view the memory limit with 'ulimit -l', "
700 "and it is normally controlled by /etc/security/limits.conf"));
702 VBox* vbox = msg.get_vbox();
704 CheckButton cb (_("Do not show this window again"));
706 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
708 hbox.pack_start (cb, true, false);
709 vbox->pack_start (hbox);
714 editor->ensure_float (msg);
728 if (session->transport_rolling()) {
729 session->request_stop ();
733 if (session->dirty()) {
734 switch (ask_about_saving_session(_("quit"))) {
739 /* use the default name */
740 if (save_state_canfail ("")) {
741 /* failed - don't quit */
742 MessageDialog msg (*editor,
744 Ardour was unable to save your session.\n\n\
745 If you still wish to quit, please use the\n\n\
746 \"Just quit\" option."));
756 session->set_deletion_in_progress ();
760 Config->save_state();
761 ARDOUR_UI::config()->save_state();
766 ARDOUR_UI::ask_about_saving_session (const string & what)
768 ArdourDialog window (_("ardour: save session?"));
769 Gtk::HBox dhbox; // the hbox for the image and text
770 Gtk::Label prompt_label;
771 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
775 msg = string_compose(_("Don't %1"), what);
776 window.add_button (msg, RESPONSE_REJECT);
777 msg = string_compose(_("Just %1"), what);
778 window.add_button (msg, RESPONSE_APPLY);
779 msg = string_compose(_("Save and %1"), what);
780 window.add_button (msg, RESPONSE_ACCEPT);
782 window.set_default_response (RESPONSE_ACCEPT);
784 Gtk::Button noquit_button (msg);
785 noquit_button.set_name ("EditorGTKButton");
790 if (session->snap_name() == session->name()) {
793 type = _("snapshot");
795 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?"),
796 type, session->snap_name());
798 prompt_label.set_text (prompt);
799 prompt_label.set_name (X_("PrompterLabel"));
800 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
802 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
804 dhbox.set_homogeneous (false);
805 dhbox.pack_start (*dimage, false, false, 5);
806 dhbox.pack_start (prompt_label, true, false, 5);
807 window.get_vbox()->pack_start (dhbox);
809 window.set_name (_("Prompter"));
810 window.set_position (Gtk::WIN_POS_MOUSE);
811 window.set_modal (true);
812 window.set_resizable (false);
819 save_the_session = 0;
821 window.set_keep_above (true);
824 ResponseType r = (ResponseType) window.run();
829 case RESPONSE_ACCEPT: // save and get out of here
831 case RESPONSE_APPLY: // get out of here
841 ARDOUR_UI::every_second ()
844 update_buffer_load ();
845 update_disk_space ();
850 ARDOUR_UI::every_point_one_seconds ()
852 update_speed_display ();
853 RapidScreenUpdate(); /* EMIT_SIGNAL */
858 ARDOUR_UI::every_point_zero_one_seconds ()
860 // august 2007: actual update frequency: 40Hz, not 100Hz
862 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
867 ARDOUR_UI::update_sample_rate (nframes_t ignored)
871 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
873 if (!engine->connected()) {
875 snprintf (buf, sizeof (buf), _("disconnected"));
879 nframes_t rate = engine->frame_rate();
881 if (fmod (rate, 1000.0) != 0.0) {
882 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
883 (float) rate/1000.0f,
884 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
886 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
888 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
892 sample_rate_label.set_text (buf);
896 ARDOUR_UI::update_cpu_load ()
899 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
900 cpu_load_label.set_text (buf);
904 ARDOUR_UI::update_buffer_load ()
909 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
910 session->playback_load(), session->capture_load());
911 buffer_load_label.set_text (buf);
913 buffer_load_label.set_text ("");
918 ARDOUR_UI::count_recenabled_streams (Route& route)
920 Track* track = dynamic_cast<Track*>(&route);
921 if (track && track->diskstream()->record_enabled()) {
922 rec_enabled_streams += track->n_inputs().n_total();
927 ARDOUR_UI::update_disk_space()
933 nframes_t frames = session->available_capture_duration();
936 if (frames == max_frames) {
937 strcpy (buf, _("Disk: 24hrs+"));
942 nframes_t fr = session->frame_rate();
944 rec_enabled_streams = 0;
945 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
947 if (rec_enabled_streams) {
948 frames /= rec_enabled_streams;
951 hrs = frames / (fr * 3600);
952 frames -= hrs * fr * 3600;
953 mins = frames / (fr * 60);
954 frames -= mins * fr * 60;
957 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
960 disk_space_label.set_text (buf);
964 ARDOUR_UI::update_wall_clock ()
971 tm_now = localtime (&now);
973 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
974 wall_clock_label.set_text (buf);
980 ARDOUR_UI::session_menu (GdkEventButton *ev)
982 session_popup_menu->popup (0, 0);
987 ARDOUR_UI::redisplay_recent_sessions ()
989 std::vector<sys::path> session_directories;
990 RecentSessionsSorter cmp;
992 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
993 recent_session_model->clear ();
995 ARDOUR::RecentSessions rs;
996 ARDOUR::read_recent_sessions (rs);
999 recent_session_display.set_model (recent_session_model);
1003 // sort them alphabetically
1004 sort (rs.begin(), rs.end(), cmp);
1006 for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1007 session_directories.push_back ((*i).second);
1010 for (vector<sys::path>::const_iterator i = session_directories.begin();
1011 i != session_directories.end(); ++i)
1013 std::vector<sys::path> state_file_paths;
1015 // now get available states for this session
1017 get_state_files_in_directory (*i, state_file_paths);
1019 if (state_file_paths.empty()) {
1024 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1026 Gtk::TreeModel::Row row = *(recent_session_model->append());
1028 const string fullpath = (*i).to_string();
1030 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1031 row[recent_session_columns.fullpath] = fullpath;
1033 if (state_file_names.size() > 1) {
1037 for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1038 i2 != state_file_names.end(); ++i2)
1041 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1043 child_row[recent_session_columns.visible_name] = *i2;
1044 child_row[recent_session_columns.fullpath] = fullpath;
1049 recent_session_display.set_model (recent_session_model);
1053 ARDOUR_UI::build_session_selector ()
1055 session_selector_window = new ArdourDialog ("session selector");
1057 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1059 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1060 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1061 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1062 recent_session_model = TreeStore::create (recent_session_columns);
1063 recent_session_display.set_model (recent_session_model);
1064 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1065 recent_session_display.set_headers_visible (false);
1066 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1067 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1069 scroller->add (recent_session_display);
1070 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1072 session_selector_window->set_name ("SessionSelectorWindow");
1073 session_selector_window->set_size_request (200, 400);
1074 session_selector_window->get_vbox()->pack_start (*scroller);
1076 recent_session_display.show();
1078 //session_selector_window->get_vbox()->show();
1082 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1084 session_selector_window->response (RESPONSE_ACCEPT);
1088 ARDOUR_UI::open_recent_session ()
1090 bool can_return = (session != 0);
1092 if (session_selector_window == 0) {
1093 build_session_selector ();
1096 redisplay_recent_sessions ();
1100 session_selector_window->set_position (WIN_POS_MOUSE);
1102 ResponseType r = (ResponseType) session_selector_window->run ();
1105 case RESPONSE_ACCEPT:
1109 session_selector_window->hide();
1116 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1120 session_selector_window->hide();
1122 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1124 if (i == recent_session_model->children().end()) {
1128 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1129 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1131 _session_is_new = false;
1133 if (load_session (path, state) == 0) {
1142 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1144 struct stat statbuf;
1146 if (stat (info.filename.c_str(), &statbuf) != 0) {
1150 if (!S_ISDIR(statbuf.st_mode)) {
1156 string session_file = info.filename;
1157 session_file += '/';
1158 session_file += Glib::path_get_basename (info.filename);
1159 session_file += ".ardour";
1161 if (stat (session_file.c_str(), &statbuf) != 0) {
1165 return S_ISREG (statbuf.st_mode);
1169 ARDOUR_UI::check_audioengine ()
1172 if (!engine->connected()) {
1173 MessageDialog msg (_("Ardour is not connected to JACK\n"
1174 "You cannot open or close sessions in this condition"));
1185 ARDOUR_UI::open_session ()
1187 if (!check_audioengine()) {
1192 /* popup selector window */
1194 if (open_session_selector == 0) {
1196 /* ardour sessions are folders */
1198 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1199 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1200 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1201 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1203 FileFilter session_filter;
1204 session_filter.add_pattern ("*.ardour");
1205 session_filter.set_name (_("Ardour sessions"));
1206 open_session_selector->add_filter (session_filter);
1207 open_session_selector->set_filter (session_filter);
1210 int response = open_session_selector->run();
1211 open_session_selector->hide ();
1214 case RESPONSE_ACCEPT:
1217 open_session_selector->hide();
1221 open_session_selector->hide();
1222 string session_path = open_session_selector->get_filename();
1226 if (session_path.length() > 0) {
1227 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1228 _session_is_new = isnew;
1229 load_session (path, name);
1236 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1238 list<boost::shared_ptr<MidiTrack> > tracks;
1241 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1248 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1250 if (tracks.size() != how_many) {
1251 if (how_many == 1) {
1252 error << _("could not create a new midi track") << endmsg;
1254 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1258 if ((route = session->new_midi_route ()) == 0) {
1259 error << _("could not create new midi bus") << endmsg;
1265 MessageDialog msg (*editor,
1266 _("There are insufficient JACK ports available\n\
1267 to create a new track or bus.\n\
1268 You should save Ardour, exit and\n\
1269 restart JACK with more ports."));
1276 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1278 list<boost::shared_ptr<AudioTrack> > tracks;
1279 Session::RouteList routes;
1282 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1288 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1290 if (tracks.size() != how_many) {
1291 if (how_many == 1) {
1292 error << _("could not create a new audio track") << endmsg;
1294 error << string_compose (_("could only create %1 of %2 new audio %3"),
1295 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1301 routes = session->new_audio_route (input_channels, output_channels, how_many);
1303 if (routes.size() != how_many) {
1304 if (how_many == 1) {
1305 error << _("could not create a new audio track") << endmsg;
1307 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1313 if (need_control_room_outs) {
1319 route->set_stereo_control_outs (control_lr_channels);
1320 route->control_outs()->set_stereo_pan (pans, this);
1322 #endif /* CONTROLOUTS */
1326 MessageDialog msg (*editor,
1327 _("There are insufficient JACK ports available\n\
1328 to create a new track or bus.\n\
1329 You should save Ardour, exit and\n\
1330 restart JACK with more ports."));
1336 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1338 nframes_t _preroll = 0;
1341 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1342 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1344 if (new_position > _preroll) {
1345 new_position -= _preroll;
1350 session->request_locate (new_position);
1355 ARDOUR_UI::transport_goto_start ()
1358 session->goto_start();
1361 /* force displayed area in editor to start no matter
1362 what "follow playhead" setting is.
1366 editor->reset_x_origin (session->current_start_frame());
1372 ARDOUR_UI::transport_goto_zero ()
1375 session->request_locate (0);
1378 /* force displayed area in editor to start no matter
1379 what "follow playhead" setting is.
1383 editor->reset_x_origin (0);
1389 ARDOUR_UI::transport_goto_end ()
1392 nframes_t frame = session->current_end_frame();
1393 session->request_locate (frame);
1395 /* force displayed area in editor to start no matter
1396 what "follow playhead" setting is.
1400 editor->reset_x_origin (frame);
1406 ARDOUR_UI::transport_stop ()
1412 if (session->is_auditioning()) {
1413 session->cancel_audition ();
1417 if (session->get_play_loop ()) {
1418 session->request_play_loop (false);
1421 session->request_stop ();
1425 ARDOUR_UI::transport_stop_and_forget_capture ()
1428 session->request_stop (true);
1433 ARDOUR_UI::remove_last_capture()
1436 editor->remove_last_capture();
1441 ARDOUR_UI::transport_record (bool roll)
1444 switch (session->record_status()) {
1445 case Session::Disabled:
1446 if (session->ntracks() == 0) {
1447 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1451 session->maybe_enable_record ();
1456 case Session::Recording:
1458 session->request_stop();
1460 session->disable_record (false, true);
1464 case Session::Enabled:
1465 session->disable_record (false, true);
1471 ARDOUR_UI::transport_roll ()
1479 rolling = session->transport_rolling ();
1481 if (session->get_play_loop()) {
1482 session->request_play_loop (false);
1483 auto_loop_button.set_visual_state (1);
1484 roll_button.set_visual_state (1);
1485 } else if (session->get_play_range ()) {
1486 session->request_play_range (false);
1487 play_selection_button.set_visual_state (0);
1488 } else if (rolling) {
1489 session->request_locate (session->last_transport_start(), true);
1492 session->request_transport_speed (1.0f);
1496 ARDOUR_UI::transport_loop()
1499 if (session->get_play_loop()) {
1500 if (session->transport_rolling()) {
1501 Location * looploc = session->locations()->auto_loop_location();
1503 session->request_locate (looploc->start(), true);
1508 session->request_play_loop (true);
1514 ARDOUR_UI::transport_play_selection ()
1520 if (!session->get_play_range()) {
1521 session->request_stop ();
1524 editor->play_selection ();
1528 ARDOUR_UI::transport_rewind (int option)
1530 float current_transport_speed;
1533 current_transport_speed = session->transport_speed();
1535 if (current_transport_speed >= 0.0f) {
1538 session->request_transport_speed (-1.0f);
1541 session->request_transport_speed (-4.0f);
1544 session->request_transport_speed (-0.5f);
1549 session->request_transport_speed (current_transport_speed * 1.5f);
1555 ARDOUR_UI::transport_forward (int option)
1557 float current_transport_speed;
1560 current_transport_speed = session->transport_speed();
1562 if (current_transport_speed <= 0.0f) {
1565 session->request_transport_speed (1.0f);
1568 session->request_transport_speed (4.0f);
1571 session->request_transport_speed (0.5f);
1576 session->request_transport_speed (current_transport_speed * 1.5f);
1582 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1588 boost::shared_ptr<Route> r;
1590 if ((r = session->route_by_remote_id (dstream)) != 0) {
1594 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1595 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1604 ARDOUR_UI::queue_transport_change ()
1606 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1610 ARDOUR_UI::map_transport_state ()
1612 float sp = session->transport_speed();
1615 transport_rolling ();
1616 } else if (sp < 0.0f) {
1617 transport_rewinding ();
1618 } else if (sp > 0.0f) {
1619 transport_forwarding ();
1621 transport_stopped ();
1626 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1628 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1629 (int) adj.get_value()].c_str());
1633 ARDOUR_UI::engine_stopped ()
1635 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1636 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1637 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1641 ARDOUR_UI::engine_running ()
1643 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1644 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1645 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1647 Glib::RefPtr<Action> action;
1648 const char* action_name = 0;
1650 switch (engine->frames_per_cycle()) {
1652 action_name = X_("JACKLatency32");
1655 action_name = X_("JACKLatency64");
1658 action_name = X_("JACKLatency128");
1661 action_name = X_("JACKLatency512");
1664 action_name = X_("JACKLatency1024");
1667 action_name = X_("JACKLatency2048");
1670 action_name = X_("JACKLatency4096");
1673 action_name = X_("JACKLatency8192");
1676 /* XXX can we do anything useful ? */
1682 action = ActionManager::get_action (X_("JACK"), action_name);
1685 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1686 ract->set_active ();
1692 ARDOUR_UI::engine_halted ()
1694 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1696 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1697 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1699 update_sample_rate (0);
1701 MessageDialog msg (*editor,
1703 JACK has either been shutdown or it\n\
1704 disconnected Ardour because Ardour\n\
1705 was not fast enough. You can save the\n\
1706 session and/or try to reconnect to JACK ."));
1711 ARDOUR_UI::do_engine_start ()
1719 error << _("Unable to start the session running")
1729 ARDOUR_UI::setup_theme ()
1731 theme_manager->setup_theme();
1735 ARDOUR_UI::update_clocks ()
1737 if (!editor || !editor->dragging_playhead()) {
1738 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1743 ARDOUR_UI::start_clocking ()
1745 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1749 ARDOUR_UI::stop_clocking ()
1751 clock_signal_connection.disconnect ();
1755 ARDOUR_UI::toggle_clocking ()
1758 if (clock_button.get_active()) {
1767 ARDOUR_UI::_blink (void *arg)
1770 ((ARDOUR_UI *) arg)->blink ();
1777 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1781 ARDOUR_UI::start_blinking ()
1783 /* Start the blink signal. Everybody with a blinking widget
1784 uses Blink to drive the widget's state.
1787 if (blink_timeout_tag < 0) {
1789 blink_timeout_tag = g_timeout_add (240, _blink, this);
1794 ARDOUR_UI::stop_blinking ()
1796 if (blink_timeout_tag >= 0) {
1797 g_source_remove (blink_timeout_tag);
1798 blink_timeout_tag = -1;
1803 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1808 vector<string> connections;
1811 if (io.n_inputs().n_total() == 0) {
1816 /* XXX we're not handling multiple ports yet. */
1818 if (io.input(0)->get_connections(connections) == 0) {
1821 buf = connections.front();
1826 if (io.n_outputs().n_total() == 0) {
1831 /* XXX we're not handling multiple ports yet. */
1833 if (io.output(0)->get_connections(connections) == 0) {
1836 buf = connections.front();
1841 /** Ask the user for the name of a new shapshot and then take it.
1844 ARDOUR_UI::snapshot_session ()
1846 ArdourPrompter prompter (true);
1850 struct tm local_time;
1853 localtime_r (&n, &local_time);
1854 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1856 prompter.set_name ("Prompter");
1857 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1858 prompter.set_prompt (_("Name of New Snapshot"));
1859 prompter.set_initial_text (timebuf);
1861 switch (prompter.run()) {
1862 case RESPONSE_ACCEPT:
1863 prompter.get_result (snapname);
1864 if (snapname.length()){
1865 save_state (snapname);
1875 ARDOUR_UI::save_state (const string & name)
1877 (void) save_state_canfail (name);
1881 ARDOUR_UI::save_state_canfail (string name)
1886 if (name.length() == 0) {
1887 name = session->snap_name();
1890 if ((ret = session->save_state (name)) != 0) {
1894 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1899 ARDOUR_UI::restore_state (string name)
1902 if (name.length() == 0) {
1903 name = session->name();
1905 session->restore_state (name);
1910 ARDOUR_UI::primary_clock_value_changed ()
1913 session->request_locate (primary_clock.current_time ());
1918 ARDOUR_UI::big_clock_value_changed ()
1921 session->request_locate (big_clock.current_time ());
1926 ARDOUR_UI::secondary_clock_value_changed ()
1929 session->request_locate (secondary_clock.current_time ());
1934 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1936 if (session && dstream && dstream->record_enabled()) {
1938 Session::RecordState rs;
1940 rs = session->record_status ();
1943 case Session::Disabled:
1944 case Session::Enabled:
1945 if (w->get_state() != STATE_SELECTED) {
1946 w->set_state (STATE_SELECTED);
1950 case Session::Recording:
1951 if (w->get_state() != STATE_ACTIVE) {
1952 w->set_state (STATE_ACTIVE);
1958 if (w->get_state() != STATE_NORMAL) {
1959 w->set_state (STATE_NORMAL);
1965 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1971 switch (session->record_status()) {
1972 case Session::Enabled:
1974 rec_button.set_visual_state (2);
1976 rec_button.set_visual_state (0);
1980 case Session::Recording:
1981 rec_button.set_visual_state (1);
1985 rec_button.set_visual_state (0);
1991 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1999 ARDOUR_UI::save_template ()
2002 ArdourPrompter prompter (true);
2005 if (!check_audioengine()) {
2009 prompter.set_name (X_("Prompter"));
2010 prompter.set_prompt (_("Name for mix template:"));
2011 prompter.set_initial_text(session->name() + _("-template"));
2012 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2014 switch (prompter.run()) {
2015 case RESPONSE_ACCEPT:
2016 prompter.get_result (name);
2018 if (name.length()) {
2019 session->save_template (name);
2029 ARDOUR_UI::fontconfig_dialog ()
2032 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2033 may not and it can take a while to build it. Warn them.
2036 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2038 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2039 MessageDialog msg (*new_session_dialog,
2040 _("Welcome to Ardour.\n\n"
2041 "The program will take a bit longer to start up\n"
2042 "while the system fonts are checked.\n\n"
2043 "This will only be done once, and you will\n"
2044 "not see this message again\n"),
2056 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2058 existing_session = false;
2060 if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2061 session_path = cmdline_path;
2062 existing_session = true;
2063 } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2064 session_path = Glib::path_get_dirname (string (cmdline_path));
2065 existing_session = true;
2067 /* it doesn't exist, assume the best */
2068 session_path = Glib::path_get_dirname (string (cmdline_path));
2071 session_name = basename_nosuffix (string (cmdline_path));
2075 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2077 /* when this is called, the backend audio system must be running */
2079 /* the main idea here is to deal with the fact that a cmdline argument for the session
2080 can be interpreted in different ways - it could be a directory or a file, and before
2081 we load, we need to know both the session directory and the snapshot (statefile) within it
2082 that we are supposed to use.
2085 if (session_name.length() == 0 || session_path.length() == 0) {
2089 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2091 Glib::ustring predicted_session_file;
2093 predicted_session_file = session_path;
2094 predicted_session_file += '/';
2095 predicted_session_file += session_name;
2096 predicted_session_file += ARDOUR::statefile_suffix;
2098 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2099 existing_session = true;
2102 } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2104 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2105 /* existing .ardour file */
2106 existing_session = true;
2110 existing_session = false;
2113 /* lets just try to load it */
2115 if (create_engine ()) {
2117 loading_dialog->hide ();
2118 backend_audio_error (false, new_session_dialog);
2122 return load_session (session_path, session_name);
2126 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2128 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2130 MessageDialog msg (str,
2132 Gtk::MESSAGE_WARNING,
2133 Gtk::BUTTONS_YES_NO,
2137 msg.set_name (X_("CleanupDialog"));
2138 msg.set_wmclass (X_("existing_session"), "Ardour");
2139 msg.set_position (Gtk::WIN_POS_MOUSE);
2141 switch (msg.run()) {
2150 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2155 AutoConnectOption iconnect;
2156 AutoConnectOption oconnect;
2160 if (Profile->get_sae()) {
2164 iconnect = AutoConnectPhysical;
2165 oconnect = AutoConnectMaster;
2166 nphysin = 0; // use all available
2167 nphysout = 0; // use all available
2171 /* get settings from advanced section of NSD */
2173 if (new_session_dialog->create_control_bus()) {
2174 cchns = (uint32_t) new_session_dialog->control_channel_count();
2179 if (new_session_dialog->create_master_bus()) {
2180 mchns = (uint32_t) new_session_dialog->master_channel_count();
2185 if (new_session_dialog->connect_inputs()) {
2186 iconnect = AutoConnectPhysical;
2188 iconnect = AutoConnectOption (0);
2191 /// @todo some minor tweaks.
2193 if (new_session_dialog->connect_outs_to_master()) {
2194 oconnect = AutoConnectMaster;
2195 } else if (new_session_dialog->connect_outs_to_physical()) {
2196 oconnect = AutoConnectPhysical;
2198 oconnect = AutoConnectOption (0);
2201 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2202 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2205 if (build_session (session_path,
2213 engine->frame_rate() * 60 * 5)) {
2223 ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
2225 bool existing_session = false;
2226 Glib::ustring session_name;
2227 Glib::ustring session_path;
2228 Glib::ustring template_name;
2230 if (!loading_dialog) {
2231 loading_dialog = new MessageDialog (*new_session_dialog,
2238 int response = Gtk::RESPONSE_NONE;
2240 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2242 parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
2244 /* don't ever reuse this */
2246 ARDOUR_COMMAND_LINE::session_name = string();
2248 if (existing_session && backend_audio_is_running) {
2250 /* just load the thing already */
2252 if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
2257 /* make the NSD use whatever information we have */
2259 new_session_dialog->set_session_name (session_name);
2260 new_session_dialog->set_session_folder (session_path);
2263 /* loading failed, or we need the NSD for something */
2265 new_session_dialog->set_modal (false);
2266 new_session_dialog->set_position (WIN_POS_CENTER);
2267 new_session_dialog->set_current_page (0);
2268 new_session_dialog->set_existing_session (existing_session);
2269 new_session_dialog->reset_recent();
2271 /* get this out of the way */
2276 new_session_dialog->set_have_engine (backend_audio_is_running);
2277 new_session_dialog->present ();
2278 response = new_session_dialog->run ();
2279 loading_dialog->hide ();
2281 _session_is_new = false;
2283 /* handle possible negative responses */
2286 case Gtk::RESPONSE_CANCEL:
2287 case Gtk::RESPONSE_DELETE_EVENT:
2291 new_session_dialog->hide ();
2294 case Gtk::RESPONSE_NONE:
2295 /* "Clear" was pressed */
2299 fontconfig_dialog();
2301 if (!backend_audio_is_running) {
2302 if (new_session_dialog->engine_control.setup_engine ()) {
2303 new_session_dialog->hide ();
2308 if (create_engine ()) {
2310 backend_audio_error (!backend_audio_is_running, new_session_dialog);
2311 loading_dialog->hide ();
2314 new_session_dialog->set_existing_session (false);
2315 new_session_dialog->set_current_page (2);
2317 response = Gtk::RESPONSE_NONE;
2321 loading_dialog->hide ();
2322 backend_audio_is_running = true;
2324 if (response == Gtk::RESPONSE_OK) {
2326 session_name = new_session_dialog->session_name();
2328 if (session_name.empty()) {
2329 response = Gtk::RESPONSE_NONE;
2333 /* if the user mistakenly typed path information into the session filename entry,
2334 convert what they typed into a path & a name
2337 if (session_name[0] == '/' ||
2338 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2339 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2341 session_path = Glib::path_get_dirname (session_name);
2342 session_name = Glib::path_get_basename (session_name);
2346 session_path = new_session_dialog->session_folder();
2349 switch (new_session_dialog->which_page()) {
2351 case NewSessionDialog::OpenPage:
2352 case NewSessionDialog::EnginePage:
2356 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2358 should_be_new = true;
2360 //XXX This is needed because session constructor wants a
2361 //non-existant path. hopefully this will be fixed at some point.
2363 session_path = Glib::build_filename (session_path, session_name);
2365 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2367 if (ask_about_loading_existing_session (session_path)) {
2370 response = RESPONSE_NONE;
2375 _session_is_new = true;
2377 if (new_session_dialog->use_session_template()) {
2379 template_name = new_session_dialog->session_template_name();
2383 if (build_session_from_nsd (session_path, session_name)) {
2384 response = RESPONSE_NONE;
2396 new_session_dialog->hide ();
2398 if (load_session (session_path, session_name)) {
2400 response = Gtk::RESPONSE_NONE;
2404 if (response == Gtk::RESPONSE_NONE) {
2405 loading_dialog->hide ();
2406 new_session_dialog->set_existing_session (false);
2407 new_session_dialog->reset ();
2411 } while (response == Gtk::RESPONSE_NONE);
2415 loading_dialog->hide ();
2416 new_session_dialog->hide();
2417 new_session_dialog->reset();
2418 goto_editor_window ();
2423 ARDOUR_UI::close_session()
2425 if (!check_audioengine()) {
2429 unload_session (true);
2431 get_session_parameters (true, false);
2435 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2437 Session *new_session;
2441 session_loaded = false;
2443 if (!check_audioengine()) {
2447 unload_status = unload_session ();
2449 if (unload_status < 0) {
2451 } else if (unload_status > 0) {
2456 /* if it already exists, we must have write access */
2458 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2459 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2460 "This prevents the session from being loaded."));
2466 // OS X where everything is sllloooowwww
2467 if (loading_dialog) {
2468 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2473 disable_screen_updates ();
2476 new_session = new Session (*engine, path, snap_name, mix_template);
2479 /* this one is special */
2481 catch (AudioEngine::PortRegistrationFailure& err) {
2483 MessageDialog msg (err.what(),
2486 Gtk::BUTTONS_OK_CANCEL);
2488 msg.set_title (_("Loading Error"));
2489 msg.set_secondary_text (_("Click the OK button to try again."));
2490 msg.set_position (Gtk::WIN_POS_CENTER);
2493 int response = msg.run ();
2498 case RESPONSE_CANCEL:
2508 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2511 Gtk::BUTTONS_OK_CANCEL);
2513 msg.set_title (_("Loading Error"));
2514 msg.set_secondary_text (_("Click the OK button to try again."));
2515 msg.set_position (Gtk::WIN_POS_CENTER);
2518 int response = msg.run ();
2523 case RESPONSE_CANCEL:
2531 connect_to_session (new_session);
2533 Config->set_current_owner (ConfigVariableBase::Interface);
2535 session_loaded = true;
2537 goto_editor_window ();
2540 session->set_clean ();
2543 enable_screen_updates ();
2552 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2553 uint32_t control_channels,
2554 uint32_t master_channels,
2555 AutoConnectOption input_connect,
2556 AutoConnectOption output_connect,
2559 nframes_t initial_length)
2561 Session *new_session;
2564 if (!check_audioengine()) {
2568 session_loaded = false;
2570 x = unload_session ();
2578 _session_is_new = true;
2581 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2582 control_channels, master_channels, nphysin, nphysout, initial_length);
2587 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2592 connect_to_session (new_session);
2594 session_loaded = true;
2602 editor->show_window ();
2613 ARDOUR_UI::show_about ()
2617 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2624 ARDOUR_UI::hide_about ()
2627 about->get_window()->set_cursor ();
2633 ARDOUR_UI::about_signal_response(int response)
2639 ARDOUR_UI::show_splash ()
2643 splash = new Splash;
2650 splash->get_window()->process_updates (true);
2655 ARDOUR_UI::hide_splash ()
2663 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2667 removed = rep.paths.size();
2670 MessageDialog msgd (*editor,
2671 _("No audio files were ready for cleanup"),
2674 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2675 msgd.set_secondary_text (_("If this seems suprising, \n\
2676 check for any existing snapshots.\n\
2677 These may still include regions that\n\
2678 require some unused files to continue to exist."));
2684 ArdourDialog results (_("ardour: cleanup"), true, false);
2686 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2687 CleanupResultsModelColumns() {
2691 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2692 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2696 CleanupResultsModelColumns results_columns;
2697 Glib::RefPtr<Gtk::ListStore> results_model;
2698 Gtk::TreeView results_display;
2700 results_model = ListStore::create (results_columns);
2701 results_display.set_model (results_model);
2702 results_display.append_column (list_title, results_columns.visible_name);
2704 results_display.set_name ("CleanupResultsList");
2705 results_display.set_headers_visible (true);
2706 results_display.set_headers_clickable (false);
2707 results_display.set_reorderable (false);
2709 Gtk::ScrolledWindow list_scroller;
2712 Gtk::HBox dhbox; // the hbox for the image and text
2713 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2714 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2716 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2718 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2720 if (rep.space < 1048576.0f) {
2722 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2724 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2728 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2730 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2734 dhbox.pack_start (*dimage, true, false, 5);
2735 dhbox.pack_start (txt, true, false, 5);
2737 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2738 TreeModel::Row row = *(results_model->append());
2739 row[results_columns.visible_name] = *i;
2740 row[results_columns.fullpath] = *i;
2743 list_scroller.add (results_display);
2744 list_scroller.set_size_request (-1, 150);
2745 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2747 dvbox.pack_start (dhbox, true, false, 5);
2748 dvbox.pack_start (list_scroller, true, false, 5);
2749 ddhbox.pack_start (dvbox, true, false, 5);
2751 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2752 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2753 results.set_default_response (RESPONSE_CLOSE);
2754 results.set_position (Gtk::WIN_POS_MOUSE);
2756 results_display.show();
2757 list_scroller.show();
2764 //results.get_vbox()->show();
2765 results.set_resizable (false);
2772 ARDOUR_UI::cleanup ()
2775 /* shouldn't happen: menu item is insensitive */
2780 MessageDialog checker (_("Are you sure you want to cleanup?"),
2782 Gtk::MESSAGE_QUESTION,
2783 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2785 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2786 ALL undo/redo information will be lost if you cleanup.\n\
2787 After cleanup, unused audio files will be moved to a \
2788 \"dead sounds\" location."));
2790 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2791 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2792 checker.set_default_response (RESPONSE_CANCEL);
2794 checker.set_name (_("CleanupDialog"));
2795 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2796 checker.set_position (Gtk::WIN_POS_MOUSE);
2798 switch (checker.run()) {
2799 case RESPONSE_ACCEPT:
2805 Session::cleanup_report rep;
2807 editor->prepare_for_cleanup ();
2809 /* do not allow flush until a session is reloaded */
2811 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2813 act->set_sensitive (false);
2816 if (session->cleanup_sources (rep)) {
2821 display_cleanup_results (rep,
2824 The following %1 %2 not in use and \n\
2825 have been moved to:\n\
2827 Flushing the wastebasket will \n\
2828 release an additional\n\
2829 %4 %5bytes of disk space.\n"
2837 ARDOUR_UI::flush_trash ()
2840 /* shouldn't happen: menu item is insensitive */
2844 Session::cleanup_report rep;
2846 if (session->cleanup_trash_sources (rep)) {
2850 display_cleanup_results (rep,
2852 _("The following %1 %2 deleted from\n\
2854 releasing %4 %5bytes of disk space"));
2858 ARDOUR_UI::add_route (Gtk::Window* float_window)
2866 if (add_route_dialog == 0) {
2867 add_route_dialog = new AddRouteDialog;
2869 add_route_dialog->set_transient_for (*float_window);
2873 if (add_route_dialog->is_visible()) {
2874 /* we're already doing this */
2878 ResponseType r = (ResponseType) add_route_dialog->run ();
2880 add_route_dialog->hide();
2883 case RESPONSE_ACCEPT:
2890 if ((count = add_route_dialog->count()) <= 0) {
2894 uint32_t input_chan = add_route_dialog->channels ();
2895 uint32_t output_chan;
2896 string name_template = add_route_dialog->name_template ();
2897 bool track = add_route_dialog->track ();
2899 AutoConnectOption oac = Config->get_output_auto_connect();
2901 if (oac & AutoConnectMaster) {
2902 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2904 output_chan = input_chan;
2907 /* XXX do something with name template */
2909 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2911 session_add_midi_track(count);
2913 MessageDialog msg (*editor,
2914 _("Sorry, MIDI Busses are not supported at this time."));
2916 //session_add_midi_bus();
2920 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2922 session_add_audio_bus (input_chan, output_chan, count);
2928 ARDOUR_UI::mixer_settings () const
2933 node = session->instant_xml(X_("Mixer"));
2935 node = Config->instant_xml(X_("Mixer"));
2939 node = new XMLNode (X_("Mixer"));
2946 ARDOUR_UI::editor_settings () const
2951 node = session->instant_xml(X_("Editor"));
2953 node = Config->instant_xml(X_("Editor"));
2957 node = new XMLNode (X_("Editor"));
2963 ARDOUR_UI::keyboard_settings () const
2967 node = Config->extra_xml(X_("Keyboard"));
2970 node = new XMLNode (X_("Keyboard"));
2976 ARDOUR_UI::halt_on_xrun_message ()
2978 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2980 MessageDialog msg (*editor,
2981 _("Recording was stopped because your system could not keep up."));
2986 ARDOUR_UI::disk_overrun_handler ()
2988 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2990 if (!have_disk_speed_dialog_displayed) {
2991 have_disk_speed_dialog_displayed = true;
2992 MessageDialog* msg = new MessageDialog (*editor, _("\
2993 The disk system on your computer\n\
2994 was not able to keep up with Ardour.\n\
2996 Specifically, it failed to write data to disk\n\
2997 quickly enough to keep up with recording.\n"));
2998 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3004 ARDOUR_UI::disk_underrun_handler ()
3006 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3008 if (!have_disk_speed_dialog_displayed) {
3009 have_disk_speed_dialog_displayed = true;
3010 MessageDialog* msg = new MessageDialog (*editor,
3011 _("The disk system on your computer\n\
3012 was not able to keep up with Ardour.\n\
3014 Specifically, it failed to read data from disk\n\
3015 quickly enough to keep up with playback.\n"));
3016 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3022 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
3024 have_disk_speed_dialog_displayed = false;
3029 ARDOUR_UI::pending_state_dialog ()
3031 HBox* hbox = new HBox();
3032 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3033 ArdourDialog dialog (_("Crash Recovery"), true);
3035 This session appears to have been in\n\
3036 middle of recording when ardour or\n\
3037 the computer was shutdown.\n\
3039 Ardour can recover any captured audio for\n\
3040 you, or it can ignore it. Please decide\n\
3041 what you would like to do.\n"));
3042 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3043 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3044 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3045 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3046 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3047 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3048 dialog.set_default_response (RESPONSE_ACCEPT);
3049 dialog.set_position (WIN_POS_CENTER);
3054 switch (dialog.run ()) {
3055 case RESPONSE_ACCEPT:
3063 ARDOUR_UI::disconnect_from_jack ()
3066 if( engine->disconnect_from_jack ()) {
3067 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3071 update_sample_rate (0);
3076 ARDOUR_UI::reconnect_to_jack ()
3079 if (engine->reconnect_to_jack ()) {
3080 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3084 update_sample_rate (0);
3089 ARDOUR_UI::use_config ()
3091 Glib::RefPtr<Action> act;
3093 switch (Config->get_native_file_data_format ()) {
3095 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3098 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3101 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3106 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3107 ract->set_active ();
3110 switch (Config->get_native_file_header_format ()) {
3112 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3115 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3118 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3121 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3124 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3127 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3130 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3135 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3136 ract->set_active ();
3139 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3141 set_transport_controllable_state (*node);
3146 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3148 if (Config->get_primary_clock_delta_edit_cursor()) {
3149 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3151 primary_clock.set (pos, 0, true);
3154 if (Config->get_secondary_clock_delta_edit_cursor()) {
3155 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3157 secondary_clock.set (pos);
3160 if (big_clock_window) {
3161 big_clock.set (pos);
3166 ARDOUR_UI::record_state_changed ()
3168 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3170 if (!session || !big_clock_window) {
3171 /* why bother - the clock isn't visible */
3175 switch (session->record_status()) {
3176 case Session::Recording:
3177 big_clock.set_widget_name ("BigClockRecording");
3180 big_clock.set_widget_name ("BigClockNonRecording");
3186 ARDOUR_UI::set_keybindings_path (string path)
3188 keybindings_path = path;
3192 ARDOUR_UI::save_keybindings ()
3194 if (can_save_keybindings) {
3195 AccelMap::save (user_keybindings_path);
3200 ARDOUR_UI::first_idle ()
3203 session->allow_auto_play (true);
3205 can_save_keybindings = true;
3210 ARDOUR_UI::store_clock_modes ()
3212 XMLNode* node = new XMLNode(X_("ClockModes"));
3214 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3215 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3218 session->add_extra_xml (*node);
3219 session->set_dirty ();
3224 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3225 : Controllable (name), ui (u), type(tp)
3231 ARDOUR_UI::TransportControllable::set_value (float val)
3233 if (type == ShuttleControl) {
3240 fract = -((0.5f - val)/0.5f);
3242 fract = ((val - 0.5f)/0.5f);
3246 ui.set_shuttle_fract (fract);
3251 /* do nothing: these are radio-style actions */
3255 const char *action = 0;
3259 action = X_("Roll");
3262 action = X_("Stop");
3265 action = X_("Goto Start");
3268 action = X_("Goto End");
3271 action = X_("Loop");
3274 action = X_("Play Selection");
3277 action = X_("Record");
3287 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3295 ARDOUR_UI::TransportControllable::get_value (void) const
3314 case ShuttleControl:
3324 ARDOUR_UI::TransportControllable::set_id (const string& str)
3330 ARDOUR_UI::setup_profile ()
3332 if (gdk_screen_width() < 1200) {
3333 Profile->set_small_screen ();
3337 if (getenv ("ARDOUR_SAE")) {
3338 Profile->set_sae ();
3339 Profile->set_single_package ();