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.
20 #define __STDC_FORMAT_MACROS 1
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
39 #include <pbd/compose.h>
40 #include <pbd/failed_constructor.h>
41 #include <pbd/enumwriter.h>
42 #include <pbd/memento_command.h>
43 #include <pbd/file_utils.h>
45 #include <gtkmm2ext/gtk_ui.h>
46 #include <gtkmm2ext/utils.h>
47 #include <gtkmm2ext/click_box.h>
48 #include <gtkmm2ext/fastmeter.h>
49 #include <gtkmm2ext/stop_signal.h>
50 #include <gtkmm2ext/popup.h>
51 #include <gtkmm2ext/window_title.h>
53 #include <midi++/port.h>
54 #include <midi++/mmc.h>
56 #include <ardour/ardour.h>
57 #include <ardour/profile.h>
58 #include <ardour/session_directory.h>
59 #include <ardour/session_route.h>
60 #include <ardour/session_utils.h>
61 #include <ardour/port.h>
62 #include <ardour/audioengine.h>
63 #include <ardour/playlist.h>
64 #include <ardour/utils.h>
65 #include <ardour/audio_diskstream.h>
66 #include <ardour/audiofilesource.h>
67 #include <ardour/recent_sessions.h>
68 #include <ardour/port.h>
69 #include <ardour/audio_track.h>
70 #include <ardour/midi_track.h>
71 #include <ardour/filesystem_paths.h>
74 #include "ardour_ui.h"
75 #include "public_editor.h"
76 #include "audio_clock.h"
81 #include "add_route_dialog.h"
82 #include "new_session_dialog.h"
85 #include "gui_thread.h"
86 #include "theme_manager.h"
91 using namespace ARDOUR;
93 using namespace Gtkmm2ext;
97 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
98 UIConfiguration *ARDOUR_UI::ui_config = 0;
100 sigc::signal<void,bool> ARDOUR_UI::Blink;
101 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
102 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
103 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
105 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
107 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
109 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
110 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
111 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
112 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
116 adjuster_table (3, 3),
120 preroll_button (_("pre\nroll")),
121 postroll_button (_("post\nroll")),
125 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
129 roll_controllable ("transport roll", *this, TransportControllable::Roll),
130 stop_controllable ("transport stop", *this, TransportControllable::Stop),
131 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
132 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
133 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
134 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
135 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
136 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
137 shuttle_controller_binding_proxy (shuttle_controllable),
139 roll_button (roll_controllable),
140 stop_button (stop_controllable),
141 goto_start_button (goto_start_controllable),
142 goto_end_button (goto_end_controllable),
143 auto_loop_button (auto_loop_controllable),
144 play_selection_button (play_selection_controllable),
145 rec_button (rec_controllable),
147 shuttle_units_button (_("% ")),
149 punch_in_button (_("Punch In")),
150 punch_out_button (_("Punch Out")),
151 auto_return_button (_("Auto Return")),
152 auto_play_button (_("Auto Play")),
153 auto_input_button (_("Auto Input")),
154 click_button (_("Click")),
155 time_master_button (_("time\nmaster")),
157 auditioning_alert_button (_("AUDITION")),
158 solo_alert_button (_("SOLO")),
161 using namespace Gtk::Menu_Helpers;
167 if (theArdourUI == 0) {
171 ui_config = new UIConfiguration();
172 theme_manager = new ThemeManager();
177 _session_is_new = false;
178 big_clock_window = 0;
179 session_selector_window = 0;
180 last_key_press_time = 0;
181 connection_editor = 0;
182 add_route_dialog = 0;
186 open_session_selector = 0;
187 have_configure_timeout = false;
188 have_disk_speed_dialog_displayed = false;
189 session_loaded = false;
190 last_speed_displayed = -1.0f;
193 sys::path key_bindings_file;
195 find_file_in_search_path (ardour_search_path() + system_config_search_path(),
196 "ardour.bindings", key_bindings_file);
198 keybindings_path = key_bindings_file.to_string();
200 can_save_keybindings = false;
202 last_configure_time.tv_sec = 0;
203 last_configure_time.tv_usec = 0;
205 shuttle_grabbed = false;
207 shuttle_max_speed = 8.0f;
209 shuttle_style_menu = 0;
210 shuttle_unit_menu = 0;
212 gettimeofday (&last_peak_grab, 0);
213 gettimeofday (&last_shuttle_request, 0);
215 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
216 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
218 /* handle pending state with a dialog */
220 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
222 /* have to wait for AudioEngine and Configuration before proceeding */
226 ARDOUR_UI::set_engine (AudioEngine& e)
230 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
231 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
232 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
233 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
235 ActionManager::init ();
236 new_session_dialog = new NewSessionDialog();
240 keyboard = new Keyboard;
242 if (setup_windows ()) {
243 throw failed_constructor ();
246 if (GTK_ARDOUR::show_key_actions) {
247 vector<string> names;
248 vector<string> paths;
250 vector<AccelKey> bindings;
252 ActionManager::get_all_actions (names, paths, keys, bindings);
254 vector<string>::iterator n;
255 vector<string>::iterator k;
256 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
257 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
263 /* start with timecode, metering enabled
266 blink_timeout_tag = -1;
268 /* the global configuration object is now valid */
272 /* this being a GUI and all, we want peakfiles */
274 AudioFileSource::set_build_peakfiles (true);
275 AudioFileSource::set_build_missing_peakfiles (true);
277 /* set default clock modes */
279 primary_clock.set_mode (AudioClock::SMPTE);
280 secondary_clock.set_mode (AudioClock::BBT);
282 /* start the time-of-day-clock */
284 update_wall_clock ();
285 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
287 update_disk_space ();
289 update_sample_rate (engine->frame_rate());
291 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
292 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
295 ARDOUR_UI::~ARDOUR_UI ()
297 save_ardour_state ();
311 if (add_route_dialog) {
312 delete add_route_dialog;
317 ARDOUR_UI::configure_timeout ()
322 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
323 /* no configure events yet */
327 gettimeofday (&now, 0);
328 timersub (&now, &last_configure_time, &diff);
330 /* force a gap of 0.5 seconds since the last configure event
333 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
336 have_configure_timeout = false;
337 save_ardour_state ();
343 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
345 if (have_configure_timeout) {
346 gettimeofday (&last_configure_time, 0);
348 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
349 have_configure_timeout = true;
356 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
358 const XMLProperty* prop;
360 if ((prop = node.property ("roll")) != 0) {
361 roll_controllable.set_id (prop->value());
363 if ((prop = node.property ("stop")) != 0) {
364 stop_controllable.set_id (prop->value());
366 if ((prop = node.property ("goto_start")) != 0) {
367 goto_start_controllable.set_id (prop->value());
369 if ((prop = node.property ("goto_end")) != 0) {
370 goto_end_controllable.set_id (prop->value());
372 if ((prop = node.property ("auto_loop")) != 0) {
373 auto_loop_controllable.set_id (prop->value());
375 if ((prop = node.property ("play_selection")) != 0) {
376 play_selection_controllable.set_id (prop->value());
378 if ((prop = node.property ("rec")) != 0) {
379 rec_controllable.set_id (prop->value());
381 if ((prop = node.property ("shuttle")) != 0) {
382 shuttle_controllable.set_id (prop->value());
387 ARDOUR_UI::get_transport_controllable_state ()
389 XMLNode* node = new XMLNode(X_("TransportControllables"));
392 roll_controllable.id().print (buf, sizeof (buf));
393 node->add_property (X_("roll"), buf);
394 stop_controllable.id().print (buf, sizeof (buf));
395 node->add_property (X_("stop"), buf);
396 goto_start_controllable.id().print (buf, sizeof (buf));
397 node->add_property (X_("goto_start"), buf);
398 goto_end_controllable.id().print (buf, sizeof (buf));
399 node->add_property (X_("goto_end"), buf);
400 auto_loop_controllable.id().print (buf, sizeof (buf));
401 node->add_property (X_("auto_loop"), buf);
402 play_selection_controllable.id().print (buf, sizeof (buf));
403 node->add_property (X_("play_selection"), buf);
404 rec_controllable.id().print (buf, sizeof (buf));
405 node->add_property (X_("rec"), buf);
406 shuttle_controllable.id().print (buf, sizeof (buf));
407 node->add_property (X_("shuttle"), buf);
413 ARDOUR_UI::save_ardour_state ()
415 if (!keyboard || !mixer || !editor) {
419 /* XXX this is all a bit dubious. add_extra_xml() uses
420 a different lifetime model from add_instant_xml().
423 XMLNode* node = new XMLNode (keyboard->get_state());
424 Config->add_extra_xml (*node);
425 Config->add_extra_xml (get_transport_controllable_state());
426 Config->save_state();
428 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
429 XMLNode mnode(mixer->get_state());
432 session->add_instant_xml (enode);
433 session->add_instant_xml (mnode);
435 Config->add_instant_xml (enode);
436 Config->add_instant_xml (mnode);
443 ARDOUR_UI::autosave_session ()
445 if (!Config->get_periodic_safety_backups())
449 session->maybe_write_autosave();
456 ARDOUR_UI::update_autosave ()
458 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
460 if (session->dirty()) {
461 if (_autosave_connection.connected()) {
462 _autosave_connection.disconnect();
465 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
466 Config->get_periodic_safety_backup_interval() * 1000);
469 if (_autosave_connection.connected()) {
470 _autosave_connection.disconnect();
476 ARDOUR_UI::startup ()
478 check_memory_locking();
482 ARDOUR_UI::no_memory_warning ()
484 XMLNode node (X_("no-memory-warning"));
485 Config->add_instant_xml (node);
489 ARDOUR_UI::check_memory_locking ()
492 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
496 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
498 if (engine->is_realtime() && memory_warning_node == 0) {
500 struct rlimit limits;
502 long pages, page_size;
504 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
507 ram = (int64_t) pages * (int64_t) page_size;
510 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
514 if (limits.rlim_cur != RLIM_INFINITY) {
516 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
519 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
520 "This might cause Ardour to run out of memory before your system "
521 "runs out of memory. \n\n"
522 "You can view the memory limit with 'ulimit -l', "
523 "and it is normally controlled by /etc/security/limits.conf"));
525 VBox* vbox = msg.get_vbox();
527 CheckButton cb (_("Do not show this window again"));
529 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
531 hbox.pack_start (cb, true, false);
532 vbox->pack_start (hbox);
535 editor->ensure_float (msg);
547 if (session && session->dirty()) {
548 switch (ask_about_saving_session(_("quit"))) {
553 /* use the default name */
554 if (save_state_canfail ("")) {
555 /* failed - don't quit */
556 MessageDialog msg (*editor,
558 Ardour was unable to save your session.\n\n\
559 If you still wish to quit, please use the\n\n\
560 \"Just quit\" option."));
571 session->set_deletion_in_progress ();
574 Config->save_state();
575 ARDOUR_UI::config()->save_state();
580 ARDOUR_UI::ask_about_saving_session (const string & what)
582 ArdourDialog window (_("ardour: save session?"));
583 Gtk::HBox dhbox; // the hbox for the image and text
584 Gtk::Label prompt_label;
585 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
589 msg = string_compose(_("Don't %1"), what);
590 window.add_button (msg, RESPONSE_REJECT);
591 msg = string_compose(_("Just %1"), what);
592 window.add_button (msg, RESPONSE_APPLY);
593 msg = string_compose(_("Save and %1"), what);
594 window.add_button (msg, RESPONSE_ACCEPT);
596 window.set_default_response (RESPONSE_ACCEPT);
598 Gtk::Button noquit_button (msg);
599 noquit_button.set_name ("EditorGTKButton");
604 if (session->snap_name() == session->name()) {
607 type = _("snapshot");
609 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?"),
610 type, session->snap_name());
612 prompt_label.set_text (prompt);
613 prompt_label.set_name (X_("PrompterLabel"));
614 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
616 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
618 dhbox.set_homogeneous (false);
619 dhbox.pack_start (*dimage, false, false, 5);
620 dhbox.pack_start (prompt_label, true, false, 5);
621 window.get_vbox()->pack_start (dhbox);
623 window.set_name (_("Prompter"));
624 window.set_position (Gtk::WIN_POS_MOUSE);
625 window.set_modal (true);
626 window.set_resizable (false);
629 save_the_session = 0;
631 window.set_keep_above (true);
634 ResponseType r = (ResponseType) window.run();
639 case RESPONSE_ACCEPT: // save and get out of here
641 case RESPONSE_APPLY: // get out of here
651 ARDOUR_UI::every_second ()
654 update_buffer_load ();
655 update_disk_space ();
660 ARDOUR_UI::every_point_one_seconds ()
662 update_speed_display ();
663 RapidScreenUpdate(); /* EMIT_SIGNAL */
668 ARDOUR_UI::every_point_zero_one_seconds ()
670 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
675 ARDOUR_UI::update_sample_rate (nframes_t ignored)
679 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
681 if (!engine->connected()) {
683 snprintf (buf, sizeof (buf), _("disconnected"));
687 nframes_t rate = engine->frame_rate();
689 if (fmod (rate, 1000.0) != 0.0) {
690 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
691 (float) rate/1000.0f,
692 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
694 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
696 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
700 sample_rate_label.set_text (buf);
704 ARDOUR_UI::update_cpu_load ()
707 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
708 cpu_load_label.set_text (buf);
712 ARDOUR_UI::update_buffer_load ()
717 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
718 session->playback_load(), session->capture_load());
719 buffer_load_label.set_text (buf);
721 buffer_load_label.set_text ("");
726 ARDOUR_UI::count_recenabled_streams (Route& route)
728 Track* track = dynamic_cast<Track*>(&route);
729 if (track && track->diskstream()->record_enabled()) {
730 rec_enabled_streams += track->n_inputs().n_total();
735 ARDOUR_UI::update_disk_space()
741 nframes_t frames = session->available_capture_duration();
744 if (frames == max_frames) {
745 strcpy (buf, _("Disk: 24hrs+"));
750 nframes_t fr = session->frame_rate();
752 rec_enabled_streams = 0;
753 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
755 if (rec_enabled_streams) {
756 frames /= rec_enabled_streams;
759 hrs = frames / (fr * 3600);
760 frames -= hrs * fr * 3600;
761 mins = frames / (fr * 60);
762 frames -= mins * fr * 60;
765 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
768 disk_space_label.set_text (buf);
772 ARDOUR_UI::update_wall_clock ()
779 tm_now = localtime (&now);
781 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
782 wall_clock_label.set_text (buf);
788 ARDOUR_UI::session_menu (GdkEventButton *ev)
790 session_popup_menu->popup (0, 0);
795 ARDOUR_UI::redisplay_recent_sessions ()
797 vector<string *> *sessions;
798 vector<string *>::iterator i;
799 RecentSessionsSorter cmp;
801 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
802 recent_session_model->clear ();
805 ARDOUR::read_recent_sessions (rs);
808 recent_session_display.set_model (recent_session_model);
812 /* sort them alphabetically */
813 sort (rs.begin(), rs.end(), cmp);
814 sessions = new vector<string*>;
816 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
817 sessions->push_back (new string ((*i).second));
820 for (i = sessions->begin(); i != sessions->end(); ++i) {
822 vector<string*>* states;
823 vector<const gchar*> item;
824 string fullpath = *(*i);
826 /* remove any trailing / */
828 if (fullpath[fullpath.length()-1] == '/') {
829 fullpath = fullpath.substr (0, fullpath.length()-1);
832 /* now get available states for this session */
834 if ((states = Session::possible_states (fullpath)) == 0) {
839 TreeModel::Row row = *(recent_session_model->append());
841 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
842 row[recent_session_columns.fullpath] = fullpath;
844 if (states->size() > 1) {
846 /* add the children */
848 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
850 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
852 child_row[recent_session_columns.visible_name] = **i2;
853 child_row[recent_session_columns.fullpath] = fullpath;
862 recent_session_display.set_model (recent_session_model);
867 ARDOUR_UI::build_session_selector ()
869 session_selector_window = new ArdourDialog ("session selector");
871 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
873 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
874 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
875 session_selector_window->set_default_response (RESPONSE_ACCEPT);
876 recent_session_model = TreeStore::create (recent_session_columns);
877 recent_session_display.set_model (recent_session_model);
878 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
879 recent_session_display.set_headers_visible (false);
880 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
882 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
884 scroller->add (recent_session_display);
885 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
887 session_selector_window->set_name ("SessionSelectorWindow");
888 session_selector_window->set_size_request (200, 400);
889 session_selector_window->get_vbox()->pack_start (*scroller);
890 session_selector_window->show_all_children();
894 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
896 session_selector_window->response (RESPONSE_ACCEPT);
900 ARDOUR_UI::open_recent_session ()
902 /* popup selector window */
904 if (session_selector_window == 0) {
905 build_session_selector ();
908 redisplay_recent_sessions ();
910 ResponseType r = (ResponseType) session_selector_window->run ();
912 session_selector_window->hide();
915 case RESPONSE_ACCEPT:
921 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
923 if (i == recent_session_model->children().end()) {
927 Glib::ustring path = (*i)[recent_session_columns.fullpath];
928 Glib::ustring state = (*i)[recent_session_columns.visible_name];
930 _session_is_new = false;
932 load_session (path, state);
936 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
940 if (stat (info.filename.c_str(), &statbuf) != 0) {
944 if (!S_ISDIR(statbuf.st_mode)) {
950 string session_file = info.filename;
952 session_file += Glib::path_get_basename (info.filename);
953 session_file += ".ardour";
955 if (stat (session_file.c_str(), &statbuf) != 0) {
959 return S_ISREG (statbuf.st_mode);
963 ARDOUR_UI::check_audioengine ()
966 if (!engine->connected()) {
967 MessageDialog msg (_("Ardour is not connected to JACK\n"
968 "You cannot open or close sessions in this condition"));
979 ARDOUR_UI::open_session ()
981 if (!check_audioengine()) {
986 /* popup selector window */
988 if (open_session_selector == 0) {
990 /* ardour sessions are folders */
992 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
993 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
994 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
996 FileFilter session_filter;
997 session_filter.add_pattern ("*.ardour");
998 session_filter.set_name (_("Ardour sessions"));
999 open_session_selector->add_filter (session_filter);
1000 open_session_selector->set_filter (session_filter);
1003 int response = open_session_selector->run();
1004 open_session_selector->hide ();
1007 case RESPONSE_ACCEPT:
1010 open_session_selector->hide();
1014 open_session_selector->hide();
1015 string session_path = open_session_selector->get_filename();
1019 if (session_path.length() > 0) {
1020 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1021 _session_is_new = isnew;
1022 load_session (path, name);
1029 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1031 list<boost::shared_ptr<MidiTrack> > tracks;
1034 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1041 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1043 if (tracks.size() != how_many) {
1044 if (how_many == 1) {
1045 error << _("could not create a new midi track") << endmsg;
1047 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1051 if ((route = session->new_midi_route ()) == 0) {
1052 error << _("could not create new midi bus") << endmsg;
1058 MessageDialog msg (*editor,
1059 _("There are insufficient JACK ports available\n\
1060 to create a new track or bus.\n\
1061 You should save Ardour, exit and\n\
1062 restart JACK with more ports."));
1069 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1071 list<boost::shared_ptr<AudioTrack> > tracks;
1072 Session::RouteList routes;
1075 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1081 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1083 if (tracks.size() != how_many) {
1084 if (how_many == 1) {
1085 error << _("could not create a new audio track") << endmsg;
1087 error << string_compose (_("could only create %1 of %2 new audio %3"),
1088 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1094 routes = session->new_audio_route (input_channels, output_channels, how_many);
1096 if (routes.size() != how_many) {
1097 if (how_many == 1) {
1098 error << _("could not create a new audio track") << endmsg;
1100 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1106 if (need_control_room_outs) {
1112 route->set_stereo_control_outs (control_lr_channels);
1113 route->control_outs()->set_stereo_pan (pans, this);
1115 #endif /* CONTROLOUTS */
1119 cerr << "About to complain about JACK\n";
1120 MessageDialog msg (*editor,
1121 _("There are insufficient JACK ports available\n\
1122 to create a new track or bus.\n\
1123 You should save Ardour, exit and\n\
1124 restart JACK with more ports."));
1130 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1132 nframes_t _preroll = 0;
1135 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1136 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1138 if (new_position > _preroll) {
1139 new_position -= _preroll;
1144 session->request_locate (new_position);
1149 ARDOUR_UI::transport_goto_start ()
1152 session->goto_start();
1155 /* force displayed area in editor to start no matter
1156 what "follow playhead" setting is.
1160 editor->reset_x_origin (session->current_start_frame());
1166 ARDOUR_UI::transport_goto_zero ()
1169 session->request_locate (0);
1172 /* force displayed area in editor to start no matter
1173 what "follow playhead" setting is.
1177 editor->reset_x_origin (0);
1183 ARDOUR_UI::transport_goto_end ()
1186 nframes_t frame = session->current_end_frame();
1187 session->request_locate (frame);
1189 /* force displayed area in editor to start no matter
1190 what "follow playhead" setting is.
1194 editor->reset_x_origin (frame);
1200 ARDOUR_UI::transport_stop ()
1206 if (session->is_auditioning()) {
1207 session->cancel_audition ();
1211 if (session->get_play_loop ()) {
1212 session->request_play_loop (false);
1215 session->request_stop ();
1219 ARDOUR_UI::transport_stop_and_forget_capture ()
1222 session->request_stop (true);
1227 ARDOUR_UI::remove_last_capture()
1230 editor->remove_last_capture();
1235 ARDOUR_UI::transport_record ()
1238 switch (session->record_status()) {
1239 case Session::Disabled:
1240 if (session->ntracks() == 0) {
1241 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1245 session->maybe_enable_record ();
1247 case Session::Recording:
1248 case Session::Enabled:
1249 session->disable_record (false, true);
1255 ARDOUR_UI::transport_roll ()
1263 rolling = session->transport_rolling ();
1265 if (session->get_play_loop()) {
1266 session->request_play_loop (false);
1267 auto_loop_button.set_visual_state (1);
1268 roll_button.set_visual_state (1);
1269 } else if (session->get_play_range ()) {
1270 session->request_play_range (false);
1271 play_selection_button.set_visual_state (0);
1272 } else if (rolling) {
1273 session->request_locate (session->last_transport_start(), true);
1276 session->request_transport_speed (1.0f);
1280 ARDOUR_UI::transport_loop()
1283 if (session->get_play_loop()) {
1284 if (session->transport_rolling()) {
1285 Location * looploc = session->locations()->auto_loop_location();
1287 session->request_locate (looploc->start(), true);
1292 session->request_play_loop (true);
1298 ARDOUR_UI::transport_play_selection ()
1304 if (!session->get_play_range()) {
1305 session->request_stop ();
1308 editor->play_selection ();
1312 ARDOUR_UI::transport_rewind (int option)
1314 float current_transport_speed;
1317 current_transport_speed = session->transport_speed();
1319 if (current_transport_speed >= 0.0f) {
1322 session->request_transport_speed (-1.0f);
1325 session->request_transport_speed (-4.0f);
1328 session->request_transport_speed (-0.5f);
1333 session->request_transport_speed (current_transport_speed * 1.5f);
1339 ARDOUR_UI::transport_forward (int option)
1341 float current_transport_speed;
1344 current_transport_speed = session->transport_speed();
1346 if (current_transport_speed <= 0.0f) {
1349 session->request_transport_speed (1.0f);
1352 session->request_transport_speed (4.0f);
1355 session->request_transport_speed (0.5f);
1360 session->request_transport_speed (current_transport_speed * 1.5f);
1366 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1372 boost::shared_ptr<Route> r;
1374 if ((r = session->route_by_remote_id (dstream)) != 0) {
1378 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1379 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1388 ARDOUR_UI::queue_transport_change ()
1390 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1394 ARDOUR_UI::map_transport_state ()
1396 float sp = session->transport_speed();
1399 transport_rolling ();
1400 } else if (sp < 0.0f) {
1401 transport_rewinding ();
1402 } else if (sp > 0.0f) {
1403 transport_forwarding ();
1405 transport_stopped ();
1410 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1412 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1413 (int) adj.get_value()].c_str());
1417 ARDOUR_UI::engine_stopped ()
1419 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1420 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1421 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1425 ARDOUR_UI::engine_running ()
1427 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1428 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1429 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1431 Glib::RefPtr<Action> action;
1432 char* action_name = 0;
1434 switch (engine->frames_per_cycle()) {
1436 action_name = X_("JACKLatency32");
1439 action_name = X_("JACKLatency64");
1442 action_name = X_("JACKLatency128");
1445 action_name = X_("JACKLatency512");
1448 action_name = X_("JACKLatency1024");
1451 action_name = X_("JACKLatency2048");
1454 action_name = X_("JACKLatency4096");
1457 action_name = X_("JACKLatency8192");
1460 /* XXX can we do anything useful ? */
1466 action = ActionManager::get_action (X_("JACK"), action_name);
1469 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1470 ract->set_active ();
1476 ARDOUR_UI::engine_halted ()
1478 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1480 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1481 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1483 update_sample_rate (0);
1485 MessageDialog msg (*editor,
1487 JACK has either been shutdown or it\n\
1488 disconnected Ardour because Ardour\n\
1489 was not fast enough. You can save the\n\
1490 session and/or try to reconnect to JACK ."));
1495 ARDOUR_UI::do_engine_start ()
1503 error << _("Unable to start the session running")
1513 ARDOUR_UI::setup_theme ()
1515 theme_manager->setup_theme();
1519 ARDOUR_UI::start_engine ()
1521 if (do_engine_start () == 0) {
1522 if (session && _session_is_new) {
1523 /* we need to retain initial visual
1524 settings for a new session
1526 session->save_state ("");
1534 ARDOUR_UI::update_clocks ()
1536 if (!editor || !editor->dragging_playhead()) {
1537 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1542 ARDOUR_UI::start_clocking ()
1544 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1548 ARDOUR_UI::stop_clocking ()
1550 clock_signal_connection.disconnect ();
1554 ARDOUR_UI::toggle_clocking ()
1557 if (clock_button.get_active()) {
1566 ARDOUR_UI::_blink (void *arg)
1569 ((ARDOUR_UI *) arg)->blink ();
1576 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1580 ARDOUR_UI::start_blinking ()
1582 /* Start the blink signal. Everybody with a blinking widget
1583 uses Blink to drive the widget's state.
1586 if (blink_timeout_tag < 0) {
1588 blink_timeout_tag = g_timeout_add (240, _blink, this);
1593 ARDOUR_UI::stop_blinking ()
1595 if (blink_timeout_tag >= 0) {
1596 g_source_remove (blink_timeout_tag);
1597 blink_timeout_tag = -1;
1602 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1608 if (io.n_inputs().n_total() == 0) {
1613 /* XXX we're not handling multiple ports yet. */
1615 const char **connections = io.input(0)->get_connections();
1617 if (connections == 0 || connections[0] == '\0') {
1620 buf = connections[0];
1627 if (io.n_outputs().n_total() == 0) {
1632 /* XXX we're not handling multiple ports yet. */
1634 const char **connections = io.output(0)->get_connections();
1636 if (connections == 0 || connections[0] == '\0') {
1639 buf = connections[0];
1646 /** Ask the user for the name of a new shapshot and then take it.
1649 ARDOUR_UI::snapshot_session ()
1651 ArdourPrompter prompter (true);
1655 struct tm local_time;
1658 localtime_r (&n, &local_time);
1659 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1661 prompter.set_name ("Prompter");
1662 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1663 prompter.set_prompt (_("Name of New Snapshot"));
1664 prompter.set_initial_text (timebuf);
1666 switch (prompter.run()) {
1667 case RESPONSE_ACCEPT:
1668 prompter.get_result (snapname);
1669 if (snapname.length()){
1670 save_state (snapname);
1680 ARDOUR_UI::save_state (const string & name)
1682 (void) save_state_canfail (name);
1686 ARDOUR_UI::save_state_canfail (string name)
1691 if (name.length() == 0) {
1692 name = session->snap_name();
1695 if ((ret = session->save_state (name)) != 0) {
1699 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1704 ARDOUR_UI::restore_state (string name)
1707 if (name.length() == 0) {
1708 name = session->name();
1710 session->restore_state (name);
1715 ARDOUR_UI::primary_clock_value_changed ()
1718 session->request_locate (primary_clock.current_time ());
1723 ARDOUR_UI::secondary_clock_value_changed ()
1726 session->request_locate (secondary_clock.current_time ());
1731 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1733 if (session && dstream && dstream->record_enabled()) {
1735 Session::RecordState rs;
1737 rs = session->record_status ();
1740 case Session::Disabled:
1741 case Session::Enabled:
1742 if (w->get_state() != STATE_SELECTED) {
1743 w->set_state (STATE_SELECTED);
1747 case Session::Recording:
1748 if (w->get_state() != STATE_ACTIVE) {
1749 w->set_state (STATE_ACTIVE);
1755 if (w->get_state() != STATE_NORMAL) {
1756 w->set_state (STATE_NORMAL);
1762 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1768 switch (session->record_status()) {
1769 case Session::Enabled:
1771 rec_button.set_visual_state (2);
1773 rec_button.set_visual_state (0);
1777 case Session::Recording:
1778 rec_button.set_visual_state (1);
1782 rec_button.set_visual_state (0);
1788 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1796 ARDOUR_UI::save_template ()
1799 ArdourPrompter prompter (true);
1802 prompter.set_name (X_("Prompter"));
1803 prompter.set_prompt (_("Name for mix template:"));
1804 prompter.set_initial_text(session->name() + _("-template"));
1805 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1807 switch (prompter.run()) {
1808 case RESPONSE_ACCEPT:
1809 prompter.get_result (name);
1811 if (name.length()) {
1812 session->save_template (name);
1822 ARDOUR_UI::new_session (std::string predetermined_path)
1824 string session_name;
1825 string session_path;
1827 if (!check_audioengine()) {
1831 int response = Gtk::RESPONSE_NONE;
1833 new_session_dialog->set_modal(true);
1834 new_session_dialog->set_name (predetermined_path);
1835 new_session_dialog->reset_recent();
1836 new_session_dialog->show();
1837 new_session_dialog->set_current_page (0);
1840 response = new_session_dialog->run ();
1842 if (!check_audioengine()) {
1843 new_session_dialog->hide ();
1847 _session_is_new = false;
1849 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1854 new_session_dialog->hide ();
1857 } else if (response == Gtk::RESPONSE_NONE) {
1859 /* Clear was pressed */
1860 new_session_dialog->reset();
1862 } else if (response == Gtk::RESPONSE_YES) {
1864 /* YES == OPEN, but there's no enum for that */
1866 session_name = new_session_dialog->session_name();
1868 if (session_name.empty()) {
1869 response = Gtk::RESPONSE_NONE;
1873 if (session_name[0] == '/' ||
1874 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1875 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1876 load_session (Glib::path_get_dirname (session_name), session_name);
1878 session_path = new_session_dialog->session_folder();
1879 load_session (session_path, session_name);
1882 } else if (response == Gtk::RESPONSE_OK) {
1884 session_name = new_session_dialog->session_name();
1886 if (!new_session_dialog->on_new_session_page ()) {
1888 /* XXX this is a bit of a hack..
1889 i really want the new sesion dialog to return RESPONSE_YES
1890 if we're on page 1 (the load page)
1891 Unfortunately i can't see how atm..
1894 if (session_name.empty()) {
1895 response = Gtk::RESPONSE_NONE;
1899 if (session_name[0] == '/' ||
1900 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1901 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1902 load_session (Glib::path_get_dirname (session_name), session_name);
1904 session_path = new_session_dialog->session_folder();
1905 load_session (session_path, session_name);
1910 if (session_name.empty()) {
1911 response = Gtk::RESPONSE_NONE;
1915 if (session_name[0] == '/' ||
1916 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1917 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1919 session_path = Glib::path_get_dirname (session_name);
1920 session_name = Glib::path_get_basename (session_name);
1924 session_path = new_session_dialog->session_folder();
1928 //XXX This is needed because session constructor wants a
1929 //non-existant path. hopefully this will be fixed at some point.
1931 session_path = Glib::build_filename (session_path, session_name);
1933 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1935 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1937 MessageDialog msg (str,
1939 Gtk::MESSAGE_WARNING,
1940 Gtk::BUTTONS_YES_NO,
1944 msg.set_name (X_("CleanupDialog"));
1945 msg.set_wmclass (X_("existing_session"), "Ardour");
1946 msg.set_position (Gtk::WIN_POS_MOUSE);
1948 switch (msg.run()) {
1950 load_session (session_path, session_name);
1954 response = RESPONSE_NONE;
1955 new_session_dialog->reset ();
1960 _session_is_new = true;
1962 std::string template_name = new_session_dialog->session_template_name();
1964 if (new_session_dialog->use_session_template()) {
1966 load_session (session_path, session_name, &template_name);
1972 AutoConnectOption iconnect;
1973 AutoConnectOption oconnect;
1975 if (new_session_dialog->create_control_bus()) {
1976 cchns = (uint32_t) new_session_dialog->control_channel_count();
1981 if (new_session_dialog->create_master_bus()) {
1982 mchns = (uint32_t) new_session_dialog->master_channel_count();
1987 if (new_session_dialog->connect_inputs()) {
1988 iconnect = AutoConnectPhysical;
1990 iconnect = AutoConnectOption (0);
1993 /// @todo some minor tweaks.
1995 if (new_session_dialog->connect_outs_to_master()) {
1996 oconnect = AutoConnectMaster;
1997 } else if (new_session_dialog->connect_outs_to_physical()) {
1998 oconnect = AutoConnectPhysical;
2000 oconnect = AutoConnectOption (0);
2003 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2004 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2006 if (!build_session (session_path,
2014 engine->frame_rate() * 60 * 5)) {
2016 response = Gtk::RESPONSE_NONE;
2017 new_session_dialog->reset ();
2024 } while (response == Gtk::RESPONSE_NONE);
2028 new_session_dialog->get_window()->set_cursor();
2029 new_session_dialog->hide();
2034 ARDOUR_UI::close_session()
2036 if (!check_audioengine()) {
2045 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2047 Session *new_session;
2048 session_loaded = false;
2050 if (!check_audioengine()) {
2054 if(!unload_session ()) return -1;
2056 /* if it already exists, we must have write access */
2058 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2059 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2060 "This prevents the session from being loaded."));
2066 new_session = new Session (*engine, path, snap_name, mix_template);
2071 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2075 connect_to_session (new_session);
2077 Config->set_current_owner (ConfigVariableBase::Interface);
2079 session_loaded = true;
2081 goto_editor_window ();
2084 session->set_clean ();
2087 editor->edit_cursor_position (true);
2092 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2093 uint32_t control_channels,
2094 uint32_t master_channels,
2095 AutoConnectOption input_connect,
2096 AutoConnectOption output_connect,
2099 nframes_t initial_length)
2101 Session *new_session;
2103 if (!check_audioengine()) {
2107 session_loaded = false;
2109 if (!unload_session ()) return false;
2111 _session_is_new = true;
2114 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2115 control_channels, master_channels, nphysin, nphysout, initial_length);
2120 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2125 connect_to_session (new_session);
2127 session_loaded = true;
2135 editor->show_window ();
2146 ARDOUR_UI::show_splash ()
2149 about = new About();
2150 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2157 ARDOUR_UI::about_signal_response(int response)
2163 ARDOUR_UI::hide_splash ()
2166 about->get_window()->set_cursor ();
2172 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2176 removed = rep.paths.size();
2179 MessageDialog msgd (*editor,
2180 _("No audio files were ready for cleanup"),
2183 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2184 msgd.set_secondary_text (_("If this seems suprising, \n\
2185 check for any existing snapshots.\n\
2186 These may still include regions that\n\
2187 require some unused files to continue to exist."));
2193 ArdourDialog results (_("ardour: cleanup"), true, false);
2195 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2196 CleanupResultsModelColumns() {
2200 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2201 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2205 CleanupResultsModelColumns results_columns;
2206 Glib::RefPtr<Gtk::ListStore> results_model;
2207 Gtk::TreeView results_display;
2209 results_model = ListStore::create (results_columns);
2210 results_display.set_model (results_model);
2211 results_display.append_column (list_title, results_columns.visible_name);
2213 results_display.set_name ("CleanupResultsList");
2214 results_display.set_headers_visible (true);
2215 results_display.set_headers_clickable (false);
2216 results_display.set_reorderable (false);
2218 Gtk::ScrolledWindow list_scroller;
2221 Gtk::HBox dhbox; // the hbox for the image and text
2222 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2223 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2225 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2227 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2229 if (rep.space < 1048576.0f) {
2231 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2233 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2237 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2239 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2243 dhbox.pack_start (*dimage, true, false, 5);
2244 dhbox.pack_start (txt, true, false, 5);
2246 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2247 TreeModel::Row row = *(results_model->append());
2248 row[results_columns.visible_name] = *i;
2249 row[results_columns.fullpath] = *i;
2252 list_scroller.add (results_display);
2253 list_scroller.set_size_request (-1, 150);
2254 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2256 dvbox.pack_start (dhbox, true, false, 5);
2257 dvbox.pack_start (list_scroller, true, false, 5);
2258 ddhbox.pack_start (dvbox, true, false, 5);
2260 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2261 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2262 results.set_default_response (RESPONSE_CLOSE);
2263 results.set_position (Gtk::WIN_POS_MOUSE);
2264 results.show_all_children ();
2265 results.set_resizable (false);
2272 ARDOUR_UI::cleanup ()
2275 /* shouldn't happen: menu item is insensitive */
2280 MessageDialog checker (_("Are you sure you want to cleanup?"),
2282 Gtk::MESSAGE_QUESTION,
2283 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2285 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2286 ALL undo/redo information will be lost if you cleanup.\n\
2287 After cleanup, unused audio files will be moved to a \
2288 \"dead sounds\" location."));
2290 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2291 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2292 checker.set_default_response (RESPONSE_CANCEL);
2294 checker.set_name (_("CleanupDialog"));
2295 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2296 checker.set_position (Gtk::WIN_POS_MOUSE);
2298 switch (checker.run()) {
2299 case RESPONSE_ACCEPT:
2305 Session::cleanup_report rep;
2307 editor->prepare_for_cleanup ();
2309 /* do not allow flush until a session is reloaded */
2311 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2313 act->set_sensitive (false);
2316 if (session->cleanup_sources (rep)) {
2321 display_cleanup_results (rep,
2324 The following %1 %2 not in use and \n\
2325 have been moved to:\n\
2327 Flushing the wastebasket will \n\
2328 release an additional\n\
2329 %4 %5bytes of disk space.\n"
2337 ARDOUR_UI::flush_trash ()
2340 /* shouldn't happen: menu item is insensitive */
2344 Session::cleanup_report rep;
2346 if (session->cleanup_trash_sources (rep)) {
2350 display_cleanup_results (rep,
2352 _("The following %1 %2 deleted from\n\
2354 releasing %4 %5bytes of disk space"));
2358 ARDOUR_UI::add_route (Gtk::Window* float_window)
2366 if (add_route_dialog == 0) {
2367 add_route_dialog = new AddRouteDialog;
2369 add_route_dialog->set_transient_for (*float_window);
2373 if (add_route_dialog->is_visible()) {
2374 /* we're already doing this */
2378 ResponseType r = (ResponseType) add_route_dialog->run ();
2380 add_route_dialog->hide();
2383 case RESPONSE_ACCEPT:
2390 if ((count = add_route_dialog->count()) <= 0) {
2394 uint32_t input_chan = add_route_dialog->channels ();
2395 uint32_t output_chan;
2396 string name_template = add_route_dialog->name_template ();
2397 bool track = add_route_dialog->track ();
2399 AutoConnectOption oac = Config->get_output_auto_connect();
2401 if (oac & AutoConnectMaster) {
2402 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2404 output_chan = input_chan;
2407 /* XXX do something with name template */
2409 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2411 session_add_midi_track(count);
2413 MessageDialog msg (*editor,
2414 _("Sorry, MIDI Busses are not supported at this time."));
2416 //session_add_midi_bus();
2420 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2422 session_add_audio_bus (input_chan, output_chan, count);
2428 ARDOUR_UI::mixer_settings () const
2433 node = session->instant_xml(X_("Mixer"));
2435 node = Config->instant_xml(X_("Mixer"));
2439 node = new XMLNode (X_("Mixer"));
2446 ARDOUR_UI::editor_settings () const
2451 node = session->instant_xml(X_("Editor"));
2453 node = Config->instant_xml(X_("Editor"));
2457 node = new XMLNode (X_("Editor"));
2463 ARDOUR_UI::keyboard_settings () const
2467 node = Config->extra_xml(X_("Keyboard"));
2470 node = new XMLNode (X_("Keyboard"));
2476 ARDOUR_UI::halt_on_xrun_message ()
2478 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2480 MessageDialog msg (*editor,
2481 _("Recording was stopped because your system could not keep up."));
2486 ARDOUR_UI::disk_overrun_handler ()
2488 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2490 if (!have_disk_speed_dialog_displayed) {
2491 have_disk_speed_dialog_displayed = true;
2492 MessageDialog* msg = new MessageDialog (*editor, _("\
2493 The disk system on your computer\n\
2494 was not able to keep up with Ardour.\n\
2496 Specifically, it failed to write data to disk\n\
2497 quickly enough to keep up with recording.\n"));
2498 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2504 ARDOUR_UI::disk_underrun_handler ()
2506 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2508 if (!have_disk_speed_dialog_displayed) {
2509 have_disk_speed_dialog_displayed = true;
2510 MessageDialog* msg = new MessageDialog (*editor,
2511 _("The disk system on your computer\n\
2512 was not able to keep up with Ardour.\n\
2514 Specifically, it failed to read data from disk\n\
2515 quickly enough to keep up with playback.\n"));
2516 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2522 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2524 have_disk_speed_dialog_displayed = false;
2529 ARDOUR_UI::pending_state_dialog ()
2531 ArdourDialog dialog ("pending state dialog");
2533 This session appears to have been in\n\
2534 middle of recording when ardour or\n\
2535 the computer was shutdown.\n\
2537 Ardour can recover any captured audio for\n\
2538 you, or it can ignore it. Please decide\n\
2539 what you would like to do.\n"));
2541 dialog.get_vbox()->pack_start (message);
2542 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2543 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2545 dialog.set_position (WIN_POS_CENTER);
2548 switch (dialog.run ()) {
2549 case RESPONSE_ACCEPT:
2557 ARDOUR_UI::disconnect_from_jack ()
2560 if( engine->disconnect_from_jack ()) {
2561 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2565 update_sample_rate (0);
2570 ARDOUR_UI::reconnect_to_jack ()
2573 if (engine->reconnect_to_jack ()) {
2574 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2578 update_sample_rate (0);
2583 ARDOUR_UI::cmdline_new_session (string path)
2585 if (path[0] != '/') {
2586 char buf[PATH_MAX+1];
2589 getcwd (buf, sizeof (buf));
2598 return FALSE; /* don't call it again */
2602 ARDOUR_UI::use_config ()
2604 Glib::RefPtr<Action> act;
2606 switch (Config->get_native_file_data_format ()) {
2608 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2611 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2616 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2617 ract->set_active ();
2620 switch (Config->get_native_file_header_format ()) {
2622 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2625 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2628 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2631 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2634 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2637 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2640 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2645 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2646 ract->set_active ();
2649 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2651 set_transport_controllable_state (*node);
2656 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2658 if (Config->get_primary_clock_delta_edit_cursor()) {
2659 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2661 primary_clock.set (pos, 0, true);
2664 if (Config->get_secondary_clock_delta_edit_cursor()) {
2665 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2667 secondary_clock.set (pos);
2670 if (big_clock_window) {
2671 big_clock.set (pos);
2676 ARDOUR_UI::record_state_changed ()
2678 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2680 if (!session || !big_clock_window) {
2681 /* why bother - the clock isn't visible */
2685 switch (session->record_status()) {
2686 case Session::Recording:
2687 big_clock.set_widget_name ("BigClockRecording");
2690 big_clock.set_widget_name ("BigClockNonRecording");
2696 ARDOUR_UI::set_keybindings_path (string path)
2698 keybindings_path = path;
2702 ARDOUR_UI::save_keybindings ()
2704 if (can_save_keybindings) {
2705 AccelMap::save (keybindings_path);
2710 ARDOUR_UI::first_idle ()
2713 session->allow_auto_play (true);
2715 can_save_keybindings = true;
2720 ARDOUR_UI::store_clock_modes ()
2722 XMLNode* node = new XMLNode(X_("ClockModes"));
2724 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2725 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2728 session->add_extra_xml (*node);
2729 session->set_dirty ();
2734 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2735 : Controllable (name), ui (u), type(tp)
2741 ARDOUR_UI::TransportControllable::set_value (float val)
2743 if (type == ShuttleControl) {
2750 fract = -((0.5f - val)/0.5f);
2752 fract = ((val - 0.5f)/0.5f);
2756 ui.set_shuttle_fract (fract);
2761 /* do nothing: these are radio-style actions */
2769 action = X_("Roll");
2772 action = X_("Stop");
2775 action = X_("Goto Start");
2778 action = X_("Goto End");
2781 action = X_("Loop");
2784 action = X_("Play Selection");
2787 action = X_("Record");
2797 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2805 ARDOUR_UI::TransportControllable::get_value (void) const
2824 case ShuttleControl:
2834 ARDOUR_UI::TransportControllable::set_id (const string& str)
2840 ARDOUR_UI::setup_profile ()
2842 if (gdk_screen_width() < 1200) {
2843 Profile->set_small_screen ();
2848 ARDOUR_UI::disable_all_plugins ()
2854 // session->begin_reversible_command (_("Disable all plugins"));
2856 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2858 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2859 // XMLNode& before = (*i)->get_redirect_state ();
2860 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2861 (*i)->disable_plugins ();
2862 // XMLNode& after = (*i)->get_redirect_state ();
2863 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2867 // session->commit_reversible_command ();
2871 ARDOUR_UI::ab_all_plugins ()
2877 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2879 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2880 (*i)->ab_plugins (ab_direction);
2883 ab_direction = !ab_direction;