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/compose.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <pbd/enumwriter.h>
40 #include <pbd/stacktrace.h>
41 #include <gtkmm2ext/gtk_ui.h>
42 #include <gtkmm2ext/utils.h>
43 #include <gtkmm2ext/click_box.h>
44 #include <gtkmm2ext/fastmeter.h>
45 #include <gtkmm2ext/stop_signal.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/window_title.h>
49 #include <midi++/port.h>
50 #include <midi++/mmc.h>
52 #include <ardour/ardour.h>
53 #include <ardour/profile.h>
54 #include <ardour/session_route.h>
55 #include <ardour/port.h>
56 #include <ardour/audioengine.h>
57 #include <ardour/playlist.h>
58 #include <ardour/utils.h>
59 #include <ardour/audio_diskstream.h>
60 #include <ardour/audiofilesource.h>
61 #include <ardour/recent_sessions.h>
62 #include <ardour/port.h>
63 #include <ardour/audio_track.h>
66 #include "ardour_ui.h"
67 #include "public_editor.h"
68 #include "audio_clock.h"
73 #include "add_route_dialog.h"
74 #include "new_session_dialog.h"
77 #include "gui_thread.h"
78 #include "theme_manager.h"
79 #include "engine_dialog.h"
83 using namespace ARDOUR;
85 using namespace Gtkmm2ext;
89 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
90 UIConfiguration *ARDOUR_UI::ui_config = 0;
92 sigc::signal<void,bool> ARDOUR_UI::Blink;
93 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
94 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
95 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
97 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
99 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
101 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
102 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
103 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
104 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
108 adjuster_table (3, 3),
112 preroll_button (_("pre\nroll")),
113 postroll_button (_("post\nroll")),
117 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
121 roll_controllable ("transport roll", *this, TransportControllable::Roll),
122 stop_controllable ("transport stop", *this, TransportControllable::Stop),
123 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
124 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
125 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
126 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
127 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
128 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
129 shuttle_controller_binding_proxy (shuttle_controllable),
131 roll_button (roll_controllable),
132 stop_button (stop_controllable),
133 goto_start_button (goto_start_controllable),
134 goto_end_button (goto_end_controllable),
135 auto_loop_button (auto_loop_controllable),
136 play_selection_button (play_selection_controllable),
137 rec_button (rec_controllable),
139 shuttle_units_button (_("% ")),
141 punch_in_button (_("Punch In")),
142 punch_out_button (_("Punch Out")),
143 auto_return_button (_("Auto Return")),
144 auto_play_button (_("Auto Play")),
145 auto_input_button (_("Auto Input")),
146 click_button (_("Click")),
147 time_master_button (_("time\nmaster")),
149 auditioning_alert_button (_("AUDITION")),
150 solo_alert_button (_("SOLO")),
153 using namespace Gtk::Menu_Helpers;
159 if (theArdourUI == 0) {
163 ui_config = new UIConfiguration();
164 theme_manager = new ThemeManager();
170 _session_is_new = false;
171 big_clock_window = 0;
172 session_selector_window = 0;
173 new_session_dialog = 0;
174 last_key_press_time = 0;
175 connection_editor = 0;
176 add_route_dialog = 0;
180 open_session_selector = 0;
181 have_configure_timeout = false;
182 have_disk_speed_dialog_displayed = false;
183 _will_create_new_session_automatically = false;
184 session_loaded = false;
185 last_speed_displayed = -1.0f;
187 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
188 /* all changes go to the user directory */
189 user_keybindings_path = get_user_ardour_path ();
190 user_keybindings_path += '/';
191 user_keybindings_path += "ardour.bindings";
193 can_save_keybindings = false;
195 last_configure_time.tv_sec = 0;
196 last_configure_time.tv_usec = 0;
198 shuttle_grabbed = false;
200 shuttle_max_speed = 8.0f;
202 shuttle_style_menu = 0;
203 shuttle_unit_menu = 0;
205 gettimeofday (&last_peak_grab, 0);
206 gettimeofday (&last_shuttle_request, 0);
208 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
209 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
211 /* handle pending state with a dialog */
213 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
215 /* lets get this party started */
218 ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
219 setup_gtk_ardour_enums ();
220 Config->set_current_owner (ConfigVariableBase::Interface);
223 } catch (failed_constructor& err) {
224 error << _("could not initialize Ardour.") << endmsg;
229 /* we like keyboards */
231 keyboard = new Keyboard;
233 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
234 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
238 ARDOUR_UI::start_backend_audio ()
240 if (new_session_dialog->engine_control.start_engine ()) {
248 ARDOUR_UI::create_engine ()
250 // this gets called every time by new_session()
257 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
258 } catch (AudioEngine::NoBackendAvailable& err) {
259 backend_audio_error ();
260 error << string_compose (_("Could not connect to JACK server as \"%1\""), ARDOUR_COMMAND_LINE::jack_client_name) << endmsg;
264 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
265 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
266 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
267 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
273 ARDOUR_UI::post_engine ()
275 /* Things to be done once we create the AudioEngine
278 check_memory_locking();
280 ActionManager::init ();
283 if (setup_windows ()) {
284 throw failed_constructor ();
287 /* this is the first point at which all the keybindings are available */
289 if (ARDOUR_COMMAND_LINE::show_key_actions) {
290 vector<string> names;
291 vector<string> paths;
293 vector<AccelKey> bindings;
295 ActionManager::get_all_actions (names, paths, keys, bindings);
297 vector<string>::iterator n;
298 vector<string>::iterator k;
299 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
300 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
306 blink_timeout_tag = -1;
308 /* the global configuration object is now valid */
312 /* this being a GUI and all, we want peakfiles */
314 AudioFileSource::set_build_peakfiles (true);
315 AudioFileSource::set_build_missing_peakfiles (true);
317 /* set default clock modes */
319 primary_clock.set_mode (AudioClock::SMPTE);
320 secondary_clock.set_mode (AudioClock::BBT);
322 /* start the time-of-day-clock */
324 update_wall_clock ();
325 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
327 update_disk_space ();
329 update_sample_rate (engine->frame_rate());
331 /* now start and maybe save state */
333 if (do_engine_start () == 0) {
334 if (session && _session_is_new) {
335 /* we need to retain initial visual
336 settings for a new session
338 session->save_state ("");
343 ARDOUR_UI::~ARDOUR_UI ()
345 save_ardour_state ();
359 if (add_route_dialog) {
360 delete add_route_dialog;
363 if (new_session_dialog) {
364 delete new_session_dialog;
369 ARDOUR_UI::configure_timeout ()
374 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
375 /* no configure events yet */
379 gettimeofday (&now, 0);
380 timersub (&now, &last_configure_time, &diff);
382 /* force a gap of 0.5 seconds since the last configure event
385 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
388 have_configure_timeout = false;
389 save_ardour_state ();
395 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
397 if (have_configure_timeout) {
398 gettimeofday (&last_configure_time, 0);
400 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
401 have_configure_timeout = true;
408 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
410 const XMLProperty* prop;
412 if ((prop = node.property ("roll")) != 0) {
413 roll_controllable.set_id (prop->value());
415 if ((prop = node.property ("stop")) != 0) {
416 stop_controllable.set_id (prop->value());
418 if ((prop = node.property ("goto_start")) != 0) {
419 goto_start_controllable.set_id (prop->value());
421 if ((prop = node.property ("goto_end")) != 0) {
422 goto_end_controllable.set_id (prop->value());
424 if ((prop = node.property ("auto_loop")) != 0) {
425 auto_loop_controllable.set_id (prop->value());
427 if ((prop = node.property ("play_selection")) != 0) {
428 play_selection_controllable.set_id (prop->value());
430 if ((prop = node.property ("rec")) != 0) {
431 rec_controllable.set_id (prop->value());
433 if ((prop = node.property ("shuttle")) != 0) {
434 shuttle_controllable.set_id (prop->value());
439 ARDOUR_UI::get_transport_controllable_state ()
441 XMLNode* node = new XMLNode(X_("TransportControllables"));
444 roll_controllable.id().print (buf, sizeof (buf));
445 node->add_property (X_("roll"), buf);
446 stop_controllable.id().print (buf, sizeof (buf));
447 node->add_property (X_("stop"), buf);
448 goto_start_controllable.id().print (buf, sizeof (buf));
449 node->add_property (X_("goto_start"), buf);
450 goto_end_controllable.id().print (buf, sizeof (buf));
451 node->add_property (X_("goto_end"), buf);
452 auto_loop_controllable.id().print (buf, sizeof (buf));
453 node->add_property (X_("auto_loop"), buf);
454 play_selection_controllable.id().print (buf, sizeof (buf));
455 node->add_property (X_("play_selection"), buf);
456 rec_controllable.id().print (buf, sizeof (buf));
457 node->add_property (X_("rec"), buf);
458 shuttle_controllable.id().print (buf, sizeof (buf));
459 node->add_property (X_("shuttle"), buf);
465 ARDOUR_UI::save_ardour_state ()
467 if (!keyboard || !mixer || !editor) {
471 /* XXX this is all a bit dubious. add_extra_xml() uses
472 a different lifetime model from add_instant_xml().
475 XMLNode* node = new XMLNode (keyboard->get_state());
476 Config->add_extra_xml (*node);
477 Config->add_extra_xml (get_transport_controllable_state());
478 if (new_session_dialog) {
479 if (new_session_dialog->engine_control.was_used()) {
480 Config->add_extra_xml (new_session_dialog->engine_control.get_state());
483 Config->save_state();
485 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
486 XMLNode mnode(mixer->get_state());
489 session->add_instant_xml (enode, session->path());
490 session->add_instant_xml (mnode, session->path());
492 Config->add_instant_xml (enode, get_user_ardour_path());
493 Config->add_instant_xml (mnode, get_user_ardour_path());
500 ARDOUR_UI::autosave_session ()
502 if (!Config->get_periodic_safety_backups())
506 session->maybe_write_autosave();
513 ARDOUR_UI::update_autosave ()
515 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
517 if (session->dirty()) {
518 if (_autosave_connection.connected()) {
519 _autosave_connection.disconnect();
522 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
523 Config->get_periodic_safety_backup_interval() * 1000);
526 if (_autosave_connection.connected()) {
527 _autosave_connection.disconnect();
533 ARDOUR_UI::backend_audio_error ()
535 MessageDialog win (_("Ardour could not connect to JACK."),
538 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
539 win.set_secondary_text(_("There are several possible reasons:\n\
541 1) JACK is not running.\n\
542 2) JACK is running as another user, perhaps root.\n\
543 3) There is already another client called \"ardour\".\n\
545 Please consider the possibilities, and perhaps (re)start JACK."));
547 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
548 win.set_default_response (RESPONSE_CLOSE);
551 win.set_position (Gtk::WIN_POS_CENTER);
553 if (!ARDOUR_COMMAND_LINE::no_splash) {
557 /* we just don't care about the result, but we want to block */
563 ARDOUR_UI::startup ()
568 new_session_dialog = new NewSessionDialog();
570 /* If no session name is given: we're not loading a session yet, nor creating a new one */
572 if (ARDOUR_COMMAND_LINE::session_name.length()) {
574 /* Load session or start the new session dialog */
576 if (Session::find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
577 error << string_compose(_("could not load command line session \"%1\""),
578 ARDOUR_COMMAND_LINE::session_name) << endmsg;
582 if (!ARDOUR_COMMAND_LINE::new_session) {
584 /* Supposed to be loading an existing session, but the session doesn't exist */
587 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
588 "To create it from the command line, start ardour as \"ardour --new %1"), path)
594 new_session_dialog->set_session_name (name);
595 new_session_dialog->set_session_folder (Glib::path_get_basename (path));
596 _session_is_new = isnew;
601 bool have_backend = EngineControl::engine_running();
603 bool load_needed = false;
607 /* backend audio is working */
609 if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
610 /* need NSD to get session name and other info */
618 XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
621 new_session_dialog->engine_control.set_state (*audio_setup);
624 /* no backend audio, must bring up NSD to check configuration */
631 if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
643 if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
652 ARDOUR_UI::no_memory_warning ()
654 XMLNode node (X_("no-memory-warning"));
655 Config->add_instant_xml (node, get_user_ardour_path());
659 ARDOUR_UI::check_memory_locking ()
662 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
666 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
668 if (engine->is_realtime() && memory_warning_node == 0) {
670 struct rlimit limits;
672 long pages, page_size;
674 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
677 ram = (int64_t) pages * (int64_t) page_size;
680 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
684 if (limits.rlim_cur != RLIM_INFINITY) {
686 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
689 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
690 "This might cause Ardour to run out of memory before your system "
691 "runs out of memory. \n\n"
692 "You can view the memory limit with 'ulimit -l', "
693 "and it is normally controlled by /etc/security/limits.conf"));
695 VBox* vbox = msg.get_vbox();
697 CheckButton cb (_("Do not show this window again"));
699 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
701 hbox.pack_start (cb, true, false);
702 vbox->pack_start (hbox);
716 if (session && session->dirty()) {
717 switch (ask_about_saving_session(_("quit"))) {
722 /* use the default name */
723 if (save_state_canfail ("")) {
724 /* failed - don't quit */
725 MessageDialog msg (*editor,
727 Ardour was unable to save your session.\n\n\
728 If you still wish to quit, please use the\n\n\
729 \"Just quit\" option."));
740 session->set_deletion_in_progress ();
743 save_ardour_state ();
748 ARDOUR_UI::ask_about_saving_session (const string & what)
750 ArdourDialog window (_("ardour: save session?"));
751 Gtk::HBox dhbox; // the hbox for the image and text
752 Gtk::Label prompt_label;
753 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
757 msg = string_compose(_("Don't %1"), what);
758 window.add_button (msg, RESPONSE_REJECT);
759 msg = string_compose(_("Just %1"), what);
760 window.add_button (msg, RESPONSE_APPLY);
761 msg = string_compose(_("Save and %1"), what);
762 window.add_button (msg, RESPONSE_ACCEPT);
764 window.set_default_response (RESPONSE_ACCEPT);
766 Gtk::Button noquit_button (msg);
767 noquit_button.set_name ("EditorGTKButton");
772 if (session->snap_name() == session->name()) {
775 type = _("snapshot");
777 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?"),
778 type, session->snap_name());
780 prompt_label.set_text (prompt);
781 prompt_label.set_name (X_("PrompterLabel"));
782 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
784 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
786 dhbox.set_homogeneous (false);
787 dhbox.pack_start (*dimage, false, false, 5);
788 dhbox.pack_start (prompt_label, true, false, 5);
789 window.get_vbox()->pack_start (dhbox);
791 window.set_name (_("Prompter"));
792 window.set_position (Gtk::WIN_POS_MOUSE);
793 window.set_modal (true);
794 window.set_resizable (false);
797 save_the_session = 0;
799 window.set_keep_above (true);
802 ResponseType r = (ResponseType) window.run();
807 case RESPONSE_ACCEPT: // save and get out of here
809 case RESPONSE_APPLY: // get out of here
819 ARDOUR_UI::every_second ()
822 update_buffer_load ();
823 update_disk_space ();
828 ARDOUR_UI::every_point_one_seconds ()
830 update_speed_display ();
831 RapidScreenUpdate(); /* EMIT_SIGNAL */
836 ARDOUR_UI::every_point_zero_one_seconds ()
838 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
843 ARDOUR_UI::update_sample_rate (nframes_t ignored)
847 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
849 if (!engine->connected()) {
851 snprintf (buf, sizeof (buf), _("disconnected"));
855 nframes_t rate = engine->frame_rate();
857 if (fmod (rate, 1000.0) != 0.0) {
858 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
859 (float) rate/1000.0f,
860 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
862 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
864 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
868 sample_rate_label.set_text (buf);
872 ARDOUR_UI::update_cpu_load ()
875 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
876 cpu_load_label.set_text (buf);
880 ARDOUR_UI::update_buffer_load ()
885 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
886 session->playback_load(), session->capture_load());
887 buffer_load_label.set_text (buf);
889 buffer_load_label.set_text ("");
894 ARDOUR_UI::count_recenabled_streams (Route& route)
896 Track* track = dynamic_cast<Track*>(&route);
897 if (track && track->diskstream()->record_enabled()) {
898 rec_enabled_streams += track->n_inputs();
903 ARDOUR_UI::update_disk_space()
909 nframes_t frames = session->available_capture_duration();
912 if (frames == max_frames) {
913 strcpy (buf, _("Disk: 24hrs+"));
918 nframes_t fr = session->frame_rate();
920 rec_enabled_streams = 0;
921 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
923 if (rec_enabled_streams) {
924 frames /= rec_enabled_streams;
927 hrs = frames / (fr * 3600);
928 frames -= hrs * fr * 3600;
929 mins = frames / (fr * 60);
930 frames -= mins * fr * 60;
933 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
936 disk_space_label.set_text (buf);
940 ARDOUR_UI::update_wall_clock ()
947 tm_now = localtime (&now);
949 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
950 wall_clock_label.set_text (buf);
956 ARDOUR_UI::session_menu (GdkEventButton *ev)
958 session_popup_menu->popup (0, 0);
963 ARDOUR_UI::redisplay_recent_sessions ()
965 vector<string *> *sessions;
966 vector<string *>::iterator i;
967 RecentSessionsSorter cmp;
969 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
970 recent_session_model->clear ();
973 ARDOUR::read_recent_sessions (rs);
976 recent_session_display.set_model (recent_session_model);
980 /* sort them alphabetically */
981 sort (rs.begin(), rs.end(), cmp);
982 sessions = new vector<string*>;
984 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
985 sessions->push_back (new string ((*i).second));
988 for (i = sessions->begin(); i != sessions->end(); ++i) {
990 vector<string*>* states;
991 vector<const gchar*> item;
992 string fullpath = *(*i);
994 /* remove any trailing / */
996 if (fullpath[fullpath.length()-1] == '/') {
997 fullpath = fullpath.substr (0, fullpath.length()-1);
1000 /* now get available states for this session */
1002 if ((states = Session::possible_states (fullpath)) == 0) {
1003 /* no state file? */
1007 TreeModel::Row row = *(recent_session_model->append());
1009 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1010 row[recent_session_columns.fullpath] = fullpath;
1012 if (states->size() > 1) {
1014 /* add the children */
1016 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1018 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1020 child_row[recent_session_columns.visible_name] = **i2;
1021 child_row[recent_session_columns.fullpath] = fullpath;
1030 recent_session_display.set_model (recent_session_model);
1035 ARDOUR_UI::build_session_selector ()
1037 session_selector_window = new ArdourDialog ("session selector");
1039 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1041 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1042 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1043 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1044 recent_session_model = TreeStore::create (recent_session_columns);
1045 recent_session_display.set_model (recent_session_model);
1046 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1047 recent_session_display.set_headers_visible (false);
1048 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1050 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1052 scroller->add (recent_session_display);
1053 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1055 session_selector_window->set_name ("SessionSelectorWindow");
1056 session_selector_window->set_size_request (200, 400);
1057 session_selector_window->get_vbox()->pack_start (*scroller);
1058 session_selector_window->show_all_children();
1062 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1064 session_selector_window->response (RESPONSE_ACCEPT);
1068 ARDOUR_UI::open_recent_session ()
1070 /* popup selector window */
1072 if (session_selector_window == 0) {
1073 build_session_selector ();
1076 redisplay_recent_sessions ();
1078 ResponseType r = (ResponseType) session_selector_window->run ();
1080 session_selector_window->hide();
1083 case RESPONSE_ACCEPT:
1089 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1091 if (i == recent_session_model->children().end()) {
1095 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1096 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1098 _session_is_new = false;
1100 load_session (path, state);
1104 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1106 struct stat statbuf;
1108 if (stat (info.filename.c_str(), &statbuf) != 0) {
1112 if (!S_ISDIR(statbuf.st_mode)) {
1118 string session_file = info.filename;
1119 session_file += '/';
1120 session_file += Glib::path_get_basename (info.filename);
1121 session_file += ".ardour";
1123 if (stat (session_file.c_str(), &statbuf) != 0) {
1127 return S_ISREG (statbuf.st_mode);
1131 ARDOUR_UI::check_audioengine ()
1134 if (!engine->connected()) {
1135 MessageDialog msg (_("Ardour is not connected to JACK\n"
1136 "You cannot open or close sessions in this condition"));
1147 ARDOUR_UI::open_session ()
1149 if (!check_audioengine()) {
1153 /* popup selector window */
1155 if (open_session_selector == 0) {
1157 /* ardour sessions are folders */
1159 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1160 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1161 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1163 FileFilter session_filter;
1164 session_filter.add_pattern ("*.ardour");
1165 session_filter.set_name (_("Ardour sessions"));
1166 open_session_selector->add_filter (session_filter);
1167 open_session_selector->set_filter (session_filter);
1170 int response = open_session_selector->run();
1171 open_session_selector->hide ();
1174 case RESPONSE_ACCEPT:
1177 open_session_selector->hide();
1181 open_session_selector->hide();
1182 string session_path = open_session_selector->get_filename();
1186 if (session_path.length() > 0) {
1187 if (Session::find_session (session_path, path, name, isnew) == 0) {
1188 _session_is_new = isnew;
1189 load_session (path, name);
1196 ARDOUR_UI::session_add_midi_track ()
1198 cerr << _("Patience is a virtue.\n");
1202 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1204 list<boost::shared_ptr<AudioTrack> > tracks;
1205 Session::RouteList routes;
1208 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1214 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1216 if (tracks.size() != how_many) {
1217 if (how_many == 1) {
1218 error << _("could not create a new audio track") << endmsg;
1220 error << string_compose (_("could only create %1 of %2 new audio %3"),
1221 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1227 routes = session->new_audio_route (input_channels, output_channels, how_many);
1229 if (routes.size() != how_many) {
1230 if (how_many == 1) {
1231 error << _("could not create a new audio track") << endmsg;
1233 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1239 if (need_control_room_outs) {
1245 route->set_stereo_control_outs (control_lr_channels);
1246 route->control_outs()->set_stereo_pan (pans, this);
1248 #endif /* CONTROLOUTS */
1252 cerr << "About to complain about JACK\n";
1253 MessageDialog msg (*editor,
1254 _("There are insufficient JACK ports available\n\
1255 to create a new track or bus.\n\
1256 You should save Ardour, exit and\n\
1257 restart JACK with more ports."));
1263 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1265 nframes_t _preroll = 0;
1268 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1269 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1271 if (new_position > _preroll) {
1272 new_position -= _preroll;
1277 session->request_locate (new_position);
1282 ARDOUR_UI::transport_goto_start ()
1285 session->goto_start();
1288 /* force displayed area in editor to start no matter
1289 what "follow playhead" setting is.
1293 editor->reset_x_origin (session->current_start_frame());
1299 ARDOUR_UI::transport_goto_zero ()
1302 session->request_locate (0);
1305 /* force displayed area in editor to start no matter
1306 what "follow playhead" setting is.
1310 editor->reset_x_origin (0);
1316 ARDOUR_UI::transport_goto_end ()
1319 nframes_t frame = session->current_end_frame();
1320 session->request_locate (frame);
1322 /* force displayed area in editor to start no matter
1323 what "follow playhead" setting is.
1327 editor->reset_x_origin (frame);
1333 ARDOUR_UI::transport_stop ()
1339 if (session->is_auditioning()) {
1340 session->cancel_audition ();
1344 if (session->get_play_loop ()) {
1345 session->request_play_loop (false);
1348 session->request_stop ();
1352 ARDOUR_UI::transport_stop_and_forget_capture ()
1355 session->request_stop (true);
1360 ARDOUR_UI::remove_last_capture()
1363 editor->remove_last_capture();
1368 ARDOUR_UI::transport_record ()
1371 switch (session->record_status()) {
1372 case Session::Disabled:
1373 if (session->ntracks() == 0) {
1374 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1378 session->maybe_enable_record ();
1380 case Session::Recording:
1381 case Session::Enabled:
1382 session->disable_record (false, true);
1388 ARDOUR_UI::transport_roll ()
1396 rolling = session->transport_rolling ();
1398 if (session->get_play_loop()) {
1399 session->request_play_loop (false);
1400 auto_loop_button.set_visual_state (1);
1401 roll_button.set_visual_state (1);
1402 } else if (session->get_play_range ()) {
1403 session->request_play_range (false);
1404 play_selection_button.set_visual_state (0);
1405 } else if (rolling) {
1406 session->request_locate (session->last_transport_start(), true);
1409 session->request_transport_speed (1.0f);
1413 ARDOUR_UI::transport_loop()
1416 if (session->get_play_loop()) {
1417 if (session->transport_rolling()) {
1418 Location * looploc = session->locations()->auto_loop_location();
1420 session->request_locate (looploc->start(), true);
1425 session->request_play_loop (true);
1431 ARDOUR_UI::transport_play_selection ()
1437 if (!session->get_play_range()) {
1438 session->request_stop ();
1441 editor->play_selection ();
1445 ARDOUR_UI::transport_rewind (int option)
1447 float current_transport_speed;
1450 current_transport_speed = session->transport_speed();
1452 if (current_transport_speed >= 0.0f) {
1455 session->request_transport_speed (-1.0f);
1458 session->request_transport_speed (-4.0f);
1461 session->request_transport_speed (-0.5f);
1466 session->request_transport_speed (current_transport_speed * 1.5f);
1472 ARDOUR_UI::transport_forward (int option)
1474 float current_transport_speed;
1477 current_transport_speed = session->transport_speed();
1479 if (current_transport_speed <= 0.0f) {
1482 session->request_transport_speed (1.0f);
1485 session->request_transport_speed (4.0f);
1488 session->request_transport_speed (0.5f);
1493 session->request_transport_speed (current_transport_speed * 1.5f);
1499 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1505 boost::shared_ptr<Route> r;
1507 if ((r = session->route_by_remote_id (dstream)) != 0) {
1511 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1512 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1521 ARDOUR_UI::queue_transport_change ()
1523 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1527 ARDOUR_UI::map_transport_state ()
1529 float sp = session->transport_speed();
1532 transport_rolling ();
1533 } else if (sp < 0.0f) {
1534 transport_rewinding ();
1535 } else if (sp > 0.0f) {
1536 transport_forwarding ();
1538 transport_stopped ();
1543 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1545 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1546 (int) adj.get_value()].c_str());
1550 ARDOUR_UI::engine_stopped ()
1552 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1553 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1554 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1558 ARDOUR_UI::engine_running ()
1560 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1561 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1562 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1564 Glib::RefPtr<Action> action;
1565 char* action_name = 0;
1567 switch (engine->frames_per_cycle()) {
1569 action_name = X_("JACKLatency32");
1572 action_name = X_("JACKLatency64");
1575 action_name = X_("JACKLatency128");
1578 action_name = X_("JACKLatency512");
1581 action_name = X_("JACKLatency1024");
1584 action_name = X_("JACKLatency2048");
1587 action_name = X_("JACKLatency4096");
1590 action_name = X_("JACKLatency8192");
1593 /* XXX can we do anything useful ? */
1599 action = ActionManager::get_action (X_("JACK"), action_name);
1602 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1603 ract->set_active ();
1609 ARDOUR_UI::engine_halted ()
1611 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1613 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1614 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1616 update_sample_rate (0);
1618 MessageDialog msg (*editor,
1620 JACK has either been shutdown or it\n\
1621 disconnected Ardour because Ardour\n\
1622 was not fast enough. You can save the\n\
1623 session and/or try to reconnect to JACK ."));
1628 ARDOUR_UI::do_engine_start ()
1636 error << _("Unable to start the session running")
1646 ARDOUR_UI::setup_theme ()
1648 theme_manager->setup_theme();
1652 ARDOUR_UI::update_clocks ()
1654 if (!editor || !editor->dragging_playhead()) {
1655 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1660 ARDOUR_UI::start_clocking ()
1662 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1666 ARDOUR_UI::stop_clocking ()
1668 clock_signal_connection.disconnect ();
1672 ARDOUR_UI::toggle_clocking ()
1675 if (clock_button.get_active()) {
1684 ARDOUR_UI::_blink (void *arg)
1687 ((ARDOUR_UI *) arg)->blink ();
1694 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1698 ARDOUR_UI::start_blinking ()
1700 /* Start the blink signal. Everybody with a blinking widget
1701 uses Blink to drive the widget's state.
1704 if (blink_timeout_tag < 0) {
1706 blink_timeout_tag = g_timeout_add (240, _blink, this);
1711 ARDOUR_UI::stop_blinking ()
1713 if (blink_timeout_tag >= 0) {
1714 g_source_remove (blink_timeout_tag);
1715 blink_timeout_tag = -1;
1720 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1726 if (io.n_inputs() == 0) {
1731 /* XXX we're not handling multiple ports yet. */
1733 const char **connections = io.input(0)->get_connections();
1735 if (connections == 0 || connections[0] == '\0') {
1738 buf = connections[0];
1745 if (io.n_outputs() == 0) {
1750 /* XXX we're not handling multiple ports yet. */
1752 const char **connections = io.output(0)->get_connections();
1754 if (connections == 0 || connections[0] == '\0') {
1757 buf = connections[0];
1764 /** Ask the user for the name of a new shapshot and then take it.
1767 ARDOUR_UI::snapshot_session ()
1769 ArdourPrompter prompter (true);
1773 struct tm local_time;
1776 localtime_r (&n, &local_time);
1777 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1779 prompter.set_name ("Prompter");
1780 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1781 prompter.set_prompt (_("Name of New Snapshot"));
1782 prompter.set_initial_text (timebuf);
1784 switch (prompter.run()) {
1785 case RESPONSE_ACCEPT:
1786 prompter.get_result (snapname);
1787 if (snapname.length()){
1788 save_state (snapname);
1798 ARDOUR_UI::save_state (const string & name)
1800 (void) save_state_canfail (name);
1804 ARDOUR_UI::save_state_canfail (string name)
1809 if (name.length() == 0) {
1810 name = session->snap_name();
1813 if ((ret = session->save_state (name)) != 0) {
1817 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1822 ARDOUR_UI::restore_state (string name)
1825 if (name.length() == 0) {
1826 name = session->name();
1828 session->restore_state (name);
1833 ARDOUR_UI::primary_clock_value_changed ()
1836 session->request_locate (primary_clock.current_time ());
1841 ARDOUR_UI::secondary_clock_value_changed ()
1844 session->request_locate (secondary_clock.current_time ());
1849 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1851 if (session && dstream && dstream->record_enabled()) {
1853 Session::RecordState rs;
1855 rs = session->record_status ();
1858 case Session::Disabled:
1859 case Session::Enabled:
1860 if (w->get_state() != STATE_SELECTED) {
1861 w->set_state (STATE_SELECTED);
1865 case Session::Recording:
1866 if (w->get_state() != STATE_ACTIVE) {
1867 w->set_state (STATE_ACTIVE);
1873 if (w->get_state() != STATE_NORMAL) {
1874 w->set_state (STATE_NORMAL);
1880 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1886 switch (session->record_status()) {
1887 case Session::Enabled:
1889 rec_button.set_visual_state (2);
1891 rec_button.set_visual_state (0);
1895 case Session::Recording:
1896 rec_button.set_visual_state (1);
1900 rec_button.set_visual_state (0);
1906 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1914 ARDOUR_UI::save_template ()
1917 ArdourPrompter prompter (true);
1920 if (!check_audioengine()) {
1924 prompter.set_name (X_("Prompter"));
1925 prompter.set_prompt (_("Name for mix template:"));
1926 prompter.set_initial_text(session->name() + _("-template"));
1927 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1929 switch (prompter.run()) {
1930 case RESPONSE_ACCEPT:
1931 prompter.get_result (name);
1933 if (name.length()) {
1934 session->save_template (name);
1944 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
1946 string session_name;
1947 string session_path;
1949 int response = Gtk::RESPONSE_NONE;
1951 new_session_dialog->set_modal(true);
1952 new_session_dialog->set_name (predetermined_path);
1953 new_session_dialog->reset_recent();
1954 new_session_dialog->show();
1955 new_session_dialog->present ();
1956 new_session_dialog->set_current_page (0);
1960 new_session_dialog->set_have_engine (have_engine);
1962 response = new_session_dialog->run ();
1964 _session_is_new = false;
1966 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1971 new_session_dialog->hide ();
1974 } else if (response == Gtk::RESPONSE_NONE) {
1976 /* Clear was pressed */
1977 new_session_dialog->reset();
1981 /* first things first ... we need an audio engine running */
1984 if (start_backend_audio ()) {
1985 new_session_dialog->hide ();
1993 /* now handle possible affirmative responses */
1995 if (response == Gtk::RESPONSE_YES) {
1997 /* YES == OPEN from the session selector */
1999 session_name = new_session_dialog->session_name();
2001 if (session_name.empty()) {
2002 response = Gtk::RESPONSE_NONE;
2006 if (session_name[0] == '/' ||
2007 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2008 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2009 load_session (Glib::path_get_dirname (session_name), session_name);
2011 session_path = new_session_dialog->session_folder();
2012 load_session (session_path, session_name);
2015 } else if (response == Gtk::RESPONSE_OK) {
2017 /* OK == OPEN button */
2019 session_name = new_session_dialog->session_name();
2021 if (new_session_dialog->get_current_page() == 1) {
2023 if (session_name.empty()) {
2024 response = Gtk::RESPONSE_NONE;
2028 if (session_name[0] == '/' ||
2029 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2030 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2031 load_session (Glib::path_get_dirname (session_name), session_name);
2033 session_path = new_session_dialog->session_folder();
2034 load_session (session_path, session_name);
2039 if (session_name.empty()) {
2040 response = Gtk::RESPONSE_NONE;
2044 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2045 should_be_new = true;
2048 /* handle what appear to be paths rather than just a name */
2050 if (session_name[0] == '/' ||
2051 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2052 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2054 session_path = Glib::path_get_dirname (session_name);
2055 session_name = Glib::path_get_basename (session_name);
2059 session_path = new_session_dialog->session_folder();
2063 //XXX This is needed because session constructor wants a
2064 //non-existant path. hopefully this will be fixed at some point.
2066 session_path = Glib::build_filename (session_path, session_name);
2068 if (should_be_new && Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2070 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2072 MessageDialog msg (str,
2074 Gtk::MESSAGE_WARNING,
2075 Gtk::BUTTONS_YES_NO,
2079 msg.set_name (X_("CleanupDialog"));
2080 msg.set_wmclass (X_("existing_session"), "Ardour");
2081 msg.set_position (Gtk::WIN_POS_MOUSE);
2083 switch (msg.run()) {
2085 load_session (session_path, session_name);
2089 response = RESPONSE_NONE;
2090 new_session_dialog->reset ();
2095 _session_is_new = true;
2097 std::string template_name = new_session_dialog->session_template_name();
2099 if (new_session_dialog->use_session_template()) {
2101 load_session (session_path, session_name, &template_name);
2107 AutoConnectOption iconnect;
2108 AutoConnectOption oconnect;
2112 if (Profile->get_sae()) {
2116 iconnect = AutoConnectPhysical;
2117 oconnect = AutoConnectMaster;
2118 nphysin = 0; // use all available
2119 nphysout = 0; // use all available
2123 /* get settings from advanced section of NSD */
2125 if (new_session_dialog->create_control_bus()) {
2126 cchns = (uint32_t) new_session_dialog->control_channel_count();
2131 if (new_session_dialog->create_master_bus()) {
2132 mchns = (uint32_t) new_session_dialog->master_channel_count();
2137 if (new_session_dialog->connect_inputs()) {
2138 iconnect = AutoConnectPhysical;
2140 iconnect = AutoConnectOption (0);
2143 /// @todo some minor tweaks.
2145 if (new_session_dialog->connect_outs_to_master()) {
2146 oconnect = AutoConnectMaster;
2147 } else if (new_session_dialog->connect_outs_to_physical()) {
2148 oconnect = AutoConnectPhysical;
2150 oconnect = AutoConnectOption (0);
2153 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2154 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2157 if (build_session (session_path,
2165 engine->frame_rate() * 60 * 5)) {
2167 response = Gtk::RESPONSE_NONE;
2168 new_session_dialog->reset ();
2175 } while (response == Gtk::RESPONSE_NONE);
2179 new_session_dialog->get_window()->set_cursor();
2180 new_session_dialog->hide();
2185 ARDOUR_UI::close_session()
2187 if (!check_audioengine()) {
2192 get_session_parameters ("", true, false);
2196 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2198 Session *new_session;
2200 session_loaded = false;
2202 if (!check_audioengine()) {
2206 x = unload_session ();
2214 /* if it already exists, we must have write access */
2216 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2217 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2218 "This prevents the session from being loaded."));
2224 new_session = new Session (*engine, path, snap_name, mix_template);
2229 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2233 connect_to_session (new_session);
2235 Config->set_current_owner (ConfigVariableBase::Interface);
2237 session_loaded = true;
2239 goto_editor_window ();
2242 session->set_clean ();
2245 editor->edit_cursor_position (true);
2250 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2251 uint32_t control_channels,
2252 uint32_t master_channels,
2253 AutoConnectOption input_connect,
2254 AutoConnectOption output_connect,
2257 nframes_t initial_length)
2259 Session *new_session;
2262 if (!check_audioengine()) {
2266 session_loaded = false;
2268 x = unload_session ();
2276 _session_is_new = true;
2279 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2280 control_channels, master_channels, nphysin, nphysout, initial_length);
2285 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2290 connect_to_session (new_session);
2292 session_loaded = true;
2300 editor->show_window ();
2311 ARDOUR_UI::show_splash ()
2314 about = new About();
2315 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2322 ARDOUR_UI::about_signal_response(int response)
2328 ARDOUR_UI::hide_splash ()
2331 about->get_window()->set_cursor ();
2337 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2341 removed = rep.paths.size();
2344 MessageDialog msgd (*editor,
2345 _("No audio files were ready for cleanup"),
2348 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2349 msgd.set_secondary_text (_("If this seems suprising, \n\
2350 check for any existing snapshots.\n\
2351 These may still include regions that\n\
2352 require some unused files to continue to exist."));
2358 ArdourDialog results (_("ardour: cleanup"), true, false);
2360 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2361 CleanupResultsModelColumns() {
2365 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2366 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2370 CleanupResultsModelColumns results_columns;
2371 Glib::RefPtr<Gtk::ListStore> results_model;
2372 Gtk::TreeView results_display;
2374 results_model = ListStore::create (results_columns);
2375 results_display.set_model (results_model);
2376 results_display.append_column (list_title, results_columns.visible_name);
2378 results_display.set_name ("CleanupResultsList");
2379 results_display.set_headers_visible (true);
2380 results_display.set_headers_clickable (false);
2381 results_display.set_reorderable (false);
2383 Gtk::ScrolledWindow list_scroller;
2386 Gtk::HBox dhbox; // the hbox for the image and text
2387 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2388 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2390 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2392 if (rep.space < 1048576.0f) {
2394 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2396 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2400 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2402 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2406 dhbox.pack_start (*dimage, true, false, 5);
2407 dhbox.pack_start (txt, true, false, 5);
2409 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2410 TreeModel::Row row = *(results_model->append());
2411 row[results_columns.visible_name] = *i;
2412 row[results_columns.fullpath] = *i;
2415 list_scroller.add (results_display);
2416 list_scroller.set_size_request (-1, 150);
2417 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2419 dvbox.pack_start (dhbox, true, false, 5);
2420 dvbox.pack_start (list_scroller, true, false, 5);
2421 ddhbox.pack_start (dvbox, true, false, 5);
2423 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2424 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2425 results.set_default_response (RESPONSE_CLOSE);
2426 results.set_position (Gtk::WIN_POS_MOUSE);
2427 results.show_all_children ();
2428 results.set_resizable (false);
2435 ARDOUR_UI::cleanup ()
2438 /* shouldn't happen: menu item is insensitive */
2443 MessageDialog checker (_("Are you sure you want to cleanup?"),
2445 Gtk::MESSAGE_QUESTION,
2446 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2448 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2449 ALL undo/redo information will be lost if you cleanup.\n\
2450 After cleanup, unused audio files will be moved to a \
2451 \"dead sounds\" location."));
2453 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2454 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2455 checker.set_default_response (RESPONSE_CANCEL);
2457 checker.set_name (_("CleanupDialog"));
2458 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2459 checker.set_position (Gtk::WIN_POS_MOUSE);
2461 switch (checker.run()) {
2462 case RESPONSE_ACCEPT:
2468 Session::cleanup_report rep;
2470 editor->prepare_for_cleanup ();
2472 /* do not allow flush until a session is reloaded */
2474 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2476 act->set_sensitive (false);
2479 if (session->cleanup_sources (rep)) {
2484 display_cleanup_results (rep,
2487 The following %1 %2 not in use and \n\
2488 have been moved to:\n\
2490 Flushing the wastebasket will \n\
2491 release an additional\n\
2492 %4 %5bytes of disk space.\n"
2500 ARDOUR_UI::flush_trash ()
2503 /* shouldn't happen: menu item is insensitive */
2507 Session::cleanup_report rep;
2509 if (session->cleanup_trash_sources (rep)) {
2513 display_cleanup_results (rep,
2515 _("The following %1 %2 deleted from\n\
2517 releasing %4 %5bytes of disk space"));
2521 ARDOUR_UI::add_route (Gtk::Window* float_window)
2529 if (add_route_dialog == 0) {
2530 add_route_dialog = new AddRouteDialog;
2532 add_route_dialog->set_transient_for (*float_window);
2536 if (add_route_dialog->is_visible()) {
2537 /* we're already doing this */
2541 ResponseType r = (ResponseType) add_route_dialog->run ();
2543 add_route_dialog->hide();
2546 case RESPONSE_ACCEPT:
2553 if ((count = add_route_dialog->count()) <= 0) {
2557 uint32_t input_chan = add_route_dialog->channels ();
2558 uint32_t output_chan;
2559 string name_template = add_route_dialog->name_template ();
2560 bool track = add_route_dialog->track ();
2562 AutoConnectOption oac = Config->get_output_auto_connect();
2564 if (oac & AutoConnectMaster) {
2565 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2567 output_chan = input_chan;
2570 /* XXX do something with name template */
2573 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2575 session_add_audio_bus (input_chan, output_chan, count);
2580 ARDOUR_UI::mixer_settings () const
2585 node = session->instant_xml(X_("Mixer"), session->path());
2587 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2591 node = new XMLNode (X_("Mixer"));
2598 ARDOUR_UI::editor_settings () const
2603 node = session->instant_xml(X_("Editor"), session->path());
2605 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2609 node = new XMLNode (X_("Editor"));
2615 ARDOUR_UI::keyboard_settings () const
2619 node = Config->extra_xml(X_("Keyboard"));
2622 node = new XMLNode (X_("Keyboard"));
2628 ARDOUR_UI::halt_on_xrun_message ()
2630 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2632 MessageDialog msg (*editor,
2633 _("Recording was stopped because your system could not keep up."));
2638 ARDOUR_UI::disk_overrun_handler ()
2640 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2642 if (!have_disk_speed_dialog_displayed) {
2643 have_disk_speed_dialog_displayed = true;
2644 MessageDialog* msg = new MessageDialog (*editor, _("\
2645 The disk system on your computer\n\
2646 was not able to keep up with Ardour.\n\
2648 Specifically, it failed to write data to disk\n\
2649 quickly enough to keep up with recording.\n"));
2650 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2656 ARDOUR_UI::disk_underrun_handler ()
2658 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2660 if (!have_disk_speed_dialog_displayed) {
2661 have_disk_speed_dialog_displayed = true;
2662 MessageDialog* msg = new MessageDialog (*editor,
2663 _("The disk system on your computer\n\
2664 was not able to keep up with Ardour.\n\
2666 Specifically, it failed to read data from disk\n\
2667 quickly enough to keep up with playback.\n"));
2668 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2674 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2676 have_disk_speed_dialog_displayed = false;
2681 ARDOUR_UI::pending_state_dialog ()
2683 ArdourDialog dialog ("pending state dialog");
2685 This session appears to have been in\n\
2686 middle of recording when ardour or\n\
2687 the computer was shutdown.\n\
2689 Ardour can recover any captured audio for\n\
2690 you, or it can ignore it. Please decide\n\
2691 what you would like to do.\n"));
2693 dialog.get_vbox()->pack_start (message);
2694 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2695 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2697 dialog.set_position (WIN_POS_CENTER);
2700 switch (dialog.run ()) {
2701 case RESPONSE_ACCEPT:
2709 ARDOUR_UI::disconnect_from_jack ()
2712 if( engine->disconnect_from_jack ()) {
2713 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2717 update_sample_rate (0);
2722 ARDOUR_UI::reconnect_to_jack ()
2725 if (engine->reconnect_to_jack ()) {
2726 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2730 update_sample_rate (0);
2735 ARDOUR_UI::cmdline_new_session (string path)
2737 if (path[0] != '/') {
2738 char buf[PATH_MAX+1];
2741 getcwd (buf, sizeof (buf));
2748 get_session_parameters (path, false, true);
2750 _will_create_new_session_automatically = false; /* done it */
2751 return FALSE; /* don't call it again */
2755 ARDOUR_UI::use_config ()
2757 Glib::RefPtr<Action> act;
2759 switch (Config->get_native_file_data_format ()) {
2761 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2764 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2767 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2772 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2773 ract->set_active ();
2776 switch (Config->get_native_file_header_format ()) {
2778 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2781 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2784 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2787 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2790 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2793 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2796 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2801 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2802 ract->set_active ();
2805 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2807 set_transport_controllable_state (*node);
2812 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2814 if (Config->get_primary_clock_delta_edit_cursor()) {
2815 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2817 primary_clock.set (pos, 0, true);
2820 if (Config->get_secondary_clock_delta_edit_cursor()) {
2821 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2823 secondary_clock.set (pos);
2826 if (big_clock_window) {
2827 big_clock.set (pos);
2832 ARDOUR_UI::record_state_changed ()
2834 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2836 if (!session || !big_clock_window) {
2837 /* why bother - the clock isn't visible */
2841 switch (session->record_status()) {
2842 case Session::Recording:
2843 big_clock.set_widget_name ("BigClockRecording");
2846 big_clock.set_widget_name ("BigClockNonRecording");
2852 ARDOUR_UI::set_keybindings_path (string path)
2854 keybindings_path = path;
2858 ARDOUR_UI::save_keybindings ()
2860 if (can_save_keybindings) {
2861 AccelMap::save (user_keybindings_path);
2866 ARDOUR_UI::first_idle ()
2869 session->allow_auto_play (true);
2871 can_save_keybindings = true;
2876 ARDOUR_UI::store_clock_modes ()
2878 XMLNode* node = new XMLNode(X_("ClockModes"));
2880 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2881 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2884 session->add_extra_xml (*node);
2885 session->set_dirty ();
2890 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2891 : Controllable (name), ui (u), type(tp)
2897 ARDOUR_UI::TransportControllable::set_value (float val)
2899 if (type == ShuttleControl) {
2906 fract = -((0.5f - val)/0.5f);
2908 fract = ((val - 0.5f)/0.5f);
2912 ui.set_shuttle_fract (fract);
2917 /* do nothing: these are radio-style actions */
2925 action = X_("Roll");
2928 action = X_("Stop");
2931 action = X_("Goto Start");
2934 action = X_("Goto End");
2937 action = X_("Loop");
2940 action = X_("Play Selection");
2943 action = X_("Record");
2953 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2961 ARDOUR_UI::TransportControllable::get_value (void) const
2980 case ShuttleControl:
2990 ARDOUR_UI::TransportControllable::set_id (const string& str)
2996 ARDOUR_UI::setup_profile ()
2998 if (gdk_screen_width() < 1200) {
2999 Profile->set_small_screen ();
3002 if (getenv ("ARDOUR_SAE")) {
3003 Profile->set_sae ();
3004 Profile->set_single_package ();
3009 ARDOUR_UI::audioengine_setup ()