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));
254 ARDOUR_UI::create_engine ()
256 // this gets called every time by new_session()
263 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
270 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
271 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
272 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
273 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
281 ARDOUR_UI::post_engine ()
283 /* Things to be done once we create the AudioEngine
286 check_memory_locking();
288 ActionManager::init ();
291 if (setup_windows ()) {
292 throw failed_constructor ();
295 /* this is the first point at which all the keybindings are available */
297 if (ARDOUR_COMMAND_LINE::show_key_actions) {
298 vector<string> names;
299 vector<string> paths;
301 vector<AccelKey> bindings;
303 ActionManager::get_all_actions (names, paths, keys, bindings);
305 vector<string>::iterator n;
306 vector<string>::iterator k;
307 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
308 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
314 blink_timeout_tag = -1;
316 /* the global configuration object is now valid */
320 /* this being a GUI and all, we want peakfiles */
322 AudioFileSource::set_build_peakfiles (true);
323 AudioFileSource::set_build_missing_peakfiles (true);
325 /* set default clock modes */
327 primary_clock.set_mode (AudioClock::SMPTE);
328 secondary_clock.set_mode (AudioClock::BBT);
330 /* start the time-of-day-clock */
333 /* OS X provides an always visible wallclock, so don't be stupid */
334 update_wall_clock ();
335 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
338 update_disk_space ();
340 update_sample_rate (engine->frame_rate());
342 platform_specific ();
344 /* now start and maybe save state */
346 if (do_engine_start () == 0) {
347 if (session && _session_is_new) {
348 /* we need to retain initial visual
349 settings for a new session
351 session->save_state ("");
356 ARDOUR_UI::~ARDOUR_UI ()
358 save_ardour_state ();
372 if (add_route_dialog) {
373 delete add_route_dialog;
376 if (new_session_dialog) {
377 delete new_session_dialog;
382 ARDOUR_UI::configure_timeout ()
387 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
388 /* no configure events yet */
392 gettimeofday (&now, 0);
393 timersub (&now, &last_configure_time, &diff);
395 /* force a gap of 0.5 seconds since the last configure event
398 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
401 have_configure_timeout = false;
402 save_ardour_state ();
408 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
410 if (have_configure_timeout) {
411 gettimeofday (&last_configure_time, 0);
413 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
414 have_configure_timeout = true;
421 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
423 const XMLProperty* prop;
425 if ((prop = node.property ("roll")) != 0) {
426 roll_controllable.set_id (prop->value());
428 if ((prop = node.property ("stop")) != 0) {
429 stop_controllable.set_id (prop->value());
431 if ((prop = node.property ("goto_start")) != 0) {
432 goto_start_controllable.set_id (prop->value());
434 if ((prop = node.property ("goto_end")) != 0) {
435 goto_end_controllable.set_id (prop->value());
437 if ((prop = node.property ("auto_loop")) != 0) {
438 auto_loop_controllable.set_id (prop->value());
440 if ((prop = node.property ("play_selection")) != 0) {
441 play_selection_controllable.set_id (prop->value());
443 if ((prop = node.property ("rec")) != 0) {
444 rec_controllable.set_id (prop->value());
446 if ((prop = node.property ("shuttle")) != 0) {
447 shuttle_controllable.set_id (prop->value());
452 ARDOUR_UI::get_transport_controllable_state ()
454 XMLNode* node = new XMLNode(X_("TransportControllables"));
457 roll_controllable.id().print (buf, sizeof (buf));
458 node->add_property (X_("roll"), buf);
459 stop_controllable.id().print (buf, sizeof (buf));
460 node->add_property (X_("stop"), buf);
461 goto_start_controllable.id().print (buf, sizeof (buf));
462 node->add_property (X_("goto_start"), buf);
463 goto_end_controllable.id().print (buf, sizeof (buf));
464 node->add_property (X_("goto_end"), buf);
465 auto_loop_controllable.id().print (buf, sizeof (buf));
466 node->add_property (X_("auto_loop"), buf);
467 play_selection_controllable.id().print (buf, sizeof (buf));
468 node->add_property (X_("play_selection"), buf);
469 rec_controllable.id().print (buf, sizeof (buf));
470 node->add_property (X_("rec"), buf);
471 shuttle_controllable.id().print (buf, sizeof (buf));
472 node->add_property (X_("shuttle"), buf);
478 ARDOUR_UI::save_ardour_state ()
480 if (!keyboard || !mixer || !editor) {
484 /* XXX this is all a bit dubious. add_extra_xml() uses
485 a different lifetime model from add_instant_xml().
488 XMLNode* node = new XMLNode (keyboard->get_state());
489 Config->add_extra_xml (*node);
490 Config->add_extra_xml (get_transport_controllable_state());
491 if (new_session_dialog) {
492 if (new_session_dialog->engine_control.was_used()) {
493 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
496 Config->save_state();
497 ui_config->save_state ();
499 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
500 XMLNode mnode(mixer->get_state());
503 session->add_instant_xml (enode, session->path());
504 session->add_instant_xml (mnode, session->path());
506 Config->add_instant_xml (enode, get_user_ardour_path());
507 Config->add_instant_xml (mnode, get_user_ardour_path());
514 ARDOUR_UI::autosave_session ()
516 if (!Config->get_periodic_safety_backups())
520 session->maybe_write_autosave();
527 ARDOUR_UI::update_autosave ()
529 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
531 if (session->dirty()) {
532 if (_autosave_connection.connected()) {
533 _autosave_connection.disconnect();
536 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
537 Config->get_periodic_safety_backup_interval() * 1000);
540 if (_autosave_connection.connected()) {
541 _autosave_connection.disconnect();
547 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
551 title = _("Ardour could not start JACK");
553 title = _("Ardour could not connect to JACK.");
556 MessageDialog win (title,
562 win.set_secondary_text(_("There are several possible reasons:\n\
564 1) You requested audio parameters that are not supported..\n\
565 2) JACK is running as another user.\n\
567 Please consider the possibilities, and perhaps try different parameters."));
569 win.set_secondary_text(_("There are several possible reasons:\n\
571 1) JACK is not running.\n\
572 2) JACK is running as another user, perhaps root.\n\
573 3) There is already another client called \"ardour\".\n\
575 Please consider the possibilities, and perhaps (re)start JACK."));
579 win.set_transient_for (*toplevel);
583 win.add_button (Stock::OK, RESPONSE_CLOSE);
585 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
588 win.set_default_response (RESPONSE_CLOSE);
591 win.set_position (Gtk::WIN_POS_CENTER);
593 if (!ARDOUR_COMMAND_LINE::no_splash) {
597 /* we just don't care about the result, but we want to block */
603 ARDOUR_UI::startup ()
608 new_session_dialog = new NewSessionDialog();
610 /* If no session name is given: we're not loading a session yet, nor creating a new one */
612 if (ARDOUR_COMMAND_LINE::session_name.length()) {
614 /* Load session or start the new session dialog */
616 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
618 MessageDialog msg (string_compose(_("Could not find command line session \"%1\""),
619 ARDOUR_COMMAND_LINE::session_name),
624 msg.set_position (Gtk::WIN_POS_MOUSE);
631 if (!ARDOUR_COMMAND_LINE::new_session) {
633 /* Supposed to be loading an existing session, but the session doesn't exist */
636 MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
637 "To create it from the command line, start ardour as:\n ardour --new %1"), path),
642 msg.set_position (Gtk::WIN_POS_MOUSE);
653 bool have_backend = EngineControl::engine_running();
654 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
657 new_session_dialog->engine_control.set_state (*audio_setup);
660 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
668 ARDOUR_UI::no_memory_warning ()
670 XMLNode node (X_("no-memory-warning"));
671 Config->add_instant_xml (node, get_user_ardour_path());
675 ARDOUR_UI::check_memory_locking ()
678 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
682 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
684 if (engine->is_realtime() && memory_warning_node == 0) {
686 struct rlimit limits;
688 long pages, page_size;
690 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
693 ram = (int64_t) pages * (int64_t) page_size;
696 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
700 if (limits.rlim_cur != RLIM_INFINITY) {
702 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
705 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
706 "This might cause Ardour to run out of memory before your system "
707 "runs out of memory. \n\n"
708 "You can view the memory limit with 'ulimit -l', "
709 "and it is normally controlled by /etc/security/limits.conf"));
711 VBox* vbox = msg.get_vbox();
713 CheckButton cb (_("Do not show this window again"));
715 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
717 hbox.pack_start (cb, true, false);
718 vbox->pack_start (hbox);
734 if (session->transport_rolling()) {
735 session->request_stop ();
739 if (session->dirty()) {
740 switch (ask_about_saving_session(_("quit"))) {
745 /* use the default name */
746 if (save_state_canfail ("")) {
747 /* failed - don't quit */
748 MessageDialog msg (*editor,
750 Ardour was unable to save your session.\n\n\
751 If you still wish to quit, please use the\n\n\
752 \"Just quit\" option."));
762 session->set_deletion_in_progress ();
766 save_ardour_state ();
771 ARDOUR_UI::ask_about_saving_session (const string & what)
773 ArdourDialog window (_("ardour: save session?"));
774 Gtk::HBox dhbox; // the hbox for the image and text
775 Gtk::Label prompt_label;
776 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
780 msg = string_compose(_("Don't %1"), what);
781 window.add_button (msg, RESPONSE_REJECT);
782 msg = string_compose(_("Just %1"), what);
783 window.add_button (msg, RESPONSE_APPLY);
784 msg = string_compose(_("Save and %1"), what);
785 window.add_button (msg, RESPONSE_ACCEPT);
787 window.set_default_response (RESPONSE_ACCEPT);
789 Gtk::Button noquit_button (msg);
790 noquit_button.set_name ("EditorGTKButton");
795 if (session->snap_name() == session->name()) {
798 type = _("snapshot");
800 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?"),
801 type, session->snap_name());
803 prompt_label.set_text (prompt);
804 prompt_label.set_name (X_("PrompterLabel"));
805 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
807 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
809 dhbox.set_homogeneous (false);
810 dhbox.pack_start (*dimage, false, false, 5);
811 dhbox.pack_start (prompt_label, true, false, 5);
812 window.get_vbox()->pack_start (dhbox);
814 window.set_name (_("Prompter"));
815 window.set_position (Gtk::WIN_POS_MOUSE);
816 window.set_modal (true);
817 window.set_resizable (false);
820 save_the_session = 0;
822 window.set_keep_above (true);
825 ResponseType r = (ResponseType) window.run();
830 case RESPONSE_ACCEPT: // save and get out of here
832 case RESPONSE_APPLY: // get out of here
842 ARDOUR_UI::every_second ()
845 update_buffer_load ();
846 update_disk_space ();
851 ARDOUR_UI::every_point_one_seconds ()
853 update_speed_display ();
854 RapidScreenUpdate(); /* EMIT_SIGNAL */
859 ARDOUR_UI::every_point_zero_one_seconds ()
861 // august 2007: actual update frequency: 40Hz, not 100Hz
863 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
868 ARDOUR_UI::update_sample_rate (nframes_t ignored)
872 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
874 if (!engine->connected()) {
876 snprintf (buf, sizeof (buf), _("disconnected"));
880 nframes_t rate = engine->frame_rate();
882 if (fmod (rate, 1000.0) != 0.0) {
883 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
884 (float) rate/1000.0f,
885 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
887 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
889 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
893 sample_rate_label.set_text (buf);
897 ARDOUR_UI::update_cpu_load ()
900 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
901 cpu_load_label.set_text (buf);
905 ARDOUR_UI::update_buffer_load ()
910 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
911 session->playback_load(), session->capture_load());
912 buffer_load_label.set_text (buf);
914 buffer_load_label.set_text ("");
919 ARDOUR_UI::count_recenabled_streams (Route& route)
921 Track* track = dynamic_cast<Track*>(&route);
922 if (track && track->diskstream()->record_enabled()) {
923 rec_enabled_streams += track->n_inputs();
928 ARDOUR_UI::update_disk_space()
934 nframes_t frames = session->available_capture_duration();
937 if (frames == max_frames) {
938 strcpy (buf, _("Disk: 24hrs+"));
943 nframes_t fr = session->frame_rate();
945 rec_enabled_streams = 0;
946 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
948 if (rec_enabled_streams) {
949 frames /= rec_enabled_streams;
952 hrs = frames / (fr * 3600);
953 frames -= hrs * fr * 3600;
954 mins = frames / (fr * 60);
955 frames -= mins * fr * 60;
958 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
961 disk_space_label.set_text (buf);
965 ARDOUR_UI::update_wall_clock ()
972 tm_now = localtime (&now);
974 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
975 wall_clock_label.set_text (buf);
981 ARDOUR_UI::session_menu (GdkEventButton *ev)
983 session_popup_menu->popup (0, 0);
988 ARDOUR_UI::redisplay_recent_sessions ()
990 vector<string *> *sessions;
991 vector<string *>::iterator i;
992 RecentSessionsSorter cmp;
994 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
995 recent_session_model->clear ();
998 ARDOUR::read_recent_sessions (rs);
1001 recent_session_display.set_model (recent_session_model);
1005 /* sort them alphabetically */
1006 sort (rs.begin(), rs.end(), cmp);
1007 sessions = new vector<string*>;
1009 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1010 sessions->push_back (new string ((*i).second));
1013 for (i = sessions->begin(); i != sessions->end(); ++i) {
1015 vector<string*>* states;
1016 vector<const gchar*> item;
1017 string fullpath = *(*i);
1019 /* remove any trailing / */
1021 if (fullpath[fullpath.length()-1] == '/') {
1022 fullpath = fullpath.substr (0, fullpath.length()-1);
1025 /* now get available states for this session */
1027 if ((states = Session::possible_states (fullpath)) == 0) {
1028 /* no state file? */
1032 TreeModel::Row row = *(recent_session_model->append());
1034 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1035 row[recent_session_columns.fullpath] = fullpath;
1037 if (states->size() > 1) {
1039 /* add the children */
1041 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1043 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1045 child_row[recent_session_columns.visible_name] = **i2;
1046 child_row[recent_session_columns.fullpath] = fullpath;
1055 recent_session_display.set_model (recent_session_model);
1060 ARDOUR_UI::build_session_selector ()
1062 session_selector_window = new ArdourDialog ("session selector");
1064 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1066 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1067 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1068 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1069 recent_session_model = TreeStore::create (recent_session_columns);
1070 recent_session_display.set_model (recent_session_model);
1071 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1072 recent_session_display.set_headers_visible (false);
1073 recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1074 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1076 scroller->add (recent_session_display);
1077 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1079 session_selector_window->set_name ("SessionSelectorWindow");
1080 session_selector_window->set_size_request (200, 400);
1081 session_selector_window->get_vbox()->pack_start (*scroller);
1082 session_selector_window->show_all_children();
1086 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1088 session_selector_window->response (RESPONSE_ACCEPT);
1092 ARDOUR_UI::open_recent_session ()
1094 bool can_return = (session != 0);
1096 if (session_selector_window == 0) {
1097 build_session_selector ();
1100 redisplay_recent_sessions ();
1104 session_selector_window->set_position (WIN_POS_MOUSE);
1106 ResponseType r = (ResponseType) session_selector_window->run ();
1109 case RESPONSE_ACCEPT:
1113 session_selector_window->hide();
1120 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1124 session_selector_window->hide();
1126 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1128 if (i == recent_session_model->children().end()) {
1132 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1133 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1135 _session_is_new = false;
1137 if (load_session (path, state) == 0) {
1146 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1148 struct stat statbuf;
1150 if (stat (info.filename.c_str(), &statbuf) != 0) {
1154 if (!S_ISDIR(statbuf.st_mode)) {
1160 string session_file = info.filename;
1161 session_file += '/';
1162 session_file += Glib::path_get_basename (info.filename);
1163 session_file += ".ardour";
1165 if (stat (session_file.c_str(), &statbuf) != 0) {
1169 return S_ISREG (statbuf.st_mode);
1173 ARDOUR_UI::check_audioengine ()
1176 if (!engine->connected()) {
1177 MessageDialog msg (_("Ardour is not connected to JACK\n"
1178 "You cannot open or close sessions in this condition"));
1189 ARDOUR_UI::open_session ()
1191 if (!check_audioengine()) {
1195 /* popup selector window */
1197 if (open_session_selector == 0) {
1199 /* ardour sessions are folders */
1201 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1202 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1203 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1204 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1206 FileFilter session_filter;
1207 session_filter.add_pattern ("*.ardour");
1208 session_filter.set_name (_("Ardour sessions"));
1209 open_session_selector->add_filter (session_filter);
1210 open_session_selector->set_filter (session_filter);
1213 int response = open_session_selector->run();
1214 open_session_selector->hide ();
1217 case RESPONSE_ACCEPT:
1220 open_session_selector->hide();
1224 open_session_selector->hide();
1225 string session_path = open_session_selector->get_filename();
1229 if (session_path.length() > 0) {
1230 if (Session::find_session (session_path, path, name, isnew) == 0) {
1231 _session_is_new = isnew;
1232 load_session (path, name);
1239 ARDOUR_UI::session_add_midi_track ()
1241 cerr << _("Patience is a virtue.\n");
1245 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1247 list<boost::shared_ptr<AudioTrack> > tracks;
1248 Session::RouteList routes;
1251 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1257 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1259 if (tracks.size() != how_many) {
1260 if (how_many == 1) {
1261 error << _("could not create a new audio track") << endmsg;
1263 error << string_compose (_("could only create %1 of %2 new audio %3"),
1264 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1270 routes = session->new_audio_route (input_channels, output_channels, how_many);
1272 if (routes.size() != how_many) {
1273 if (how_many == 1) {
1274 error << _("could not create a new audio track") << endmsg;
1276 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1282 if (need_control_room_outs) {
1288 route->set_stereo_control_outs (control_lr_channels);
1289 route->control_outs()->set_stereo_pan (pans, this);
1291 #endif /* CONTROLOUTS */
1295 cerr << "About to complain about JACK\n";
1296 MessageDialog msg (*editor,
1297 _("There are insufficient JACK ports available\n\
1298 to create a new track or bus.\n\
1299 You should save Ardour, exit and\n\
1300 restart JACK with more ports."));
1306 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1308 nframes_t _preroll = 0;
1311 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1312 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1314 if (new_position > _preroll) {
1315 new_position -= _preroll;
1320 session->request_locate (new_position);
1325 ARDOUR_UI::transport_goto_start ()
1328 session->goto_start();
1331 /* force displayed area in editor to start no matter
1332 what "follow playhead" setting is.
1336 editor->reset_x_origin (session->current_start_frame());
1342 ARDOUR_UI::transport_goto_zero ()
1345 session->request_locate (0);
1348 /* force displayed area in editor to start no matter
1349 what "follow playhead" setting is.
1353 editor->reset_x_origin (0);
1359 ARDOUR_UI::transport_goto_end ()
1362 nframes_t frame = session->current_end_frame();
1363 session->request_locate (frame);
1365 /* force displayed area in editor to start no matter
1366 what "follow playhead" setting is.
1370 editor->reset_x_origin (frame);
1376 ARDOUR_UI::transport_stop ()
1382 if (session->is_auditioning()) {
1383 session->cancel_audition ();
1387 if (session->get_play_loop ()) {
1388 session->request_play_loop (false);
1391 session->request_stop ();
1395 ARDOUR_UI::transport_stop_and_forget_capture ()
1398 session->request_stop (true);
1403 ARDOUR_UI::remove_last_capture()
1406 editor->remove_last_capture();
1411 ARDOUR_UI::transport_record (bool roll)
1414 switch (session->record_status()) {
1415 case Session::Disabled:
1416 if (session->ntracks() == 0) {
1417 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1421 session->maybe_enable_record ();
1426 case Session::Recording:
1428 session->request_stop();
1430 session->disable_record (false, true);
1434 case Session::Enabled:
1435 session->disable_record (false, true);
1441 ARDOUR_UI::transport_roll ()
1449 rolling = session->transport_rolling ();
1451 if (session->get_play_loop()) {
1452 session->request_play_loop (false);
1453 auto_loop_button.set_visual_state (1);
1454 roll_button.set_visual_state (1);
1455 } else if (session->get_play_range ()) {
1456 session->request_play_range (false);
1457 play_selection_button.set_visual_state (0);
1458 } else if (rolling) {
1459 session->request_locate (session->last_transport_start(), true);
1462 session->request_transport_speed (1.0f);
1466 ARDOUR_UI::transport_loop()
1469 if (session->get_play_loop()) {
1470 if (session->transport_rolling()) {
1471 Location * looploc = session->locations()->auto_loop_location();
1473 session->request_locate (looploc->start(), true);
1478 session->request_play_loop (true);
1484 ARDOUR_UI::transport_play_selection ()
1490 if (!session->get_play_range()) {
1491 session->request_stop ();
1494 editor->play_selection ();
1498 ARDOUR_UI::transport_rewind (int option)
1500 float current_transport_speed;
1503 current_transport_speed = session->transport_speed();
1505 if (current_transport_speed >= 0.0f) {
1508 session->request_transport_speed (-1.0f);
1511 session->request_transport_speed (-4.0f);
1514 session->request_transport_speed (-0.5f);
1519 session->request_transport_speed (current_transport_speed * 1.5f);
1525 ARDOUR_UI::transport_forward (int option)
1527 float current_transport_speed;
1530 current_transport_speed = session->transport_speed();
1532 if (current_transport_speed <= 0.0f) {
1535 session->request_transport_speed (1.0f);
1538 session->request_transport_speed (4.0f);
1541 session->request_transport_speed (0.5f);
1546 session->request_transport_speed (current_transport_speed * 1.5f);
1552 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1558 boost::shared_ptr<Route> r;
1560 if ((r = session->route_by_remote_id (dstream)) != 0) {
1564 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1565 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1574 ARDOUR_UI::queue_transport_change ()
1576 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1580 ARDOUR_UI::map_transport_state ()
1582 float sp = session->transport_speed();
1585 transport_rolling ();
1586 } else if (sp < 0.0f) {
1587 transport_rewinding ();
1588 } else if (sp > 0.0f) {
1589 transport_forwarding ();
1591 transport_stopped ();
1596 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1598 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1599 (int) adj.get_value()].c_str());
1603 ARDOUR_UI::engine_stopped ()
1605 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1606 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1607 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1611 ARDOUR_UI::engine_running ()
1613 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1614 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1615 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1617 Glib::RefPtr<Action> action;
1618 char* action_name = 0;
1620 switch (engine->frames_per_cycle()) {
1622 action_name = X_("JACKLatency32");
1625 action_name = X_("JACKLatency64");
1628 action_name = X_("JACKLatency128");
1631 action_name = X_("JACKLatency512");
1634 action_name = X_("JACKLatency1024");
1637 action_name = X_("JACKLatency2048");
1640 action_name = X_("JACKLatency4096");
1643 action_name = X_("JACKLatency8192");
1646 /* XXX can we do anything useful ? */
1652 action = ActionManager::get_action (X_("JACK"), action_name);
1655 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1656 ract->set_active ();
1662 ARDOUR_UI::engine_halted ()
1664 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1666 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1667 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1669 update_sample_rate (0);
1671 MessageDialog msg (*editor,
1673 JACK has either been shutdown or it\n\
1674 disconnected Ardour because Ardour\n\
1675 was not fast enough. You can save the\n\
1676 session and/or try to reconnect to JACK ."));
1681 ARDOUR_UI::do_engine_start ()
1689 error << _("Unable to start the session running")
1699 ARDOUR_UI::setup_theme ()
1701 theme_manager->setup_theme();
1705 ARDOUR_UI::update_clocks ()
1707 if (!editor || !editor->dragging_playhead()) {
1708 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1713 ARDOUR_UI::start_clocking ()
1715 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1719 ARDOUR_UI::stop_clocking ()
1721 clock_signal_connection.disconnect ();
1725 ARDOUR_UI::toggle_clocking ()
1728 if (clock_button.get_active()) {
1737 ARDOUR_UI::_blink (void *arg)
1740 ((ARDOUR_UI *) arg)->blink ();
1747 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1751 ARDOUR_UI::start_blinking ()
1753 /* Start the blink signal. Everybody with a blinking widget
1754 uses Blink to drive the widget's state.
1757 if (blink_timeout_tag < 0) {
1759 blink_timeout_tag = g_timeout_add (240, _blink, this);
1764 ARDOUR_UI::stop_blinking ()
1766 if (blink_timeout_tag >= 0) {
1767 g_source_remove (blink_timeout_tag);
1768 blink_timeout_tag = -1;
1773 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1779 if (io.n_inputs() == 0) {
1784 /* XXX we're not handling multiple ports yet. */
1786 const char **connections = io.input(0)->get_connections();
1788 if (connections == 0 || connections[0] == '\0') {
1791 buf = connections[0];
1798 if (io.n_outputs() == 0) {
1803 /* XXX we're not handling multiple ports yet. */
1805 const char **connections = io.output(0)->get_connections();
1807 if (connections == 0 || connections[0] == '\0') {
1810 buf = connections[0];
1817 /** Ask the user for the name of a new shapshot and then take it.
1820 ARDOUR_UI::snapshot_session ()
1822 ArdourPrompter prompter (true);
1826 struct tm local_time;
1829 localtime_r (&n, &local_time);
1830 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1832 prompter.set_name ("Prompter");
1833 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1834 prompter.set_prompt (_("Name of New Snapshot"));
1835 prompter.set_initial_text (timebuf);
1837 switch (prompter.run()) {
1838 case RESPONSE_ACCEPT:
1839 prompter.get_result (snapname);
1840 if (snapname.length()){
1841 save_state (snapname);
1851 ARDOUR_UI::save_state (const string & name)
1853 (void) save_state_canfail (name);
1857 ARDOUR_UI::save_state_canfail (string name)
1862 if (name.length() == 0) {
1863 name = session->snap_name();
1866 if ((ret = session->save_state (name)) != 0) {
1870 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1875 ARDOUR_UI::restore_state (string name)
1878 if (name.length() == 0) {
1879 name = session->name();
1881 session->restore_state (name);
1886 ARDOUR_UI::primary_clock_value_changed ()
1889 session->request_locate (primary_clock.current_time ());
1894 ARDOUR_UI::big_clock_value_changed ()
1897 session->request_locate (big_clock.current_time ());
1902 ARDOUR_UI::secondary_clock_value_changed ()
1905 session->request_locate (secondary_clock.current_time ());
1910 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1912 if (session && dstream && dstream->record_enabled()) {
1914 Session::RecordState rs;
1916 rs = session->record_status ();
1919 case Session::Disabled:
1920 case Session::Enabled:
1921 if (w->get_state() != STATE_SELECTED) {
1922 w->set_state (STATE_SELECTED);
1926 case Session::Recording:
1927 if (w->get_state() != STATE_ACTIVE) {
1928 w->set_state (STATE_ACTIVE);
1934 if (w->get_state() != STATE_NORMAL) {
1935 w->set_state (STATE_NORMAL);
1941 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1947 switch (session->record_status()) {
1948 case Session::Enabled:
1950 rec_button.set_visual_state (2);
1952 rec_button.set_visual_state (0);
1956 case Session::Recording:
1957 rec_button.set_visual_state (1);
1961 rec_button.set_visual_state (0);
1967 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1975 ARDOUR_UI::save_template ()
1978 ArdourPrompter prompter (true);
1981 if (!check_audioengine()) {
1985 prompter.set_name (X_("Prompter"));
1986 prompter.set_prompt (_("Name for mix template:"));
1987 prompter.set_initial_text(session->name() + _("-template"));
1988 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1990 switch (prompter.run()) {
1991 case RESPONSE_ACCEPT:
1992 prompter.get_result (name);
1994 if (name.length()) {
1995 session->save_template (name);
2005 ARDOUR_UI::fontconfig_dialog ()
2008 /* X11 users will always have fontconfig info around, but new GTK-OSX users
2009 may not and it can take a while to build it. Warn them.
2012 Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2014 if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2015 MessageDialog msg (*new_session_dialog,
2016 _("Welcome to Ardour.\n\n"
2017 "The program will take a bit longer to start up\n"
2018 "while the system fonts are checked.\n\n"
2019 "This will only be done once, and you will\n"
2020 "not see this message again\n"),
2032 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
2034 bool existing_session = false;
2035 Glib::ustring session_name;
2036 Glib::ustring session_path;
2037 Glib::ustring template_name;
2039 if (!loading_dialog) {
2040 loading_dialog = new MessageDialog (*new_session_dialog,
2048 int response = Gtk::RESPONSE_NONE;
2050 if (predetermined_path.length()) {
2052 /* before we start, lets see if the given path looks like
2053 an existing ardour session. if it does, skip the
2054 tabs that we don't need
2057 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2058 session_path = predetermined_path;
2059 existing_session = true;
2060 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_REGULAR)) {
2061 session_path = Glib::path_get_dirname (string (predetermined_path));
2062 existing_session = true;
2064 /* it doesn't exist, assume the best */
2065 session_path = Glib::path_get_dirname (string (predetermined_path));
2068 session_name = basename_nosuffix (string (predetermined_path));
2070 new_session_dialog->set_session_name (session_name);
2071 new_session_dialog->set_session_folder (session_path);
2072 new_session_dialog->set_modal (true);
2074 if (existing_session) {
2076 if (session_name.length() == 0 || session_path.length() == 0) {
2077 error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
2081 if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
2082 Glib::ustring predicted_session_file;
2084 predicted_session_file = predetermined_path;
2085 predicted_session_file += '/';
2086 predicted_session_file += session_name;
2087 predicted_session_file += Session::statefile_suffix();
2089 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2090 existing_session = true;
2093 } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
2095 if (predetermined_path.find (Session::statefile_suffix()) == predetermined_path.length() - 7) {
2096 /* existing .ardour file */
2097 existing_session = true;
2100 existing_session = false;
2103 if (existing_session && have_engine) {
2104 /* lets just try to load it */
2106 loading_dialog->set_message (_("Starting audio engine"));
2107 loading_dialog->show_all ();
2110 if (create_engine ()) {
2111 backend_audio_error (!have_engine, new_session_dialog);
2112 loading_dialog->hide ();
2116 if (load_session (session_path, session_name) == 0) {
2123 /* loading failed, or we need the NSD for something */
2125 new_session_dialog->set_position (WIN_POS_CENTER);
2126 new_session_dialog->set_current_page (0);
2127 new_session_dialog->set_existing_session (existing_session);
2128 new_session_dialog->reset_recent();
2131 new_session_dialog->set_have_engine (have_engine);
2132 new_session_dialog->present ();
2133 response = new_session_dialog->run ();
2134 loading_dialog->hide ();
2136 _session_is_new = false;
2138 /* handle possible negative responses */
2140 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
2145 new_session_dialog->hide ();
2148 } else if (response == Gtk::RESPONSE_NONE) {
2149 /* "Clear" was pressed */
2154 fontconfig_dialog();
2156 /* if we're here to help set up audio parameters this is where want to do that.
2160 if (new_session_dialog->engine_control.setup_engine ()) {
2161 new_session_dialog->hide ();
2165 loading_dialog->set_message (_("Starting audio engine"));
2166 loading_dialog->show_all ();
2170 if (create_engine ()) {
2171 backend_audio_error (!have_engine, new_session_dialog);
2172 loading_dialog->hide ();
2174 /* audio setup page */
2175 new_session_dialog->set_existing_session (false);
2176 new_session_dialog->set_current_page (2);
2177 response = Gtk::RESPONSE_NONE;
2181 loading_dialog->hide ();
2184 /* now handle possible affirmative responses */
2186 if (response == Gtk::RESPONSE_YES) {
2188 /* YES == OPEN from the session selector */
2190 session_name = new_session_dialog->session_name();
2192 if (session_name.empty()) {
2193 response = Gtk::RESPONSE_NONE;
2197 if (session_name[0] == '/' ||
2198 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2199 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2200 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2201 response = Gtk::RESPONSE_NONE;
2205 session_path = new_session_dialog->session_folder();
2206 if (load_session (session_path, session_name)) {
2207 response = Gtk::RESPONSE_NONE;
2212 } else if (response == Gtk::RESPONSE_OK) {
2214 /* OK == OPEN button */
2216 session_name = new_session_dialog->session_name();
2218 if (session_name.empty()) {
2219 response = Gtk::RESPONSE_NONE;
2223 switch (new_session_dialog->which_page()) {
2224 case NewSessionDialog::OpenPage:
2225 case NewSessionDialog::EnginePage:
2227 if (session_name[0] == '/' ||
2228 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2229 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2230 if (load_session (Glib::path_get_dirname (session_name), session_name)) {
2231 response = Gtk::RESPONSE_NONE;
2236 session_path = new_session_dialog->session_folder();
2237 if (load_session (session_path, session_name)) {
2238 response = Gtk::RESPONSE_NONE;
2244 case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
2246 cerr << "on page zero\n";
2248 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2249 should_be_new = true;
2252 /* handle what appear to be paths rather than just a name */
2254 if (session_name[0] == '/' ||
2255 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2256 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2258 session_path = Glib::path_get_dirname (session_name);
2259 session_name = Glib::path_get_basename (session_name);
2263 session_path = new_session_dialog->session_folder();
2267 //XXX This is needed because session constructor wants a
2268 //non-existant path. hopefully this will be fixed at some point.
2270 session_path = Glib::build_filename (session_path, session_name);
2272 if (!should_be_new) {
2274 if (load_session (session_path, session_name)) {
2275 response = Gtk::RESPONSE_NONE;
2279 continue; /* leaves while() loop because response != NONE */
2281 } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2283 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2285 MessageDialog msg (str,
2287 Gtk::MESSAGE_WARNING,
2288 Gtk::BUTTONS_YES_NO,
2292 msg.set_name (X_("CleanupDialog"));
2293 msg.set_wmclass (X_("existing_session"), "Ardour");
2294 msg.set_position (Gtk::WIN_POS_MOUSE);
2296 switch (msg.run()) {
2298 new_session_dialog->hide ();
2299 goto_editor_window ();
2301 if (load_session (session_path, session_name)) {
2302 response = Gtk::RESPONSE_NONE;
2308 response = RESPONSE_NONE;
2309 new_session_dialog->reset ();
2310 new_session_dialog->set_existing_session (false);
2311 loading_dialog->hide ();
2316 _session_is_new = true;
2318 if (new_session_dialog->use_session_template()) {
2320 template_name = new_session_dialog->session_template_name();
2322 new_session_dialog->hide ();
2323 goto_editor_window ();
2326 if (load_session (session_path, session_name, template_name)) {
2327 response = Gtk::RESPONSE_NONE;
2336 AutoConnectOption iconnect;
2337 AutoConnectOption oconnect;
2341 if (Profile->get_sae()) {
2345 iconnect = AutoConnectPhysical;
2346 oconnect = AutoConnectMaster;
2347 nphysin = 0; // use all available
2348 nphysout = 0; // use all available
2352 /* get settings from advanced section of NSD */
2354 if (new_session_dialog->create_control_bus()) {
2355 cchns = (uint32_t) new_session_dialog->control_channel_count();
2360 if (new_session_dialog->create_master_bus()) {
2361 mchns = (uint32_t) new_session_dialog->master_channel_count();
2366 if (new_session_dialog->connect_inputs()) {
2367 iconnect = AutoConnectPhysical;
2369 iconnect = AutoConnectOption (0);
2372 /// @todo some minor tweaks.
2374 if (new_session_dialog->connect_outs_to_master()) {
2375 oconnect = AutoConnectMaster;
2376 } else if (new_session_dialog->connect_outs_to_physical()) {
2377 oconnect = AutoConnectPhysical;
2379 oconnect = AutoConnectOption (0);
2382 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2383 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2386 if (build_session (session_path,
2394 engine->frame_rate() * 60 * 5)) {
2396 response = Gtk::RESPONSE_NONE;
2400 new_session_dialog->hide ();
2401 goto_editor_window ();
2412 if (response == Gtk::RESPONSE_NONE) {
2413 loading_dialog->hide ();
2414 new_session_dialog->set_existing_session (false);
2415 new_session_dialog->reset ();
2418 } while (response == Gtk::RESPONSE_NONE);
2422 loading_dialog->hide ();
2423 new_session_dialog->hide();
2428 ARDOUR_UI::close_session ()
2430 if (!check_audioengine()) {
2434 unload_session (true);
2436 get_session_parameters ("", true, false);
2440 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2442 Session *new_session;
2446 session_loaded = false;
2448 if (!check_audioengine()) {
2452 unload_status = unload_session ();
2454 if (unload_status < 0) {
2456 } else if (unload_status > 0) {
2461 /* if it already exists, we must have write access */
2463 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS) && ::access (path.c_str(), W_OK)) {
2464 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2465 "This prevents the session from being loaded."));
2470 if (loading_dialog) {
2471 loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
2475 disable_screen_updates ();
2478 new_session = new Session (*engine, path, snap_name, mix_template);
2481 /* this one is special */
2483 catch (AudioEngine::PortRegistrationFailure& err) {
2485 MessageDialog msg (err.what(),
2488 Gtk::BUTTONS_OK_CANCEL);
2490 msg.set_title (_("Loading Error"));
2491 msg.set_secondary_text (_("Click the OK button to try again."));
2492 msg.set_position (Gtk::WIN_POS_CENTER);
2495 int response = msg.run ();
2500 case RESPONSE_CANCEL:
2510 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2513 Gtk::BUTTONS_OK_CANCEL);
2515 msg.set_title (_("Loading Error"));
2516 msg.set_secondary_text (_("Click the OK button to try again."));
2517 msg.set_position (Gtk::WIN_POS_CENTER);
2520 int response = msg.run ();
2525 case RESPONSE_CANCEL:
2533 connect_to_session (new_session);
2535 Config->set_current_owner (ConfigVariableBase::Interface);
2537 session_loaded = true;
2539 goto_editor_window ();
2542 session->set_clean ();
2545 enable_screen_updates ();
2554 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2555 uint32_t control_channels,
2556 uint32_t master_channels,
2557 AutoConnectOption input_connect,
2558 AutoConnectOption output_connect,
2561 nframes_t initial_length)
2563 Session *new_session;
2566 if (!check_audioengine()) {
2570 session_loaded = false;
2572 x = unload_session ();
2580 _session_is_new = true;
2583 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2584 control_channels, master_channels, nphysin, nphysout, initial_length);
2589 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2594 connect_to_session (new_session);
2596 session_loaded = true;
2604 editor->show_window ();
2615 ARDOUR_UI::show_splash ()
2618 about = new About();
2619 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2626 ARDOUR_UI::about_signal_response(int response)
2632 ARDOUR_UI::hide_splash ()
2635 about->get_window()->set_cursor ();
2641 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2645 removed = rep.paths.size();
2648 MessageDialog msgd (*editor,
2649 _("No audio files were ready for cleanup"),
2652 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2653 msgd.set_secondary_text (_("If this seems suprising, \n\
2654 check for any existing snapshots.\n\
2655 These may still include regions that\n\
2656 require some unused files to continue to exist."));
2662 ArdourDialog results (_("ardour: cleanup"), true, false);
2664 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2665 CleanupResultsModelColumns() {
2669 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2670 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2674 CleanupResultsModelColumns results_columns;
2675 Glib::RefPtr<Gtk::ListStore> results_model;
2676 Gtk::TreeView results_display;
2678 results_model = ListStore::create (results_columns);
2679 results_display.set_model (results_model);
2680 results_display.append_column (list_title, results_columns.visible_name);
2682 results_display.set_name ("CleanupResultsList");
2683 results_display.set_headers_visible (true);
2684 results_display.set_headers_clickable (false);
2685 results_display.set_reorderable (false);
2687 Gtk::ScrolledWindow list_scroller;
2690 Gtk::HBox dhbox; // the hbox for the image and text
2691 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2692 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2694 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2696 if (rep.space < 1048576.0f) {
2698 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2700 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2704 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2706 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2710 dhbox.pack_start (*dimage, true, false, 5);
2711 dhbox.pack_start (txt, true, false, 5);
2713 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2714 TreeModel::Row row = *(results_model->append());
2715 row[results_columns.visible_name] = *i;
2716 row[results_columns.fullpath] = *i;
2719 list_scroller.add (results_display);
2720 list_scroller.set_size_request (-1, 150);
2721 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2723 dvbox.pack_start (dhbox, true, false, 5);
2724 dvbox.pack_start (list_scroller, true, false, 5);
2725 ddhbox.pack_start (dvbox, true, false, 5);
2727 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2728 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2729 results.set_default_response (RESPONSE_CLOSE);
2730 results.set_position (Gtk::WIN_POS_MOUSE);
2731 results.show_all_children ();
2732 results.set_resizable (false);
2739 ARDOUR_UI::cleanup ()
2742 /* shouldn't happen: menu item is insensitive */
2747 MessageDialog checker (_("Are you sure you want to cleanup?"),
2749 Gtk::MESSAGE_QUESTION,
2750 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2752 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2753 ALL undo/redo information will be lost if you cleanup.\n\
2754 After cleanup, unused audio files will be moved to a \
2755 \"dead sounds\" location."));
2757 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2758 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2759 checker.set_default_response (RESPONSE_CANCEL);
2761 checker.set_name (_("CleanupDialog"));
2762 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2763 checker.set_position (Gtk::WIN_POS_MOUSE);
2765 switch (checker.run()) {
2766 case RESPONSE_ACCEPT:
2772 Session::cleanup_report rep;
2774 editor->prepare_for_cleanup ();
2776 /* do not allow flush until a session is reloaded */
2778 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2780 act->set_sensitive (false);
2783 if (session->cleanup_sources (rep)) {
2788 display_cleanup_results (rep,
2791 The following %1 %2 not in use and \n\
2792 have been moved to:\n\
2794 Flushing the wastebasket will \n\
2795 release an additional\n\
2796 %4 %5bytes of disk space.\n"
2804 ARDOUR_UI::flush_trash ()
2807 /* shouldn't happen: menu item is insensitive */
2811 Session::cleanup_report rep;
2813 if (session->cleanup_trash_sources (rep)) {
2817 display_cleanup_results (rep,
2819 _("The following %1 %2 deleted from\n\
2821 releasing %4 %5bytes of disk space"));
2825 ARDOUR_UI::add_route (Gtk::Window* float_window)
2833 if (add_route_dialog == 0) {
2834 add_route_dialog = new AddRouteDialog;
2836 add_route_dialog->set_transient_for (*float_window);
2840 if (add_route_dialog->is_visible()) {
2841 /* we're already doing this */
2845 ResponseType r = (ResponseType) add_route_dialog->run ();
2847 add_route_dialog->hide();
2850 case RESPONSE_ACCEPT:
2857 if ((count = add_route_dialog->count()) <= 0) {
2861 uint32_t input_chan = add_route_dialog->channels ();
2862 uint32_t output_chan;
2863 string name_template = add_route_dialog->name_template ();
2864 bool track = add_route_dialog->track ();
2866 AutoConnectOption oac = Config->get_output_auto_connect();
2868 if (oac & AutoConnectMaster) {
2869 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2871 output_chan = input_chan;
2874 /* XXX do something with name template */
2877 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2879 session_add_audio_bus (input_chan, output_chan, count);
2884 ARDOUR_UI::mixer_settings () const
2889 node = session->instant_xml(X_("Mixer"), session->path());
2891 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2895 node = new XMLNode (X_("Mixer"));
2902 ARDOUR_UI::editor_settings () const
2907 node = session->instant_xml(X_("Editor"), session->path());
2909 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2913 node = new XMLNode (X_("Editor"));
2919 ARDOUR_UI::keyboard_settings () const
2923 node = Config->extra_xml(X_("Keyboard"));
2926 node = new XMLNode (X_("Keyboard"));
2932 ARDOUR_UI::halt_on_xrun_message ()
2934 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2936 MessageDialog msg (*editor,
2937 _("Recording was stopped because your system could not keep up."));
2942 ARDOUR_UI::disk_overrun_handler ()
2944 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2946 if (!have_disk_speed_dialog_displayed) {
2947 have_disk_speed_dialog_displayed = true;
2948 MessageDialog* msg = new MessageDialog (*editor, _("\
2949 The disk system on your computer\n\
2950 was not able to keep up with Ardour.\n\
2952 Specifically, it failed to write data to disk\n\
2953 quickly enough to keep up with recording.\n"));
2954 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2960 ARDOUR_UI::disk_underrun_handler ()
2962 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2964 if (!have_disk_speed_dialog_displayed) {
2965 have_disk_speed_dialog_displayed = true;
2966 MessageDialog* msg = new MessageDialog (*editor,
2967 _("The disk system on your computer\n\
2968 was not able to keep up with Ardour.\n\
2970 Specifically, it failed to read data from disk\n\
2971 quickly enough to keep up with playback.\n"));
2972 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2978 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2980 have_disk_speed_dialog_displayed = false;
2985 ARDOUR_UI::pending_state_dialog ()
2987 HBox* hbox = new HBox();
2988 Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
2989 ArdourDialog dialog (_("Crash Recovery"), true);
2991 This session appears to have been in\n\
2992 middle of recording when ardour or\n\
2993 the computer was shutdown.\n\
2995 Ardour can recover any captured audio for\n\
2996 you, or it can ignore it. Please decide\n\
2997 what you would like to do.\n"));
2998 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2999 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3000 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3001 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3002 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3003 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3004 dialog.set_default_response (RESPONSE_ACCEPT);
3005 dialog.set_position (WIN_POS_CENTER);
3010 switch (dialog.run ()) {
3011 case RESPONSE_ACCEPT:
3019 ARDOUR_UI::disconnect_from_jack ()
3022 if( engine->disconnect_from_jack ()) {
3023 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3027 update_sample_rate (0);
3032 ARDOUR_UI::reconnect_to_jack ()
3035 if (engine->reconnect_to_jack ()) {
3036 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
3040 update_sample_rate (0);
3045 ARDOUR_UI::cmdline_new_session (string path)
3047 if (path[0] != '/') {
3048 char buf[PATH_MAX+1];
3051 getcwd (buf, sizeof (buf));
3058 get_session_parameters (path, false, true);
3060 _will_create_new_session_automatically = false; /* done it */
3061 return FALSE; /* don't call it again */
3065 ARDOUR_UI::use_config ()
3067 Glib::RefPtr<Action> act;
3069 switch (Config->get_native_file_data_format ()) {
3071 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
3074 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
3077 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
3082 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3083 ract->set_active ();
3086 switch (Config->get_native_file_header_format ()) {
3088 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
3091 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
3094 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
3097 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
3100 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
3103 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
3106 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
3111 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
3112 ract->set_active ();
3115 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3117 set_transport_controllable_state (*node);
3122 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3124 if (Config->get_primary_clock_delta_edit_cursor()) {
3125 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3127 primary_clock.set (pos, 0, true);
3130 if (Config->get_secondary_clock_delta_edit_cursor()) {
3131 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3133 secondary_clock.set (pos);
3136 if (big_clock_window) {
3137 big_clock.set (pos);
3142 ARDOUR_UI::record_state_changed ()
3144 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3146 if (!session || !big_clock_window) {
3147 /* why bother - the clock isn't visible */
3151 switch (session->record_status()) {
3152 case Session::Recording:
3153 big_clock.set_widget_name ("BigClockRecording");
3156 big_clock.set_widget_name ("BigClockNonRecording");
3162 ARDOUR_UI::set_keybindings_path (string path)
3164 keybindings_path = path;
3168 ARDOUR_UI::save_keybindings ()
3170 if (can_save_keybindings) {
3171 AccelMap::save (user_keybindings_path);
3176 ARDOUR_UI::first_idle ()
3179 session->allow_auto_play (true);
3181 can_save_keybindings = true;
3186 ARDOUR_UI::store_clock_modes ()
3188 XMLNode* node = new XMLNode(X_("ClockModes"));
3190 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3191 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3194 session->add_extra_xml (*node);
3195 session->set_dirty ();
3200 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3201 : Controllable (name), ui (u), type(tp)
3207 ARDOUR_UI::TransportControllable::set_value (float val)
3209 if (type == ShuttleControl) {
3216 fract = -((0.5f - val)/0.5f);
3218 fract = ((val - 0.5f)/0.5f);
3222 ui.set_shuttle_fract (fract);
3227 /* do nothing: these are radio-style actions */
3235 action = X_("Roll");
3238 action = X_("Stop");
3241 action = X_("Goto Start");
3244 action = X_("Goto End");
3247 action = X_("Loop");
3250 action = X_("Play Selection");
3253 action = X_("Record");
3263 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3271 ARDOUR_UI::TransportControllable::get_value (void) const
3290 case ShuttleControl:
3300 ARDOUR_UI::TransportControllable::set_id (const string& str)
3306 ARDOUR_UI::setup_profile ()
3308 if (gdk_screen_width() < 1200) {
3309 Profile->set_small_screen ();
3312 if (getenv ("ARDOUR_SAE")) {
3313 Profile->set_sae ();
3314 Profile->set_single_package ();