2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/basename.h>
37 #include <pbd/compose.h>
39 #include <pbd/pathscanner.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/stacktrace.h>
43 #include <gtkmm2ext/gtk_ui.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/click_box.h>
46 #include <gtkmm2ext/fastmeter.h>
47 #include <gtkmm2ext/stop_signal.h>
48 #include <gtkmm2ext/popup.h>
49 #include <gtkmm2ext/window_title.h>
51 #include <midi++/port.h>
52 #include <midi++/mmc.h>
54 #include <ardour/ardour.h>
55 #include <ardour/profile.h>
56 #include <ardour/session_route.h>
57 #include <ardour/port.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/playlist.h>
60 #include <ardour/utils.h>
61 #include <ardour/audio_diskstream.h>
62 #include <ardour/audiofilesource.h>
63 #include <ardour/recent_sessions.h>
64 #include <ardour/port.h>
65 #include <ardour/audio_track.h>
68 #include "ardour_ui.h"
69 #include "public_editor.h"
70 #include "audio_clock.h"
75 #include "add_route_dialog.h"
76 #include "new_session_dialog.h"
79 #include "gui_thread.h"
80 #include "theme_manager.h"
81 #include "engine_dialog.h"
85 using namespace ARDOUR;
87 using namespace Gtkmm2ext;
91 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
92 UIConfiguration *ARDOUR_UI::ui_config = 0;
94 sigc::signal<void,bool> ARDOUR_UI::Blink;
95 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
96 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
97 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
99 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
101 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
103 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
104 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
105 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
106 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
110 adjuster_table (3, 3),
114 preroll_button (_("pre\nroll")),
115 postroll_button (_("post\nroll")),
119 big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
123 roll_controllable ("transport roll", *this, TransportControllable::Roll),
124 stop_controllable ("transport stop", *this, TransportControllable::Stop),
125 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
126 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
127 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
128 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
129 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
130 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
131 shuttle_controller_binding_proxy (shuttle_controllable),
133 roll_button (roll_controllable),
134 stop_button (stop_controllable),
135 goto_start_button (goto_start_controllable),
136 goto_end_button (goto_end_controllable),
137 auto_loop_button (auto_loop_controllable),
138 play_selection_button (play_selection_controllable),
139 rec_button (rec_controllable),
141 shuttle_units_button (_("% ")),
143 punch_in_button (_("Punch In")),
144 punch_out_button (_("Punch Out")),
145 auto_return_button (_("Auto Return")),
146 auto_play_button (_("Auto Play")),
147 auto_input_button (_("Auto Input")),
148 click_button (_("Click")),
149 time_master_button (_("time\nmaster")),
151 auditioning_alert_button (_("AUDITION")),
152 solo_alert_button (_("SOLO")),
154 error_log_button (_("Errors"))
156 using namespace Gtk::Menu_Helpers;
161 _auto_display_errors = false;
164 if (getenv ("ARDOUR_DEBUG_UPDATES")) {
165 gdk_window_set_debug_updates (true);
170 if (theArdourUI == 0) {
174 ui_config = new UIConfiguration();
175 theme_manager = new ThemeManager();
181 _session_is_new = false;
182 big_clock_window = 0;
183 session_selector_window = 0;
184 new_session_dialog = 0;
185 last_key_press_time = 0;
186 connection_editor = 0;
187 add_route_dialog = 0;
192 open_session_selector = 0;
193 have_configure_timeout = false;
194 have_disk_speed_dialog_displayed = false;
195 _will_create_new_session_automatically = false;
196 session_loaded = false;
198 last_speed_displayed = -1.0f;
200 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
201 /* all changes go to the user directory */
202 user_keybindings_path = get_user_ardour_path ();
203 user_keybindings_path += '/';
204 user_keybindings_path += "ardour.bindings";
206 can_save_keybindings = false;
208 last_configure_time.tv_sec = 0;
209 last_configure_time.tv_usec = 0;
211 shuttle_grabbed = false;
213 shuttle_max_speed = 8.0f;
215 shuttle_style_menu = 0;
216 shuttle_unit_menu = 0;
218 gettimeofday (&last_peak_grab, 0);
219 gettimeofday (&last_shuttle_request, 0);
221 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
222 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
224 /* handle pending state with a dialog */
226 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
228 /* lets get this party started */
231 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
232 setup_gtk_ardour_enums ();
233 Config->set_current_owner (ConfigVariableBase::Interface);
236 } catch (failed_constructor& err) {
237 error << _("could not initialize Ardour.") << endmsg;
242 /* we like keyboards */
244 keyboard = new Keyboard;
246 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
247 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
251 ARDOUR_UI::create_engine ()
253 // this gets called every time by new_session()
260 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
267 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
268 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
269 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
270 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
278 ARDOUR_UI::post_engine ()
280 /* Things to be done once we create the AudioEngine
283 check_memory_locking();
285 ActionManager::init ();
288 if (setup_windows ()) {
289 throw failed_constructor ();
292 /* this is the first point at which all the keybindings are available */
294 if (ARDOUR_COMMAND_LINE::show_key_actions) {
295 vector<string> names;
296 vector<string> paths;
298 vector<AccelKey> bindings;
300 ActionManager::get_all_actions (names, paths, keys, bindings);
302 vector<string>::iterator n;
303 vector<string>::iterator k;
304 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
305 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
311 blink_timeout_tag = -1;
313 /* the global configuration object is now valid */
317 /* this being a GUI and all, we want peakfiles */
319 AudioFileSource::set_build_peakfiles (true);
320 AudioFileSource::set_build_missing_peakfiles (true);
322 /* set default clock modes */
324 primary_clock.set_mode (AudioClock::SMPTE);
325 secondary_clock.set_mode (AudioClock::BBT);
327 /* start the time-of-day-clock */
330 /* OS X provides an always visible wallclock, so don't be stupid */
331 update_wall_clock ();
332 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
335 update_disk_space ();
337 update_sample_rate (engine->frame_rate());
339 platform_specific ();
341 /* now start and maybe save state */
343 if (do_engine_start () == 0) {
344 if (session && _session_is_new) {
345 /* we need to retain initial visual
346 settings for a new session
348 session->save_state ("");
353 ARDOUR_UI::~ARDOUR_UI ()
355 save_ardour_state ();
369 if (add_route_dialog) {
370 delete add_route_dialog;
373 if (new_session_dialog) {
374 delete new_session_dialog;
379 ARDOUR_UI::configure_timeout ()
384 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
385 /* no configure events yet */
389 gettimeofday (&now, 0);
390 timersub (&now, &last_configure_time, &diff);
392 /* force a gap of 0.5 seconds since the last configure event
395 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
398 have_configure_timeout = false;
399 save_ardour_state ();
405 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
407 if (have_configure_timeout) {
408 gettimeofday (&last_configure_time, 0);
410 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
411 have_configure_timeout = true;
418 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
420 const XMLProperty* prop;
422 if ((prop = node.property ("roll")) != 0) {
423 roll_controllable.set_id (prop->value());
425 if ((prop = node.property ("stop")) != 0) {
426 stop_controllable.set_id (prop->value());
428 if ((prop = node.property ("goto_start")) != 0) {
429 goto_start_controllable.set_id (prop->value());
431 if ((prop = node.property ("goto_end")) != 0) {
432 goto_end_controllable.set_id (prop->value());
434 if ((prop = node.property ("auto_loop")) != 0) {
435 auto_loop_controllable.set_id (prop->value());
437 if ((prop = node.property ("play_selection")) != 0) {
438 play_selection_controllable.set_id (prop->value());
440 if ((prop = node.property ("rec")) != 0) {
441 rec_controllable.set_id (prop->value());
443 if ((prop = node.property ("shuttle")) != 0) {
444 shuttle_controllable.set_id (prop->value());
449 ARDOUR_UI::get_transport_controllable_state ()
451 XMLNode* node = new XMLNode(X_("TransportControllables"));
454 roll_controllable.id().print (buf, sizeof (buf));
455 node->add_property (X_("roll"), buf);
456 stop_controllable.id().print (buf, sizeof (buf));
457 node->add_property (X_("stop"), buf);
458 goto_start_controllable.id().print (buf, sizeof (buf));
459 node->add_property (X_("goto_start"), buf);
460 goto_end_controllable.id().print (buf, sizeof (buf));
461 node->add_property (X_("goto_end"), buf);
462 auto_loop_controllable.id().print (buf, sizeof (buf));
463 node->add_property (X_("auto_loop"), buf);
464 play_selection_controllable.id().print (buf, sizeof (buf));
465 node->add_property (X_("play_selection"), buf);
466 rec_controllable.id().print (buf, sizeof (buf));
467 node->add_property (X_("rec"), buf);
468 shuttle_controllable.id().print (buf, sizeof (buf));
469 node->add_property (X_("shuttle"), buf);
475 ARDOUR_UI::save_ardour_state ()
477 if (!keyboard || !mixer || !editor) {
481 /* XXX this is all a bit dubious. add_extra_xml() uses
482 a different lifetime model from add_instant_xml().
485 XMLNode* node = new XMLNode (keyboard->get_state());
486 Config->add_extra_xml (*node);
487 Config->add_extra_xml (get_transport_controllable_state());
488 if (new_session_dialog) {
489 if (new_session_dialog->engine_control.was_used()) {
490 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
493 Config->save_state();
494 ui_config->save_state ();
496 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
497 XMLNode mnode(mixer->get_state());
500 session->add_instant_xml (enode, session->path());
501 session->add_instant_xml (mnode, session->path());
503 Config->add_instant_xml (enode, get_user_ardour_path());
504 Config->add_instant_xml (mnode, get_user_ardour_path());
511 ARDOUR_UI::autosave_session ()
513 if (!Config->get_periodic_safety_backups())
517 session->maybe_write_autosave();
524 ARDOUR_UI::update_autosave ()
526 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
528 if (session->dirty()) {
529 if (_autosave_connection.connected()) {
530 _autosave_connection.disconnect();
533 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
534 Config->get_periodic_safety_backup_interval() * 1000);
537 if (_autosave_connection.connected()) {
538 _autosave_connection.disconnect();
544 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
548 title = _("Ardour could not start JACK");
550 title = _("Ardour could not connect to JACK.");
553 MessageDialog win (title,
559 win.set_secondary_text(_("There are several possible reasons:\n\
561 1) You requested audio parameters that are not supported..\n\
562 2) JACK is running as another user.\n\
564 Please consider the possibilities, and perhaps try different parameters."));
566 win.set_secondary_text(_("There are several possible reasons:\n\
568 1) JACK is not running.\n\
569 2) JACK is running as another user, perhaps root.\n\
570 3) There is already another client called \"ardour\".\n\
572 Please consider the possibilities, and perhaps (re)start JACK."));
576 win.set_transient_for (*toplevel);
580 win.add_button (Stock::OK, RESPONSE_CLOSE);
582 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
585 win.set_default_response (RESPONSE_CLOSE);
588 win.set_position (Gtk::WIN_POS_CENTER);
590 if (!ARDOUR_COMMAND_LINE::no_splash) {
594 /* we just don't care about the result, but we want to block */
600 ARDOUR_UI::startup ()
605 new_session_dialog = new NewSessionDialog();
607 /* If no session name is given: we're not loading a session yet, nor creating a new one */
609 if (ARDOUR_COMMAND_LINE::session_name.length()) {
611 /* Load session or start the new session dialog */
613 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
614 error << string_compose(_("could not load command line session \"%1\""),
615 ARDOUR_COMMAND_LINE::session_name) << endmsg;
619 if (!ARDOUR_COMMAND_LINE::new_session) {
621 /* Supposed to be loading an existing session, but the session doesn't exist */
624 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
625 "To create it from the command line, start ardour as \"ardour --new %1"), path)
631 new_session_dialog->set_session_name (name);
632 new_session_dialog->set_session_folder (Glib::path_get_dirname (path));
633 _session_is_new = isnew;
638 bool have_backend = EngineControl::engine_running();
640 bool load_needed = false;
644 /* backend audio is working */
646 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
647 /* need NSD to get session name and other info */
655 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
658 new_session_dialog->engine_control.set_state (*audio_setup);
661 /* no backend audio, must bring up NSD to check configuration */
668 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
674 if (create_engine ()) {
675 backend_audio_error (false);
683 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
692 ARDOUR_UI::no_memory_warning ()
694 XMLNode node (X_("no-memory-warning"));
695 Config->add_instant_xml (node, get_user_ardour_path());
699 ARDOUR_UI::check_memory_locking ()
702 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
706 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
708 if (engine->is_realtime() && memory_warning_node == 0) {
710 struct rlimit limits;
712 long pages, page_size;
714 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
717 ram = (int64_t) pages * (int64_t) page_size;
720 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
724 if (limits.rlim_cur != RLIM_INFINITY) {
726 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
729 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
730 "This might cause Ardour to run out of memory before your system "
731 "runs out of memory. \n\n"
732 "You can view the memory limit with 'ulimit -l', "
733 "and it is normally controlled by /etc/security/limits.conf"));
735 VBox* vbox = msg.get_vbox();
737 CheckButton cb (_("Do not show this window again"));
739 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
741 hbox.pack_start (cb, true, false);
742 vbox->pack_start (hbox);
756 if (session && session->dirty()) {
757 switch (ask_about_saving_session(_("quit"))) {
762 /* use the default name */
763 if (save_state_canfail ("")) {
764 /* failed - don't quit */
765 MessageDialog msg (*editor,
767 Ardour was unable to save your session.\n\n\
768 If you still wish to quit, please use the\n\n\
769 \"Just quit\" option."));
780 session->set_deletion_in_progress ();
783 save_ardour_state ();
788 ARDOUR_UI::ask_about_saving_session (const string & what)
790 ArdourDialog window (_("ardour: save session?"));
791 Gtk::HBox dhbox; // the hbox for the image and text
792 Gtk::Label prompt_label;
793 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
797 msg = string_compose(_("Don't %1"), what);
798 window.add_button (msg, RESPONSE_REJECT);
799 msg = string_compose(_("Just %1"), what);
800 window.add_button (msg, RESPONSE_APPLY);
801 msg = string_compose(_("Save and %1"), what);
802 window.add_button (msg, RESPONSE_ACCEPT);
804 window.set_default_response (RESPONSE_ACCEPT);
806 Gtk::Button noquit_button (msg);
807 noquit_button.set_name ("EditorGTKButton");
812 if (session->snap_name() == session->name()) {
815 type = _("snapshot");
817 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?"),
818 type, session->snap_name());
820 prompt_label.set_text (prompt);
821 prompt_label.set_name (X_("PrompterLabel"));
822 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
824 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
826 dhbox.set_homogeneous (false);
827 dhbox.pack_start (*dimage, false, false, 5);
828 dhbox.pack_start (prompt_label, true, false, 5);
829 window.get_vbox()->pack_start (dhbox);
831 window.set_name (_("Prompter"));
832 window.set_position (Gtk::WIN_POS_MOUSE);
833 window.set_modal (true);
834 window.set_resizable (false);
837 save_the_session = 0;
839 window.set_keep_above (true);
842 ResponseType r = (ResponseType) window.run();
847 case RESPONSE_ACCEPT: // save and get out of here
849 case RESPONSE_APPLY: // get out of here
859 ARDOUR_UI::every_second ()
862 update_buffer_load ();
863 update_disk_space ();
868 ARDOUR_UI::every_point_one_seconds ()
870 update_speed_display ();
871 RapidScreenUpdate(); /* EMIT_SIGNAL */
876 ARDOUR_UI::every_point_zero_one_seconds ()
878 // august 2007: actual update frequency: 40Hz, not 100Hz
880 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
885 ARDOUR_UI::update_sample_rate (nframes_t ignored)
889 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
891 if (!engine->connected()) {
893 snprintf (buf, sizeof (buf), _("disconnected"));
897 nframes_t rate = engine->frame_rate();
899 if (fmod (rate, 1000.0) != 0.0) {
900 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
901 (float) rate/1000.0f,
902 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
904 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
906 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
910 sample_rate_label.set_text (buf);
914 ARDOUR_UI::update_cpu_load ()
917 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
918 cpu_load_label.set_text (buf);
922 ARDOUR_UI::update_buffer_load ()
927 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
928 session->playback_load(), session->capture_load());
929 buffer_load_label.set_text (buf);
931 buffer_load_label.set_text ("");
936 ARDOUR_UI::count_recenabled_streams (Route& route)
938 Track* track = dynamic_cast<Track*>(&route);
939 if (track && track->diskstream()->record_enabled()) {
940 rec_enabled_streams += track->n_inputs();
945 ARDOUR_UI::update_disk_space()
951 nframes_t frames = session->available_capture_duration();
954 if (frames == max_frames) {
955 strcpy (buf, _("Disk: 24hrs+"));
960 nframes_t fr = session->frame_rate();
962 rec_enabled_streams = 0;
963 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
965 if (rec_enabled_streams) {
966 frames /= rec_enabled_streams;
969 hrs = frames / (fr * 3600);
970 frames -= hrs * fr * 3600;
971 mins = frames / (fr * 60);
972 frames -= mins * fr * 60;
975 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
978 disk_space_label.set_text (buf);
982 ARDOUR_UI::update_wall_clock ()
989 tm_now = localtime (&now);
991 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
992 wall_clock_label.set_text (buf);
998 ARDOUR_UI::session_menu (GdkEventButton *ev)
1000 session_popup_menu->popup (0, 0);
1005 ARDOUR_UI::redisplay_recent_sessions ()
1007 vector<string *> *sessions;
1008 vector<string *>::iterator i;
1009 RecentSessionsSorter cmp;
1011 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1012 recent_session_model->clear ();
1015 ARDOUR::read_recent_sessions (rs);
1018 recent_session_display.set_model (recent_session_model);
1022 /* sort them alphabetically */
1023 sort (rs.begin(), rs.end(), cmp);
1024 sessions = new vector<string*>;
1026 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1027 sessions->push_back (new string ((*i).second));
1030 for (i = sessions->begin(); i != sessions->end(); ++i) {
1032 vector<string*>* states;
1033 vector<const gchar*> item;
1034 string fullpath = *(*i);
1036 /* remove any trailing / */
1038 if (fullpath[fullpath.length()-1] == '/') {
1039 fullpath = fullpath.substr (0, fullpath.length()-1);
1042 /* now get available states for this session */
1044 if ((states = Session::possible_states (fullpath)) == 0) {
1045 /* no state file? */
1049 TreeModel::Row row = *(recent_session_model->append());
1051 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1052 row[recent_session_columns.fullpath] = fullpath;
1054 if (states->size() > 1) {
1056 /* add the children */
1058 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1060 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1062 child_row[recent_session_columns.visible_name] = **i2;
1063 child_row[recent_session_columns.fullpath] = fullpath;
1072 recent_session_display.set_model (recent_session_model);
1077 ARDOUR_UI::build_session_selector ()
1079 session_selector_window = new ArdourDialog ("session selector");
1081 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1083 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1084 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1085 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1086 recent_session_model = TreeStore::create (recent_session_columns);
1087 recent_session_display.set_model (recent_session_model);
1088 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1089 recent_session_display.set_headers_visible (false);
1090 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1092 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1094 scroller->add (recent_session_display);
1095 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1097 session_selector_window->set_name ("SessionSelectorWindow");
1098 session_selector_window->set_size_request (200, 400);
1099 session_selector_window->get_vbox()->pack_start (*scroller);
1100 session_selector_window->show_all_children();
1104 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1106 session_selector_window->response (RESPONSE_ACCEPT);
1110 ARDOUR_UI::open_recent_session ()
1112 /* popup selector window */
1114 if (session_selector_window == 0) {
1115 build_session_selector ();
1118 redisplay_recent_sessions ();
1120 ResponseType r = (ResponseType) session_selector_window->run ();
1122 session_selector_window->hide();
1125 case RESPONSE_ACCEPT:
1131 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1133 if (i == recent_session_model->children().end()) {
1137 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1138 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1140 _session_is_new = false;
1142 load_session (path, state);
1146 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1148 struct stat statbuf;
1150 if (stat (info.filename.c_str(), &statbuf) != 0) {
1154 if (!S_ISDIR(statbuf.st_mode)) {
1160 string session_file = info.filename;
1161 session_file += '/';
1162 session_file += Glib::path_get_basename (info.filename);
1163 session_file += ".ardour";
1165 if (stat (session_file.c_str(), &statbuf) != 0) {
1169 return S_ISREG (statbuf.st_mode);
1173 ARDOUR_UI::check_audioengine ()
1176 if (!engine->connected()) {
1177 MessageDialog msg (_("Ardour is not connected to JACK\n"
1178 "You cannot open or close sessions in this condition"));
1189 ARDOUR_UI::open_session ()
1191 if (!check_audioengine()) {
1195 /* popup selector window */
1197 if (open_session_selector == 0) {
1199 /* ardour sessions are folders */
1201 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1202 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1203 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1204 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1206 FileFilter session_filter;
1207 session_filter.add_pattern ("*.ardour");
1208 session_filter.set_name (_("Ardour sessions"));
1209 open_session_selector->add_filter (session_filter);
1210 open_session_selector->set_filter (session_filter);
1213 int response = open_session_selector->run();
1214 open_session_selector->hide ();
1217 case RESPONSE_ACCEPT:
1220 open_session_selector->hide();
1224 open_session_selector->hide();
1225 string session_path = open_session_selector->get_filename();
1229 if (session_path.length() > 0) {
1230 if (Session::find_session (session_path, path, name, isnew) == 0) {
1231 _session_is_new = isnew;
1232 load_session (path, name);
1239 ARDOUR_UI::session_add_midi_track ()
1241 cerr << _("Patience is a virtue.\n");
1245 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1247 list<boost::shared_ptr<AudioTrack> > tracks;
1248 Session::RouteList routes;
1251 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1257 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1259 if (tracks.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new audio track") << endmsg;
1263 error << string_compose (_("could only create %1 of %2 new audio %3"),
1264 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1270 routes = session->new_audio_route (input_channels, output_channels, how_many);
1272 if (routes.size() != how_many) {
1273 if (how_many == 1) {
1274 error << _("could not create a new audio track") << endmsg;
1276 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1282 if (need_control_room_outs) {
1288 route->set_stereo_control_outs (control_lr_channels);
1289 route->control_outs()->set_stereo_pan (pans, this);
1291 #endif /* CONTROLOUTS */
1295 cerr << "About to complain about JACK\n";
1296 MessageDialog msg (*editor,
1297 _("There are insufficient JACK ports available\n\
1298 to create a new track or bus.\n\
1299 You should save Ardour, exit and\n\
1300 restart JACK with more ports."));
1306 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1308 nframes_t _preroll = 0;
1311 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1312 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1314 if (new_position > _preroll) {
1315 new_position -= _preroll;
1320 session->request_locate (new_position);
1325 ARDOUR_UI::transport_goto_start ()
1328 session->goto_start();
1331 /* force displayed area in editor to start no matter
1332 what "follow playhead" setting is.
1336 editor->reset_x_origin (session->current_start_frame());
1342 ARDOUR_UI::transport_goto_zero ()
1345 session->request_locate (0);
1348 /* force displayed area in editor to start no matter
1349 what "follow playhead" setting is.
1353 editor->reset_x_origin (0);
1359 ARDOUR_UI::transport_goto_end ()
1362 nframes_t frame = session->current_end_frame();
1363 session->request_locate (frame);
1365 /* force displayed area in editor to start no matter
1366 what "follow playhead" setting is.
1370 editor->reset_x_origin (frame);
1376 ARDOUR_UI::transport_stop ()
1382 if (session->is_auditioning()) {
1383 session->cancel_audition ();
1387 if (session->get_play_loop ()) {
1388 session->request_play_loop (false);
1391 session->request_stop ();
1395 ARDOUR_UI::transport_stop_and_forget_capture ()
1398 session->request_stop (true);
1403 ARDOUR_UI::remove_last_capture()
1406 editor->remove_last_capture();
1411 ARDOUR_UI::transport_record (bool roll)
1414 switch (session->record_status()) {
1415 case Session::Disabled:
1416 if (session->ntracks() == 0) {
1417 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1421 session->maybe_enable_record ();
1426 case Session::Recording:
1428 session->request_stop();
1430 session->disable_record (false, true);
1434 case Session::Enabled:
1435 session->disable_record (false, true);
1441 ARDOUR_UI::transport_roll ()
1449 rolling = session->transport_rolling ();
1451 if (session->get_play_loop()) {
1452 session->request_play_loop (false);
1453 auto_loop_button.set_visual_state (1);
1454 roll_button.set_visual_state (1);
1455 } else if (session->get_play_range ()) {
1456 session->request_play_range (false);
1457 play_selection_button.set_visual_state (0);
1458 } else if (rolling) {
1459 session->request_locate (session->last_transport_start(), true);
1462 session->request_transport_speed (1.0f);
1466 ARDOUR_UI::transport_loop()
1469 if (session->get_play_loop()) {
1470 if (session->transport_rolling()) {
1471 Location * looploc = session->locations()->auto_loop_location();
1473 session->request_locate (looploc->start(), true);
1478 session->request_play_loop (true);
1484 ARDOUR_UI::transport_play_selection ()
1490 if (!session->get_play_range()) {
1491 session->request_stop ();
1494 editor->play_selection ();
1498 ARDOUR_UI::transport_rewind (int option)
1500 float current_transport_speed;
1503 current_transport_speed = session->transport_speed();
1505 if (current_transport_speed >= 0.0f) {
1508 session->request_transport_speed (-1.0f);
1511 session->request_transport_speed (-4.0f);
1514 session->request_transport_speed (-0.5f);
1519 session->request_transport_speed (current_transport_speed * 1.5f);
1525 ARDOUR_UI::transport_forward (int option)
1527 float current_transport_speed;
1530 current_transport_speed = session->transport_speed();
1532 if (current_transport_speed <= 0.0f) {
1535 session->request_transport_speed (1.0f);
1538 session->request_transport_speed (4.0f);
1541 session->request_transport_speed (0.5f);
1546 session->request_transport_speed (current_transport_speed * 1.5f);
1552 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1558 boost::shared_ptr<Route> r;
1560 if ((r = session->route_by_remote_id (dstream)) != 0) {
1564 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1565 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1574 ARDOUR_UI::queue_transport_change ()
1576 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1580 ARDOUR_UI::map_transport_state ()
1582 float sp = session->transport_speed();
1585 transport_rolling ();
1586 } else if (sp < 0.0f) {
1587 transport_rewinding ();
1588 } else if (sp > 0.0f) {
1589 transport_forwarding ();
1591 transport_stopped ();
1596 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1598 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1599 (int) adj.get_value()].c_str());
1603 ARDOUR_UI::engine_stopped ()
1605 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1606 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1607 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1611 ARDOUR_UI::engine_running ()
1613 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1614 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1615 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1617 Glib::RefPtr<Action> action;
1618 char* action_name = 0;
1620 switch (engine->frames_per_cycle()) {
1622 action_name = X_("JACKLatency32");
1625 action_name = X_("JACKLatency64");
1628 action_name = X_("JACKLatency128");
1631 action_name = X_("JACKLatency512");
1634 action_name = X_("JACKLatency1024");
1637 action_name = X_("JACKLatency2048");
1640 action_name = X_("JACKLatency4096");
1643 action_name = X_("JACKLatency8192");
1646 /* XXX can we do anything useful ? */
1652 action = ActionManager::get_action (X_("JACK"), action_name);
1655 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1656 ract->set_active ();
1662 ARDOUR_UI::engine_halted ()
1664 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1666 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1667 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1669 update_sample_rate (0);
1671 MessageDialog msg (*editor,
1673 JACK has either been shutdown or it\n\
1674 disconnected Ardour because Ardour\n\
1675 was not fast enough. You can save the\n\
1676 session and/or try to reconnect to JACK ."));
1681 ARDOUR_UI::do_engine_start ()
1689 error << _("Unable to start the session running")
1699 ARDOUR_UI::setup_theme ()
1701 theme_manager->setup_theme();
1705 ARDOUR_UI::update_clocks ()
1707 if (!editor || !editor->dragging_playhead()) {
1708 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1713 ARDOUR_UI::start_clocking ()
1715 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1719 ARDOUR_UI::stop_clocking ()
1721 clock_signal_connection.disconnect ();
1725 ARDOUR_UI::toggle_clocking ()
1728 if (clock_button.get_active()) {
1737 ARDOUR_UI::_blink (void *arg)
1740 ((ARDOUR_UI *) arg)->blink ();
1747 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1751 ARDOUR_UI::start_blinking ()
1753 /* Start the blink signal. Everybody with a blinking widget
1754 uses Blink to drive the widget's state.
1757 if (blink_timeout_tag < 0) {
1759 blink_timeout_tag = g_timeout_add (240, _blink, this);
1764 ARDOUR_UI::stop_blinking ()
1766 if (blink_timeout_tag >= 0) {
1767 g_source_remove (blink_timeout_tag);
1768 blink_timeout_tag = -1;
1773 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1779 if (io.n_inputs() == 0) {
1784 /* XXX we're not handling multiple ports yet. */
1786 const char **connections = io.input(0)->get_connections();
1788 if (connections == 0 || connections[0] == '\0') {
1791 buf = connections[0];
1798 if (io.n_outputs() == 0) {
1803 /* XXX we're not handling multiple ports yet. */
1805 const char **connections = io.output(0)->get_connections();
1807 if (connections == 0 || connections[0] == '\0') {
1810 buf = connections[0];
1817 /** Ask the user for the name of a new shapshot and then take it.
1820 ARDOUR_UI::snapshot_session ()
1822 ArdourPrompter prompter (true);
1826 struct tm local_time;
1829 localtime_r (&n, &local_time);
1830 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1832 prompter.set_name ("Prompter");
1833 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1834 prompter.set_prompt (_("Name of New Snapshot"));
1835 prompter.set_initial_text (timebuf);
1837 switch (prompter.run()) {
1838 case RESPONSE_ACCEPT:
1839 prompter.get_result (snapname);
1840 if (snapname.length()){
1841 save_state (snapname);
1851 ARDOUR_UI::save_state (const string & name)
1853 (void) save_state_canfail (name);
1857 ARDOUR_UI::save_state_canfail (string name)
1862 if (name.length() == 0) {
1863 name = session->snap_name();
1866 if ((ret = session->save_state (name)) != 0) {
1870 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1875 ARDOUR_UI::restore_state (string name)
1878 if (name.length() == 0) {
1879 name = session->name();
1881 session->restore_state (name);
1886 ARDOUR_UI::primary_clock_value_changed ()
1889 session->request_locate (primary_clock.current_time ());
1894 ARDOUR_UI::big_clock_value_changed ()
1897 session->request_locate (big_clock.current_time ());
1902 ARDOUR_UI::secondary_clock_value_changed ()
1905 session->request_locate (secondary_clock.current_time ());
1910 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1912 if (session && dstream && dstream->record_enabled()) {
1914 Session::RecordState rs;
1916 rs = session->record_status ();
1919 case Session::Disabled:
1920 case Session::Enabled:
1921 if (w->get_state() != STATE_SELECTED) {
1922 w->set_state (STATE_SELECTED);
1926 case Session::Recording:
1927 if (w->get_state() != STATE_ACTIVE) {
1928 w->set_state (STATE_ACTIVE);
1934 if (w->get_state() != STATE_NORMAL) {
1935 w->set_state (STATE_NORMAL);
1941 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1947 switch (session->record_status()) {
1948 case Session::Enabled:
1950 rec_button.set_visual_state (2);
1952 rec_button.set_visual_state (0);
1956 case Session::Recording:
1957 rec_button.set_visual_state (1);
1961 rec_button.set_visual_state (0);
1967 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1975 ARDOUR_UI::save_template ()
1978 ArdourPrompter prompter (true);
1981 if (!check_audioengine()) {
1985 prompter.set_name (X_("Prompter"));
1986 prompter.set_prompt (_("Name for mix template:"));
1987 prompter.set_initial_text(session->name() + _("-template"));
1988 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1990 switch (prompter.run()) {
1991 case RESPONSE_ACCEPT:
1992 prompter.get_result (name);
1994 if (name.length()) {
1995 session->save_template (name);
2005 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2007 bool existing_session = false;
2009 string session_name;
2010 string session_path;
2011 string template_name;
2013 if (!loading_dialog) {
2014 loading_dialog = new MessageDialog (*new_session_dialog,
2022 int response = Gtk::RESPONSE_NONE;
2024 if (predetermined_path.length()) {
2026 /* before we start, lets see if the given path looks like
2027 an existing ardour session. if it does, skip the
2028 tabs that we don't need
2032 Glib::ustring dir = Glib::path_get_dirname (string (predetermined_path));
2033 Glib::ustring name = basename_nosuffix (string (predetermined_path));
2036 if (name.length() == 0 || dir.length() == 0) {
2037 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2041 new_session_dialog->set_session_name (name);
2042 new_session_dialog->set_session_folder (dir);
2044 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2046 Glib::ustring predicted_session_file;
2048 predicted_session_file = predetermined_path;
2049 predicted_session_file += '/';
2050 predicted_session_file += name;
2051 predicted_session_file += Session::statefile_suffix();
2053 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2054 existing_session = true;
2057 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2059 if (predetermined_path.find (Session::statefile_suffix()) == predetermined_path.length() - 7) {
2060 /* existing .ardour file */
2061 existing_session = true;
2065 new_session_dialog->set_modal(true);
2068 new_session_dialog->set_position (WIN_POS_CENTER);
2069 new_session_dialog->set_current_page (0);
2070 new_session_dialog->set_existing_session (existing_session);
2071 new_session_dialog->reset_recent();
2074 new_session_dialog->set_have_engine (have_engine);
2076 new_session_dialog->show();
2077 new_session_dialog->present ();
2078 response = new_session_dialog->run ();
2080 loading_dialog->hide ();
2082 _session_is_new = false;
2084 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2089 new_session_dialog->hide ();
2092 } else if (response == Gtk::RESPONSE_NONE) {
2094 /* Clear was pressed */
2095 new_session_dialog->reset();
2099 /* first things first ... if we're here to help set up audio parameters
2100 this is where want to do that.
2104 if (new_session_dialog->engine_control.setup_engine ()) {
2105 new_session_dialog->hide ();
2111 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2112 may not and it can take a while to build it. Warn them.
2115 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2117 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2118 MessageDialog msg (*new_session_dialog,
2119 _("Welcome to Ardour.\n\n"
2120 "The program will take a bit longer to start up\n"
2121 "while the system fonts are checked.\n\n"
2122 "This will only be done once, and you will\n"
2123 "not see this message again\n"),
2132 loading_dialog->set_message (_("Starting audio engine"));
2133 loading_dialog->show_all ();
2136 if (create_engine ()) {
2137 backend_audio_error (!have_engine, new_session_dialog);
2138 loading_dialog->hide ();
2140 /* audio setup page */
2141 new_session_dialog->set_current_page (2);
2143 response = Gtk::RESPONSE_NONE;
2149 /* now handle possible affirmative responses */
2151 if (response == Gtk::RESPONSE_YES) {
2153 /* YES == OPEN from the session selector */
2155 session_name = new_session_dialog->session_name();
2157 if (session_name.empty()) {
2158 response = Gtk::RESPONSE_NONE;
2162 if (session_name[0] == '/' ||
2163 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2164 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2165 load_session (Glib::path_get_dirname (session_name), session_name);
2167 session_path = new_session_dialog->session_folder();
2168 load_session (session_path, session_name);
2171 } else if (response == Gtk::RESPONSE_OK) {
2173 /* OK == OPEN button */
2175 session_name = new_session_dialog->session_name();
2177 if (session_name.empty()) {
2178 response = Gtk::RESPONSE_NONE;
2182 switch (new_session_dialog->get_current_page()) {
2183 case 1: /* recent session selector */
2184 case 2: /* audio engine control */
2186 if (session_name[0] == '/' ||
2187 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2188 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2189 load_session (Glib::path_get_dirname (session_name), session_name);
2191 session_path = new_session_dialog->session_folder();
2192 load_session (session_path, session_name);
2196 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2198 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2199 should_be_new = true;
2202 /* handle what appear to be paths rather than just a name */
2204 if (session_name[0] == '/' ||
2205 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2206 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2208 session_path = Glib::path_get_dirname (session_name);
2209 session_name = Glib::path_get_basename (session_name);
2213 session_path = new_session_dialog->session_folder();
2217 //XXX This is needed because session constructor wants a
2218 //non-existant path. hopefully this will be fixed at some point.
2220 session_path = Glib::build_filename (session_path, session_name);
2222 if (!should_be_new) {
2224 load_session (session_path, session_name);
2225 continue; /* leaves while() loop because response != NONE */
2227 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2229 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2231 MessageDialog msg (str,
2233 Gtk::MESSAGE_WARNING,
2234 Gtk::BUTTONS_YES_NO,
2238 msg.set_name (X_("CleanupDialog"));
2239 msg.set_wmclass (X_("existing_session"), "Ardour");
2240 msg.set_position (Gtk::WIN_POS_MOUSE);
2242 switch (msg.run()) {
2244 new_session_dialog->hide ();
2245 goto_editor_window ();
2247 load_session (session_path, session_name);
2251 response = RESPONSE_NONE;
2252 new_session_dialog->reset ();
2253 loading_dialog->hide ();
2258 _session_is_new = true;
2260 if (new_session_dialog->use_session_template()) {
2262 template_name = new_session_dialog->session_template_name();
2264 new_session_dialog->hide ();
2265 goto_editor_window ();
2268 load_session (session_path, session_name, &template_name);
2274 AutoConnectOption iconnect;
2275 AutoConnectOption oconnect;
2279 if (Profile->get_sae()) {
2283 iconnect = AutoConnectPhysical;
2284 oconnect = AutoConnectMaster;
2285 nphysin = 0; // use all available
2286 nphysout = 0; // use all available
2290 /* get settings from advanced section of NSD */
2292 if (new_session_dialog->create_control_bus()) {
2293 cchns = (uint32_t) new_session_dialog->control_channel_count();
2298 if (new_session_dialog->create_master_bus()) {
2299 mchns = (uint32_t) new_session_dialog->master_channel_count();
2304 if (new_session_dialog->connect_inputs()) {
2305 iconnect = AutoConnectPhysical;
2307 iconnect = AutoConnectOption (0);
2310 /// @todo some minor tweaks.
2312 if (new_session_dialog->connect_outs_to_master()) {
2313 oconnect = AutoConnectMaster;
2314 } else if (new_session_dialog->connect_outs_to_physical()) {
2315 oconnect = AutoConnectPhysical;
2317 oconnect = AutoConnectOption (0);
2320 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2321 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2324 new_session_dialog->hide ();
2325 goto_editor_window ();
2328 if (build_session (session_path,
2336 engine->frame_rate() * 60 * 5)) {
2338 response = Gtk::RESPONSE_NONE;
2339 new_session_dialog->reset ();
2350 } while (response == Gtk::RESPONSE_NONE);
2354 loading_dialog->hide ();
2355 new_session_dialog->hide();
2360 ARDOUR_UI::close_session ()
2362 if (!check_audioengine()) {
2366 unload_session (true);
2368 get_session_parameters ("", true, false);
2372 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2374 Session *new_session;
2378 session_loaded = false;
2380 if (!check_audioengine()) {
2384 unload_status = unload_session ();
2386 if (unload_status < 0) {
2388 } else if (unload_status > 0) {
2393 /* if it already exists, we must have write access */
2395 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2396 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2397 "This prevents the session from being loaded."));
2402 if (loading_dialog) {
2403 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2407 disable_screen_updates ();
2410 new_session = new Session (*engine, path, snap_name, mix_template);
2414 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2418 connect_to_session (new_session);
2420 Config->set_current_owner (ConfigVariableBase::Interface);
2422 session_loaded = true;
2424 goto_editor_window ();
2427 session->set_clean ();
2430 enable_screen_updates ();
2439 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2440 uint32_t control_channels,
2441 uint32_t master_channels,
2442 AutoConnectOption input_connect,
2443 AutoConnectOption output_connect,
2446 nframes_t initial_length)
2448 Session *new_session;
2451 if (!check_audioengine()) {
2455 session_loaded = false;
2457 x = unload_session ();
2465 _session_is_new = true;
2468 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2469 control_channels, master_channels, nphysin, nphysout, initial_length);
2474 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2479 connect_to_session (new_session);
2481 session_loaded = true;
2489 editor->show_window ();
2500 ARDOUR_UI::show_splash ()
2503 about = new About();
2504 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2511 ARDOUR_UI::about_signal_response(int response)
2517 ARDOUR_UI::hide_splash ()
2520 about->get_window()->set_cursor ();
2526 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2530 removed = rep.paths.size();
2533 MessageDialog msgd (*editor,
2534 _("No audio files were ready for cleanup"),
2537 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2538 msgd.set_secondary_text (_("If this seems suprising, \n\
2539 check for any existing snapshots.\n\
2540 These may still include regions that\n\
2541 require some unused files to continue to exist."));
2547 ArdourDialog results (_("ardour: cleanup"), true, false);
2549 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2550 CleanupResultsModelColumns() {
2554 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2555 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2559 CleanupResultsModelColumns results_columns;
2560 Glib::RefPtr<Gtk::ListStore> results_model;
2561 Gtk::TreeView results_display;
2563 results_model = ListStore::create (results_columns);
2564 results_display.set_model (results_model);
2565 results_display.append_column (list_title, results_columns.visible_name);
2567 results_display.set_name ("CleanupResultsList");
2568 results_display.set_headers_visible (true);
2569 results_display.set_headers_clickable (false);
2570 results_display.set_reorderable (false);
2572 Gtk::ScrolledWindow list_scroller;
2575 Gtk::HBox dhbox; // the hbox for the image and text
2576 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2577 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2579 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2581 if (rep.space < 1048576.0f) {
2583 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2585 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2589 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2591 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2595 dhbox.pack_start (*dimage, true, false, 5);
2596 dhbox.pack_start (txt, true, false, 5);
2598 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2599 TreeModel::Row row = *(results_model->append());
2600 row[results_columns.visible_name] = *i;
2601 row[results_columns.fullpath] = *i;
2604 list_scroller.add (results_display);
2605 list_scroller.set_size_request (-1, 150);
2606 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2608 dvbox.pack_start (dhbox, true, false, 5);
2609 dvbox.pack_start (list_scroller, true, false, 5);
2610 ddhbox.pack_start (dvbox, true, false, 5);
2612 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2613 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2614 results.set_default_response (RESPONSE_CLOSE);
2615 results.set_position (Gtk::WIN_POS_MOUSE);
2616 results.show_all_children ();
2617 results.set_resizable (false);
2624 ARDOUR_UI::cleanup ()
2627 /* shouldn't happen: menu item is insensitive */
2632 MessageDialog checker (_("Are you sure you want to cleanup?"),
2634 Gtk::MESSAGE_QUESTION,
2635 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2637 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2638 ALL undo/redo information will be lost if you cleanup.\n\
2639 After cleanup, unused audio files will be moved to a \
2640 \"dead sounds\" location."));
2642 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2643 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2644 checker.set_default_response (RESPONSE_CANCEL);
2646 checker.set_name (_("CleanupDialog"));
2647 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2648 checker.set_position (Gtk::WIN_POS_MOUSE);
2650 switch (checker.run()) {
2651 case RESPONSE_ACCEPT:
2657 Session::cleanup_report rep;
2659 editor->prepare_for_cleanup ();
2661 /* do not allow flush until a session is reloaded */
2663 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2665 act->set_sensitive (false);
2668 if (session->cleanup_sources (rep)) {
2673 display_cleanup_results (rep,
2676 The following %1 %2 not in use and \n\
2677 have been moved to:\n\
2679 Flushing the wastebasket will \n\
2680 release an additional\n\
2681 %4 %5bytes of disk space.\n"
2689 ARDOUR_UI::flush_trash ()
2692 /* shouldn't happen: menu item is insensitive */
2696 Session::cleanup_report rep;
2698 if (session->cleanup_trash_sources (rep)) {
2702 display_cleanup_results (rep,
2704 _("The following %1 %2 deleted from\n\
2706 releasing %4 %5bytes of disk space"));
2710 ARDOUR_UI::add_route (Gtk::Window* float_window)
2718 if (add_route_dialog == 0) {
2719 add_route_dialog = new AddRouteDialog;
2721 add_route_dialog->set_transient_for (*float_window);
2725 if (add_route_dialog->is_visible()) {
2726 /* we're already doing this */
2730 ResponseType r = (ResponseType) add_route_dialog->run ();
2732 add_route_dialog->hide();
2735 case RESPONSE_ACCEPT:
2742 if ((count = add_route_dialog->count()) <= 0) {
2746 uint32_t input_chan = add_route_dialog->channels ();
2747 uint32_t output_chan;
2748 string name_template = add_route_dialog->name_template ();
2749 bool track = add_route_dialog->track ();
2751 AutoConnectOption oac = Config->get_output_auto_connect();
2753 if (oac & AutoConnectMaster) {
2754 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2756 output_chan = input_chan;
2759 /* XXX do something with name template */
2762 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2764 session_add_audio_bus (input_chan, output_chan, count);
2769 ARDOUR_UI::mixer_settings () const
2774 node = session->instant_xml(X_("Mixer"), session->path());
2776 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2780 node = new XMLNode (X_("Mixer"));
2787 ARDOUR_UI::editor_settings () const
2792 node = session->instant_xml(X_("Editor"), session->path());
2794 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
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 ArdourDialog dialog ("pending state dialog");
2874 This session appears to have been in\n\
2875 middle of recording when ardour or\n\
2876 the computer was shutdown.\n\
2878 Ardour can recover any captured audio for\n\
2879 you, or it can ignore it. Please decide\n\
2880 what you would like to do.\n"));
2882 dialog.get_vbox()->pack_start (message);
2883 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2884 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2886 dialog.set_position (WIN_POS_CENTER);
2889 switch (dialog.run ()) {
2890 case RESPONSE_ACCEPT:
2898 ARDOUR_UI::disconnect_from_jack ()
2901 if( engine->disconnect_from_jack ()) {
2902 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2906 update_sample_rate (0);
2911 ARDOUR_UI::reconnect_to_jack ()
2914 if (engine->reconnect_to_jack ()) {
2915 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2919 update_sample_rate (0);
2924 ARDOUR_UI::cmdline_new_session (string path)
2926 if (path[0] != '/') {
2927 char buf[PATH_MAX+1];
2930 getcwd (buf, sizeof (buf));
2937 get_session_parameters (path, false, true);
2939 _will_create_new_session_automatically = false; /* done it */
2940 return FALSE; /* don't call it again */
2944 ARDOUR_UI::use_config ()
2946 Glib::RefPtr<Action> act;
2948 switch (Config->get_native_file_data_format ()) {
2950 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2953 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2956 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2961 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2962 ract->set_active ();
2965 switch (Config->get_native_file_header_format ()) {
2967 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2970 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2973 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2976 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2979 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2982 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2985 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2990 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2991 ract->set_active ();
2994 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2996 set_transport_controllable_state (*node);
3001 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3003 if (Config->get_primary_clock_delta_edit_cursor()) {
3004 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3006 primary_clock.set (pos, 0, true);
3009 if (Config->get_secondary_clock_delta_edit_cursor()) {
3010 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3012 secondary_clock.set (pos);
3015 if (big_clock_window) {
3016 big_clock.set (pos);
3021 ARDOUR_UI::record_state_changed ()
3023 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3025 if (!session || !big_clock_window) {
3026 /* why bother - the clock isn't visible */
3030 switch (session->record_status()) {
3031 case Session::Recording:
3032 big_clock.set_widget_name ("BigClockRecording");
3035 big_clock.set_widget_name ("BigClockNonRecording");
3041 ARDOUR_UI::set_keybindings_path (string path)
3043 keybindings_path = path;
3047 ARDOUR_UI::save_keybindings ()
3049 if (can_save_keybindings) {
3050 AccelMap::save (user_keybindings_path);
3055 ARDOUR_UI::first_idle ()
3058 session->allow_auto_play (true);
3060 can_save_keybindings = true;
3065 ARDOUR_UI::store_clock_modes ()
3067 XMLNode* node = new XMLNode(X_("ClockModes"));
3069 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3070 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3073 session->add_extra_xml (*node);
3074 session->set_dirty ();
3079 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3080 : Controllable (name), ui (u), type(tp)
3086 ARDOUR_UI::TransportControllable::set_value (float val)
3088 if (type == ShuttleControl) {
3095 fract = -((0.5f - val)/0.5f);
3097 fract = ((val - 0.5f)/0.5f);
3101 ui.set_shuttle_fract (fract);
3106 /* do nothing: these are radio-style actions */
3114 action = X_("Roll");
3117 action = X_("Stop");
3120 action = X_("Goto Start");
3123 action = X_("Goto End");
3126 action = X_("Loop");
3129 action = X_("Play Selection");
3132 action = X_("Record");
3142 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3150 ARDOUR_UI::TransportControllable::get_value (void) const
3169 case ShuttleControl:
3179 ARDOUR_UI::TransportControllable::set_id (const string& str)
3185 ARDOUR_UI::setup_profile ()
3187 if (gdk_screen_width() < 1200) {
3188 Profile->set_small_screen ();
3191 if (getenv ("ARDOUR_SAE")) {
3192 Profile->set_sae ();
3193 Profile->set_single_package ();