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);
2447 /* this one is special */
2449 catch (AudioEngine::PortRegistrationFailure& err) {
2451 MessageDialog msg (err.what(),
2454 Gtk::BUTTONS_OK_CANCEL);
2456 msg.set_title (_("Loading Error"));
2457 msg.set_secondary_text (_("Click the OK button to try again."));
2458 msg.set_position (Gtk::WIN_POS_CENTER);
2461 int response = msg.run ();
2466 case RESPONSE_CANCEL:
2475 cerr << "Caught something\n";
2476 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2479 Gtk::BUTTONS_OK_CANCEL);
2481 msg.set_title (_("Loading Error"));
2482 msg.set_secondary_text (_("Click the OK button to try again."));
2483 msg.set_position (Gtk::WIN_POS_CENTER);
2486 int response = msg.run ();
2491 case RESPONSE_CANCEL:
2499 connect_to_session (new_session);
2501 Config->set_current_owner (ConfigVariableBase::Interface);
2503 session_loaded = true;
2505 goto_editor_window ();
2508 session->set_clean ();
2511 enable_screen_updates ();
2520 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2521 uint32_t control_channels,
2522 uint32_t master_channels,
2523 AutoConnectOption input_connect,
2524 AutoConnectOption output_connect,
2527 nframes_t initial_length)
2529 Session *new_session;
2532 if (!check_audioengine()) {
2536 session_loaded = false;
2538 x = unload_session ();
2546 _session_is_new = true;
2549 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2550 control_channels, master_channels, nphysin, nphysout, initial_length);
2555 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2560 connect_to_session (new_session);
2562 session_loaded = true;
2570 editor->show_window ();
2581 ARDOUR_UI::show_splash ()
2584 about = new About();
2585 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2592 ARDOUR_UI::about_signal_response(int response)
2598 ARDOUR_UI::hide_splash ()
2601 about->get_window()->set_cursor ();
2607 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2611 removed = rep.paths.size();
2614 MessageDialog msgd (*editor,
2615 _("No audio files were ready for cleanup"),
2618 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2619 msgd.set_secondary_text (_("If this seems suprising, \n\
2620 check for any existing snapshots.\n\
2621 These may still include regions that\n\
2622 require some unused files to continue to exist."));
2628 ArdourDialog results (_("ardour: cleanup"), true, false);
2630 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2631 CleanupResultsModelColumns() {
2635 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2636 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2640 CleanupResultsModelColumns results_columns;
2641 Glib::RefPtr<Gtk::ListStore> results_model;
2642 Gtk::TreeView results_display;
2644 results_model = ListStore::create (results_columns);
2645 results_display.set_model (results_model);
2646 results_display.append_column (list_title, results_columns.visible_name);
2648 results_display.set_name ("CleanupResultsList");
2649 results_display.set_headers_visible (true);
2650 results_display.set_headers_clickable (false);
2651 results_display.set_reorderable (false);
2653 Gtk::ScrolledWindow list_scroller;
2656 Gtk::HBox dhbox; // the hbox for the image and text
2657 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2658 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2660 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2662 if (rep.space < 1048576.0f) {
2664 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2666 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2670 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2672 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2676 dhbox.pack_start (*dimage, true, false, 5);
2677 dhbox.pack_start (txt, true, false, 5);
2679 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2680 TreeModel::Row row = *(results_model->append());
2681 row[results_columns.visible_name] = *i;
2682 row[results_columns.fullpath] = *i;
2685 list_scroller.add (results_display);
2686 list_scroller.set_size_request (-1, 150);
2687 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2689 dvbox.pack_start (dhbox, true, false, 5);
2690 dvbox.pack_start (list_scroller, true, false, 5);
2691 ddhbox.pack_start (dvbox, true, false, 5);
2693 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2694 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2695 results.set_default_response (RESPONSE_CLOSE);
2696 results.set_position (Gtk::WIN_POS_MOUSE);
2697 results.show_all_children ();
2698 results.set_resizable (false);
2705 ARDOUR_UI::cleanup ()
2708 /* shouldn't happen: menu item is insensitive */
2713 MessageDialog checker (_("Are you sure you want to cleanup?"),
2715 Gtk::MESSAGE_QUESTION,
2716 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2718 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2719 ALL undo/redo information will be lost if you cleanup.\n\
2720 After cleanup, unused audio files will be moved to a \
2721 \"dead sounds\" location."));
2723 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2724 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2725 checker.set_default_response (RESPONSE_CANCEL);
2727 checker.set_name (_("CleanupDialog"));
2728 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2729 checker.set_position (Gtk::WIN_POS_MOUSE);
2731 switch (checker.run()) {
2732 case RESPONSE_ACCEPT:
2738 Session::cleanup_report rep;
2740 editor->prepare_for_cleanup ();
2742 /* do not allow flush until a session is reloaded */
2744 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2746 act->set_sensitive (false);
2749 if (session->cleanup_sources (rep)) {
2754 display_cleanup_results (rep,
2757 The following %1 %2 not in use and \n\
2758 have been moved to:\n\
2760 Flushing the wastebasket will \n\
2761 release an additional\n\
2762 %4 %5bytes of disk space.\n"
2770 ARDOUR_UI::flush_trash ()
2773 /* shouldn't happen: menu item is insensitive */
2777 Session::cleanup_report rep;
2779 if (session->cleanup_trash_sources (rep)) {
2783 display_cleanup_results (rep,
2785 _("The following %1 %2 deleted from\n\
2787 releasing %4 %5bytes of disk space"));
2791 ARDOUR_UI::add_route (Gtk::Window* float_window)
2799 if (add_route_dialog == 0) {
2800 add_route_dialog = new AddRouteDialog;
2802 add_route_dialog->set_transient_for (*float_window);
2806 if (add_route_dialog->is_visible()) {
2807 /* we're already doing this */
2811 ResponseType r = (ResponseType) add_route_dialog->run ();
2813 add_route_dialog->hide();
2816 case RESPONSE_ACCEPT:
2823 if ((count = add_route_dialog->count()) <= 0) {
2827 uint32_t input_chan = add_route_dialog->channels ();
2828 uint32_t output_chan;
2829 string name_template = add_route_dialog->name_template ();
2830 bool track = add_route_dialog->track ();
2832 AutoConnectOption oac = Config->get_output_auto_connect();
2834 if (oac & AutoConnectMaster) {
2835 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2837 output_chan = input_chan;
2840 /* XXX do something with name template */
2843 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2845 session_add_audio_bus (input_chan, output_chan, count);
2850 ARDOUR_UI::mixer_settings () const
2855 node = session->instant_xml(X_("Mixer"), session->path());
2857 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2861 node = new XMLNode (X_("Mixer"));
2868 ARDOUR_UI::editor_settings () const
2873 node = session->instant_xml(X_("Editor"), session->path());
2875 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2879 node = new XMLNode (X_("Editor"));
2885 ARDOUR_UI::keyboard_settings () const
2889 node = Config->extra_xml(X_("Keyboard"));
2892 node = new XMLNode (X_("Keyboard"));
2898 ARDOUR_UI::halt_on_xrun_message ()
2900 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2902 MessageDialog msg (*editor,
2903 _("Recording was stopped because your system could not keep up."));
2908 ARDOUR_UI::disk_overrun_handler ()
2910 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2912 if (!have_disk_speed_dialog_displayed) {
2913 have_disk_speed_dialog_displayed = true;
2914 MessageDialog* msg = new MessageDialog (*editor, _("\
2915 The disk system on your computer\n\
2916 was not able to keep up with Ardour.\n\
2918 Specifically, it failed to write data to disk\n\
2919 quickly enough to keep up with recording.\n"));
2920 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2926 ARDOUR_UI::disk_underrun_handler ()
2928 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2930 if (!have_disk_speed_dialog_displayed) {
2931 have_disk_speed_dialog_displayed = true;
2932 MessageDialog* msg = new MessageDialog (*editor,
2933 _("The disk system on your computer\n\
2934 was not able to keep up with Ardour.\n\
2936 Specifically, it failed to read data from disk\n\
2937 quickly enough to keep up with playback.\n"));
2938 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2944 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2946 have_disk_speed_dialog_displayed = false;
2951 ARDOUR_UI::pending_state_dialog ()
2953 ArdourDialog dialog ("pending state dialog");
2955 This session appears to have been in\n\
2956 middle of recording when ardour or\n\
2957 the computer was shutdown.\n\
2959 Ardour can recover any captured audio for\n\
2960 you, or it can ignore it. Please decide\n\
2961 what you would like to do.\n"));
2963 dialog.get_vbox()->pack_start (message);
2964 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2965 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2967 dialog.set_position (WIN_POS_CENTER);
2970 switch (dialog.run ()) {
2971 case RESPONSE_ACCEPT:
2979 ARDOUR_UI::disconnect_from_jack ()
2982 if( engine->disconnect_from_jack ()) {
2983 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2987 update_sample_rate (0);
2992 ARDOUR_UI::reconnect_to_jack ()
2995 if (engine->reconnect_to_jack ()) {
2996 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3000 update_sample_rate (0);
3005 ARDOUR_UI::cmdline_new_session (string path)
3007 if (path[0] != '/') {
3008 char buf[PATH_MAX+1];
3011 getcwd (buf, sizeof (buf));
3018 get_session_parameters (path, false, true);
3020 _will_create_new_session_automatically = false; /* done it */
3021 return FALSE; /* don't call it again */
3025 ARDOUR_UI::use_config ()
3027 Glib::RefPtr<Action> act;
3029 switch (Config->get_native_file_data_format ()) {
3031 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3034 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3037 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3042 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3043 ract->set_active ();
3046 switch (Config->get_native_file_header_format ()) {
3048 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3051 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3054 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3057 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3060 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3063 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3066 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3071 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3072 ract->set_active ();
3075 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3077 set_transport_controllable_state (*node);
3082 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3084 if (Config->get_primary_clock_delta_edit_cursor()) {
3085 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3087 primary_clock.set (pos, 0, true);
3090 if (Config->get_secondary_clock_delta_edit_cursor()) {
3091 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3093 secondary_clock.set (pos);
3096 if (big_clock_window) {
3097 big_clock.set (pos);
3102 ARDOUR_UI::record_state_changed ()
3104 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3106 if (!session || !big_clock_window) {
3107 /* why bother - the clock isn't visible */
3111 switch (session->record_status()) {
3112 case Session::Recording:
3113 big_clock.set_widget_name ("BigClockRecording");
3116 big_clock.set_widget_name ("BigClockNonRecording");
3122 ARDOUR_UI::set_keybindings_path (string path)
3124 keybindings_path = path;
3128 ARDOUR_UI::save_keybindings ()
3130 if (can_save_keybindings) {
3131 AccelMap::save (user_keybindings_path);
3136 ARDOUR_UI::first_idle ()
3139 session->allow_auto_play (true);
3141 can_save_keybindings = true;
3146 ARDOUR_UI::store_clock_modes ()
3148 XMLNode* node = new XMLNode(X_("ClockModes"));
3150 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3151 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3154 session->add_extra_xml (*node);
3155 session->set_dirty ();
3160 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3161 : Controllable (name), ui (u), type(tp)
3167 ARDOUR_UI::TransportControllable::set_value (float val)
3169 if (type == ShuttleControl) {
3176 fract = -((0.5f - val)/0.5f);
3178 fract = ((val - 0.5f)/0.5f);
3182 ui.set_shuttle_fract (fract);
3187 /* do nothing: these are radio-style actions */
3195 action = X_("Roll");
3198 action = X_("Stop");
3201 action = X_("Goto Start");
3204 action = X_("Goto End");
3207 action = X_("Loop");
3210 action = X_("Play Selection");
3213 action = X_("Record");
3223 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3231 ARDOUR_UI::TransportControllable::get_value (void) const
3250 case ShuttleControl:
3260 ARDOUR_UI::TransportControllable::set_id (const string& str)
3266 ARDOUR_UI::setup_profile ()
3268 if (gdk_screen_width() < 1200) {
3269 Profile->set_small_screen ();
3272 if (getenv ("ARDOUR_SAE")) {
3273 Profile->set_sae ();
3274 Profile->set_single_package ();