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/pathscanner.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/memento_command.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_route.h>
59 #include <ardour/session_utils.h>
60 #include <ardour/port.h>
61 #include <ardour/audioengine.h>
62 #include <ardour/playlist.h>
63 #include <ardour/utils.h>
64 #include <ardour/audio_diskstream.h>
65 #include <ardour/audiofilesource.h>
66 #include <ardour/recent_sessions.h>
67 #include <ardour/port.h>
68 #include <ardour/audio_track.h>
69 #include <ardour/midi_track.h>
72 #include "ardour_ui.h"
73 #include "public_editor.h"
74 #include "audio_clock.h"
79 #include "add_route_dialog.h"
80 #include "new_session_dialog.h"
83 #include "gui_thread.h"
84 #include "theme_manager.h"
88 using namespace ARDOUR;
90 using namespace Gtkmm2ext;
94 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
96 sigc::signal<void,bool> ARDOUR_UI::Blink;
97 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
98 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
99 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
100 sigc::signal<int,string> ThemeChanged;
102 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
104 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
106 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
107 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
108 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
109 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
113 adjuster_table (3, 3),
117 preroll_button (_("pre\nroll")),
118 postroll_button (_("post\nroll")),
122 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
126 roll_controllable ("transport roll", *this, TransportControllable::Roll),
127 stop_controllable ("transport stop", *this, TransportControllable::Stop),
128 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
129 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
130 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
131 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
132 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
133 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
134 shuttle_controller_binding_proxy (shuttle_controllable),
136 roll_button (roll_controllable),
137 stop_button (stop_controllable),
138 goto_start_button (goto_start_controllable),
139 goto_end_button (goto_end_controllable),
140 auto_loop_button (auto_loop_controllable),
141 play_selection_button (play_selection_controllable),
142 rec_button (rec_controllable),
144 shuttle_units_button (_("% ")),
146 punch_in_button (_("Punch In")),
147 punch_out_button (_("Punch Out")),
148 auto_return_button (_("Auto Return")),
149 auto_play_button (_("Auto Play")),
150 auto_input_button (_("Auto Input")),
151 click_button (_("Click")),
152 time_master_button (_("time\nmaster")),
154 auditioning_alert_button (_("AUDITION")),
155 solo_alert_button (_("SOLO")),
158 using namespace Gtk::Menu_Helpers;
164 if (theArdourUI == 0) {
170 theme_manager = new ThemeManager();
172 std::string color_file = ARDOUR::find_config_file("ardour.colors");
174 theme_manager->load (color_file);
179 _session_is_new = false;
180 big_clock_window = 0;
181 session_selector_window = 0;
182 last_key_press_time = 0;
183 connection_editor = 0;
184 add_route_dialog = 0;
188 open_session_selector = 0;
189 have_configure_timeout = false;
190 have_disk_speed_dialog_displayed = false;
191 session_loaded = false;
192 last_speed_displayed = -1.0f;
193 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
196 can_save_keybindings = false;
198 last_configure_time.tv_sec = 0;
199 last_configure_time.tv_usec = 0;
201 shuttle_grabbed = false;
203 shuttle_max_speed = 8.0f;
205 shuttle_style_menu = 0;
206 shuttle_unit_menu = 0;
208 gettimeofday (&last_peak_grab, 0);
209 gettimeofday (&last_shuttle_request, 0);
211 ThemeChanged.connect (mem_fun(*this, &ARDOUR_UI::load_rcfile));
213 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
214 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
216 /* handle pending state with a dialog */
218 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
220 /* have to wait for AudioEngine and Configuration before proceeding */
224 ARDOUR_UI::set_engine (AudioEngine& e)
228 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
229 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
230 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
231 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
233 ActionManager::init ();
234 new_session_dialog = new NewSessionDialog();
238 keyboard = new Keyboard;
240 if (setup_windows ()) {
241 throw failed_constructor ();
244 if (GTK_ARDOUR::show_key_actions) {
245 vector<string> names;
246 vector<string> paths;
248 vector<AccelKey> bindings;
250 ActionManager::get_all_actions (names, paths, keys, bindings);
252 vector<string>::iterator n;
253 vector<string>::iterator k;
254 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
255 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
261 /* start with timecode, metering enabled
264 blink_timeout_tag = -1;
266 /* the global configuration object is now valid */
270 /* this being a GUI and all, we want peakfiles */
272 AudioFileSource::set_build_peakfiles (true);
273 AudioFileSource::set_build_missing_peakfiles (true);
275 /* set default clock modes */
277 primary_clock.set_mode (AudioClock::SMPTE);
278 secondary_clock.set_mode (AudioClock::BBT);
280 /* start the time-of-day-clock */
282 update_wall_clock ();
283 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
285 update_disk_space ();
287 update_sample_rate (engine->frame_rate());
289 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
290 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
293 ARDOUR_UI::~ARDOUR_UI ()
295 save_ardour_state ();
309 if (add_route_dialog) {
310 delete add_route_dialog;
315 ARDOUR_UI::configure_timeout ()
320 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
321 /* no configure events yet */
325 gettimeofday (&now, 0);
326 timersub (&now, &last_configure_time, &diff);
328 /* force a gap of 0.5 seconds since the last configure event
331 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
334 have_configure_timeout = false;
335 save_ardour_state ();
341 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
343 if (have_configure_timeout) {
344 gettimeofday (&last_configure_time, 0);
346 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
347 have_configure_timeout = true;
354 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
356 const XMLProperty* prop;
358 if ((prop = node.property ("roll")) != 0) {
359 roll_controllable.set_id (prop->value());
361 if ((prop = node.property ("stop")) != 0) {
362 stop_controllable.set_id (prop->value());
364 if ((prop = node.property ("goto_start")) != 0) {
365 goto_start_controllable.set_id (prop->value());
367 if ((prop = node.property ("goto_end")) != 0) {
368 goto_end_controllable.set_id (prop->value());
370 if ((prop = node.property ("auto_loop")) != 0) {
371 auto_loop_controllable.set_id (prop->value());
373 if ((prop = node.property ("play_selection")) != 0) {
374 play_selection_controllable.set_id (prop->value());
376 if ((prop = node.property ("rec")) != 0) {
377 rec_controllable.set_id (prop->value());
379 if ((prop = node.property ("shuttle")) != 0) {
380 shuttle_controllable.set_id (prop->value());
385 ARDOUR_UI::get_transport_controllable_state ()
387 XMLNode* node = new XMLNode(X_("TransportControllables"));
390 roll_controllable.id().print (buf, sizeof (buf));
391 node->add_property (X_("roll"), buf);
392 stop_controllable.id().print (buf, sizeof (buf));
393 node->add_property (X_("stop"), buf);
394 goto_start_controllable.id().print (buf, sizeof (buf));
395 node->add_property (X_("goto_start"), buf);
396 goto_end_controllable.id().print (buf, sizeof (buf));
397 node->add_property (X_("goto_end"), buf);
398 auto_loop_controllable.id().print (buf, sizeof (buf));
399 node->add_property (X_("auto_loop"), buf);
400 play_selection_controllable.id().print (buf, sizeof (buf));
401 node->add_property (X_("play_selection"), buf);
402 rec_controllable.id().print (buf, sizeof (buf));
403 node->add_property (X_("rec"), buf);
404 shuttle_controllable.id().print (buf, sizeof (buf));
405 node->add_property (X_("shuttle"), buf);
411 ARDOUR_UI::save_ardour_state ()
413 if (!keyboard || !mixer || !editor) {
417 /* XXX this is all a bit dubious. add_extra_xml() uses
418 a different lifetime model from add_instant_xml().
421 XMLNode* node = new XMLNode (keyboard->get_state());
422 Config->add_extra_xml (*node);
423 Config->add_extra_xml (get_transport_controllable_state());
424 Config->save_state();
426 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
427 XMLNode mnode(mixer->get_state());
430 session->add_instant_xml (enode, session->path());
431 session->add_instant_xml (mnode, session->path());
433 Config->add_instant_xml (enode, get_user_ardour_path());
434 Config->add_instant_xml (mnode, get_user_ardour_path());
441 ARDOUR_UI::autosave_session ()
443 if (!Config->get_periodic_safety_backups())
447 session->maybe_write_autosave();
454 ARDOUR_UI::update_autosave ()
456 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
458 if (session->dirty()) {
459 if (_autosave_connection.connected()) {
460 _autosave_connection.disconnect();
463 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
464 Config->get_periodic_safety_backup_interval() * 1000);
467 if (_autosave_connection.connected()) {
468 _autosave_connection.disconnect();
474 ARDOUR_UI::startup ()
476 check_memory_locking();
480 ARDOUR_UI::no_memory_warning ()
482 XMLNode node (X_("no-memory-warning"));
483 Config->add_instant_xml (node, get_user_ardour_path());
487 ARDOUR_UI::check_memory_locking ()
490 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
494 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
496 if (engine->is_realtime() && memory_warning_node == 0) {
498 struct rlimit limits;
500 long pages, page_size;
502 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
505 ram = (int64_t) pages * (int64_t) page_size;
508 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
512 if (limits.rlim_cur != RLIM_INFINITY) {
514 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
517 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
518 "This might cause Ardour to run out of memory before your system "
519 "runs out of memory. \n\n"
520 "You can view the memory limit with 'ulimit -l', "
521 "and it is normally controlled by /etc/security/limits.conf"));
523 VBox* vbox = msg.get_vbox();
525 CheckButton cb (_("Do not show this window again"));
527 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
529 hbox.pack_start (cb, true, false);
530 vbox->pack_start (hbox);
533 editor->ensure_float (msg);
545 if (session && session->dirty()) {
546 switch (ask_about_saving_session(_("quit"))) {
551 /* use the default name */
552 if (save_state_canfail ("")) {
553 /* failed - don't quit */
554 MessageDialog msg (*editor,
556 Ardour was unable to save your session.\n\n\
557 If you still wish to quit, please use the\n\n\
558 \"Just quit\" option."));
569 session->set_deletion_in_progress ();
572 Config->save_state();
577 ARDOUR_UI::ask_about_saving_session (const string & what)
579 ArdourDialog window (_("ardour: save session?"));
580 Gtk::HBox dhbox; // the hbox for the image and text
581 Gtk::Label prompt_label;
582 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
586 msg = string_compose(_("Don't %1"), what);
587 window.add_button (msg, RESPONSE_REJECT);
588 msg = string_compose(_("Just %1"), what);
589 window.add_button (msg, RESPONSE_APPLY);
590 msg = string_compose(_("Save and %1"), what);
591 window.add_button (msg, RESPONSE_ACCEPT);
593 window.set_default_response (RESPONSE_ACCEPT);
595 Gtk::Button noquit_button (msg);
596 noquit_button.set_name ("EditorGTKButton");
601 if (session->snap_name() == session->name()) {
604 type = _("snapshot");
606 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?"),
607 type, session->snap_name());
609 prompt_label.set_text (prompt);
610 prompt_label.set_name (X_("PrompterLabel"));
611 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
613 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
615 dhbox.set_homogeneous (false);
616 dhbox.pack_start (*dimage, false, false, 5);
617 dhbox.pack_start (prompt_label, true, false, 5);
618 window.get_vbox()->pack_start (dhbox);
620 window.set_name (_("Prompter"));
621 window.set_position (Gtk::WIN_POS_MOUSE);
622 window.set_modal (true);
623 window.set_resizable (false);
626 save_the_session = 0;
628 window.set_keep_above (true);
631 ResponseType r = (ResponseType) window.run();
636 case RESPONSE_ACCEPT: // save and get out of here
638 case RESPONSE_APPLY: // get out of here
648 ARDOUR_UI::every_second ()
651 update_buffer_load ();
652 update_disk_space ();
657 ARDOUR_UI::every_point_one_seconds ()
659 update_speed_display ();
660 RapidScreenUpdate(); /* EMIT_SIGNAL */
665 ARDOUR_UI::every_point_zero_one_seconds ()
667 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
672 ARDOUR_UI::update_sample_rate (nframes_t ignored)
676 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
678 if (!engine->connected()) {
680 snprintf (buf, sizeof (buf), _("disconnected"));
684 nframes_t rate = engine->frame_rate();
686 if (fmod (rate, 1000.0) != 0.0) {
687 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
688 (float) rate/1000.0f,
689 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
691 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
693 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
697 sample_rate_label.set_text (buf);
701 ARDOUR_UI::update_cpu_load ()
704 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
705 cpu_load_label.set_text (buf);
709 ARDOUR_UI::update_buffer_load ()
714 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
715 session->playback_load(), session->capture_load());
716 buffer_load_label.set_text (buf);
718 buffer_load_label.set_text ("");
723 ARDOUR_UI::count_recenabled_streams (Route& route)
725 Track* track = dynamic_cast<Track*>(&route);
726 if (track && track->diskstream()->record_enabled()) {
727 rec_enabled_streams += track->n_inputs().get_total();
732 ARDOUR_UI::update_disk_space()
738 nframes_t frames = session->available_capture_duration();
741 if (frames == max_frames) {
742 strcpy (buf, _("Disk: 24hrs+"));
747 nframes_t fr = session->frame_rate();
749 rec_enabled_streams = 0;
750 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
752 if (rec_enabled_streams) {
753 frames /= rec_enabled_streams;
756 hrs = frames / (fr * 3600);
757 frames -= hrs * fr * 3600;
758 mins = frames / (fr * 60);
759 frames -= mins * fr * 60;
762 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
765 disk_space_label.set_text (buf);
769 ARDOUR_UI::update_wall_clock ()
776 tm_now = localtime (&now);
778 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
779 wall_clock_label.set_text (buf);
785 ARDOUR_UI::session_menu (GdkEventButton *ev)
787 session_popup_menu->popup (0, 0);
792 ARDOUR_UI::redisplay_recent_sessions ()
794 vector<string *> *sessions;
795 vector<string *>::iterator i;
796 RecentSessionsSorter cmp;
798 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
799 recent_session_model->clear ();
802 ARDOUR::read_recent_sessions (rs);
805 recent_session_display.set_model (recent_session_model);
809 /* sort them alphabetically */
810 sort (rs.begin(), rs.end(), cmp);
811 sessions = new vector<string*>;
813 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
814 sessions->push_back (new string ((*i).second));
817 for (i = sessions->begin(); i != sessions->end(); ++i) {
819 vector<string*>* states;
820 vector<const gchar*> item;
821 string fullpath = *(*i);
823 /* remove any trailing / */
825 if (fullpath[fullpath.length()-1] == '/') {
826 fullpath = fullpath.substr (0, fullpath.length()-1);
829 /* now get available states for this session */
831 if ((states = Session::possible_states (fullpath)) == 0) {
836 TreeModel::Row row = *(recent_session_model->append());
838 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
839 row[recent_session_columns.fullpath] = fullpath;
841 if (states->size() > 1) {
843 /* add the children */
845 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
847 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
849 child_row[recent_session_columns.visible_name] = **i2;
850 child_row[recent_session_columns.fullpath] = fullpath;
859 recent_session_display.set_model (recent_session_model);
864 ARDOUR_UI::build_session_selector ()
866 session_selector_window = new ArdourDialog ("session selector");
868 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
870 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
871 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
872 session_selector_window->set_default_response (RESPONSE_ACCEPT);
873 recent_session_model = TreeStore::create (recent_session_columns);
874 recent_session_display.set_model (recent_session_model);
875 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
876 recent_session_display.set_headers_visible (false);
877 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
879 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
881 scroller->add (recent_session_display);
882 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
884 session_selector_window->set_name ("SessionSelectorWindow");
885 session_selector_window->set_size_request (200, 400);
886 session_selector_window->get_vbox()->pack_start (*scroller);
887 session_selector_window->show_all_children();
891 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
893 session_selector_window->response (RESPONSE_ACCEPT);
897 ARDOUR_UI::open_recent_session ()
899 /* popup selector window */
901 if (session_selector_window == 0) {
902 build_session_selector ();
905 redisplay_recent_sessions ();
907 ResponseType r = (ResponseType) session_selector_window->run ();
909 session_selector_window->hide();
912 case RESPONSE_ACCEPT:
918 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
920 if (i == recent_session_model->children().end()) {
924 Glib::ustring path = (*i)[recent_session_columns.fullpath];
925 Glib::ustring state = (*i)[recent_session_columns.visible_name];
927 _session_is_new = false;
929 load_session (path, state);
933 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
937 if (stat (info.filename.c_str(), &statbuf) != 0) {
941 if (!S_ISDIR(statbuf.st_mode)) {
947 string session_file = info.filename;
949 session_file += Glib::path_get_basename (info.filename);
950 session_file += ".ardour";
952 if (stat (session_file.c_str(), &statbuf) != 0) {
956 return S_ISREG (statbuf.st_mode);
960 ARDOUR_UI::check_audioengine ()
963 if (!engine->connected()) {
964 MessageDialog msg (_("Ardour is not connected to JACK\n"
965 "You cannot open or close sessions in this condition"));
976 ARDOUR_UI::open_session ()
978 if (!check_audioengine()) {
983 /* popup selector window */
985 if (open_session_selector == 0) {
987 /* ardour sessions are folders */
989 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
990 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
991 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
993 FileFilter session_filter;
994 session_filter.add_pattern ("*.ardour");
995 session_filter.set_name (_("Ardour sessions"));
996 open_session_selector->add_filter (session_filter);
997 open_session_selector->set_filter (session_filter);
1000 int response = open_session_selector->run();
1001 open_session_selector->hide ();
1004 case RESPONSE_ACCEPT:
1007 open_session_selector->hide();
1011 open_session_selector->hide();
1012 string session_path = open_session_selector->get_filename();
1016 if (session_path.length() > 0) {
1017 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1018 _session_is_new = isnew;
1019 load_session (path, name);
1026 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1028 list<boost::shared_ptr<MidiTrack> > tracks;
1031 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1038 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1040 if (tracks.size() != how_many) {
1041 if (how_many == 1) {
1042 error << _("could not create a new midi track") << endmsg;
1044 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1048 if ((route = session->new_midi_route ()) == 0) {
1049 error << _("could not create new midi bus") << endmsg;
1055 MessageDialog msg (*editor,
1056 _("There are insufficient JACK ports available\n\
1057 to create a new track or bus.\n\
1058 You should save Ardour, exit and\n\
1059 restart JACK with more ports."));
1066 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1068 list<boost::shared_ptr<AudioTrack> > tracks;
1069 Session::RouteList routes;
1072 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1078 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1080 if (tracks.size() != how_many) {
1081 if (how_many == 1) {
1082 error << _("could not create a new audio track") << endmsg;
1084 error << string_compose (_("could only create %1 of %2 new audio %3"),
1085 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1091 routes = session->new_audio_route (input_channels, output_channels, how_many);
1093 if (routes.size() != how_many) {
1094 if (how_many == 1) {
1095 error << _("could not create a new audio track") << endmsg;
1097 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1103 if (need_control_room_outs) {
1109 route->set_stereo_control_outs (control_lr_channels);
1110 route->control_outs()->set_stereo_pan (pans, this);
1112 #endif /* CONTROLOUTS */
1116 cerr << "About to complain about JACK\n";
1117 MessageDialog msg (*editor,
1118 _("There are insufficient JACK ports available\n\
1119 to create a new track or bus.\n\
1120 You should save Ardour, exit and\n\
1121 restart JACK with more ports."));
1127 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1129 nframes_t _preroll = 0;
1132 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1133 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1135 if (new_position > _preroll) {
1136 new_position -= _preroll;
1141 session->request_locate (new_position);
1146 ARDOUR_UI::transport_goto_start ()
1149 session->goto_start();
1152 /* force displayed area in editor to start no matter
1153 what "follow playhead" setting is.
1157 editor->reset_x_origin (session->current_start_frame());
1163 ARDOUR_UI::transport_goto_zero ()
1166 session->request_locate (0);
1169 /* force displayed area in editor to start no matter
1170 what "follow playhead" setting is.
1174 editor->reset_x_origin (0);
1180 ARDOUR_UI::transport_goto_end ()
1183 nframes_t frame = session->current_end_frame();
1184 session->request_locate (frame);
1186 /* force displayed area in editor to start no matter
1187 what "follow playhead" setting is.
1191 editor->reset_x_origin (frame);
1197 ARDOUR_UI::transport_stop ()
1203 if (session->is_auditioning()) {
1204 session->cancel_audition ();
1208 if (session->get_play_loop ()) {
1209 session->request_play_loop (false);
1212 session->request_stop ();
1216 ARDOUR_UI::transport_stop_and_forget_capture ()
1219 session->request_stop (true);
1224 ARDOUR_UI::remove_last_capture()
1227 editor->remove_last_capture();
1232 ARDOUR_UI::transport_record ()
1235 switch (session->record_status()) {
1236 case Session::Disabled:
1237 if (session->ntracks() == 0) {
1238 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1242 session->maybe_enable_record ();
1244 case Session::Recording:
1245 case Session::Enabled:
1246 session->disable_record (true);
1252 ARDOUR_UI::transport_roll ()
1260 rolling = session->transport_rolling ();
1262 if (session->get_play_loop()) {
1263 session->request_play_loop (false);
1264 auto_loop_button.set_visual_state (1);
1265 roll_button.set_visual_state (1);
1266 } else if (session->get_play_range ()) {
1267 session->request_play_range (false);
1268 play_selection_button.set_visual_state (0);
1269 } else if (rolling) {
1270 session->request_locate (session->last_transport_start(), true);
1273 session->request_transport_speed (1.0f);
1277 ARDOUR_UI::transport_loop()
1280 if (session->get_play_loop()) {
1281 if (session->transport_rolling()) {
1282 Location * looploc = session->locations()->auto_loop_location();
1284 session->request_locate (looploc->start(), true);
1289 session->request_play_loop (true);
1295 ARDOUR_UI::transport_play_selection ()
1301 if (!session->get_play_range()) {
1302 session->request_stop ();
1305 editor->play_selection ();
1309 ARDOUR_UI::transport_rewind (int option)
1311 float current_transport_speed;
1314 current_transport_speed = session->transport_speed();
1316 if (current_transport_speed >= 0.0f) {
1319 session->request_transport_speed (-1.0f);
1322 session->request_transport_speed (-4.0f);
1325 session->request_transport_speed (-0.5f);
1330 session->request_transport_speed (current_transport_speed * 1.5f);
1336 ARDOUR_UI::transport_forward (int option)
1338 float current_transport_speed;
1341 current_transport_speed = session->transport_speed();
1343 if (current_transport_speed <= 0.0f) {
1346 session->request_transport_speed (1.0f);
1349 session->request_transport_speed (4.0f);
1352 session->request_transport_speed (0.5f);
1357 session->request_transport_speed (current_transport_speed * 1.5f);
1363 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1369 boost::shared_ptr<Route> r;
1371 if ((r = session->route_by_remote_id (dstream)) != 0) {
1375 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1376 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1385 ARDOUR_UI::queue_transport_change ()
1387 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1391 ARDOUR_UI::map_transport_state ()
1393 float sp = session->transport_speed();
1396 transport_rolling ();
1397 } else if (sp < 0.0f) {
1398 transport_rewinding ();
1399 } else if (sp > 0.0f) {
1400 transport_forwarding ();
1402 transport_stopped ();
1407 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1409 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1410 (int) adj.get_value()].c_str());
1414 ARDOUR_UI::engine_stopped ()
1416 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1417 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1418 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1422 ARDOUR_UI::engine_running ()
1424 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1425 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1426 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1428 Glib::RefPtr<Action> action;
1429 char* action_name = 0;
1431 switch (engine->frames_per_cycle()) {
1433 action_name = X_("JACKLatency32");
1436 action_name = X_("JACKLatency64");
1439 action_name = X_("JACKLatency128");
1442 action_name = X_("JACKLatency512");
1445 action_name = X_("JACKLatency1024");
1448 action_name = X_("JACKLatency2048");
1451 action_name = X_("JACKLatency4096");
1454 action_name = X_("JACKLatency8192");
1457 /* XXX can we do anything useful ? */
1463 action = ActionManager::get_action (X_("JACK"), action_name);
1466 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1467 ract->set_active ();
1473 ARDOUR_UI::engine_halted ()
1475 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1477 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1478 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1480 update_sample_rate (0);
1482 MessageDialog msg (*editor,
1484 JACK has either been shutdown or it\n\
1485 disconnected Ardour because Ardour\n\
1486 was not fast enough. You can save the\n\
1487 session and/or try to reconnect to JACK ."));
1492 ARDOUR_UI::do_engine_start ()
1500 error << _("Unable to start the session running")
1510 ARDOUR_UI::setup_theme ()
1515 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
1518 rcfile = Config->get_ui_rc_file();
1521 rcfile = find_config_file (rcfile);
1523 if (rcfile.empty()) {
1524 warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg;
1526 cerr << "Loading ui configuration file " << rcfile << endl;
1529 ThemeChanged (rcfile); //EMIT SIGNAL
1530 theme_manager->setup_theme_buttons();
1534 ARDOUR_UI::start_engine ()
1536 if (do_engine_start () == 0) {
1537 if (session && _session_is_new) {
1538 /* we need to retain initial visual
1539 settings for a new session
1541 session->save_state ("");
1549 ARDOUR_UI::update_clocks ()
1551 if (!editor || !editor->dragging_playhead()) {
1552 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1557 ARDOUR_UI::start_clocking ()
1559 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1563 ARDOUR_UI::stop_clocking ()
1565 clock_signal_connection.disconnect ();
1569 ARDOUR_UI::toggle_clocking ()
1572 if (clock_button.get_active()) {
1581 ARDOUR_UI::_blink (void *arg)
1584 ((ARDOUR_UI *) arg)->blink ();
1591 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1595 ARDOUR_UI::start_blinking ()
1597 /* Start the blink signal. Everybody with a blinking widget
1598 uses Blink to drive the widget's state.
1601 if (blink_timeout_tag < 0) {
1603 blink_timeout_tag = g_timeout_add (240, _blink, this);
1608 ARDOUR_UI::stop_blinking ()
1610 if (blink_timeout_tag >= 0) {
1611 g_source_remove (blink_timeout_tag);
1612 blink_timeout_tag = -1;
1617 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1623 if (io.n_inputs().get_total() == 0) {
1628 /* XXX we're not handling multiple ports yet. */
1630 const char **connections = io.input(0)->get_connections();
1632 if (connections == 0 || connections[0] == '\0') {
1635 buf = connections[0];
1642 if (io.n_outputs().get_total() == 0) {
1647 /* XXX we're not handling multiple ports yet. */
1649 const char **connections = io.output(0)->get_connections();
1651 if (connections == 0 || connections[0] == '\0') {
1654 buf = connections[0];
1661 /** Ask the user for the name of a new shapshot and then take it.
1664 ARDOUR_UI::snapshot_session ()
1666 ArdourPrompter prompter (true);
1670 struct tm local_time;
1673 localtime_r (&n, &local_time);
1674 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1676 prompter.set_name ("Prompter");
1677 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1678 prompter.set_prompt (_("Name of New Snapshot"));
1679 prompter.set_initial_text (timebuf);
1681 switch (prompter.run()) {
1682 case RESPONSE_ACCEPT:
1683 prompter.get_result (snapname);
1684 if (snapname.length()){
1685 save_state (snapname);
1695 ARDOUR_UI::save_state (const string & name)
1697 (void) save_state_canfail (name);
1701 ARDOUR_UI::save_state_canfail (string name)
1706 if (name.length() == 0) {
1707 name = session->snap_name();
1710 if ((ret = session->save_state (name)) != 0) {
1714 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1719 ARDOUR_UI::restore_state (string name)
1722 if (name.length() == 0) {
1723 name = session->name();
1725 session->restore_state (name);
1730 ARDOUR_UI::primary_clock_value_changed ()
1733 session->request_locate (primary_clock.current_time ());
1738 ARDOUR_UI::secondary_clock_value_changed ()
1741 session->request_locate (secondary_clock.current_time ());
1746 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1748 if (session && dstream && dstream->record_enabled()) {
1750 Session::RecordState rs;
1752 rs = session->record_status ();
1755 case Session::Disabled:
1756 case Session::Enabled:
1757 if (w->get_state() != STATE_SELECTED) {
1758 w->set_state (STATE_SELECTED);
1762 case Session::Recording:
1763 if (w->get_state() != STATE_ACTIVE) {
1764 w->set_state (STATE_ACTIVE);
1770 if (w->get_state() != STATE_NORMAL) {
1771 w->set_state (STATE_NORMAL);
1777 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1783 switch (session->record_status()) {
1784 case Session::Enabled:
1786 rec_button.set_visual_state (2);
1788 rec_button.set_visual_state (0);
1792 case Session::Recording:
1793 rec_button.set_visual_state (1);
1797 rec_button.set_visual_state (0);
1803 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1811 ARDOUR_UI::save_template ()
1814 ArdourPrompter prompter (true);
1817 prompter.set_name (X_("Prompter"));
1818 prompter.set_prompt (_("Name for mix template:"));
1819 prompter.set_initial_text(session->name() + _("-template"));
1820 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1822 switch (prompter.run()) {
1823 case RESPONSE_ACCEPT:
1824 prompter.get_result (name);
1826 if (name.length()) {
1827 session->save_template (name);
1837 ARDOUR_UI::new_session (std::string predetermined_path)
1839 string session_name;
1840 string session_path;
1842 if (!check_audioengine()) {
1846 int response = Gtk::RESPONSE_NONE;
1848 new_session_dialog->set_modal(true);
1849 new_session_dialog->set_name (predetermined_path);
1850 new_session_dialog->reset_recent();
1851 new_session_dialog->show();
1852 new_session_dialog->set_current_page (0);
1855 response = new_session_dialog->run ();
1857 if (!check_audioengine()) {
1858 new_session_dialog->hide ();
1862 _session_is_new = false;
1864 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1869 new_session_dialog->hide ();
1872 } else if (response == Gtk::RESPONSE_NONE) {
1874 /* Clear was pressed */
1875 new_session_dialog->reset();
1877 } else if (response == Gtk::RESPONSE_YES) {
1879 /* YES == OPEN, but there's no enum for that */
1881 session_name = new_session_dialog->session_name();
1883 if (session_name.empty()) {
1884 response = Gtk::RESPONSE_NONE;
1888 if (session_name[0] == '/' ||
1889 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1890 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1891 load_session (Glib::path_get_dirname (session_name), session_name);
1893 session_path = new_session_dialog->session_folder();
1894 load_session (session_path, session_name);
1897 } else if (response == Gtk::RESPONSE_OK) {
1899 session_name = new_session_dialog->session_name();
1901 if (!new_session_dialog->on_new_session_page ()) {
1903 /* XXX this is a bit of a hack..
1904 i really want the new sesion dialog to return RESPONSE_YES
1905 if we're on page 1 (the load page)
1906 Unfortunately i can't see how atm..
1909 if (session_name.empty()) {
1910 response = Gtk::RESPONSE_NONE;
1914 if (session_name[0] == '/' ||
1915 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1916 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1917 load_session (Glib::path_get_dirname (session_name), session_name);
1919 session_path = new_session_dialog->session_folder();
1920 load_session (session_path, session_name);
1925 if (session_name.empty()) {
1926 response = Gtk::RESPONSE_NONE;
1930 if (session_name[0] == '/' ||
1931 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1932 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1934 session_path = Glib::path_get_dirname (session_name);
1935 session_name = Glib::path_get_basename (session_name);
1939 session_path = new_session_dialog->session_folder();
1943 //XXX This is needed because session constructor wants a
1944 //non-existant path. hopefully this will be fixed at some point.
1946 session_path = Glib::build_filename (session_path, session_name);
1948 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1950 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1952 MessageDialog msg (str,
1954 Gtk::MESSAGE_WARNING,
1955 Gtk::BUTTONS_YES_NO,
1959 msg.set_name (X_("CleanupDialog"));
1960 msg.set_wmclass (X_("existing_session"), "Ardour");
1961 msg.set_position (Gtk::WIN_POS_MOUSE);
1963 switch (msg.run()) {
1965 load_session (session_path, session_name);
1969 response = RESPONSE_NONE;
1970 new_session_dialog->reset ();
1975 _session_is_new = true;
1977 std::string template_name = new_session_dialog->session_template_name();
1979 if (new_session_dialog->use_session_template()) {
1981 load_session (session_path, session_name, &template_name);
1987 AutoConnectOption iconnect;
1988 AutoConnectOption oconnect;
1990 if (new_session_dialog->create_control_bus()) {
1991 cchns = (uint32_t) new_session_dialog->control_channel_count();
1996 if (new_session_dialog->create_master_bus()) {
1997 mchns = (uint32_t) new_session_dialog->master_channel_count();
2002 if (new_session_dialog->connect_inputs()) {
2003 iconnect = AutoConnectPhysical;
2005 iconnect = AutoConnectOption (0);
2008 /// @todo some minor tweaks.
2010 if (new_session_dialog->connect_outs_to_master()) {
2011 oconnect = AutoConnectMaster;
2012 } else if (new_session_dialog->connect_outs_to_physical()) {
2013 oconnect = AutoConnectPhysical;
2015 oconnect = AutoConnectOption (0);
2018 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2019 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2021 if (!build_session (session_path,
2029 engine->frame_rate() * 60 * 5)) {
2031 response = Gtk::RESPONSE_NONE;
2032 new_session_dialog->reset ();
2039 } while (response == Gtk::RESPONSE_NONE);
2043 new_session_dialog->get_window()->set_cursor();
2044 new_session_dialog->hide();
2049 ARDOUR_UI::close_session()
2051 if (!check_audioengine()) {
2060 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2062 Session *new_session;
2063 session_loaded = false;
2065 if (!check_audioengine()) {
2069 if(!unload_session ()) return -1;
2071 /* if it already exists, we must have write access */
2073 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2074 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2075 "This prevents the session from being loaded."));
2081 new_session = new Session (*engine, path, snap_name, mix_template);
2086 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2090 connect_to_session (new_session);
2092 Config->set_current_owner (ConfigVariableBase::Interface);
2094 session_loaded = true;
2096 goto_editor_window ();
2099 session->set_clean ();
2102 editor->edit_cursor_position (true);
2107 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2108 uint32_t control_channels,
2109 uint32_t master_channels,
2110 AutoConnectOption input_connect,
2111 AutoConnectOption output_connect,
2114 nframes_t initial_length)
2116 Session *new_session;
2118 if (!check_audioengine()) {
2122 session_loaded = false;
2124 if (!unload_session ()) return false;
2126 _session_is_new = true;
2129 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2130 control_channels, master_channels, nphysin, nphysout, initial_length);
2135 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2140 connect_to_session (new_session);
2142 session_loaded = true;
2150 editor->show_window ();
2161 ARDOUR_UI::show_splash ()
2164 about = new About();
2165 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2172 ARDOUR_UI::about_signal_response(int response)
2178 ARDOUR_UI::hide_splash ()
2181 about->get_window()->set_cursor ();
2187 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2191 removed = rep.paths.size();
2194 MessageDialog msgd (*editor,
2195 _("No audio files were ready for cleanup"),
2198 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2199 msgd.set_secondary_text (_("If this seems suprising, \n\
2200 check for any existing snapshots.\n\
2201 These may still include regions that\n\
2202 require some unused files to continue to exist."));
2208 ArdourDialog results (_("ardour: cleanup"), true, false);
2210 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2211 CleanupResultsModelColumns() {
2215 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2216 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2220 CleanupResultsModelColumns results_columns;
2221 Glib::RefPtr<Gtk::ListStore> results_model;
2222 Gtk::TreeView results_display;
2224 results_model = ListStore::create (results_columns);
2225 results_display.set_model (results_model);
2226 results_display.append_column (list_title, results_columns.visible_name);
2228 results_display.set_name ("CleanupResultsList");
2229 results_display.set_headers_visible (true);
2230 results_display.set_headers_clickable (false);
2231 results_display.set_reorderable (false);
2233 Gtk::ScrolledWindow list_scroller;
2236 Gtk::HBox dhbox; // the hbox for the image and text
2237 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2238 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2240 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2242 if (rep.space < 1048576.0f) {
2244 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2246 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2250 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2252 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2256 dhbox.pack_start (*dimage, true, false, 5);
2257 dhbox.pack_start (txt, true, false, 5);
2259 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2260 TreeModel::Row row = *(results_model->append());
2261 row[results_columns.visible_name] = *i;
2262 row[results_columns.fullpath] = *i;
2265 list_scroller.add (results_display);
2266 list_scroller.set_size_request (-1, 150);
2267 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2269 dvbox.pack_start (dhbox, true, false, 5);
2270 dvbox.pack_start (list_scroller, true, false, 5);
2271 ddhbox.pack_start (dvbox, true, false, 5);
2273 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2274 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2275 results.set_default_response (RESPONSE_CLOSE);
2276 results.set_position (Gtk::WIN_POS_MOUSE);
2277 results.show_all_children ();
2278 results.set_resizable (false);
2285 ARDOUR_UI::cleanup ()
2288 /* shouldn't happen: menu item is insensitive */
2293 MessageDialog checker (_("Are you sure you want to cleanup?"),
2295 Gtk::MESSAGE_QUESTION,
2296 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2298 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2299 ALL undo/redo information will be lost if you cleanup.\n\
2300 After cleanup, unused audio files will be moved to a \
2301 \"dead sounds\" location."));
2303 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2304 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2305 checker.set_default_response (RESPONSE_CANCEL);
2307 checker.set_name (_("CleanupDialog"));
2308 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2309 checker.set_position (Gtk::WIN_POS_MOUSE);
2311 switch (checker.run()) {
2312 case RESPONSE_ACCEPT:
2318 Session::cleanup_report rep;
2320 editor->prepare_for_cleanup ();
2322 /* do not allow flush until a session is reloaded */
2324 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2326 act->set_sensitive (false);
2329 if (session->cleanup_sources (rep)) {
2334 display_cleanup_results (rep,
2337 The following %1 %2 not in use and \n\
2338 have been moved to:\n\
2340 Flushing the wastebasket will \n\
2341 release an additional\n\
2342 %4 %5bytes of disk space.\n"
2350 ARDOUR_UI::flush_trash ()
2353 /* shouldn't happen: menu item is insensitive */
2357 Session::cleanup_report rep;
2359 if (session->cleanup_trash_sources (rep)) {
2363 display_cleanup_results (rep,
2365 _("The following %1 %2 deleted from\n\
2367 releasing %4 %5bytes of disk space"));
2371 ARDOUR_UI::add_route (Gtk::Window* float_window)
2379 if (add_route_dialog == 0) {
2380 add_route_dialog = new AddRouteDialog;
2382 add_route_dialog->set_transient_for (*float_window);
2386 if (add_route_dialog->is_visible()) {
2387 /* we're already doing this */
2391 ResponseType r = (ResponseType) add_route_dialog->run ();
2393 add_route_dialog->hide();
2396 case RESPONSE_ACCEPT:
2403 if ((count = add_route_dialog->count()) <= 0) {
2407 uint32_t input_chan = add_route_dialog->channels ();
2408 uint32_t output_chan;
2409 string name_template = add_route_dialog->name_template ();
2410 bool track = add_route_dialog->track ();
2412 AutoConnectOption oac = Config->get_output_auto_connect();
2414 if (oac & AutoConnectMaster) {
2415 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2417 output_chan = input_chan;
2420 /* XXX do something with name template */
2422 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2424 session_add_midi_track(count);
2426 MessageDialog msg (*editor,
2427 _("Sorry, MIDI Busses are not supported at this time."));
2429 //session_add_midi_bus();
2433 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2435 session_add_audio_bus (input_chan, output_chan, count);
2441 ARDOUR_UI::mixer_settings () const
2446 node = session->instant_xml(X_("Mixer"), session->path());
2448 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2452 node = new XMLNode (X_("Mixer"));
2459 ARDOUR_UI::editor_settings () const
2464 node = session->instant_xml(X_("Editor"), session->path());
2466 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2470 node = new XMLNode (X_("Editor"));
2476 ARDOUR_UI::keyboard_settings () const
2480 node = Config->extra_xml(X_("Keyboard"));
2483 node = new XMLNode (X_("Keyboard"));
2489 ARDOUR_UI::halt_on_xrun_message ()
2491 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2493 MessageDialog msg (*editor,
2494 _("Recording was stopped because your system could not keep up."));
2499 ARDOUR_UI::disk_overrun_handler ()
2501 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2503 if (!have_disk_speed_dialog_displayed) {
2504 have_disk_speed_dialog_displayed = true;
2505 MessageDialog* msg = new MessageDialog (*editor, _("\
2506 The disk system on your computer\n\
2507 was not able to keep up with Ardour.\n\
2509 Specifically, it failed to write data to disk\n\
2510 quickly enough to keep up with recording.\n"));
2511 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2517 ARDOUR_UI::disk_underrun_handler ()
2519 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2521 if (!have_disk_speed_dialog_displayed) {
2522 have_disk_speed_dialog_displayed = true;
2523 MessageDialog* msg = new MessageDialog (*editor,
2524 _("The disk system on your computer\n\
2525 was not able to keep up with Ardour.\n\
2527 Specifically, it failed to read data from disk\n\
2528 quickly enough to keep up with playback.\n"));
2529 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2535 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2537 have_disk_speed_dialog_displayed = false;
2542 ARDOUR_UI::pending_state_dialog ()
2544 ArdourDialog dialog ("pending state dialog");
2546 This session appears to have been in\n\
2547 middle of recording when ardour or\n\
2548 the computer was shutdown.\n\
2550 Ardour can recover any captured audio for\n\
2551 you, or it can ignore it. Please decide\n\
2552 what you would like to do.\n"));
2554 dialog.get_vbox()->pack_start (message);
2555 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2556 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2558 dialog.set_position (WIN_POS_CENTER);
2561 switch (dialog.run ()) {
2562 case RESPONSE_ACCEPT:
2570 ARDOUR_UI::disconnect_from_jack ()
2573 if( engine->disconnect_from_jack ()) {
2574 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2578 update_sample_rate (0);
2583 ARDOUR_UI::reconnect_to_jack ()
2586 if (engine->reconnect_to_jack ()) {
2587 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2591 update_sample_rate (0);
2596 ARDOUR_UI::cmdline_new_session (string path)
2598 if (path[0] != '/') {
2599 char buf[PATH_MAX+1];
2602 getcwd (buf, sizeof (buf));
2611 return FALSE; /* don't call it again */
2615 ARDOUR_UI::use_config ()
2617 Glib::RefPtr<Action> act;
2619 switch (Config->get_native_file_data_format ()) {
2621 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2624 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2629 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2630 ract->set_active ();
2633 switch (Config->get_native_file_header_format ()) {
2635 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2638 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2641 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2644 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2647 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2650 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2653 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2658 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2659 ract->set_active ();
2662 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2664 set_transport_controllable_state (*node);
2669 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2671 if (Config->get_primary_clock_delta_edit_cursor()) {
2672 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2674 primary_clock.set (pos, 0, true);
2677 if (Config->get_secondary_clock_delta_edit_cursor()) {
2678 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2680 secondary_clock.set (pos);
2683 if (big_clock_window) {
2684 big_clock.set (pos);
2689 ARDOUR_UI::record_state_changed ()
2691 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2693 if (!session || !big_clock_window) {
2694 /* why bother - the clock isn't visible */
2698 switch (session->record_status()) {
2699 case Session::Recording:
2700 big_clock.set_widget_name ("BigClockRecording");
2703 big_clock.set_widget_name ("BigClockNonRecording");
2709 ARDOUR_UI::set_keybindings_path (string path)
2711 keybindings_path = path;
2715 ARDOUR_UI::save_keybindings ()
2717 if (can_save_keybindings) {
2718 AccelMap::save (keybindings_path);
2723 ARDOUR_UI::first_idle ()
2726 session->allow_auto_play (true);
2728 can_save_keybindings = true;
2733 ARDOUR_UI::store_clock_modes ()
2735 XMLNode* node = new XMLNode(X_("ClockModes"));
2737 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2738 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2741 session->add_extra_xml (*node);
2742 session->set_dirty ();
2747 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2748 : Controllable (name), ui (u), type(tp)
2754 ARDOUR_UI::TransportControllable::set_value (float val)
2756 if (type == ShuttleControl) {
2763 fract = -((0.5f - val)/0.5f);
2765 fract = ((val - 0.5f)/0.5f);
2769 ui.set_shuttle_fract (fract);
2774 /* do nothing: these are radio-style actions */
2782 action = X_("Roll");
2785 action = X_("Stop");
2788 action = X_("Goto Start");
2791 action = X_("Goto End");
2794 action = X_("Loop");
2797 action = X_("Play Selection");
2800 action = X_("Record");
2810 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2818 ARDOUR_UI::TransportControllable::get_value (void) const
2837 case ShuttleControl:
2847 ARDOUR_UI::TransportControllable::set_id (const string& str)
2853 ARDOUR_UI::setup_profile ()
2855 if (gdk_screen_width() < 1200) {
2856 Profile->set_small_screen ();
2861 ARDOUR_UI::disable_all_plugins ()
2867 // session->begin_reversible_command (_("Disable all plugins"));
2869 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2871 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2872 // XMLNode& before = (*i)->get_redirect_state ();
2873 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2874 (*i)->disable_plugins ();
2875 // XMLNode& after = (*i)->get_redirect_state ();
2876 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2880 // session->commit_reversible_command ();
2884 ARDOUR_UI::ab_all_plugins ()
2890 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2892 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2893 (*i)->ab_plugins (ab_direction);
2896 ab_direction = !ab_direction;