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);
537 editor->ensure_float (msg);
549 if (session && session->dirty()) {
550 switch (ask_about_saving_session(_("quit"))) {
555 /* use the default name */
556 if (save_state_canfail ("")) {
557 /* failed - don't quit */
558 MessageDialog msg (*editor,
560 Ardour was unable to save your session.\n\n\
561 If you still wish to quit, please use the\n\n\
562 \"Just quit\" option."));
573 session->set_deletion_in_progress ();
576 Config->save_state();
577 ARDOUR_UI::config()->save_state();
582 ARDOUR_UI::ask_about_saving_session (const string & what)
584 ArdourDialog window (_("ardour: save session?"));
585 Gtk::HBox dhbox; // the hbox for the image and text
586 Gtk::Label prompt_label;
587 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
591 msg = string_compose(_("Don't %1"), what);
592 window.add_button (msg, RESPONSE_REJECT);
593 msg = string_compose(_("Just %1"), what);
594 window.add_button (msg, RESPONSE_APPLY);
595 msg = string_compose(_("Save and %1"), what);
596 window.add_button (msg, RESPONSE_ACCEPT);
598 window.set_default_response (RESPONSE_ACCEPT);
600 Gtk::Button noquit_button (msg);
601 noquit_button.set_name ("EditorGTKButton");
606 if (session->snap_name() == session->name()) {
609 type = _("snapshot");
611 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?"),
612 type, session->snap_name());
614 prompt_label.set_text (prompt);
615 prompt_label.set_name (X_("PrompterLabel"));
616 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
618 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
620 dhbox.set_homogeneous (false);
621 dhbox.pack_start (*dimage, false, false, 5);
622 dhbox.pack_start (prompt_label, true, false, 5);
623 window.get_vbox()->pack_start (dhbox);
625 window.set_name (_("Prompter"));
626 window.set_position (Gtk::WIN_POS_MOUSE);
627 window.set_modal (true);
628 window.set_resizable (false);
635 save_the_session = 0;
637 window.set_keep_above (true);
640 ResponseType r = (ResponseType) window.run();
645 case RESPONSE_ACCEPT: // save and get out of here
647 case RESPONSE_APPLY: // get out of here
657 ARDOUR_UI::every_second ()
660 update_buffer_load ();
661 update_disk_space ();
666 ARDOUR_UI::every_point_one_seconds ()
668 update_speed_display ();
669 RapidScreenUpdate(); /* EMIT_SIGNAL */
674 ARDOUR_UI::every_point_zero_one_seconds ()
676 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
681 ARDOUR_UI::update_sample_rate (nframes_t ignored)
685 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
687 if (!engine->connected()) {
689 snprintf (buf, sizeof (buf), _("disconnected"));
693 nframes_t rate = engine->frame_rate();
695 if (fmod (rate, 1000.0) != 0.0) {
696 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
697 (float) rate/1000.0f,
698 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
700 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
702 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
706 sample_rate_label.set_text (buf);
710 ARDOUR_UI::update_cpu_load ()
713 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
714 cpu_load_label.set_text (buf);
718 ARDOUR_UI::update_buffer_load ()
723 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
724 session->playback_load(), session->capture_load());
725 buffer_load_label.set_text (buf);
727 buffer_load_label.set_text ("");
732 ARDOUR_UI::count_recenabled_streams (Route& route)
734 Track* track = dynamic_cast<Track*>(&route);
735 if (track && track->diskstream()->record_enabled()) {
736 rec_enabled_streams += track->n_inputs().n_total();
741 ARDOUR_UI::update_disk_space()
747 nframes_t frames = session->available_capture_duration();
750 if (frames == max_frames) {
751 strcpy (buf, _("Disk: 24hrs+"));
756 nframes_t fr = session->frame_rate();
758 rec_enabled_streams = 0;
759 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
761 if (rec_enabled_streams) {
762 frames /= rec_enabled_streams;
765 hrs = frames / (fr * 3600);
766 frames -= hrs * fr * 3600;
767 mins = frames / (fr * 60);
768 frames -= mins * fr * 60;
771 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
774 disk_space_label.set_text (buf);
778 ARDOUR_UI::update_wall_clock ()
785 tm_now = localtime (&now);
787 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
788 wall_clock_label.set_text (buf);
794 ARDOUR_UI::session_menu (GdkEventButton *ev)
796 session_popup_menu->popup (0, 0);
801 ARDOUR_UI::redisplay_recent_sessions ()
803 vector<string *> *sessions;
804 vector<string *>::iterator i;
805 RecentSessionsSorter cmp;
807 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
808 recent_session_model->clear ();
811 ARDOUR::read_recent_sessions (rs);
814 recent_session_display.set_model (recent_session_model);
818 /* sort them alphabetically */
819 sort (rs.begin(), rs.end(), cmp);
820 sessions = new vector<string*>;
822 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
823 sessions->push_back (new string ((*i).second));
826 for (i = sessions->begin(); i != sessions->end(); ++i) {
828 vector<string*>* states;
829 vector<const gchar*> item;
830 string fullpath = *(*i);
832 /* remove any trailing / */
834 if (fullpath[fullpath.length()-1] == '/') {
835 fullpath = fullpath.substr (0, fullpath.length()-1);
838 /* now get available states for this session */
840 if ((states = Session::possible_states (fullpath)) == 0) {
845 TreeModel::Row row = *(recent_session_model->append());
847 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
848 row[recent_session_columns.fullpath] = fullpath;
850 if (states->size() > 1) {
852 /* add the children */
854 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
856 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
858 child_row[recent_session_columns.visible_name] = **i2;
859 child_row[recent_session_columns.fullpath] = fullpath;
868 recent_session_display.set_model (recent_session_model);
873 ARDOUR_UI::build_session_selector ()
875 session_selector_window = new ArdourDialog ("session selector");
877 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
879 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
880 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
881 session_selector_window->set_default_response (RESPONSE_ACCEPT);
882 recent_session_model = TreeStore::create (recent_session_columns);
883 recent_session_display.set_model (recent_session_model);
884 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
885 recent_session_display.set_headers_visible (false);
886 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
888 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
890 scroller->add (recent_session_display);
891 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
893 session_selector_window->set_name ("SessionSelectorWindow");
894 session_selector_window->set_size_request (200, 400);
895 session_selector_window->get_vbox()->pack_start (*scroller);
897 recent_session_display.show();
899 //session_selector_window->get_vbox()->show();
903 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
905 session_selector_window->response (RESPONSE_ACCEPT);
909 ARDOUR_UI::open_recent_session ()
911 /* popup selector window */
913 if (session_selector_window == 0) {
914 build_session_selector ();
917 redisplay_recent_sessions ();
919 ResponseType r = (ResponseType) session_selector_window->run ();
921 session_selector_window->hide();
924 case RESPONSE_ACCEPT:
930 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
932 if (i == recent_session_model->children().end()) {
936 Glib::ustring path = (*i)[recent_session_columns.fullpath];
937 Glib::ustring state = (*i)[recent_session_columns.visible_name];
939 _session_is_new = false;
941 load_session (path, state);
945 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
949 if (stat (info.filename.c_str(), &statbuf) != 0) {
953 if (!S_ISDIR(statbuf.st_mode)) {
959 string session_file = info.filename;
961 session_file += Glib::path_get_basename (info.filename);
962 session_file += ".ardour";
964 if (stat (session_file.c_str(), &statbuf) != 0) {
968 return S_ISREG (statbuf.st_mode);
972 ARDOUR_UI::check_audioengine ()
975 if (!engine->connected()) {
976 MessageDialog msg (_("Ardour is not connected to JACK\n"
977 "You cannot open or close sessions in this condition"));
988 ARDOUR_UI::open_session ()
990 if (!check_audioengine()) {
995 /* popup selector window */
997 if (open_session_selector == 0) {
999 /* ardour sessions are folders */
1001 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1002 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1003 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1005 FileFilter session_filter;
1006 session_filter.add_pattern ("*.ardour");
1007 session_filter.set_name (_("Ardour sessions"));
1008 open_session_selector->add_filter (session_filter);
1009 open_session_selector->set_filter (session_filter);
1012 int response = open_session_selector->run();
1013 open_session_selector->hide ();
1016 case RESPONSE_ACCEPT:
1019 open_session_selector->hide();
1023 open_session_selector->hide();
1024 string session_path = open_session_selector->get_filename();
1028 if (session_path.length() > 0) {
1029 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1030 _session_is_new = isnew;
1031 load_session (path, name);
1038 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1040 list<boost::shared_ptr<MidiTrack> > tracks;
1043 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1050 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1052 if (tracks.size() != how_many) {
1053 if (how_many == 1) {
1054 error << _("could not create a new midi track") << endmsg;
1056 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1060 if ((route = session->new_midi_route ()) == 0) {
1061 error << _("could not create new midi bus") << endmsg;
1067 MessageDialog msg (*editor,
1068 _("There are insufficient JACK ports available\n\
1069 to create a new track or bus.\n\
1070 You should save Ardour, exit and\n\
1071 restart JACK with more ports."));
1078 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1080 list<boost::shared_ptr<AudioTrack> > tracks;
1081 Session::RouteList routes;
1084 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1090 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1092 if (tracks.size() != how_many) {
1093 if (how_many == 1) {
1094 error << _("could not create a new audio track") << endmsg;
1096 error << string_compose (_("could only create %1 of %2 new audio %3"),
1097 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1103 routes = session->new_audio_route (input_channels, output_channels, how_many);
1105 if (routes.size() != how_many) {
1106 if (how_many == 1) {
1107 error << _("could not create a new audio track") << endmsg;
1109 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1115 if (need_control_room_outs) {
1121 route->set_stereo_control_outs (control_lr_channels);
1122 route->control_outs()->set_stereo_pan (pans, this);
1124 #endif /* CONTROLOUTS */
1128 cerr << "About to complain about JACK\n";
1129 MessageDialog msg (*editor,
1130 _("There are insufficient JACK ports available\n\
1131 to create a new track or bus.\n\
1132 You should save Ardour, exit and\n\
1133 restart JACK with more ports."));
1139 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1141 nframes_t _preroll = 0;
1144 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1145 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1147 if (new_position > _preroll) {
1148 new_position -= _preroll;
1153 session->request_locate (new_position);
1158 ARDOUR_UI::transport_goto_start ()
1161 session->goto_start();
1164 /* force displayed area in editor to start no matter
1165 what "follow playhead" setting is.
1169 editor->reset_x_origin (session->current_start_frame());
1175 ARDOUR_UI::transport_goto_zero ()
1178 session->request_locate (0);
1181 /* force displayed area in editor to start no matter
1182 what "follow playhead" setting is.
1186 editor->reset_x_origin (0);
1192 ARDOUR_UI::transport_goto_end ()
1195 nframes_t frame = session->current_end_frame();
1196 session->request_locate (frame);
1198 /* force displayed area in editor to start no matter
1199 what "follow playhead" setting is.
1203 editor->reset_x_origin (frame);
1209 ARDOUR_UI::transport_stop ()
1215 if (session->is_auditioning()) {
1216 session->cancel_audition ();
1220 if (session->get_play_loop ()) {
1221 session->request_play_loop (false);
1224 session->request_stop ();
1228 ARDOUR_UI::transport_stop_and_forget_capture ()
1231 session->request_stop (true);
1236 ARDOUR_UI::remove_last_capture()
1239 editor->remove_last_capture();
1244 ARDOUR_UI::transport_record ()
1247 switch (session->record_status()) {
1248 case Session::Disabled:
1249 if (session->ntracks() == 0) {
1250 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1254 session->maybe_enable_record ();
1256 case Session::Recording:
1257 case Session::Enabled:
1258 session->disable_record (false, true);
1264 ARDOUR_UI::transport_roll ()
1272 rolling = session->transport_rolling ();
1274 if (session->get_play_loop()) {
1275 session->request_play_loop (false);
1276 auto_loop_button.set_visual_state (1);
1277 roll_button.set_visual_state (1);
1278 } else if (session->get_play_range ()) {
1279 session->request_play_range (false);
1280 play_selection_button.set_visual_state (0);
1281 } else if (rolling) {
1282 session->request_locate (session->last_transport_start(), true);
1285 session->request_transport_speed (1.0f);
1289 ARDOUR_UI::transport_loop()
1292 if (session->get_play_loop()) {
1293 if (session->transport_rolling()) {
1294 Location * looploc = session->locations()->auto_loop_location();
1296 session->request_locate (looploc->start(), true);
1301 session->request_play_loop (true);
1307 ARDOUR_UI::transport_play_selection ()
1313 if (!session->get_play_range()) {
1314 session->request_stop ();
1317 editor->play_selection ();
1321 ARDOUR_UI::transport_rewind (int option)
1323 float current_transport_speed;
1326 current_transport_speed = session->transport_speed();
1328 if (current_transport_speed >= 0.0f) {
1331 session->request_transport_speed (-1.0f);
1334 session->request_transport_speed (-4.0f);
1337 session->request_transport_speed (-0.5f);
1342 session->request_transport_speed (current_transport_speed * 1.5f);
1348 ARDOUR_UI::transport_forward (int option)
1350 float current_transport_speed;
1353 current_transport_speed = session->transport_speed();
1355 if (current_transport_speed <= 0.0f) {
1358 session->request_transport_speed (1.0f);
1361 session->request_transport_speed (4.0f);
1364 session->request_transport_speed (0.5f);
1369 session->request_transport_speed (current_transport_speed * 1.5f);
1375 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1381 boost::shared_ptr<Route> r;
1383 if ((r = session->route_by_remote_id (dstream)) != 0) {
1387 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1388 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1397 ARDOUR_UI::queue_transport_change ()
1399 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1403 ARDOUR_UI::map_transport_state ()
1405 float sp = session->transport_speed();
1408 transport_rolling ();
1409 } else if (sp < 0.0f) {
1410 transport_rewinding ();
1411 } else if (sp > 0.0f) {
1412 transport_forwarding ();
1414 transport_stopped ();
1419 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1421 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1422 (int) adj.get_value()].c_str());
1426 ARDOUR_UI::engine_stopped ()
1428 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1429 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1430 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1434 ARDOUR_UI::engine_running ()
1436 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1437 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1438 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1440 Glib::RefPtr<Action> action;
1441 char* action_name = 0;
1443 switch (engine->frames_per_cycle()) {
1445 action_name = X_("JACKLatency32");
1448 action_name = X_("JACKLatency64");
1451 action_name = X_("JACKLatency128");
1454 action_name = X_("JACKLatency512");
1457 action_name = X_("JACKLatency1024");
1460 action_name = X_("JACKLatency2048");
1463 action_name = X_("JACKLatency4096");
1466 action_name = X_("JACKLatency8192");
1469 /* XXX can we do anything useful ? */
1475 action = ActionManager::get_action (X_("JACK"), action_name);
1478 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1479 ract->set_active ();
1485 ARDOUR_UI::engine_halted ()
1487 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1489 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1490 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1492 update_sample_rate (0);
1494 MessageDialog msg (*editor,
1496 JACK has either been shutdown or it\n\
1497 disconnected Ardour because Ardour\n\
1498 was not fast enough. You can save the\n\
1499 session and/or try to reconnect to JACK ."));
1504 ARDOUR_UI::do_engine_start ()
1512 error << _("Unable to start the session running")
1522 ARDOUR_UI::setup_theme ()
1524 theme_manager->setup_theme();
1528 ARDOUR_UI::start_engine ()
1530 if (do_engine_start () == 0) {
1531 if (session && _session_is_new) {
1532 /* we need to retain initial visual
1533 settings for a new session
1535 session->save_state ("");
1543 ARDOUR_UI::update_clocks ()
1545 if (!editor || !editor->dragging_playhead()) {
1546 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1551 ARDOUR_UI::start_clocking ()
1553 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1557 ARDOUR_UI::stop_clocking ()
1559 clock_signal_connection.disconnect ();
1563 ARDOUR_UI::toggle_clocking ()
1566 if (clock_button.get_active()) {
1575 ARDOUR_UI::_blink (void *arg)
1578 ((ARDOUR_UI *) arg)->blink ();
1585 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1589 ARDOUR_UI::start_blinking ()
1591 /* Start the blink signal. Everybody with a blinking widget
1592 uses Blink to drive the widget's state.
1595 if (blink_timeout_tag < 0) {
1597 blink_timeout_tag = g_timeout_add (240, _blink, this);
1602 ARDOUR_UI::stop_blinking ()
1604 if (blink_timeout_tag >= 0) {
1605 g_source_remove (blink_timeout_tag);
1606 blink_timeout_tag = -1;
1611 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1617 if (io.n_inputs().n_total() == 0) {
1622 /* XXX we're not handling multiple ports yet. */
1624 const char **connections = io.input(0)->get_connections();
1626 if (connections == 0 || connections[0] == '\0') {
1629 buf = connections[0];
1636 if (io.n_outputs().n_total() == 0) {
1641 /* XXX we're not handling multiple ports yet. */
1643 const char **connections = io.output(0)->get_connections();
1645 if (connections == 0 || connections[0] == '\0') {
1648 buf = connections[0];
1655 /** Ask the user for the name of a new shapshot and then take it.
1658 ARDOUR_UI::snapshot_session ()
1660 ArdourPrompter prompter (true);
1664 struct tm local_time;
1667 localtime_r (&n, &local_time);
1668 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1670 prompter.set_name ("Prompter");
1671 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1672 prompter.set_prompt (_("Name of New Snapshot"));
1673 prompter.set_initial_text (timebuf);
1675 switch (prompter.run()) {
1676 case RESPONSE_ACCEPT:
1677 prompter.get_result (snapname);
1678 if (snapname.length()){
1679 save_state (snapname);
1689 ARDOUR_UI::save_state (const string & name)
1691 (void) save_state_canfail (name);
1695 ARDOUR_UI::save_state_canfail (string name)
1700 if (name.length() == 0) {
1701 name = session->snap_name();
1704 if ((ret = session->save_state (name)) != 0) {
1708 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1713 ARDOUR_UI::restore_state (string name)
1716 if (name.length() == 0) {
1717 name = session->name();
1719 session->restore_state (name);
1724 ARDOUR_UI::primary_clock_value_changed ()
1727 session->request_locate (primary_clock.current_time ());
1732 ARDOUR_UI::secondary_clock_value_changed ()
1735 session->request_locate (secondary_clock.current_time ());
1740 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1742 if (session && dstream && dstream->record_enabled()) {
1744 Session::RecordState rs;
1746 rs = session->record_status ();
1749 case Session::Disabled:
1750 case Session::Enabled:
1751 if (w->get_state() != STATE_SELECTED) {
1752 w->set_state (STATE_SELECTED);
1756 case Session::Recording:
1757 if (w->get_state() != STATE_ACTIVE) {
1758 w->set_state (STATE_ACTIVE);
1764 if (w->get_state() != STATE_NORMAL) {
1765 w->set_state (STATE_NORMAL);
1771 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1777 switch (session->record_status()) {
1778 case Session::Enabled:
1780 rec_button.set_visual_state (2);
1782 rec_button.set_visual_state (0);
1786 case Session::Recording:
1787 rec_button.set_visual_state (1);
1791 rec_button.set_visual_state (0);
1797 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1805 ARDOUR_UI::save_template ()
1808 ArdourPrompter prompter (true);
1811 prompter.set_name (X_("Prompter"));
1812 prompter.set_prompt (_("Name for mix template:"));
1813 prompter.set_initial_text(session->name() + _("-template"));
1814 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1816 switch (prompter.run()) {
1817 case RESPONSE_ACCEPT:
1818 prompter.get_result (name);
1820 if (name.length()) {
1821 session->save_template (name);
1831 ARDOUR_UI::new_session (std::string predetermined_path)
1833 string session_name;
1834 string session_path;
1836 if (!check_audioengine()) {
1840 int response = Gtk::RESPONSE_NONE;
1842 new_session_dialog->set_modal(true);
1843 new_session_dialog->set_name (predetermined_path);
1844 new_session_dialog->reset_recent();
1845 new_session_dialog->show();
1846 new_session_dialog->set_current_page (0);
1849 response = new_session_dialog->run ();
1851 if (!check_audioengine()) {
1852 new_session_dialog->hide ();
1856 _session_is_new = false;
1858 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1863 new_session_dialog->hide ();
1866 } else if (response == Gtk::RESPONSE_NONE) {
1868 /* Clear was pressed */
1869 new_session_dialog->reset();
1871 } else if (response == Gtk::RESPONSE_YES) {
1873 /* YES == OPEN, but there's no enum for that */
1875 session_name = new_session_dialog->session_name();
1877 if (session_name.empty()) {
1878 response = Gtk::RESPONSE_NONE;
1882 if (session_name[0] == '/' ||
1883 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1884 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1885 load_session (Glib::path_get_dirname (session_name), session_name);
1887 session_path = new_session_dialog->session_folder();
1888 load_session (session_path, session_name);
1891 } else if (response == Gtk::RESPONSE_OK) {
1893 session_name = new_session_dialog->session_name();
1895 if (!new_session_dialog->on_new_session_page ()) {
1897 /* XXX this is a bit of a hack..
1898 i really want the new sesion dialog to return RESPONSE_YES
1899 if we're on page 1 (the load page)
1900 Unfortunately i can't see how atm..
1903 if (session_name.empty()) {
1904 response = Gtk::RESPONSE_NONE;
1908 if (session_name[0] == '/' ||
1909 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1910 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1911 load_session (Glib::path_get_dirname (session_name), session_name);
1913 session_path = new_session_dialog->session_folder();
1914 load_session (session_path, session_name);
1919 if (session_name.empty()) {
1920 response = Gtk::RESPONSE_NONE;
1924 if (session_name[0] == '/' ||
1925 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1926 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1928 session_path = Glib::path_get_dirname (session_name);
1929 session_name = Glib::path_get_basename (session_name);
1933 session_path = new_session_dialog->session_folder();
1937 //XXX This is needed because session constructor wants a
1938 //non-existant path. hopefully this will be fixed at some point.
1940 session_path = Glib::build_filename (session_path, session_name);
1942 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1944 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1946 MessageDialog msg (str,
1948 Gtk::MESSAGE_WARNING,
1949 Gtk::BUTTONS_YES_NO,
1953 msg.set_name (X_("CleanupDialog"));
1954 msg.set_wmclass (X_("existing_session"), "Ardour");
1955 msg.set_position (Gtk::WIN_POS_MOUSE);
1957 switch (msg.run()) {
1959 load_session (session_path, session_name);
1963 response = RESPONSE_NONE;
1964 new_session_dialog->reset ();
1969 _session_is_new = true;
1971 std::string template_name = new_session_dialog->session_template_name();
1973 if (new_session_dialog->use_session_template()) {
1975 load_session (session_path, session_name, &template_name);
1981 AutoConnectOption iconnect;
1982 AutoConnectOption oconnect;
1984 if (new_session_dialog->create_control_bus()) {
1985 cchns = (uint32_t) new_session_dialog->control_channel_count();
1990 if (new_session_dialog->create_master_bus()) {
1991 mchns = (uint32_t) new_session_dialog->master_channel_count();
1996 if (new_session_dialog->connect_inputs()) {
1997 iconnect = AutoConnectPhysical;
1999 iconnect = AutoConnectOption (0);
2002 /// @todo some minor tweaks.
2004 if (new_session_dialog->connect_outs_to_master()) {
2005 oconnect = AutoConnectMaster;
2006 } else if (new_session_dialog->connect_outs_to_physical()) {
2007 oconnect = AutoConnectPhysical;
2009 oconnect = AutoConnectOption (0);
2012 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2013 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2015 if (!build_session (session_path,
2023 engine->frame_rate() * 60 * 5)) {
2025 response = Gtk::RESPONSE_NONE;
2026 new_session_dialog->reset ();
2033 } while (response == Gtk::RESPONSE_NONE);
2037 new_session_dialog->get_window()->set_cursor();
2038 new_session_dialog->hide();
2043 ARDOUR_UI::close_session()
2045 if (!check_audioengine()) {
2054 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2056 Session *new_session;
2057 session_loaded = false;
2059 if (!check_audioengine()) {
2063 if(!unload_session ()) return -1;
2065 /* if it already exists, we must have write access */
2067 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2068 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2069 "This prevents the session from being loaded."));
2075 new_session = new Session (*engine, path, snap_name, mix_template);
2080 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2084 connect_to_session (new_session);
2086 Config->set_current_owner (ConfigVariableBase::Interface);
2088 session_loaded = true;
2090 goto_editor_window ();
2093 session->set_clean ();
2096 editor->edit_cursor_position (true);
2101 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2102 uint32_t control_channels,
2103 uint32_t master_channels,
2104 AutoConnectOption input_connect,
2105 AutoConnectOption output_connect,
2108 nframes_t initial_length)
2110 Session *new_session;
2112 if (!check_audioengine()) {
2116 session_loaded = false;
2118 if (!unload_session ()) return false;
2120 _session_is_new = true;
2123 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2124 control_channels, master_channels, nphysin, nphysout, initial_length);
2129 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2134 connect_to_session (new_session);
2136 session_loaded = true;
2144 editor->show_window ();
2155 ARDOUR_UI::show_splash ()
2158 about = new About();
2159 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2166 ARDOUR_UI::about_signal_response(int response)
2172 ARDOUR_UI::hide_splash ()
2175 about->get_window()->set_cursor ();
2181 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2185 removed = rep.paths.size();
2188 MessageDialog msgd (*editor,
2189 _("No audio files were ready for cleanup"),
2192 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2193 msgd.set_secondary_text (_("If this seems suprising, \n\
2194 check for any existing snapshots.\n\
2195 These may still include regions that\n\
2196 require some unused files to continue to exist."));
2202 ArdourDialog results (_("ardour: cleanup"), true, false);
2204 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2205 CleanupResultsModelColumns() {
2209 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2210 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2214 CleanupResultsModelColumns results_columns;
2215 Glib::RefPtr<Gtk::ListStore> results_model;
2216 Gtk::TreeView results_display;
2218 results_model = ListStore::create (results_columns);
2219 results_display.set_model (results_model);
2220 results_display.append_column (list_title, results_columns.visible_name);
2222 results_display.set_name ("CleanupResultsList");
2223 results_display.set_headers_visible (true);
2224 results_display.set_headers_clickable (false);
2225 results_display.set_reorderable (false);
2227 Gtk::ScrolledWindow list_scroller;
2230 Gtk::HBox dhbox; // the hbox for the image and text
2231 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2232 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2234 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2236 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2238 if (rep.space < 1048576.0f) {
2240 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2242 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2246 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2248 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2252 dhbox.pack_start (*dimage, true, false, 5);
2253 dhbox.pack_start (txt, true, false, 5);
2255 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2256 TreeModel::Row row = *(results_model->append());
2257 row[results_columns.visible_name] = *i;
2258 row[results_columns.fullpath] = *i;
2261 list_scroller.add (results_display);
2262 list_scroller.set_size_request (-1, 150);
2263 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2265 dvbox.pack_start (dhbox, true, false, 5);
2266 dvbox.pack_start (list_scroller, true, false, 5);
2267 ddhbox.pack_start (dvbox, true, false, 5);
2269 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2270 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2271 results.set_default_response (RESPONSE_CLOSE);
2272 results.set_position (Gtk::WIN_POS_MOUSE);
2274 results_display.show();
2275 list_scroller.show();
2282 //results.get_vbox()->show();
2283 results.set_resizable (false);
2290 ARDOUR_UI::cleanup ()
2293 /* shouldn't happen: menu item is insensitive */
2298 MessageDialog checker (_("Are you sure you want to cleanup?"),
2300 Gtk::MESSAGE_QUESTION,
2301 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2303 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2304 ALL undo/redo information will be lost if you cleanup.\n\
2305 After cleanup, unused audio files will be moved to a \
2306 \"dead sounds\" location."));
2308 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2309 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2310 checker.set_default_response (RESPONSE_CANCEL);
2312 checker.set_name (_("CleanupDialog"));
2313 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2314 checker.set_position (Gtk::WIN_POS_MOUSE);
2316 switch (checker.run()) {
2317 case RESPONSE_ACCEPT:
2323 Session::cleanup_report rep;
2325 editor->prepare_for_cleanup ();
2327 /* do not allow flush until a session is reloaded */
2329 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2331 act->set_sensitive (false);
2334 if (session->cleanup_sources (rep)) {
2339 display_cleanup_results (rep,
2342 The following %1 %2 not in use and \n\
2343 have been moved to:\n\
2345 Flushing the wastebasket will \n\
2346 release an additional\n\
2347 %4 %5bytes of disk space.\n"
2355 ARDOUR_UI::flush_trash ()
2358 /* shouldn't happen: menu item is insensitive */
2362 Session::cleanup_report rep;
2364 if (session->cleanup_trash_sources (rep)) {
2368 display_cleanup_results (rep,
2370 _("The following %1 %2 deleted from\n\
2372 releasing %4 %5bytes of disk space"));
2376 ARDOUR_UI::add_route (Gtk::Window* float_window)
2384 if (add_route_dialog == 0) {
2385 add_route_dialog = new AddRouteDialog;
2387 add_route_dialog->set_transient_for (*float_window);
2391 if (add_route_dialog->is_visible()) {
2392 /* we're already doing this */
2396 ResponseType r = (ResponseType) add_route_dialog->run ();
2398 add_route_dialog->hide();
2401 case RESPONSE_ACCEPT:
2408 if ((count = add_route_dialog->count()) <= 0) {
2412 uint32_t input_chan = add_route_dialog->channels ();
2413 uint32_t output_chan;
2414 string name_template = add_route_dialog->name_template ();
2415 bool track = add_route_dialog->track ();
2417 AutoConnectOption oac = Config->get_output_auto_connect();
2419 if (oac & AutoConnectMaster) {
2420 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2422 output_chan = input_chan;
2425 /* XXX do something with name template */
2427 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2429 session_add_midi_track(count);
2431 MessageDialog msg (*editor,
2432 _("Sorry, MIDI Busses are not supported at this time."));
2434 //session_add_midi_bus();
2438 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2440 session_add_audio_bus (input_chan, output_chan, count);
2446 ARDOUR_UI::mixer_settings () const
2451 node = session->instant_xml(X_("Mixer"));
2453 node = Config->instant_xml(X_("Mixer"));
2457 node = new XMLNode (X_("Mixer"));
2464 ARDOUR_UI::editor_settings () const
2469 node = session->instant_xml(X_("Editor"));
2471 node = Config->instant_xml(X_("Editor"));
2475 node = new XMLNode (X_("Editor"));
2481 ARDOUR_UI::keyboard_settings () const
2485 node = Config->extra_xml(X_("Keyboard"));
2488 node = new XMLNode (X_("Keyboard"));
2494 ARDOUR_UI::halt_on_xrun_message ()
2496 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2498 MessageDialog msg (*editor,
2499 _("Recording was stopped because your system could not keep up."));
2504 ARDOUR_UI::disk_overrun_handler ()
2506 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_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 write data to disk\n\
2515 quickly enough to keep up with recording.\n"));
2516 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2522 ARDOUR_UI::disk_underrun_handler ()
2524 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2526 if (!have_disk_speed_dialog_displayed) {
2527 have_disk_speed_dialog_displayed = true;
2528 MessageDialog* msg = new MessageDialog (*editor,
2529 _("The disk system on your computer\n\
2530 was not able to keep up with Ardour.\n\
2532 Specifically, it failed to read data from disk\n\
2533 quickly enough to keep up with playback.\n"));
2534 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2540 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2542 have_disk_speed_dialog_displayed = false;
2547 ARDOUR_UI::pending_state_dialog ()
2549 ArdourDialog dialog ("pending state dialog");
2551 This session appears to have been in\n\
2552 middle of recording when ardour or\n\
2553 the computer was shutdown.\n\
2555 Ardour can recover any captured audio for\n\
2556 you, or it can ignore it. Please decide\n\
2557 what you would like to do.\n"));
2559 dialog.get_vbox()->pack_start (message);
2560 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2561 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2563 dialog.set_position (WIN_POS_CENTER);
2565 //dialog.get_vbox()->show();
2567 switch (dialog.run ()) {
2568 case RESPONSE_ACCEPT:
2576 ARDOUR_UI::disconnect_from_jack ()
2579 if( engine->disconnect_from_jack ()) {
2580 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2584 update_sample_rate (0);
2589 ARDOUR_UI::reconnect_to_jack ()
2592 if (engine->reconnect_to_jack ()) {
2593 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2597 update_sample_rate (0);
2602 ARDOUR_UI::cmdline_new_session (string path)
2604 if (path[0] != '/') {
2605 char buf[PATH_MAX+1];
2608 getcwd (buf, sizeof (buf));
2617 return FALSE; /* don't call it again */
2621 ARDOUR_UI::use_config ()
2623 Glib::RefPtr<Action> act;
2625 switch (Config->get_native_file_data_format ()) {
2627 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2630 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2635 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2636 ract->set_active ();
2639 switch (Config->get_native_file_header_format ()) {
2641 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2644 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2647 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2650 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2653 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2656 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2659 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2664 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2665 ract->set_active ();
2668 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2670 set_transport_controllable_state (*node);
2675 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2677 if (Config->get_primary_clock_delta_edit_cursor()) {
2678 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2680 primary_clock.set (pos, 0, true);
2683 if (Config->get_secondary_clock_delta_edit_cursor()) {
2684 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2686 secondary_clock.set (pos);
2689 if (big_clock_window) {
2690 big_clock.set (pos);
2695 ARDOUR_UI::record_state_changed ()
2697 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2699 if (!session || !big_clock_window) {
2700 /* why bother - the clock isn't visible */
2704 switch (session->record_status()) {
2705 case Session::Recording:
2706 big_clock.set_widget_name ("BigClockRecording");
2709 big_clock.set_widget_name ("BigClockNonRecording");
2715 ARDOUR_UI::set_keybindings_path (string path)
2717 keybindings_path = path;
2721 ARDOUR_UI::save_keybindings ()
2723 if (can_save_keybindings) {
2724 AccelMap::save (keybindings_path);
2729 ARDOUR_UI::first_idle ()
2732 session->allow_auto_play (true);
2734 can_save_keybindings = true;
2739 ARDOUR_UI::store_clock_modes ()
2741 XMLNode* node = new XMLNode(X_("ClockModes"));
2743 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2744 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2747 session->add_extra_xml (*node);
2748 session->set_dirty ();
2753 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2754 : Controllable (name), ui (u), type(tp)
2760 ARDOUR_UI::TransportControllable::set_value (float val)
2762 if (type == ShuttleControl) {
2769 fract = -((0.5f - val)/0.5f);
2771 fract = ((val - 0.5f)/0.5f);
2775 ui.set_shuttle_fract (fract);
2780 /* do nothing: these are radio-style actions */
2788 action = X_("Roll");
2791 action = X_("Stop");
2794 action = X_("Goto Start");
2797 action = X_("Goto End");
2800 action = X_("Loop");
2803 action = X_("Play Selection");
2806 action = X_("Record");
2816 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2824 ARDOUR_UI::TransportControllable::get_value (void) const
2843 case ShuttleControl:
2853 ARDOUR_UI::TransportControllable::set_id (const string& str)
2859 ARDOUR_UI::setup_profile ()
2861 if (gdk_screen_width() < 1200) {
2862 Profile->set_small_screen ();
2867 ARDOUR_UI::disable_all_plugins ()
2873 // session->begin_reversible_command (_("Disable all plugins"));
2875 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2877 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2878 // XMLNode& before = (*i)->get_redirect_state ();
2879 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2880 (*i)->disable_plugins ();
2881 // XMLNode& after = (*i)->get_redirect_state ();
2882 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2886 // session->commit_reversible_command ();
2890 ARDOUR_UI::ab_all_plugins ()
2896 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2898 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2899 (*i)->ab_plugins (ab_direction);
2902 ab_direction = !ab_direction;