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 Config->save_state();
744 ARDOUR_UI::config()->save_state();
749 ARDOUR_UI::ask_about_saving_session (const string & what)
751 ArdourDialog window (_("ardour: save session?"));
752 Gtk::HBox dhbox; // the hbox for the image and text
753 Gtk::Label prompt_label;
754 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
758 msg = string_compose(_("Don't %1"), what);
759 window.add_button (msg, RESPONSE_REJECT);
760 msg = string_compose(_("Just %1"), what);
761 window.add_button (msg, RESPONSE_APPLY);
762 msg = string_compose(_("Save and %1"), what);
763 window.add_button (msg, RESPONSE_ACCEPT);
765 window.set_default_response (RESPONSE_ACCEPT);
767 Gtk::Button noquit_button (msg);
768 noquit_button.set_name ("EditorGTKButton");
773 if (session->snap_name() == session->name()) {
776 type = _("snapshot");
778 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?"),
779 type, session->snap_name());
781 prompt_label.set_text (prompt);
782 prompt_label.set_name (X_("PrompterLabel"));
783 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
785 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
787 dhbox.set_homogeneous (false);
788 dhbox.pack_start (*dimage, false, false, 5);
789 dhbox.pack_start (prompt_label, true, false, 5);
790 window.get_vbox()->pack_start (dhbox);
792 window.set_name (_("Prompter"));
793 window.set_position (Gtk::WIN_POS_MOUSE);
794 window.set_modal (true);
795 window.set_resizable (false);
798 save_the_session = 0;
800 window.set_keep_above (true);
803 ResponseType r = (ResponseType) window.run();
808 case RESPONSE_ACCEPT: // save and get out of here
810 case RESPONSE_APPLY: // get out of here
820 ARDOUR_UI::every_second ()
823 update_buffer_load ();
824 update_disk_space ();
829 ARDOUR_UI::every_point_one_seconds ()
831 update_speed_display ();
832 RapidScreenUpdate(); /* EMIT_SIGNAL */
837 ARDOUR_UI::every_point_zero_one_seconds ()
839 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
844 ARDOUR_UI::update_sample_rate (nframes_t ignored)
848 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
850 if (!engine->connected()) {
852 snprintf (buf, sizeof (buf), _("disconnected"));
856 nframes_t rate = engine->frame_rate();
858 if (fmod (rate, 1000.0) != 0.0) {
859 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
860 (float) rate/1000.0f,
861 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
863 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
865 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
869 sample_rate_label.set_text (buf);
873 ARDOUR_UI::update_cpu_load ()
876 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
877 cpu_load_label.set_text (buf);
881 ARDOUR_UI::update_buffer_load ()
886 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
887 session->playback_load(), session->capture_load());
888 buffer_load_label.set_text (buf);
890 buffer_load_label.set_text ("");
895 ARDOUR_UI::count_recenabled_streams (Route& route)
897 Track* track = dynamic_cast<Track*>(&route);
898 if (track && track->diskstream()->record_enabled()) {
899 rec_enabled_streams += track->n_inputs();
904 ARDOUR_UI::update_disk_space()
910 nframes_t frames = session->available_capture_duration();
913 if (frames == max_frames) {
914 strcpy (buf, _("Disk: 24hrs+"));
919 nframes_t fr = session->frame_rate();
921 rec_enabled_streams = 0;
922 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
924 if (rec_enabled_streams) {
925 frames /= rec_enabled_streams;
928 hrs = frames / (fr * 3600);
929 frames -= hrs * fr * 3600;
930 mins = frames / (fr * 60);
931 frames -= mins * fr * 60;
934 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
937 disk_space_label.set_text (buf);
941 ARDOUR_UI::update_wall_clock ()
948 tm_now = localtime (&now);
950 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
951 wall_clock_label.set_text (buf);
957 ARDOUR_UI::session_menu (GdkEventButton *ev)
959 session_popup_menu->popup (0, 0);
964 ARDOUR_UI::redisplay_recent_sessions ()
966 vector<string *> *sessions;
967 vector<string *>::iterator i;
968 RecentSessionsSorter cmp;
970 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
971 recent_session_model->clear ();
974 ARDOUR::read_recent_sessions (rs);
977 recent_session_display.set_model (recent_session_model);
981 /* sort them alphabetically */
982 sort (rs.begin(), rs.end(), cmp);
983 sessions = new vector<string*>;
985 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
986 sessions->push_back (new string ((*i).second));
989 for (i = sessions->begin(); i != sessions->end(); ++i) {
991 vector<string*>* states;
992 vector<const gchar*> item;
993 string fullpath = *(*i);
995 /* remove any trailing / */
997 if (fullpath[fullpath.length()-1] == '/') {
998 fullpath = fullpath.substr (0, fullpath.length()-1);
1001 /* now get available states for this session */
1003 if ((states = Session::possible_states (fullpath)) == 0) {
1004 /* no state file? */
1008 TreeModel::Row row = *(recent_session_model->append());
1010 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1011 row[recent_session_columns.fullpath] = fullpath;
1013 if (states->size() > 1) {
1015 /* add the children */
1017 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1019 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1021 child_row[recent_session_columns.visible_name] = **i2;
1022 child_row[recent_session_columns.fullpath] = fullpath;
1031 recent_session_display.set_model (recent_session_model);
1036 ARDOUR_UI::build_session_selector ()
1038 session_selector_window = new ArdourDialog ("session selector");
1040 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1042 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1043 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1044 session_selector_window->set_default_response (RESPONSE_ACCEPT);
1045 recent_session_model = TreeStore::create (recent_session_columns);
1046 recent_session_display.set_model (recent_session_model);
1047 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1048 recent_session_display.set_headers_visible (false);
1049 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
1051 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1053 scroller->add (recent_session_display);
1054 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1056 session_selector_window->set_name ("SessionSelectorWindow");
1057 session_selector_window->set_size_request (200, 400);
1058 session_selector_window->get_vbox()->pack_start (*scroller);
1059 session_selector_window->show_all_children();
1063 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
1065 session_selector_window->response (RESPONSE_ACCEPT);
1069 ARDOUR_UI::open_recent_session ()
1071 /* popup selector window */
1073 if (session_selector_window == 0) {
1074 build_session_selector ();
1077 redisplay_recent_sessions ();
1079 ResponseType r = (ResponseType) session_selector_window->run ();
1081 session_selector_window->hide();
1084 case RESPONSE_ACCEPT:
1090 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1092 if (i == recent_session_model->children().end()) {
1096 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1097 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1099 _session_is_new = false;
1101 load_session (path, state);
1105 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1107 struct stat statbuf;
1109 if (stat (info.filename.c_str(), &statbuf) != 0) {
1113 if (!S_ISDIR(statbuf.st_mode)) {
1119 string session_file = info.filename;
1120 session_file += '/';
1121 session_file += Glib::path_get_basename (info.filename);
1122 session_file += ".ardour";
1124 if (stat (session_file.c_str(), &statbuf) != 0) {
1128 return S_ISREG (statbuf.st_mode);
1132 ARDOUR_UI::check_audioengine ()
1135 if (!engine->connected()) {
1136 MessageDialog msg (_("Ardour is not connected to JACK\n"
1137 "You cannot open or close sessions in this condition"));
1148 ARDOUR_UI::open_session ()
1150 if (!check_audioengine()) {
1154 /* popup selector window */
1156 if (open_session_selector == 0) {
1158 /* ardour sessions are folders */
1160 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1161 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1162 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1164 FileFilter session_filter;
1165 session_filter.add_pattern ("*.ardour");
1166 session_filter.set_name (_("Ardour sessions"));
1167 open_session_selector->add_filter (session_filter);
1168 open_session_selector->set_filter (session_filter);
1171 int response = open_session_selector->run();
1172 open_session_selector->hide ();
1175 case RESPONSE_ACCEPT:
1178 open_session_selector->hide();
1182 open_session_selector->hide();
1183 string session_path = open_session_selector->get_filename();
1187 if (session_path.length() > 0) {
1188 if (Session::find_session (session_path, path, name, isnew) == 0) {
1189 _session_is_new = isnew;
1190 load_session (path, name);
1197 ARDOUR_UI::session_add_midi_track ()
1199 cerr << _("Patience is a virtue.\n");
1203 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1205 list<boost::shared_ptr<AudioTrack> > tracks;
1206 Session::RouteList routes;
1209 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1215 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1217 if (tracks.size() != how_many) {
1218 if (how_many == 1) {
1219 error << _("could not create a new audio track") << endmsg;
1221 error << string_compose (_("could only create %1 of %2 new audio %3"),
1222 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1228 routes = session->new_audio_route (input_channels, output_channels, how_many);
1230 if (routes.size() != how_many) {
1231 if (how_many == 1) {
1232 error << _("could not create a new audio track") << endmsg;
1234 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1240 if (need_control_room_outs) {
1246 route->set_stereo_control_outs (control_lr_channels);
1247 route->control_outs()->set_stereo_pan (pans, this);
1249 #endif /* CONTROLOUTS */
1253 cerr << "About to complain about JACK\n";
1254 MessageDialog msg (*editor,
1255 _("There are insufficient JACK ports available\n\
1256 to create a new track or bus.\n\
1257 You should save Ardour, exit and\n\
1258 restart JACK with more ports."));
1264 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1266 nframes_t _preroll = 0;
1269 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1270 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1272 if (new_position > _preroll) {
1273 new_position -= _preroll;
1278 session->request_locate (new_position);
1283 ARDOUR_UI::transport_goto_start ()
1286 session->goto_start();
1289 /* force displayed area in editor to start no matter
1290 what "follow playhead" setting is.
1294 editor->reset_x_origin (session->current_start_frame());
1300 ARDOUR_UI::transport_goto_zero ()
1303 session->request_locate (0);
1306 /* force displayed area in editor to start no matter
1307 what "follow playhead" setting is.
1311 editor->reset_x_origin (0);
1317 ARDOUR_UI::transport_goto_end ()
1320 nframes_t frame = session->current_end_frame();
1321 session->request_locate (frame);
1323 /* force displayed area in editor to start no matter
1324 what "follow playhead" setting is.
1328 editor->reset_x_origin (frame);
1334 ARDOUR_UI::transport_stop ()
1340 if (session->is_auditioning()) {
1341 session->cancel_audition ();
1345 if (session->get_play_loop ()) {
1346 session->request_play_loop (false);
1349 session->request_stop ();
1353 ARDOUR_UI::transport_stop_and_forget_capture ()
1356 session->request_stop (true);
1361 ARDOUR_UI::remove_last_capture()
1364 editor->remove_last_capture();
1369 ARDOUR_UI::transport_record ()
1372 switch (session->record_status()) {
1373 case Session::Disabled:
1374 if (session->ntracks() == 0) {
1375 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1379 session->maybe_enable_record ();
1381 case Session::Recording:
1382 case Session::Enabled:
1383 session->disable_record (false, true);
1389 ARDOUR_UI::transport_roll ()
1397 rolling = session->transport_rolling ();
1399 if (session->get_play_loop()) {
1400 session->request_play_loop (false);
1401 auto_loop_button.set_visual_state (1);
1402 roll_button.set_visual_state (1);
1403 } else if (session->get_play_range ()) {
1404 session->request_play_range (false);
1405 play_selection_button.set_visual_state (0);
1406 } else if (rolling) {
1407 session->request_locate (session->last_transport_start(), true);
1410 session->request_transport_speed (1.0f);
1414 ARDOUR_UI::transport_loop()
1417 if (session->get_play_loop()) {
1418 if (session->transport_rolling()) {
1419 Location * looploc = session->locations()->auto_loop_location();
1421 session->request_locate (looploc->start(), true);
1426 session->request_play_loop (true);
1432 ARDOUR_UI::transport_play_selection ()
1438 if (!session->get_play_range()) {
1439 session->request_stop ();
1442 editor->play_selection ();
1446 ARDOUR_UI::transport_rewind (int option)
1448 float current_transport_speed;
1451 current_transport_speed = session->transport_speed();
1453 if (current_transport_speed >= 0.0f) {
1456 session->request_transport_speed (-1.0f);
1459 session->request_transport_speed (-4.0f);
1462 session->request_transport_speed (-0.5f);
1467 session->request_transport_speed (current_transport_speed * 1.5f);
1473 ARDOUR_UI::transport_forward (int option)
1475 float current_transport_speed;
1478 current_transport_speed = session->transport_speed();
1480 if (current_transport_speed <= 0.0f) {
1483 session->request_transport_speed (1.0f);
1486 session->request_transport_speed (4.0f);
1489 session->request_transport_speed (0.5f);
1494 session->request_transport_speed (current_transport_speed * 1.5f);
1500 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1506 boost::shared_ptr<Route> r;
1508 if ((r = session->route_by_remote_id (dstream)) != 0) {
1512 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1513 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1522 ARDOUR_UI::queue_transport_change ()
1524 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1528 ARDOUR_UI::map_transport_state ()
1530 float sp = session->transport_speed();
1533 transport_rolling ();
1534 } else if (sp < 0.0f) {
1535 transport_rewinding ();
1536 } else if (sp > 0.0f) {
1537 transport_forwarding ();
1539 transport_stopped ();
1544 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1546 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1547 (int) adj.get_value()].c_str());
1551 ARDOUR_UI::engine_stopped ()
1553 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1554 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1555 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1559 ARDOUR_UI::engine_running ()
1561 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1562 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1563 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1565 Glib::RefPtr<Action> action;
1566 char* action_name = 0;
1568 switch (engine->frames_per_cycle()) {
1570 action_name = X_("JACKLatency32");
1573 action_name = X_("JACKLatency64");
1576 action_name = X_("JACKLatency128");
1579 action_name = X_("JACKLatency512");
1582 action_name = X_("JACKLatency1024");
1585 action_name = X_("JACKLatency2048");
1588 action_name = X_("JACKLatency4096");
1591 action_name = X_("JACKLatency8192");
1594 /* XXX can we do anything useful ? */
1600 action = ActionManager::get_action (X_("JACK"), action_name);
1603 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1604 ract->set_active ();
1610 ARDOUR_UI::engine_halted ()
1612 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1614 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1615 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1617 update_sample_rate (0);
1619 MessageDialog msg (*editor,
1621 JACK has either been shutdown or it\n\
1622 disconnected Ardour because Ardour\n\
1623 was not fast enough. You can save the\n\
1624 session and/or try to reconnect to JACK ."));
1629 ARDOUR_UI::do_engine_start ()
1637 error << _("Unable to start the session running")
1647 ARDOUR_UI::setup_theme ()
1649 theme_manager->setup_theme();
1653 ARDOUR_UI::update_clocks ()
1655 if (!editor || !editor->dragging_playhead()) {
1656 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1661 ARDOUR_UI::start_clocking ()
1663 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1667 ARDOUR_UI::stop_clocking ()
1669 clock_signal_connection.disconnect ();
1673 ARDOUR_UI::toggle_clocking ()
1676 if (clock_button.get_active()) {
1685 ARDOUR_UI::_blink (void *arg)
1688 ((ARDOUR_UI *) arg)->blink ();
1695 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1699 ARDOUR_UI::start_blinking ()
1701 /* Start the blink signal. Everybody with a blinking widget
1702 uses Blink to drive the widget's state.
1705 if (blink_timeout_tag < 0) {
1707 blink_timeout_tag = g_timeout_add (240, _blink, this);
1712 ARDOUR_UI::stop_blinking ()
1714 if (blink_timeout_tag >= 0) {
1715 g_source_remove (blink_timeout_tag);
1716 blink_timeout_tag = -1;
1721 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1727 if (io.n_inputs() == 0) {
1732 /* XXX we're not handling multiple ports yet. */
1734 const char **connections = io.input(0)->get_connections();
1736 if (connections == 0 || connections[0] == '\0') {
1739 buf = connections[0];
1746 if (io.n_outputs() == 0) {
1751 /* XXX we're not handling multiple ports yet. */
1753 const char **connections = io.output(0)->get_connections();
1755 if (connections == 0 || connections[0] == '\0') {
1758 buf = connections[0];
1765 /** Ask the user for the name of a new shapshot and then take it.
1768 ARDOUR_UI::snapshot_session ()
1770 ArdourPrompter prompter (true);
1774 struct tm local_time;
1777 localtime_r (&n, &local_time);
1778 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1780 prompter.set_name ("Prompter");
1781 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1782 prompter.set_prompt (_("Name of New Snapshot"));
1783 prompter.set_initial_text (timebuf);
1785 switch (prompter.run()) {
1786 case RESPONSE_ACCEPT:
1787 prompter.get_result (snapname);
1788 if (snapname.length()){
1789 save_state (snapname);
1799 ARDOUR_UI::save_state (const string & name)
1801 (void) save_state_canfail (name);
1805 ARDOUR_UI::save_state_canfail (string name)
1810 if (name.length() == 0) {
1811 name = session->snap_name();
1814 if ((ret = session->save_state (name)) != 0) {
1818 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1823 ARDOUR_UI::restore_state (string name)
1826 if (name.length() == 0) {
1827 name = session->name();
1829 session->restore_state (name);
1834 ARDOUR_UI::primary_clock_value_changed ()
1837 session->request_locate (primary_clock.current_time ());
1842 ARDOUR_UI::secondary_clock_value_changed ()
1845 session->request_locate (secondary_clock.current_time ());
1850 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1852 if (session && dstream && dstream->record_enabled()) {
1854 Session::RecordState rs;
1856 rs = session->record_status ();
1859 case Session::Disabled:
1860 case Session::Enabled:
1861 if (w->get_state() != STATE_SELECTED) {
1862 w->set_state (STATE_SELECTED);
1866 case Session::Recording:
1867 if (w->get_state() != STATE_ACTIVE) {
1868 w->set_state (STATE_ACTIVE);
1874 if (w->get_state() != STATE_NORMAL) {
1875 w->set_state (STATE_NORMAL);
1881 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1887 switch (session->record_status()) {
1888 case Session::Enabled:
1890 rec_button.set_visual_state (2);
1892 rec_button.set_visual_state (0);
1896 case Session::Recording:
1897 rec_button.set_visual_state (1);
1901 rec_button.set_visual_state (0);
1907 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1915 ARDOUR_UI::save_template ()
1918 ArdourPrompter prompter (true);
1921 if (!check_audioengine()) {
1925 prompter.set_name (X_("Prompter"));
1926 prompter.set_prompt (_("Name for mix template:"));
1927 prompter.set_initial_text(session->name() + _("-template"));
1928 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1930 switch (prompter.run()) {
1931 case RESPONSE_ACCEPT:
1932 prompter.get_result (name);
1934 if (name.length()) {
1935 session->save_template (name);
1945 ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
1947 string session_name;
1948 string session_path;
1950 int response = Gtk::RESPONSE_NONE;
1952 new_session_dialog->set_modal(true);
1953 new_session_dialog->set_name (predetermined_path);
1954 new_session_dialog->reset_recent();
1955 new_session_dialog->show();
1956 new_session_dialog->present ();
1957 new_session_dialog->set_current_page (0);
1961 new_session_dialog->set_have_engine (have_engine);
1963 response = new_session_dialog->run ();
1965 _session_is_new = false;
1967 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1972 new_session_dialog->hide ();
1975 } else if (response == Gtk::RESPONSE_NONE) {
1977 /* Clear was pressed */
1978 new_session_dialog->reset();
1982 /* first things first ... we need an audio engine running */
1985 if (start_backend_audio ()) {
1986 new_session_dialog->hide ();
1994 /* now handle possible affirmative responses */
1996 if (response == Gtk::RESPONSE_YES) {
1998 /* YES == OPEN from the session selector */
2000 session_name = new_session_dialog->session_name();
2002 if (session_name.empty()) {
2003 response = Gtk::RESPONSE_NONE;
2007 if (session_name[0] == '/' ||
2008 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2009 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2010 load_session (Glib::path_get_dirname (session_name), session_name);
2012 session_path = new_session_dialog->session_folder();
2013 load_session (session_path, session_name);
2016 } else if (response == Gtk::RESPONSE_OK) {
2018 /* OK == OPEN button */
2020 session_name = new_session_dialog->session_name();
2022 if (new_session_dialog->get_current_page() == 1) {
2024 if (session_name.empty()) {
2025 response = Gtk::RESPONSE_NONE;
2029 if (session_name[0] == '/' ||
2030 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2031 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2032 load_session (Glib::path_get_dirname (session_name), session_name);
2034 session_path = new_session_dialog->session_folder();
2035 load_session (session_path, session_name);
2040 if (session_name.empty()) {
2041 response = Gtk::RESPONSE_NONE;
2045 if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
2046 should_be_new = true;
2049 /* handle what appear to be paths rather than just a name */
2051 if (session_name[0] == '/' ||
2052 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2053 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2055 session_path = Glib::path_get_dirname (session_name);
2056 session_name = Glib::path_get_basename (session_name);
2060 session_path = new_session_dialog->session_folder();
2064 //XXX This is needed because session constructor wants a
2065 //non-existant path. hopefully this will be fixed at some point.
2067 session_path = Glib::build_filename (session_path, session_name);
2069 if (should_be_new && Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2071 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2073 MessageDialog msg (str,
2075 Gtk::MESSAGE_WARNING,
2076 Gtk::BUTTONS_YES_NO,
2080 msg.set_name (X_("CleanupDialog"));
2081 msg.set_wmclass (X_("existing_session"), "Ardour");
2082 msg.set_position (Gtk::WIN_POS_MOUSE);
2084 switch (msg.run()) {
2086 load_session (session_path, session_name);
2090 response = RESPONSE_NONE;
2091 new_session_dialog->reset ();
2096 _session_is_new = true;
2098 std::string template_name = new_session_dialog->session_template_name();
2100 if (new_session_dialog->use_session_template()) {
2102 load_session (session_path, session_name, &template_name);
2108 AutoConnectOption iconnect;
2109 AutoConnectOption oconnect;
2113 if (Profile->get_sae()) {
2117 iconnect = AutoConnectPhysical;
2118 oconnect = AutoConnectMaster;
2119 nphysin = 0; // use all available
2120 nphysout = 0; // use all available
2124 /* get settings from advanced section of NSD */
2126 if (new_session_dialog->create_control_bus()) {
2127 cchns = (uint32_t) new_session_dialog->control_channel_count();
2132 if (new_session_dialog->create_master_bus()) {
2133 mchns = (uint32_t) new_session_dialog->master_channel_count();
2138 if (new_session_dialog->connect_inputs()) {
2139 iconnect = AutoConnectPhysical;
2141 iconnect = AutoConnectOption (0);
2144 /// @todo some minor tweaks.
2146 if (new_session_dialog->connect_outs_to_master()) {
2147 oconnect = AutoConnectMaster;
2148 } else if (new_session_dialog->connect_outs_to_physical()) {
2149 oconnect = AutoConnectPhysical;
2151 oconnect = AutoConnectOption (0);
2154 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2155 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2158 if (build_session (session_path,
2166 engine->frame_rate() * 60 * 5)) {
2168 response = Gtk::RESPONSE_NONE;
2169 new_session_dialog->reset ();
2176 } while (response == Gtk::RESPONSE_NONE);
2180 new_session_dialog->get_window()->set_cursor();
2181 new_session_dialog->hide();
2186 ARDOUR_UI::close_session()
2188 if (!check_audioengine()) {
2193 get_session_parameters ("", true, false);
2197 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2199 Session *new_session;
2201 session_loaded = false;
2203 if (!check_audioengine()) {
2207 x = unload_session ();
2215 /* if it already exists, we must have write access */
2217 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2218 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2219 "This prevents the session from being loaded."));
2225 new_session = new Session (*engine, path, snap_name, mix_template);
2230 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2234 connect_to_session (new_session);
2236 Config->set_current_owner (ConfigVariableBase::Interface);
2238 session_loaded = true;
2240 goto_editor_window ();
2243 session->set_clean ();
2246 editor->edit_cursor_position (true);
2251 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2252 uint32_t control_channels,
2253 uint32_t master_channels,
2254 AutoConnectOption input_connect,
2255 AutoConnectOption output_connect,
2258 nframes_t initial_length)
2260 Session *new_session;
2263 if (!check_audioengine()) {
2267 session_loaded = false;
2269 x = unload_session ();
2277 _session_is_new = true;
2280 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2281 control_channels, master_channels, nphysin, nphysout, initial_length);
2286 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2291 connect_to_session (new_session);
2293 session_loaded = true;
2301 editor->show_window ();
2312 ARDOUR_UI::show_splash ()
2315 about = new About();
2316 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2323 ARDOUR_UI::about_signal_response(int response)
2329 ARDOUR_UI::hide_splash ()
2332 about->get_window()->set_cursor ();
2338 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2342 removed = rep.paths.size();
2345 MessageDialog msgd (*editor,
2346 _("No audio files were ready for cleanup"),
2349 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2350 msgd.set_secondary_text (_("If this seems suprising, \n\
2351 check for any existing snapshots.\n\
2352 These may still include regions that\n\
2353 require some unused files to continue to exist."));
2359 ArdourDialog results (_("ardour: cleanup"), true, false);
2361 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2362 CleanupResultsModelColumns() {
2366 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2367 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2371 CleanupResultsModelColumns results_columns;
2372 Glib::RefPtr<Gtk::ListStore> results_model;
2373 Gtk::TreeView results_display;
2375 results_model = ListStore::create (results_columns);
2376 results_display.set_model (results_model);
2377 results_display.append_column (list_title, results_columns.visible_name);
2379 results_display.set_name ("CleanupResultsList");
2380 results_display.set_headers_visible (true);
2381 results_display.set_headers_clickable (false);
2382 results_display.set_reorderable (false);
2384 Gtk::ScrolledWindow list_scroller;
2387 Gtk::HBox dhbox; // the hbox for the image and text
2388 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2389 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2391 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2393 if (rep.space < 1048576.0f) {
2395 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2397 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2401 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2403 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2407 dhbox.pack_start (*dimage, true, false, 5);
2408 dhbox.pack_start (txt, true, false, 5);
2410 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2411 TreeModel::Row row = *(results_model->append());
2412 row[results_columns.visible_name] = *i;
2413 row[results_columns.fullpath] = *i;
2416 list_scroller.add (results_display);
2417 list_scroller.set_size_request (-1, 150);
2418 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2420 dvbox.pack_start (dhbox, true, false, 5);
2421 dvbox.pack_start (list_scroller, true, false, 5);
2422 ddhbox.pack_start (dvbox, true, false, 5);
2424 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2425 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2426 results.set_default_response (RESPONSE_CLOSE);
2427 results.set_position (Gtk::WIN_POS_MOUSE);
2428 results.show_all_children ();
2429 results.set_resizable (false);
2436 ARDOUR_UI::cleanup ()
2439 /* shouldn't happen: menu item is insensitive */
2444 MessageDialog checker (_("Are you sure you want to cleanup?"),
2446 Gtk::MESSAGE_QUESTION,
2447 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2449 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2450 ALL undo/redo information will be lost if you cleanup.\n\
2451 After cleanup, unused audio files will be moved to a \
2452 \"dead sounds\" location."));
2454 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2455 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2456 checker.set_default_response (RESPONSE_CANCEL);
2458 checker.set_name (_("CleanupDialog"));
2459 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2460 checker.set_position (Gtk::WIN_POS_MOUSE);
2462 switch (checker.run()) {
2463 case RESPONSE_ACCEPT:
2469 Session::cleanup_report rep;
2471 editor->prepare_for_cleanup ();
2473 /* do not allow flush until a session is reloaded */
2475 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2477 act->set_sensitive (false);
2480 if (session->cleanup_sources (rep)) {
2485 display_cleanup_results (rep,
2488 The following %1 %2 not in use and \n\
2489 have been moved to:\n\
2491 Flushing the wastebasket will \n\
2492 release an additional\n\
2493 %4 %5bytes of disk space.\n"
2501 ARDOUR_UI::flush_trash ()
2504 /* shouldn't happen: menu item is insensitive */
2508 Session::cleanup_report rep;
2510 if (session->cleanup_trash_sources (rep)) {
2514 display_cleanup_results (rep,
2516 _("The following %1 %2 deleted from\n\
2518 releasing %4 %5bytes of disk space"));
2522 ARDOUR_UI::add_route (Gtk::Window* float_window)
2530 if (add_route_dialog == 0) {
2531 add_route_dialog = new AddRouteDialog;
2533 add_route_dialog->set_transient_for (*float_window);
2537 if (add_route_dialog->is_visible()) {
2538 /* we're already doing this */
2542 ResponseType r = (ResponseType) add_route_dialog->run ();
2544 add_route_dialog->hide();
2547 case RESPONSE_ACCEPT:
2554 if ((count = add_route_dialog->count()) <= 0) {
2558 uint32_t input_chan = add_route_dialog->channels ();
2559 uint32_t output_chan;
2560 string name_template = add_route_dialog->name_template ();
2561 bool track = add_route_dialog->track ();
2563 AutoConnectOption oac = Config->get_output_auto_connect();
2565 if (oac & AutoConnectMaster) {
2566 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2568 output_chan = input_chan;
2571 /* XXX do something with name template */
2574 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2576 session_add_audio_bus (input_chan, output_chan, count);
2581 ARDOUR_UI::mixer_settings () const
2586 node = session->instant_xml(X_("Mixer"), session->path());
2588 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2592 node = new XMLNode (X_("Mixer"));
2599 ARDOUR_UI::editor_settings () const
2604 node = session->instant_xml(X_("Editor"), session->path());
2606 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2610 node = new XMLNode (X_("Editor"));
2616 ARDOUR_UI::keyboard_settings () const
2620 node = Config->extra_xml(X_("Keyboard"));
2623 node = new XMLNode (X_("Keyboard"));
2629 ARDOUR_UI::halt_on_xrun_message ()
2631 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2633 MessageDialog msg (*editor,
2634 _("Recording was stopped because your system could not keep up."));
2639 ARDOUR_UI::disk_overrun_handler ()
2641 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2643 if (!have_disk_speed_dialog_displayed) {
2644 have_disk_speed_dialog_displayed = true;
2645 MessageDialog* msg = new MessageDialog (*editor, _("\
2646 The disk system on your computer\n\
2647 was not able to keep up with Ardour.\n\
2649 Specifically, it failed to write data to disk\n\
2650 quickly enough to keep up with recording.\n"));
2651 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2657 ARDOUR_UI::disk_underrun_handler ()
2659 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2661 if (!have_disk_speed_dialog_displayed) {
2662 have_disk_speed_dialog_displayed = true;
2663 MessageDialog* msg = new MessageDialog (*editor,
2664 _("The disk system on your computer\n\
2665 was not able to keep up with Ardour.\n\
2667 Specifically, it failed to read data from disk\n\
2668 quickly enough to keep up with playback.\n"));
2669 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2675 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2677 have_disk_speed_dialog_displayed = false;
2682 ARDOUR_UI::pending_state_dialog ()
2684 ArdourDialog dialog ("pending state dialog");
2686 This session appears to have been in\n\
2687 middle of recording when ardour or\n\
2688 the computer was shutdown.\n\
2690 Ardour can recover any captured audio for\n\
2691 you, or it can ignore it. Please decide\n\
2692 what you would like to do.\n"));
2694 dialog.get_vbox()->pack_start (message);
2695 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2696 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2698 dialog.set_position (WIN_POS_CENTER);
2701 switch (dialog.run ()) {
2702 case RESPONSE_ACCEPT:
2710 ARDOUR_UI::disconnect_from_jack ()
2713 if( engine->disconnect_from_jack ()) {
2714 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2718 update_sample_rate (0);
2723 ARDOUR_UI::reconnect_to_jack ()
2726 if (engine->reconnect_to_jack ()) {
2727 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2731 update_sample_rate (0);
2736 ARDOUR_UI::cmdline_new_session (string path)
2738 if (path[0] != '/') {
2739 char buf[PATH_MAX+1];
2742 getcwd (buf, sizeof (buf));
2749 get_session_parameters (path, false, true);
2751 _will_create_new_session_automatically = false; /* done it */
2752 return FALSE; /* don't call it again */
2756 ARDOUR_UI::use_config ()
2758 Glib::RefPtr<Action> act;
2760 switch (Config->get_native_file_data_format ()) {
2762 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2765 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2768 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2773 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2774 ract->set_active ();
2777 switch (Config->get_native_file_header_format ()) {
2779 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2782 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2785 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2788 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2791 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2794 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2797 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2802 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2803 ract->set_active ();
2806 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2808 set_transport_controllable_state (*node);
2813 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2815 if (Config->get_primary_clock_delta_edit_cursor()) {
2816 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2818 primary_clock.set (pos, 0, true);
2821 if (Config->get_secondary_clock_delta_edit_cursor()) {
2822 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2824 secondary_clock.set (pos);
2827 if (big_clock_window) {
2828 big_clock.set (pos);
2833 ARDOUR_UI::record_state_changed ()
2835 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2837 if (!session || !big_clock_window) {
2838 /* why bother - the clock isn't visible */
2842 switch (session->record_status()) {
2843 case Session::Recording:
2844 big_clock.set_widget_name ("BigClockRecording");
2847 big_clock.set_widget_name ("BigClockNonRecording");
2853 ARDOUR_UI::set_keybindings_path (string path)
2855 keybindings_path = path;
2859 ARDOUR_UI::save_keybindings ()
2861 if (can_save_keybindings) {
2862 AccelMap::save (user_keybindings_path);
2867 ARDOUR_UI::first_idle ()
2870 session->allow_auto_play (true);
2872 can_save_keybindings = true;
2877 ARDOUR_UI::store_clock_modes ()
2879 XMLNode* node = new XMLNode(X_("ClockModes"));
2881 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2882 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2885 session->add_extra_xml (*node);
2886 session->set_dirty ();
2891 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2892 : Controllable (name), ui (u), type(tp)
2898 ARDOUR_UI::TransportControllable::set_value (float val)
2900 if (type == ShuttleControl) {
2907 fract = -((0.5f - val)/0.5f);
2909 fract = ((val - 0.5f)/0.5f);
2913 ui.set_shuttle_fract (fract);
2918 /* do nothing: these are radio-style actions */
2926 action = X_("Roll");
2929 action = X_("Stop");
2932 action = X_("Goto Start");
2935 action = X_("Goto End");
2938 action = X_("Loop");
2941 action = X_("Play Selection");
2944 action = X_("Record");
2954 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2962 ARDOUR_UI::TransportControllable::get_value (void) const
2981 case ShuttleControl:
2991 ARDOUR_UI::TransportControllable::set_id (const string& str)
2997 ARDOUR_UI::setup_profile ()
2999 if (gdk_screen_width() < 1200) {
3000 Profile->set_small_screen ();
3003 if (getenv ("ARDOUR_SAE")) {
3004 Profile->set_sae ();
3005 Profile->set_single_package ();
3010 ARDOUR_UI::audioengine_setup ()