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)) {
615 MessageDialog msg (string_compose(_("Could not find command line session \"%1\""),
616 ARDOUR_COMMAND_LINE::session_name),
621 msg.set_position (Gtk::WIN_POS_MOUSE);
628 if (!ARDOUR_COMMAND_LINE::new_session) {
630 /* Supposed to be loading an existing session, but the session doesn't exist */
633 MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
634 "To create it from the command line, start ardour as:\n ardour --new %1"), path),
639 msg.set_position (Gtk::WIN_POS_MOUSE);
650 bool have_backend = EngineControl::engine_running();
651 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
654 new_session_dialog->engine_control.set_state (*audio_setup);
657 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
665 ARDOUR_UI::no_memory_warning ()
667 XMLNode node (X_("no-memory-warning"));
668 Config->add_instant_xml (node, get_user_ardour_path());
672 ARDOUR_UI::check_memory_locking ()
675 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
679 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
681 if (engine->is_realtime() && memory_warning_node == 0) {
683 struct rlimit limits;
685 long pages, page_size;
687 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
690 ram = (int64_t) pages * (int64_t) page_size;
693 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
697 if (limits.rlim_cur != RLIM_INFINITY) {
699 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
702 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
703 "This might cause Ardour to run out of memory before your system "
704 "runs out of memory. \n\n"
705 "You can view the memory limit with 'ulimit -l', "
706 "and it is normally controlled by /etc/security/limits.conf"));
708 VBox* vbox = msg.get_vbox();
710 CheckButton cb (_("Do not show this window again"));
712 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
714 hbox.pack_start (cb, true, false);
715 vbox->pack_start (hbox);
729 if (session && session->dirty()) {
730 switch (ask_about_saving_session(_("quit"))) {
735 /* use the default name */
736 if (save_state_canfail ("")) {
737 /* failed - don't quit */
738 MessageDialog msg (*editor,
740 Ardour was unable to save your session.\n\n\
741 If you still wish to quit, please use the\n\n\
742 \"Just quit\" option."));
753 session->set_deletion_in_progress ();
756 save_ardour_state ();
761 ARDOUR_UI::ask_about_saving_session (const string & what)
763 ArdourDialog window (_("ardour: save session?"));
764 Gtk::HBox dhbox; // the hbox for the image and text
765 Gtk::Label prompt_label;
766 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
770 msg = string_compose(_("Don't %1"), what);
771 window.add_button (msg, RESPONSE_REJECT);
772 msg = string_compose(_("Just %1"), what);
773 window.add_button (msg, RESPONSE_APPLY);
774 msg = string_compose(_("Save and %1"), what);
775 window.add_button (msg, RESPONSE_ACCEPT);
777 window.set_default_response (RESPONSE_ACCEPT);
779 Gtk::Button noquit_button (msg);
780 noquit_button.set_name ("EditorGTKButton");
785 if (session->snap_name() == session->name()) {
788 type = _("snapshot");
790 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?"),
791 type, session->snap_name());
793 prompt_label.set_text (prompt);
794 prompt_label.set_name (X_("PrompterLabel"));
795 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
797 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
799 dhbox.set_homogeneous (false);
800 dhbox.pack_start (*dimage, false, false, 5);
801 dhbox.pack_start (prompt_label, true, false, 5);
802 window.get_vbox()->pack_start (dhbox);
804 window.set_name (_("Prompter"));
805 window.set_position (Gtk::WIN_POS_MOUSE);
806 window.set_modal (true);
807 window.set_resizable (false);
810 save_the_session = 0;
812 window.set_keep_above (true);
815 ResponseType r = (ResponseType) window.run();
820 case RESPONSE_ACCEPT: // save and get out of here
822 case RESPONSE_APPLY: // get out of here
832 ARDOUR_UI::every_second ()
835 update_buffer_load ();
836 update_disk_space ();
841 ARDOUR_UI::every_point_one_seconds ()
843 update_speed_display ();
844 RapidScreenUpdate(); /* EMIT_SIGNAL */
849 ARDOUR_UI::every_point_zero_one_seconds ()
851 // august 2007: actual update frequency: 40Hz, not 100Hz
853 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
858 ARDOUR_UI::update_sample_rate (nframes_t ignored)
862 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
864 if (!engine->connected()) {
866 snprintf (buf, sizeof (buf), _("disconnected"));
870 nframes_t rate = engine->frame_rate();
872 if (fmod (rate, 1000.0) != 0.0) {
873 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
874 (float) rate/1000.0f,
875 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
877 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
879 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
883 sample_rate_label.set_text (buf);
887 ARDOUR_UI::update_cpu_load ()
890 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
891 cpu_load_label.set_text (buf);
895 ARDOUR_UI::update_buffer_load ()
900 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
901 session->playback_load(), session->capture_load());
902 buffer_load_label.set_text (buf);
904 buffer_load_label.set_text ("");
909 ARDOUR_UI::count_recenabled_streams (Route& route)
911 Track* track = dynamic_cast<Track*>(&route);
912 if (track && track->diskstream()->record_enabled()) {
913 rec_enabled_streams += track->n_inputs();
918 ARDOUR_UI::update_disk_space()
924 nframes_t frames = session->available_capture_duration();
927 if (frames == max_frames) {
928 strcpy (buf, _("Disk: 24hrs+"));
933 nframes_t fr = session->frame_rate();
935 rec_enabled_streams = 0;
936 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
938 if (rec_enabled_streams) {
939 frames /= rec_enabled_streams;
942 hrs = frames / (fr * 3600);
943 frames -= hrs * fr * 3600;
944 mins = frames / (fr * 60);
945 frames -= mins * fr * 60;
948 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
951 disk_space_label.set_text (buf);
955 ARDOUR_UI::update_wall_clock ()
962 tm_now = localtime (&now);
964 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
965 wall_clock_label.set_text (buf);
971 ARDOUR_UI::session_menu (GdkEventButton *ev)
973 session_popup_menu->popup (0, 0);
978 ARDOUR_UI::redisplay_recent_sessions ()
980 vector<string *> *sessions;
981 vector<string *>::iterator i;
982 RecentSessionsSorter cmp;
984 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
985 recent_session_model->clear ();
988 ARDOUR::read_recent_sessions (rs);
991 recent_session_display.set_model (recent_session_model);
995 /* sort them alphabetically */
996 sort (rs.begin(), rs.end(), cmp);
997 sessions = new vector<string*>;
999 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1000 sessions->push_back (new string ((*i).second));
1003 for (i = sessions->begin(); i != sessions->end(); ++i) {
1005 vector<string*>* states;
1006 vector<const gchar*> item;
1007 string fullpath = *(*i);
1009 /* remove any trailing / */
1011 if (fullpath[fullpath.length()-1] == '/') {
1012 fullpath = fullpath.substr (0, fullpath.length()-1);
1015 /* now get available states for this session */
1017 if ((states = Session::possible_states (fullpath)) == 0) {
1018 /* no state file? */
1022 TreeModel::Row row = *(recent_session_model->append());
1024 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1025 row[recent_session_columns.fullpath] = fullpath;
1027 if (states->size() > 1) {
1029 /* add the children */
1031 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1033 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1035 child_row[recent_session_columns.visible_name] = **i2;
1036 child_row[recent_session_columns.fullpath] = fullpath;
1045 recent_session_display.set_model (recent_session_model);
1050 ARDOUR_UI::build_session_selector ()
1052 session_selector_window = new ArdourDialog ("session selector");
1054 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1056 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1057 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1058 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1059 recent_session_model = TreeStore::create (recent_session_columns);
1060 recent_session_display.set_model (recent_session_model);
1061 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1062 recent_session_display.set_headers_visible (false);
1063 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1065 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1067 scroller->add (recent_session_display);
1068 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1070 session_selector_window->set_name ("SessionSelectorWindow");
1071 session_selector_window->set_size_request (200, 400);
1072 session_selector_window->get_vbox()->pack_start (*scroller);
1073 session_selector_window->show_all_children();
1077 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1079 session_selector_window->response (RESPONSE_ACCEPT);
1083 ARDOUR_UI::open_recent_session ()
1085 /* popup selector window */
1087 if (session_selector_window == 0) {
1088 build_session_selector ();
1091 redisplay_recent_sessions ();
1093 ResponseType r = (ResponseType) session_selector_window->run ();
1095 session_selector_window->hide();
1098 case RESPONSE_ACCEPT:
1104 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1106 if (i == recent_session_model->children().end()) {
1110 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1111 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1113 _session_is_new = false;
1115 load_session (path, state);
1119 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1121 struct stat statbuf;
1123 if (stat (info.filename.c_str(), &statbuf) != 0) {
1127 if (!S_ISDIR(statbuf.st_mode)) {
1133 string session_file = info.filename;
1134 session_file += '/';
1135 session_file += Glib::path_get_basename (info.filename);
1136 session_file += ".ardour";
1138 if (stat (session_file.c_str(), &statbuf) != 0) {
1142 return S_ISREG (statbuf.st_mode);
1146 ARDOUR_UI::check_audioengine ()
1149 if (!engine->connected()) {
1150 MessageDialog msg (_("Ardour is not connected to JACK\n"
1151 "You cannot open or close sessions in this condition"));
1162 ARDOUR_UI::open_session ()
1164 if (!check_audioengine()) {
1168 /* popup selector window */
1170 if (open_session_selector == 0) {
1172 /* ardour sessions are folders */
1174 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1175 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1176 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1177 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1179 FileFilter session_filter;
1180 session_filter.add_pattern ("*.ardour");
1181 session_filter.set_name (_("Ardour sessions"));
1182 open_session_selector->add_filter (session_filter);
1183 open_session_selector->set_filter (session_filter);
1186 int response = open_session_selector->run();
1187 open_session_selector->hide ();
1190 case RESPONSE_ACCEPT:
1193 open_session_selector->hide();
1197 open_session_selector->hide();
1198 string session_path = open_session_selector->get_filename();
1202 if (session_path.length() > 0) {
1203 if (Session::find_session (session_path, path, name, isnew) == 0) {
1204 _session_is_new = isnew;
1205 load_session (path, name);
1212 ARDOUR_UI::session_add_midi_track ()
1214 cerr << _("Patience is a virtue.\n");
1218 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1220 list<boost::shared_ptr<AudioTrack> > tracks;
1221 Session::RouteList routes;
1224 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1230 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1232 if (tracks.size() != how_many) {
1233 if (how_many == 1) {
1234 error << _("could not create a new audio track") << endmsg;
1236 error << string_compose (_("could only create %1 of %2 new audio %3"),
1237 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1243 routes = session->new_audio_route (input_channels, output_channels, how_many);
1245 if (routes.size() != how_many) {
1246 if (how_many == 1) {
1247 error << _("could not create a new audio track") << endmsg;
1249 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1255 if (need_control_room_outs) {
1261 route->set_stereo_control_outs (control_lr_channels);
1262 route->control_outs()->set_stereo_pan (pans, this);
1264 #endif /* CONTROLOUTS */
1268 cerr << "About to complain about JACK\n";
1269 MessageDialog msg (*editor,
1270 _("There are insufficient JACK ports available\n\
1271 to create a new track or bus.\n\
1272 You should save Ardour, exit and\n\
1273 restart JACK with more ports."));
1279 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1281 nframes_t _preroll = 0;
1284 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1285 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1287 if (new_position > _preroll) {
1288 new_position -= _preroll;
1293 session->request_locate (new_position);
1298 ARDOUR_UI::transport_goto_start ()
1301 session->goto_start();
1304 /* force displayed area in editor to start no matter
1305 what "follow playhead" setting is.
1309 editor->reset_x_origin (session->current_start_frame());
1315 ARDOUR_UI::transport_goto_zero ()
1318 session->request_locate (0);
1321 /* force displayed area in editor to start no matter
1322 what "follow playhead" setting is.
1326 editor->reset_x_origin (0);
1332 ARDOUR_UI::transport_goto_end ()
1335 nframes_t frame = session->current_end_frame();
1336 session->request_locate (frame);
1338 /* force displayed area in editor to start no matter
1339 what "follow playhead" setting is.
1343 editor->reset_x_origin (frame);
1349 ARDOUR_UI::transport_stop ()
1355 if (session->is_auditioning()) {
1356 session->cancel_audition ();
1360 if (session->get_play_loop ()) {
1361 session->request_play_loop (false);
1364 session->request_stop ();
1368 ARDOUR_UI::transport_stop_and_forget_capture ()
1371 session->request_stop (true);
1376 ARDOUR_UI::remove_last_capture()
1379 editor->remove_last_capture();
1384 ARDOUR_UI::transport_record (bool roll)
1387 switch (session->record_status()) {
1388 case Session::Disabled:
1389 if (session->ntracks() == 0) {
1390 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1394 session->maybe_enable_record ();
1399 case Session::Recording:
1401 session->request_stop();
1403 session->disable_record (false, true);
1407 case Session::Enabled:
1408 session->disable_record (false, true);
1414 ARDOUR_UI::transport_roll ()
1422 rolling = session->transport_rolling ();
1424 if (session->get_play_loop()) {
1425 session->request_play_loop (false);
1426 auto_loop_button.set_visual_state (1);
1427 roll_button.set_visual_state (1);
1428 } else if (session->get_play_range ()) {
1429 session->request_play_range (false);
1430 play_selection_button.set_visual_state (0);
1431 } else if (rolling) {
1432 session->request_locate (session->last_transport_start(), true);
1435 session->request_transport_speed (1.0f);
1439 ARDOUR_UI::transport_loop()
1442 if (session->get_play_loop()) {
1443 if (session->transport_rolling()) {
1444 Location * looploc = session->locations()->auto_loop_location();
1446 session->request_locate (looploc->start(), true);
1451 session->request_play_loop (true);
1457 ARDOUR_UI::transport_play_selection ()
1463 if (!session->get_play_range()) {
1464 session->request_stop ();
1467 editor->play_selection ();
1471 ARDOUR_UI::transport_rewind (int option)
1473 float current_transport_speed;
1476 current_transport_speed = session->transport_speed();
1478 if (current_transport_speed >= 0.0f) {
1481 session->request_transport_speed (-1.0f);
1484 session->request_transport_speed (-4.0f);
1487 session->request_transport_speed (-0.5f);
1492 session->request_transport_speed (current_transport_speed * 1.5f);
1498 ARDOUR_UI::transport_forward (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::toggle_record_enable (uint32_t dstream)
1531 boost::shared_ptr<Route> r;
1533 if ((r = session->route_by_remote_id (dstream)) != 0) {
1537 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1538 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1547 ARDOUR_UI::queue_transport_change ()
1549 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1553 ARDOUR_UI::map_transport_state ()
1555 float sp = session->transport_speed();
1558 transport_rolling ();
1559 } else if (sp < 0.0f) {
1560 transport_rewinding ();
1561 } else if (sp > 0.0f) {
1562 transport_forwarding ();
1564 transport_stopped ();
1569 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1571 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1572 (int) adj.get_value()].c_str());
1576 ARDOUR_UI::engine_stopped ()
1578 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1579 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1580 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1584 ARDOUR_UI::engine_running ()
1586 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1587 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1588 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1590 Glib::RefPtr<Action> action;
1591 char* action_name = 0;
1593 switch (engine->frames_per_cycle()) {
1595 action_name = X_("JACKLatency32");
1598 action_name = X_("JACKLatency64");
1601 action_name = X_("JACKLatency128");
1604 action_name = X_("JACKLatency512");
1607 action_name = X_("JACKLatency1024");
1610 action_name = X_("JACKLatency2048");
1613 action_name = X_("JACKLatency4096");
1616 action_name = X_("JACKLatency8192");
1619 /* XXX can we do anything useful ? */
1625 action = ActionManager::get_action (X_("JACK"), action_name);
1628 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1629 ract->set_active ();
1635 ARDOUR_UI::engine_halted ()
1637 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1639 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1640 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1642 update_sample_rate (0);
1644 MessageDialog msg (*editor,
1646 JACK has either been shutdown or it\n\
1647 disconnected Ardour because Ardour\n\
1648 was not fast enough. You can save the\n\
1649 session and/or try to reconnect to JACK ."));
1654 ARDOUR_UI::do_engine_start ()
1662 error << _("Unable to start the session running")
1672 ARDOUR_UI::setup_theme ()
1674 theme_manager->setup_theme();
1678 ARDOUR_UI::update_clocks ()
1680 if (!editor || !editor->dragging_playhead()) {
1681 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1686 ARDOUR_UI::start_clocking ()
1688 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1692 ARDOUR_UI::stop_clocking ()
1694 clock_signal_connection.disconnect ();
1698 ARDOUR_UI::toggle_clocking ()
1701 if (clock_button.get_active()) {
1710 ARDOUR_UI::_blink (void *arg)
1713 ((ARDOUR_UI *) arg)->blink ();
1720 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1724 ARDOUR_UI::start_blinking ()
1726 /* Start the blink signal. Everybody with a blinking widget
1727 uses Blink to drive the widget's state.
1730 if (blink_timeout_tag < 0) {
1732 blink_timeout_tag = g_timeout_add (240, _blink, this);
1737 ARDOUR_UI::stop_blinking ()
1739 if (blink_timeout_tag >= 0) {
1740 g_source_remove (blink_timeout_tag);
1741 blink_timeout_tag = -1;
1746 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1752 if (io.n_inputs() == 0) {
1757 /* XXX we're not handling multiple ports yet. */
1759 const char **connections = io.input(0)->get_connections();
1761 if (connections == 0 || connections[0] == '\0') {
1764 buf = connections[0];
1771 if (io.n_outputs() == 0) {
1776 /* XXX we're not handling multiple ports yet. */
1778 const char **connections = io.output(0)->get_connections();
1780 if (connections == 0 || connections[0] == '\0') {
1783 buf = connections[0];
1790 /** Ask the user for the name of a new shapshot and then take it.
1793 ARDOUR_UI::snapshot_session ()
1795 ArdourPrompter prompter (true);
1799 struct tm local_time;
1802 localtime_r (&n, &local_time);
1803 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1805 prompter.set_name ("Prompter");
1806 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1807 prompter.set_prompt (_("Name of New Snapshot"));
1808 prompter.set_initial_text (timebuf);
1810 switch (prompter.run()) {
1811 case RESPONSE_ACCEPT:
1812 prompter.get_result (snapname);
1813 if (snapname.length()){
1814 save_state (snapname);
1824 ARDOUR_UI::save_state (const string & name)
1826 (void) save_state_canfail (name);
1830 ARDOUR_UI::save_state_canfail (string name)
1835 if (name.length() == 0) {
1836 name = session->snap_name();
1839 if ((ret = session->save_state (name)) != 0) {
1843 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1848 ARDOUR_UI::restore_state (string name)
1851 if (name.length() == 0) {
1852 name = session->name();
1854 session->restore_state (name);
1859 ARDOUR_UI::primary_clock_value_changed ()
1862 session->request_locate (primary_clock.current_time ());
1867 ARDOUR_UI::big_clock_value_changed ()
1870 session->request_locate (big_clock.current_time ());
1875 ARDOUR_UI::secondary_clock_value_changed ()
1878 session->request_locate (secondary_clock.current_time ());
1883 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1885 if (session && dstream && dstream->record_enabled()) {
1887 Session::RecordState rs;
1889 rs = session->record_status ();
1892 case Session::Disabled:
1893 case Session::Enabled:
1894 if (w->get_state() != STATE_SELECTED) {
1895 w->set_state (STATE_SELECTED);
1899 case Session::Recording:
1900 if (w->get_state() != STATE_ACTIVE) {
1901 w->set_state (STATE_ACTIVE);
1907 if (w->get_state() != STATE_NORMAL) {
1908 w->set_state (STATE_NORMAL);
1914 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1920 switch (session->record_status()) {
1921 case Session::Enabled:
1923 rec_button.set_visual_state (2);
1925 rec_button.set_visual_state (0);
1929 case Session::Recording:
1930 rec_button.set_visual_state (1);
1934 rec_button.set_visual_state (0);
1940 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1948 ARDOUR_UI::save_template ()
1951 ArdourPrompter prompter (true);
1954 if (!check_audioengine()) {
1958 prompter.set_name (X_("Prompter"));
1959 prompter.set_prompt (_("Name for mix template:"));
1960 prompter.set_initial_text(session->name() + _("-template"));
1961 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1963 switch (prompter.run()) {
1964 case RESPONSE_ACCEPT:
1965 prompter.get_result (name);
1967 if (name.length()) {
1968 session->save_template (name);
1978 ARDOUR_UI::fontconfig_dialog ()
1981 /* X11 users will always have fontconfig info around, but new GTK-OSX users
1982 may not and it can take a while to build it. Warn them.
1985 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
1987 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
1988 MessageDialog msg (*new_session_dialog,
1989 _("Welcome to Ardour.\n\n"
1990 "The program will take a bit longer to start up\n"
1991 "while the system fonts are checked.\n\n"
1992 "This will only be done once, and you will\n"
1993 "not see this message again\n"),
2005 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2007 bool existing_session = false;
2008 Glib::ustring session_name;
2009 Glib::ustring session_path;
2010 Glib::ustring template_name;
2012 if (!loading_dialog) {
2013 loading_dialog = new MessageDialog (*new_session_dialog,
2021 int response = Gtk::RESPONSE_NONE;
2023 if (predetermined_path.length()) {
2025 /* before we start, lets see if the given path looks like
2026 an existing ardour session. if it does, skip the
2027 tabs that we don't need
2030 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2031 session_path = predetermined_path;
2033 session_path = Glib::path_get_dirname (string (predetermined_path));
2036 session_name = basename_nosuffix (string (predetermined_path));
2038 if (session_name.length() == 0 || session_path.length() == 0) {
2039 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2043 new_session_dialog->set_session_name (session_name);
2044 new_session_dialog->set_session_folder (session_path);
2046 cerr << "Set name to " << session_name << " and dir to " << session_path << endl;
2048 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2049 Glib::ustring predicted_session_file;
2051 predicted_session_file = predetermined_path;
2052 predicted_session_file += '/';
2053 predicted_session_file += session_name;
2054 predicted_session_file += Session::statefile_suffix();
2056 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2057 existing_session = true;
2060 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2062 if (predetermined_path.find (Session::statefile_suffix()) == predetermined_path.length() - 7) {
2063 /* existing .ardour file */
2064 existing_session = true;
2068 new_session_dialog->set_modal (true);
2071 if (existing_session && have_engine) {
2072 /* lets just try to load it */
2074 loading_dialog->set_message (_("Starting audio engine"));
2075 loading_dialog->show_all ();
2078 if (create_engine ()) {
2079 backend_audio_error (!have_engine, new_session_dialog);
2080 loading_dialog->hide ();
2084 if (load_session (session_path, session_name) == 0) {
2089 /* loading failed, or we need the NSD for something */
2091 new_session_dialog->set_position (WIN_POS_CENTER);
2092 new_session_dialog->set_current_page (0);
2093 new_session_dialog->set_existing_session (existing_session);
2094 new_session_dialog->reset_recent();
2097 new_session_dialog->set_have_engine (have_engine);
2098 new_session_dialog->present ();
2099 response = new_session_dialog->run ();
2100 loading_dialog->hide ();
2102 _session_is_new = false;
2104 /* handle possible negative responses */
2106 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2111 new_session_dialog->hide ();
2114 } else if (response == Gtk::RESPONSE_NONE) {
2115 /* "Clear" was pressed */
2120 fontconfig_dialog();
2122 /* if we're here to help set up audio parameters this is where want to do that.
2126 if (new_session_dialog->engine_control.setup_engine ()) {
2127 new_session_dialog->hide ();
2131 loading_dialog->set_message (_("Starting audio engine"));
2132 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_existing_session (false);
2142 new_session_dialog->set_current_page (2);
2143 response = Gtk::RESPONSE_NONE;
2147 loading_dialog->hide ();
2150 /* now handle possible affirmative responses */
2152 if (response == Gtk::RESPONSE_YES) {
2154 /* YES == OPEN from the session selector */
2156 session_name = new_session_dialog->session_name();
2158 if (session_name.empty()) {
2159 response = Gtk::RESPONSE_NONE;
2163 if (session_name[0] == '/' ||
2164 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2165 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2166 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2167 response = Gtk::RESPONSE_NONE;
2171 session_path = new_session_dialog->session_folder();
2172 if (load_session (session_path, session_name)) {
2173 response = Gtk::RESPONSE_NONE;
2178 } else if (response == Gtk::RESPONSE_OK) {
2180 /* OK == OPEN button */
2182 session_name = new_session_dialog->session_name();
2184 if (session_name.empty()) {
2185 response = Gtk::RESPONSE_NONE;
2189 cerr << "nsd now on page " << new_session_dialog->get_current_page() << endl;
2191 switch (new_session_dialog->get_current_page()) {
2192 case 1: /* recent session selector */
2193 case 2: /* audio engine control */
2195 if (session_name[0] == '/' ||
2196 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2197 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2198 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2199 response = Gtk::RESPONSE_NONE;
2204 session_path = new_session_dialog->session_folder();
2205 if (load_session (session_path, session_name)) {
2206 response = Gtk::RESPONSE_NONE;
2212 case 0: /* nominally the "new" session creator, but could be in use for an old session */
2214 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2215 should_be_new = true;
2218 /* handle what appear to be paths rather than just a name */
2220 if (session_name[0] == '/' ||
2221 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2222 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2224 session_path = Glib::path_get_dirname (session_name);
2225 session_name = Glib::path_get_basename (session_name);
2229 session_path = new_session_dialog->session_folder();
2233 //XXX This is needed because session constructor wants a
2234 //non-existant path. hopefully this will be fixed at some point.
2236 session_path = Glib::build_filename (session_path, session_name);
2238 if (!should_be_new) {
2240 if (load_session (session_path, session_name)) {
2241 response = Gtk::RESPONSE_NONE;
2245 continue; /* leaves while() loop because response != NONE */
2247 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2249 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2251 MessageDialog msg (str,
2253 Gtk::MESSAGE_WARNING,
2254 Gtk::BUTTONS_YES_NO,
2258 msg.set_name (X_("CleanupDialog"));
2259 msg.set_wmclass (X_("existing_session"), "Ardour");
2260 msg.set_position (Gtk::WIN_POS_MOUSE);
2262 switch (msg.run()) {
2264 new_session_dialog->hide ();
2265 goto_editor_window ();
2267 if (load_session (session_path, session_name)) {
2268 response = Gtk::RESPONSE_NONE;
2274 response = RESPONSE_NONE;
2275 new_session_dialog->reset ();
2276 new_session_dialog->set_existing_session (false);
2277 loading_dialog->hide ();
2282 _session_is_new = true;
2284 if (new_session_dialog->use_session_template()) {
2286 template_name = new_session_dialog->session_template_name();
2288 new_session_dialog->hide ();
2289 goto_editor_window ();
2292 if (load_session (session_path, session_name, template_name)) {
2293 response = Gtk::RESPONSE_NONE;
2302 AutoConnectOption iconnect;
2303 AutoConnectOption oconnect;
2307 if (Profile->get_sae()) {
2311 iconnect = AutoConnectPhysical;
2312 oconnect = AutoConnectMaster;
2313 nphysin = 0; // use all available
2314 nphysout = 0; // use all available
2318 /* get settings from advanced section of NSD */
2320 if (new_session_dialog->create_control_bus()) {
2321 cchns = (uint32_t) new_session_dialog->control_channel_count();
2326 if (new_session_dialog->create_master_bus()) {
2327 mchns = (uint32_t) new_session_dialog->master_channel_count();
2332 if (new_session_dialog->connect_inputs()) {
2333 iconnect = AutoConnectPhysical;
2335 iconnect = AutoConnectOption (0);
2338 /// @todo some minor tweaks.
2340 if (new_session_dialog->connect_outs_to_master()) {
2341 oconnect = AutoConnectMaster;
2342 } else if (new_session_dialog->connect_outs_to_physical()) {
2343 oconnect = AutoConnectPhysical;
2345 oconnect = AutoConnectOption (0);
2348 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2349 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2352 if (build_session (session_path,
2360 engine->frame_rate() * 60 * 5)) {
2362 response = Gtk::RESPONSE_NONE;
2366 new_session_dialog->hide ();
2367 goto_editor_window ();
2378 if (response == Gtk::RESPONSE_NONE) {
2379 loading_dialog->hide ();
2380 new_session_dialog->set_existing_session (false);
2381 new_session_dialog->reset ();
2384 } while (response == Gtk::RESPONSE_NONE);
2388 loading_dialog->hide ();
2389 new_session_dialog->hide();
2394 ARDOUR_UI::close_session ()
2396 if (!check_audioengine()) {
2400 unload_session (true);
2402 get_session_parameters ("", true, false);
2406 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2408 Session *new_session;
2412 session_loaded = false;
2414 if (!check_audioengine()) {
2418 unload_status = unload_session ();
2420 if (unload_status < 0) {
2422 } else if (unload_status > 0) {
2427 /* if it already exists, we must have write access */
2429 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2430 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2431 "This prevents the session from being loaded."));
2436 if (loading_dialog) {
2437 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2441 disable_screen_updates ();
2444 new_session = new Session (*engine, path, snap_name, mix_template);
2448 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2451 Gtk::BUTTONS_OK_CANCEL);
2453 msg.set_title (_("Loading Error"));
2454 msg.set_secondary_text (_("Click the OK button to try again."));
2455 msg.set_position (Gtk::WIN_POS_CENTER);
2458 int response = msg.run ();
2463 case RESPONSE_CANCEL:
2471 connect_to_session (new_session);
2473 Config->set_current_owner (ConfigVariableBase::Interface);
2475 session_loaded = true;
2477 goto_editor_window ();
2480 session->set_clean ();
2483 enable_screen_updates ();
2492 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2493 uint32_t control_channels,
2494 uint32_t master_channels,
2495 AutoConnectOption input_connect,
2496 AutoConnectOption output_connect,
2499 nframes_t initial_length)
2501 Session *new_session;
2504 if (!check_audioengine()) {
2508 session_loaded = false;
2510 x = unload_session ();
2518 _session_is_new = true;
2521 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2522 control_channels, master_channels, nphysin, nphysout, initial_length);
2527 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2532 connect_to_session (new_session);
2534 session_loaded = true;
2542 editor->show_window ();
2553 ARDOUR_UI::show_splash ()
2556 about = new About();
2557 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2564 ARDOUR_UI::about_signal_response(int response)
2570 ARDOUR_UI::hide_splash ()
2573 about->get_window()->set_cursor ();
2579 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2583 removed = rep.paths.size();
2586 MessageDialog msgd (*editor,
2587 _("No audio files were ready for cleanup"),
2590 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2591 msgd.set_secondary_text (_("If this seems suprising, \n\
2592 check for any existing snapshots.\n\
2593 These may still include regions that\n\
2594 require some unused files to continue to exist."));
2600 ArdourDialog results (_("ardour: cleanup"), true, false);
2602 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2603 CleanupResultsModelColumns() {
2607 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2608 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2612 CleanupResultsModelColumns results_columns;
2613 Glib::RefPtr<Gtk::ListStore> results_model;
2614 Gtk::TreeView results_display;
2616 results_model = ListStore::create (results_columns);
2617 results_display.set_model (results_model);
2618 results_display.append_column (list_title, results_columns.visible_name);
2620 results_display.set_name ("CleanupResultsList");
2621 results_display.set_headers_visible (true);
2622 results_display.set_headers_clickable (false);
2623 results_display.set_reorderable (false);
2625 Gtk::ScrolledWindow list_scroller;
2628 Gtk::HBox dhbox; // the hbox for the image and text
2629 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2630 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2632 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2634 if (rep.space < 1048576.0f) {
2636 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2638 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2642 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2644 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2648 dhbox.pack_start (*dimage, true, false, 5);
2649 dhbox.pack_start (txt, true, false, 5);
2651 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2652 TreeModel::Row row = *(results_model->append());
2653 row[results_columns.visible_name] = *i;
2654 row[results_columns.fullpath] = *i;
2657 list_scroller.add (results_display);
2658 list_scroller.set_size_request (-1, 150);
2659 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2661 dvbox.pack_start (dhbox, true, false, 5);
2662 dvbox.pack_start (list_scroller, true, false, 5);
2663 ddhbox.pack_start (dvbox, true, false, 5);
2665 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2666 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2667 results.set_default_response (RESPONSE_CLOSE);
2668 results.set_position (Gtk::WIN_POS_MOUSE);
2669 results.show_all_children ();
2670 results.set_resizable (false);
2677 ARDOUR_UI::cleanup ()
2680 /* shouldn't happen: menu item is insensitive */
2685 MessageDialog checker (_("Are you sure you want to cleanup?"),
2687 Gtk::MESSAGE_QUESTION,
2688 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2690 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2691 ALL undo/redo information will be lost if you cleanup.\n\
2692 After cleanup, unused audio files will be moved to a \
2693 \"dead sounds\" location."));
2695 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2696 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2697 checker.set_default_response (RESPONSE_CANCEL);
2699 checker.set_name (_("CleanupDialog"));
2700 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2701 checker.set_position (Gtk::WIN_POS_MOUSE);
2703 switch (checker.run()) {
2704 case RESPONSE_ACCEPT:
2710 Session::cleanup_report rep;
2712 editor->prepare_for_cleanup ();
2714 /* do not allow flush until a session is reloaded */
2716 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2718 act->set_sensitive (false);
2721 if (session->cleanup_sources (rep)) {
2726 display_cleanup_results (rep,
2729 The following %1 %2 not in use and \n\
2730 have been moved to:\n\
2732 Flushing the wastebasket will \n\
2733 release an additional\n\
2734 %4 %5bytes of disk space.\n"
2742 ARDOUR_UI::flush_trash ()
2745 /* shouldn't happen: menu item is insensitive */
2749 Session::cleanup_report rep;
2751 if (session->cleanup_trash_sources (rep)) {
2755 display_cleanup_results (rep,
2757 _("The following %1 %2 deleted from\n\
2759 releasing %4 %5bytes of disk space"));
2763 ARDOUR_UI::add_route (Gtk::Window* float_window)
2771 if (add_route_dialog == 0) {
2772 add_route_dialog = new AddRouteDialog;
2774 add_route_dialog->set_transient_for (*float_window);
2778 if (add_route_dialog->is_visible()) {
2779 /* we're already doing this */
2783 ResponseType r = (ResponseType) add_route_dialog->run ();
2785 add_route_dialog->hide();
2788 case RESPONSE_ACCEPT:
2795 if ((count = add_route_dialog->count()) <= 0) {
2799 uint32_t input_chan = add_route_dialog->channels ();
2800 uint32_t output_chan;
2801 string name_template = add_route_dialog->name_template ();
2802 bool track = add_route_dialog->track ();
2804 AutoConnectOption oac = Config->get_output_auto_connect();
2806 if (oac & AutoConnectMaster) {
2807 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2809 output_chan = input_chan;
2812 /* XXX do something with name template */
2815 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2817 session_add_audio_bus (input_chan, output_chan, count);
2822 ARDOUR_UI::mixer_settings () const
2827 node = session->instant_xml(X_("Mixer"), session->path());
2829 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2833 node = new XMLNode (X_("Mixer"));
2840 ARDOUR_UI::editor_settings () const
2845 node = session->instant_xml(X_("Editor"), session->path());
2847 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2851 node = new XMLNode (X_("Editor"));
2857 ARDOUR_UI::keyboard_settings () const
2861 node = Config->extra_xml(X_("Keyboard"));
2864 node = new XMLNode (X_("Keyboard"));
2870 ARDOUR_UI::halt_on_xrun_message ()
2872 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2874 MessageDialog msg (*editor,
2875 _("Recording was stopped because your system could not keep up."));
2880 ARDOUR_UI::disk_overrun_handler ()
2882 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2884 if (!have_disk_speed_dialog_displayed) {
2885 have_disk_speed_dialog_displayed = true;
2886 MessageDialog* msg = new MessageDialog (*editor, _("\
2887 The disk system on your computer\n\
2888 was not able to keep up with Ardour.\n\
2890 Specifically, it failed to write data to disk\n\
2891 quickly enough to keep up with recording.\n"));
2892 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2898 ARDOUR_UI::disk_underrun_handler ()
2900 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2902 if (!have_disk_speed_dialog_displayed) {
2903 have_disk_speed_dialog_displayed = true;
2904 MessageDialog* msg = new MessageDialog (*editor,
2905 _("The disk system on your computer\n\
2906 was not able to keep up with Ardour.\n\
2908 Specifically, it failed to read data from disk\n\
2909 quickly enough to keep up with playback.\n"));
2910 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2916 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2918 have_disk_speed_dialog_displayed = false;
2923 ARDOUR_UI::pending_state_dialog ()
2925 ArdourDialog dialog ("pending state dialog");
2927 This session appears to have been in\n\
2928 middle of recording when ardour or\n\
2929 the computer was shutdown.\n\
2931 Ardour can recover any captured audio for\n\
2932 you, or it can ignore it. Please decide\n\
2933 what you would like to do.\n"));
2935 dialog.get_vbox()->pack_start (message);
2936 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2937 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2939 dialog.set_position (WIN_POS_CENTER);
2942 switch (dialog.run ()) {
2943 case RESPONSE_ACCEPT:
2951 ARDOUR_UI::disconnect_from_jack ()
2954 if( engine->disconnect_from_jack ()) {
2955 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2959 update_sample_rate (0);
2964 ARDOUR_UI::reconnect_to_jack ()
2967 if (engine->reconnect_to_jack ()) {
2968 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2972 update_sample_rate (0);
2977 ARDOUR_UI::cmdline_new_session (string path)
2979 if (path[0] != '/') {
2980 char buf[PATH_MAX+1];
2983 getcwd (buf, sizeof (buf));
2990 get_session_parameters (path, false, true);
2992 _will_create_new_session_automatically = false; /* done it */
2993 return FALSE; /* don't call it again */
2997 ARDOUR_UI::use_config ()
2999 Glib::RefPtr<Action> act;
3001 switch (Config->get_native_file_data_format ()) {
3003 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3006 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3009 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3014 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3015 ract->set_active ();
3018 switch (Config->get_native_file_header_format ()) {
3020 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3023 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3026 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3029 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3032 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3035 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3038 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3043 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3044 ract->set_active ();
3047 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3049 set_transport_controllable_state (*node);
3054 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3056 if (Config->get_primary_clock_delta_edit_cursor()) {
3057 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3059 primary_clock.set (pos, 0, true);
3062 if (Config->get_secondary_clock_delta_edit_cursor()) {
3063 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3065 secondary_clock.set (pos);
3068 if (big_clock_window) {
3069 big_clock.set (pos);
3074 ARDOUR_UI::record_state_changed ()
3076 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3078 if (!session || !big_clock_window) {
3079 /* why bother - the clock isn't visible */
3083 switch (session->record_status()) {
3084 case Session::Recording:
3085 big_clock.set_widget_name ("BigClockRecording");
3088 big_clock.set_widget_name ("BigClockNonRecording");
3094 ARDOUR_UI::set_keybindings_path (string path)
3096 keybindings_path = path;
3100 ARDOUR_UI::save_keybindings ()
3102 if (can_save_keybindings) {
3103 AccelMap::save (user_keybindings_path);
3108 ARDOUR_UI::first_idle ()
3111 session->allow_auto_play (true);
3113 can_save_keybindings = true;
3118 ARDOUR_UI::store_clock_modes ()
3120 XMLNode* node = new XMLNode(X_("ClockModes"));
3122 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3123 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3126 session->add_extra_xml (*node);
3127 session->set_dirty ();
3132 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3133 : Controllable (name), ui (u), type(tp)
3139 ARDOUR_UI::TransportControllable::set_value (float val)
3141 if (type == ShuttleControl) {
3148 fract = -((0.5f - val)/0.5f);
3150 fract = ((val - 0.5f)/0.5f);
3154 ui.set_shuttle_fract (fract);
3159 /* do nothing: these are radio-style actions */
3167 action = X_("Roll");
3170 action = X_("Stop");
3173 action = X_("Goto Start");
3176 action = X_("Goto End");
3179 action = X_("Loop");
3182 action = X_("Play Selection");
3185 action = X_("Record");
3195 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3203 ARDOUR_UI::TransportControllable::get_value (void) const
3222 case ShuttleControl:
3232 ARDOUR_UI::TransportControllable::set_id (const string& str)
3238 ARDOUR_UI::setup_profile ()
3240 if (gdk_screen_width() < 1200) {
3241 Profile->set_small_screen ();
3244 if (getenv ("ARDOUR_SAE")) {
3245 Profile->set_sae ();
3246 Profile->set_single_package ();