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_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>
73 #include "ardour_ui.h"
74 #include "public_editor.h"
75 #include "audio_clock.h"
80 #include "add_route_dialog.h"
81 #include "new_session_dialog.h"
84 #include "gui_thread.h"
85 #include "theme_manager.h"
89 using namespace ARDOUR;
91 using namespace Gtkmm2ext;
95 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
97 sigc::signal<void,bool> ARDOUR_UI::Blink;
98 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
99 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
100 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
101 sigc::signal<int,string> ThemeChanged;
103 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
105 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
107 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
108 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
109 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
110 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
114 adjuster_table (3, 3),
118 preroll_button (_("pre\nroll")),
119 postroll_button (_("post\nroll")),
123 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
127 roll_controllable ("transport roll", *this, TransportControllable::Roll),
128 stop_controllable ("transport stop", *this, TransportControllable::Stop),
129 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
130 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
131 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
132 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
133 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
134 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
135 shuttle_controller_binding_proxy (shuttle_controllable),
137 roll_button (roll_controllable),
138 stop_button (stop_controllable),
139 goto_start_button (goto_start_controllable),
140 goto_end_button (goto_end_controllable),
141 auto_loop_button (auto_loop_controllable),
142 play_selection_button (play_selection_controllable),
143 rec_button (rec_controllable),
145 shuttle_units_button (_("% ")),
147 punch_in_button (_("Punch In")),
148 punch_out_button (_("Punch Out")),
149 auto_return_button (_("Auto Return")),
150 auto_play_button (_("Auto Play")),
151 auto_input_button (_("Auto Input")),
152 click_button (_("Click")),
153 time_master_button (_("time\nmaster")),
155 auditioning_alert_button (_("AUDITION")),
156 solo_alert_button (_("SOLO")),
159 using namespace Gtk::Menu_Helpers;
165 if (theArdourUI == 0) {
171 theme_manager = new ThemeManager();
173 //std::string color_file = ARDOUR::find_config_file("ardour.colors");
175 //theme_manager->load (color_file);
180 _session_is_new = false;
181 big_clock_window = 0;
182 session_selector_window = 0;
183 last_key_press_time = 0;
184 connection_editor = 0;
185 add_route_dialog = 0;
189 open_session_selector = 0;
190 have_configure_timeout = false;
191 have_disk_speed_dialog_displayed = false;
192 session_loaded = false;
193 last_speed_displayed = -1.0f;
194 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
197 can_save_keybindings = false;
199 last_configure_time.tv_sec = 0;
200 last_configure_time.tv_usec = 0;
202 shuttle_grabbed = false;
204 shuttle_max_speed = 8.0f;
206 shuttle_style_menu = 0;
207 shuttle_unit_menu = 0;
209 gettimeofday (&last_peak_grab, 0);
210 gettimeofday (&last_shuttle_request, 0);
212 ThemeChanged.connect (mem_fun(*this, &ARDOUR_UI::load_rcfile));
214 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
215 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
217 /* handle pending state with a dialog */
219 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
221 /* have to wait for AudioEngine and Configuration before proceeding */
225 ARDOUR_UI::set_engine (AudioEngine& e)
229 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
230 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
231 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
232 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
234 ActionManager::init ();
235 new_session_dialog = new NewSessionDialog();
239 keyboard = new Keyboard;
241 if (setup_windows ()) {
242 throw failed_constructor ();
245 if (GTK_ARDOUR::show_key_actions) {
246 vector<string> names;
247 vector<string> paths;
249 vector<AccelKey> bindings;
251 ActionManager::get_all_actions (names, paths, keys, bindings);
253 vector<string>::iterator n;
254 vector<string>::iterator k;
255 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
256 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
262 /* start with timecode, metering enabled
265 blink_timeout_tag = -1;
267 /* the global configuration object is now valid */
271 /* this being a GUI and all, we want peakfiles */
273 AudioFileSource::set_build_peakfiles (true);
274 AudioFileSource::set_build_missing_peakfiles (true);
276 /* set default clock modes */
278 primary_clock.set_mode (AudioClock::SMPTE);
279 secondary_clock.set_mode (AudioClock::BBT);
281 /* start the time-of-day-clock */
283 update_wall_clock ();
284 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
286 update_disk_space ();
288 update_sample_rate (engine->frame_rate());
290 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
291 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
294 ARDOUR_UI::~ARDOUR_UI ()
296 save_ardour_state ();
310 if (add_route_dialog) {
311 delete add_route_dialog;
316 ARDOUR_UI::configure_timeout ()
321 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
322 /* no configure events yet */
326 gettimeofday (&now, 0);
327 timersub (&now, &last_configure_time, &diff);
329 /* force a gap of 0.5 seconds since the last configure event
332 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
335 have_configure_timeout = false;
336 save_ardour_state ();
342 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
344 if (have_configure_timeout) {
345 gettimeofday (&last_configure_time, 0);
347 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
348 have_configure_timeout = true;
355 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
357 const XMLProperty* prop;
359 if ((prop = node.property ("roll")) != 0) {
360 roll_controllable.set_id (prop->value());
362 if ((prop = node.property ("stop")) != 0) {
363 stop_controllable.set_id (prop->value());
365 if ((prop = node.property ("goto_start")) != 0) {
366 goto_start_controllable.set_id (prop->value());
368 if ((prop = node.property ("goto_end")) != 0) {
369 goto_end_controllable.set_id (prop->value());
371 if ((prop = node.property ("auto_loop")) != 0) {
372 auto_loop_controllable.set_id (prop->value());
374 if ((prop = node.property ("play_selection")) != 0) {
375 play_selection_controllable.set_id (prop->value());
377 if ((prop = node.property ("rec")) != 0) {
378 rec_controllable.set_id (prop->value());
380 if ((prop = node.property ("shuttle")) != 0) {
381 shuttle_controllable.set_id (prop->value());
386 ARDOUR_UI::get_transport_controllable_state ()
388 XMLNode* node = new XMLNode(X_("TransportControllables"));
391 roll_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("roll"), buf);
393 stop_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("stop"), buf);
395 goto_start_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("goto_start"), buf);
397 goto_end_controllable.id().print (buf, sizeof (buf));
398 node->add_property (X_("goto_end"), buf);
399 auto_loop_controllable.id().print (buf, sizeof (buf));
400 node->add_property (X_("auto_loop"), buf);
401 play_selection_controllable.id().print (buf, sizeof (buf));
402 node->add_property (X_("play_selection"), buf);
403 rec_controllable.id().print (buf, sizeof (buf));
404 node->add_property (X_("rec"), buf);
405 shuttle_controllable.id().print (buf, sizeof (buf));
406 node->add_property (X_("shuttle"), buf);
412 ARDOUR_UI::save_ardour_state ()
414 if (!keyboard || !mixer || !editor) {
418 /* XXX this is all a bit dubious. add_extra_xml() uses
419 a different lifetime model from add_instant_xml().
422 XMLNode* node = new XMLNode (keyboard->get_state());
423 Config->add_extra_xml (*node);
424 Config->add_extra_xml (get_transport_controllable_state());
425 Config->save_state();
427 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
428 XMLNode mnode(mixer->get_state());
431 session->add_instant_xml (enode);
432 session->add_instant_xml (mnode);
434 Config->add_instant_xml (enode);
435 Config->add_instant_xml (mnode);
442 ARDOUR_UI::autosave_session ()
444 if (!Config->get_periodic_safety_backups())
448 session->maybe_write_autosave();
455 ARDOUR_UI::update_autosave ()
457 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
459 if (session->dirty()) {
460 if (_autosave_connection.connected()) {
461 _autosave_connection.disconnect();
464 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
465 Config->get_periodic_safety_backup_interval() * 1000);
468 if (_autosave_connection.connected()) {
469 _autosave_connection.disconnect();
475 ARDOUR_UI::startup ()
477 check_memory_locking();
481 ARDOUR_UI::no_memory_warning ()
483 XMLNode node (X_("no-memory-warning"));
484 Config->add_instant_xml (node);
488 ARDOUR_UI::check_memory_locking ()
491 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
495 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
497 if (engine->is_realtime() && memory_warning_node == 0) {
499 struct rlimit limits;
501 long pages, page_size;
503 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
506 ram = (int64_t) pages * (int64_t) page_size;
509 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
513 if (limits.rlim_cur != RLIM_INFINITY) {
515 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
518 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
519 "This might cause Ardour to run out of memory before your system "
520 "runs out of memory. \n\n"
521 "You can view the memory limit with 'ulimit -l', "
522 "and it is normally controlled by /etc/security/limits.conf"));
524 VBox* vbox = msg.get_vbox();
526 CheckButton cb (_("Do not show this window again"));
528 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
530 hbox.pack_start (cb, true, false);
531 vbox->pack_start (hbox);
534 editor->ensure_float (msg);
546 if (session && session->dirty()) {
547 switch (ask_about_saving_session(_("quit"))) {
552 /* use the default name */
553 if (save_state_canfail ("")) {
554 /* failed - don't quit */
555 MessageDialog msg (*editor,
557 Ardour was unable to save your session.\n\n\
558 If you still wish to quit, please use the\n\n\
559 \"Just quit\" option."));
570 session->set_deletion_in_progress ();
573 Config->save_state();
578 ARDOUR_UI::ask_about_saving_session (const string & what)
580 ArdourDialog window (_("ardour: save session?"));
581 Gtk::HBox dhbox; // the hbox for the image and text
582 Gtk::Label prompt_label;
583 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
587 msg = string_compose(_("Don't %1"), what);
588 window.add_button (msg, RESPONSE_REJECT);
589 msg = string_compose(_("Just %1"), what);
590 window.add_button (msg, RESPONSE_APPLY);
591 msg = string_compose(_("Save and %1"), what);
592 window.add_button (msg, RESPONSE_ACCEPT);
594 window.set_default_response (RESPONSE_ACCEPT);
596 Gtk::Button noquit_button (msg);
597 noquit_button.set_name ("EditorGTKButton");
602 if (session->snap_name() == session->name()) {
605 type = _("snapshot");
607 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?"),
608 type, session->snap_name());
610 prompt_label.set_text (prompt);
611 prompt_label.set_name (X_("PrompterLabel"));
612 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
614 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
616 dhbox.set_homogeneous (false);
617 dhbox.pack_start (*dimage, false, false, 5);
618 dhbox.pack_start (prompt_label, true, false, 5);
619 window.get_vbox()->pack_start (dhbox);
621 window.set_name (_("Prompter"));
622 window.set_position (Gtk::WIN_POS_MOUSE);
623 window.set_modal (true);
624 window.set_resizable (false);
627 save_the_session = 0;
629 window.set_keep_above (true);
632 ResponseType r = (ResponseType) window.run();
637 case RESPONSE_ACCEPT: // save and get out of here
639 case RESPONSE_APPLY: // get out of here
649 ARDOUR_UI::every_second ()
652 update_buffer_load ();
653 update_disk_space ();
658 ARDOUR_UI::every_point_one_seconds ()
660 update_speed_display ();
661 RapidScreenUpdate(); /* EMIT_SIGNAL */
666 ARDOUR_UI::every_point_zero_one_seconds ()
668 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
673 ARDOUR_UI::update_sample_rate (nframes_t ignored)
677 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
679 if (!engine->connected()) {
681 snprintf (buf, sizeof (buf), _("disconnected"));
685 nframes_t rate = engine->frame_rate();
687 if (fmod (rate, 1000.0) != 0.0) {
688 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
689 (float) rate/1000.0f,
690 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
692 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
694 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
698 sample_rate_label.set_text (buf);
702 ARDOUR_UI::update_cpu_load ()
705 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
706 cpu_load_label.set_text (buf);
710 ARDOUR_UI::update_buffer_load ()
715 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
716 session->playback_load(), session->capture_load());
717 buffer_load_label.set_text (buf);
719 buffer_load_label.set_text ("");
724 ARDOUR_UI::count_recenabled_streams (Route& route)
726 Track* track = dynamic_cast<Track*>(&route);
727 if (track && track->diskstream()->record_enabled()) {
728 rec_enabled_streams += track->n_inputs().n_total();
733 ARDOUR_UI::update_disk_space()
739 nframes_t frames = session->available_capture_duration();
742 if (frames == max_frames) {
743 strcpy (buf, _("Disk: 24hrs+"));
748 nframes_t fr = session->frame_rate();
750 rec_enabled_streams = 0;
751 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
753 if (rec_enabled_streams) {
754 frames /= rec_enabled_streams;
757 hrs = frames / (fr * 3600);
758 frames -= hrs * fr * 3600;
759 mins = frames / (fr * 60);
760 frames -= mins * fr * 60;
763 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
766 disk_space_label.set_text (buf);
770 ARDOUR_UI::update_wall_clock ()
777 tm_now = localtime (&now);
779 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
780 wall_clock_label.set_text (buf);
786 ARDOUR_UI::session_menu (GdkEventButton *ev)
788 session_popup_menu->popup (0, 0);
793 ARDOUR_UI::redisplay_recent_sessions ()
795 vector<string *> *sessions;
796 vector<string *>::iterator i;
797 RecentSessionsSorter cmp;
799 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
800 recent_session_model->clear ();
803 ARDOUR::read_recent_sessions (rs);
806 recent_session_display.set_model (recent_session_model);
810 /* sort them alphabetically */
811 sort (rs.begin(), rs.end(), cmp);
812 sessions = new vector<string*>;
814 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
815 sessions->push_back (new string ((*i).second));
818 for (i = sessions->begin(); i != sessions->end(); ++i) {
820 vector<string*>* states;
821 vector<const gchar*> item;
822 string fullpath = *(*i);
824 /* remove any trailing / */
826 if (fullpath[fullpath.length()-1] == '/') {
827 fullpath = fullpath.substr (0, fullpath.length()-1);
830 /* now get available states for this session */
832 if ((states = Session::possible_states (fullpath)) == 0) {
837 TreeModel::Row row = *(recent_session_model->append());
839 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
840 row[recent_session_columns.fullpath] = fullpath;
842 if (states->size() > 1) {
844 /* add the children */
846 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
848 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
850 child_row[recent_session_columns.visible_name] = **i2;
851 child_row[recent_session_columns.fullpath] = fullpath;
860 recent_session_display.set_model (recent_session_model);
865 ARDOUR_UI::build_session_selector ()
867 session_selector_window = new ArdourDialog ("session selector");
869 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
871 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
872 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
873 session_selector_window->set_default_response (RESPONSE_ACCEPT);
874 recent_session_model = TreeStore::create (recent_session_columns);
875 recent_session_display.set_model (recent_session_model);
876 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
877 recent_session_display.set_headers_visible (false);
878 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
880 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
882 scroller->add (recent_session_display);
883 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
885 session_selector_window->set_name ("SessionSelectorWindow");
886 session_selector_window->set_size_request (200, 400);
887 session_selector_window->get_vbox()->pack_start (*scroller);
888 session_selector_window->show_all_children();
892 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
894 session_selector_window->response (RESPONSE_ACCEPT);
898 ARDOUR_UI::open_recent_session ()
900 /* popup selector window */
902 if (session_selector_window == 0) {
903 build_session_selector ();
906 redisplay_recent_sessions ();
908 ResponseType r = (ResponseType) session_selector_window->run ();
910 session_selector_window->hide();
913 case RESPONSE_ACCEPT:
919 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
921 if (i == recent_session_model->children().end()) {
925 Glib::ustring path = (*i)[recent_session_columns.fullpath];
926 Glib::ustring state = (*i)[recent_session_columns.visible_name];
928 _session_is_new = false;
930 load_session (path, state);
934 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
938 if (stat (info.filename.c_str(), &statbuf) != 0) {
942 if (!S_ISDIR(statbuf.st_mode)) {
948 string session_file = info.filename;
950 session_file += Glib::path_get_basename (info.filename);
951 session_file += ".ardour";
953 if (stat (session_file.c_str(), &statbuf) != 0) {
957 return S_ISREG (statbuf.st_mode);
961 ARDOUR_UI::check_audioengine ()
964 if (!engine->connected()) {
965 MessageDialog msg (_("Ardour is not connected to JACK\n"
966 "You cannot open or close sessions in this condition"));
977 ARDOUR_UI::open_session ()
979 if (!check_audioengine()) {
984 /* popup selector window */
986 if (open_session_selector == 0) {
988 /* ardour sessions are folders */
990 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
991 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
992 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
994 FileFilter session_filter;
995 session_filter.add_pattern ("*.ardour");
996 session_filter.set_name (_("Ardour sessions"));
997 open_session_selector->add_filter (session_filter);
998 open_session_selector->set_filter (session_filter);
1001 int response = open_session_selector->run();
1002 open_session_selector->hide ();
1005 case RESPONSE_ACCEPT:
1008 open_session_selector->hide();
1012 open_session_selector->hide();
1013 string session_path = open_session_selector->get_filename();
1017 if (session_path.length() > 0) {
1018 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1019 _session_is_new = isnew;
1020 load_session (path, name);
1027 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1029 list<boost::shared_ptr<MidiTrack> > tracks;
1032 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1039 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1041 if (tracks.size() != how_many) {
1042 if (how_many == 1) {
1043 error << _("could not create a new midi track") << endmsg;
1045 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1049 if ((route = session->new_midi_route ()) == 0) {
1050 error << _("could not create new midi bus") << endmsg;
1056 MessageDialog msg (*editor,
1057 _("There are insufficient JACK ports available\n\
1058 to create a new track or bus.\n\
1059 You should save Ardour, exit and\n\
1060 restart JACK with more ports."));
1067 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1069 list<boost::shared_ptr<AudioTrack> > tracks;
1070 Session::RouteList routes;
1073 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1079 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1081 if (tracks.size() != how_many) {
1082 if (how_many == 1) {
1083 error << _("could not create a new audio track") << endmsg;
1085 error << string_compose (_("could only create %1 of %2 new audio %3"),
1086 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1092 routes = session->new_audio_route (input_channels, output_channels, how_many);
1094 if (routes.size() != how_many) {
1095 if (how_many == 1) {
1096 error << _("could not create a new audio track") << endmsg;
1098 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1104 if (need_control_room_outs) {
1110 route->set_stereo_control_outs (control_lr_channels);
1111 route->control_outs()->set_stereo_pan (pans, this);
1113 #endif /* CONTROLOUTS */
1117 cerr << "About to complain about JACK\n";
1118 MessageDialog msg (*editor,
1119 _("There are insufficient JACK ports available\n\
1120 to create a new track or bus.\n\
1121 You should save Ardour, exit and\n\
1122 restart JACK with more ports."));
1128 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1130 nframes_t _preroll = 0;
1133 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1134 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1136 if (new_position > _preroll) {
1137 new_position -= _preroll;
1142 session->request_locate (new_position);
1147 ARDOUR_UI::transport_goto_start ()
1150 session->goto_start();
1153 /* force displayed area in editor to start no matter
1154 what "follow playhead" setting is.
1158 editor->reset_x_origin (session->current_start_frame());
1164 ARDOUR_UI::transport_goto_zero ()
1167 session->request_locate (0);
1170 /* force displayed area in editor to start no matter
1171 what "follow playhead" setting is.
1175 editor->reset_x_origin (0);
1181 ARDOUR_UI::transport_goto_end ()
1184 nframes_t frame = session->current_end_frame();
1185 session->request_locate (frame);
1187 /* force displayed area in editor to start no matter
1188 what "follow playhead" setting is.
1192 editor->reset_x_origin (frame);
1198 ARDOUR_UI::transport_stop ()
1204 if (session->is_auditioning()) {
1205 session->cancel_audition ();
1209 if (session->get_play_loop ()) {
1210 session->request_play_loop (false);
1213 session->request_stop ();
1217 ARDOUR_UI::transport_stop_and_forget_capture ()
1220 session->request_stop (true);
1225 ARDOUR_UI::remove_last_capture()
1228 editor->remove_last_capture();
1233 ARDOUR_UI::transport_record ()
1236 switch (session->record_status()) {
1237 case Session::Disabled:
1238 if (session->ntracks() == 0) {
1239 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1243 session->maybe_enable_record ();
1245 case Session::Recording:
1246 case Session::Enabled:
1247 session->disable_record (false, true);
1253 ARDOUR_UI::transport_roll ()
1261 rolling = session->transport_rolling ();
1263 if (session->get_play_loop()) {
1264 session->request_play_loop (false);
1265 auto_loop_button.set_visual_state (1);
1266 roll_button.set_visual_state (1);
1267 } else if (session->get_play_range ()) {
1268 session->request_play_range (false);
1269 play_selection_button.set_visual_state (0);
1270 } else if (rolling) {
1271 session->request_locate (session->last_transport_start(), true);
1274 session->request_transport_speed (1.0f);
1278 ARDOUR_UI::transport_loop()
1281 if (session->get_play_loop()) {
1282 if (session->transport_rolling()) {
1283 Location * looploc = session->locations()->auto_loop_location();
1285 session->request_locate (looploc->start(), true);
1290 session->request_play_loop (true);
1296 ARDOUR_UI::transport_play_selection ()
1302 if (!session->get_play_range()) {
1303 session->request_stop ();
1306 editor->play_selection ();
1310 ARDOUR_UI::transport_rewind (int option)
1312 float current_transport_speed;
1315 current_transport_speed = session->transport_speed();
1317 if (current_transport_speed >= 0.0f) {
1320 session->request_transport_speed (-1.0f);
1323 session->request_transport_speed (-4.0f);
1326 session->request_transport_speed (-0.5f);
1331 session->request_transport_speed (current_transport_speed * 1.5f);
1337 ARDOUR_UI::transport_forward (int option)
1339 float current_transport_speed;
1342 current_transport_speed = session->transport_speed();
1344 if (current_transport_speed <= 0.0f) {
1347 session->request_transport_speed (1.0f);
1350 session->request_transport_speed (4.0f);
1353 session->request_transport_speed (0.5f);
1358 session->request_transport_speed (current_transport_speed * 1.5f);
1364 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1370 boost::shared_ptr<Route> r;
1372 if ((r = session->route_by_remote_id (dstream)) != 0) {
1376 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1377 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1386 ARDOUR_UI::queue_transport_change ()
1388 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1392 ARDOUR_UI::map_transport_state ()
1394 float sp = session->transport_speed();
1397 transport_rolling ();
1398 } else if (sp < 0.0f) {
1399 transport_rewinding ();
1400 } else if (sp > 0.0f) {
1401 transport_forwarding ();
1403 transport_stopped ();
1408 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1410 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1411 (int) adj.get_value()].c_str());
1415 ARDOUR_UI::engine_stopped ()
1417 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1418 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1419 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1423 ARDOUR_UI::engine_running ()
1425 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1426 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1427 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1429 Glib::RefPtr<Action> action;
1430 char* action_name = 0;
1432 switch (engine->frames_per_cycle()) {
1434 action_name = X_("JACKLatency32");
1437 action_name = X_("JACKLatency64");
1440 action_name = X_("JACKLatency128");
1443 action_name = X_("JACKLatency512");
1446 action_name = X_("JACKLatency1024");
1449 action_name = X_("JACKLatency2048");
1452 action_name = X_("JACKLatency4096");
1455 action_name = X_("JACKLatency8192");
1458 /* XXX can we do anything useful ? */
1464 action = ActionManager::get_action (X_("JACK"), action_name);
1467 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1468 ract->set_active ();
1474 ARDOUR_UI::engine_halted ()
1476 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1478 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1479 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1481 update_sample_rate (0);
1483 MessageDialog msg (*editor,
1485 JACK has either been shutdown or it\n\
1486 disconnected Ardour because Ardour\n\
1487 was not fast enough. You can save the\n\
1488 session and/or try to reconnect to JACK ."));
1493 ARDOUR_UI::do_engine_start ()
1501 error << _("Unable to start the session running")
1511 ARDOUR_UI::setup_theme ()
1516 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
1519 rcfile = Config->get_ui_rc_file();
1522 rcfile = find_config_file (rcfile);
1524 if (rcfile.empty()) {
1525 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;
1527 cerr << "Loading ui configuration file " << rcfile << endl;
1530 ThemeChanged (rcfile); //EMIT SIGNAL
1531 theme_manager->setup_theme();
1535 ARDOUR_UI::start_engine ()
1537 if (do_engine_start () == 0) {
1538 if (session && _session_is_new) {
1539 /* we need to retain initial visual
1540 settings for a new session
1542 session->save_state ("");
1550 ARDOUR_UI::update_clocks ()
1552 if (!editor || !editor->dragging_playhead()) {
1553 Clock (session->audible_frame(), false, editor->edit_cursor_position(false)); /* EMIT_SIGNAL */
1558 ARDOUR_UI::start_clocking ()
1560 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1564 ARDOUR_UI::stop_clocking ()
1566 clock_signal_connection.disconnect ();
1570 ARDOUR_UI::toggle_clocking ()
1573 if (clock_button.get_active()) {
1582 ARDOUR_UI::_blink (void *arg)
1585 ((ARDOUR_UI *) arg)->blink ();
1592 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1596 ARDOUR_UI::start_blinking ()
1598 /* Start the blink signal. Everybody with a blinking widget
1599 uses Blink to drive the widget's state.
1602 if (blink_timeout_tag < 0) {
1604 blink_timeout_tag = g_timeout_add (240, _blink, this);
1609 ARDOUR_UI::stop_blinking ()
1611 if (blink_timeout_tag >= 0) {
1612 g_source_remove (blink_timeout_tag);
1613 blink_timeout_tag = -1;
1618 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1624 if (io.n_inputs().n_total() == 0) {
1629 /* XXX we're not handling multiple ports yet. */
1631 const char **connections = io.input(0)->get_connections();
1633 if (connections == 0 || connections[0] == '\0') {
1636 buf = connections[0];
1643 if (io.n_outputs().n_total() == 0) {
1648 /* XXX we're not handling multiple ports yet. */
1650 const char **connections = io.output(0)->get_connections();
1652 if (connections == 0 || connections[0] == '\0') {
1655 buf = connections[0];
1662 /** Ask the user for the name of a new shapshot and then take it.
1665 ARDOUR_UI::snapshot_session ()
1667 ArdourPrompter prompter (true);
1671 struct tm local_time;
1674 localtime_r (&n, &local_time);
1675 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1677 prompter.set_name ("Prompter");
1678 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1679 prompter.set_prompt (_("Name of New Snapshot"));
1680 prompter.set_initial_text (timebuf);
1682 switch (prompter.run()) {
1683 case RESPONSE_ACCEPT:
1684 prompter.get_result (snapname);
1685 if (snapname.length()){
1686 save_state (snapname);
1696 ARDOUR_UI::save_state (const string & name)
1698 (void) save_state_canfail (name);
1702 ARDOUR_UI::save_state_canfail (string name)
1707 if (name.length() == 0) {
1708 name = session->snap_name();
1711 if ((ret = session->save_state (name)) != 0) {
1715 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1720 ARDOUR_UI::restore_state (string name)
1723 if (name.length() == 0) {
1724 name = session->name();
1726 session->restore_state (name);
1731 ARDOUR_UI::primary_clock_value_changed ()
1734 session->request_locate (primary_clock.current_time ());
1739 ARDOUR_UI::secondary_clock_value_changed ()
1742 session->request_locate (secondary_clock.current_time ());
1747 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1749 if (session && dstream && dstream->record_enabled()) {
1751 Session::RecordState rs;
1753 rs = session->record_status ();
1756 case Session::Disabled:
1757 case Session::Enabled:
1758 if (w->get_state() != STATE_SELECTED) {
1759 w->set_state (STATE_SELECTED);
1763 case Session::Recording:
1764 if (w->get_state() != STATE_ACTIVE) {
1765 w->set_state (STATE_ACTIVE);
1771 if (w->get_state() != STATE_NORMAL) {
1772 w->set_state (STATE_NORMAL);
1778 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1784 switch (session->record_status()) {
1785 case Session::Enabled:
1787 rec_button.set_visual_state (2);
1789 rec_button.set_visual_state (0);
1793 case Session::Recording:
1794 rec_button.set_visual_state (1);
1798 rec_button.set_visual_state (0);
1804 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1812 ARDOUR_UI::save_template ()
1815 ArdourPrompter prompter (true);
1818 prompter.set_name (X_("Prompter"));
1819 prompter.set_prompt (_("Name for mix template:"));
1820 prompter.set_initial_text(session->name() + _("-template"));
1821 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1823 switch (prompter.run()) {
1824 case RESPONSE_ACCEPT:
1825 prompter.get_result (name);
1827 if (name.length()) {
1828 session->save_template (name);
1838 ARDOUR_UI::new_session (std::string predetermined_path)
1840 string session_name;
1841 string session_path;
1843 if (!check_audioengine()) {
1847 int response = Gtk::RESPONSE_NONE;
1849 new_session_dialog->set_modal(true);
1850 new_session_dialog->set_name (predetermined_path);
1851 new_session_dialog->reset_recent();
1852 new_session_dialog->show();
1853 new_session_dialog->set_current_page (0);
1856 response = new_session_dialog->run ();
1858 if (!check_audioengine()) {
1859 new_session_dialog->hide ();
1863 _session_is_new = false;
1865 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1870 new_session_dialog->hide ();
1873 } else if (response == Gtk::RESPONSE_NONE) {
1875 /* Clear was pressed */
1876 new_session_dialog->reset();
1878 } else if (response == Gtk::RESPONSE_YES) {
1880 /* YES == OPEN, but there's no enum for that */
1882 session_name = new_session_dialog->session_name();
1884 if (session_name.empty()) {
1885 response = Gtk::RESPONSE_NONE;
1889 if (session_name[0] == '/' ||
1890 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1891 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1892 load_session (Glib::path_get_dirname (session_name), session_name);
1894 session_path = new_session_dialog->session_folder();
1895 load_session (session_path, session_name);
1898 } else if (response == Gtk::RESPONSE_OK) {
1900 session_name = new_session_dialog->session_name();
1902 if (!new_session_dialog->on_new_session_page ()) {
1904 /* XXX this is a bit of a hack..
1905 i really want the new sesion dialog to return RESPONSE_YES
1906 if we're on page 1 (the load page)
1907 Unfortunately i can't see how atm..
1910 if (session_name.empty()) {
1911 response = Gtk::RESPONSE_NONE;
1915 if (session_name[0] == '/' ||
1916 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1917 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1918 load_session (Glib::path_get_dirname (session_name), session_name);
1920 session_path = new_session_dialog->session_folder();
1921 load_session (session_path, session_name);
1926 if (session_name.empty()) {
1927 response = Gtk::RESPONSE_NONE;
1931 if (session_name[0] == '/' ||
1932 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1933 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1935 session_path = Glib::path_get_dirname (session_name);
1936 session_name = Glib::path_get_basename (session_name);
1940 session_path = new_session_dialog->session_folder();
1944 //XXX This is needed because session constructor wants a
1945 //non-existant path. hopefully this will be fixed at some point.
1947 session_path = Glib::build_filename (session_path, session_name);
1949 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1951 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1953 MessageDialog msg (str,
1955 Gtk::MESSAGE_WARNING,
1956 Gtk::BUTTONS_YES_NO,
1960 msg.set_name (X_("CleanupDialog"));
1961 msg.set_wmclass (X_("existing_session"), "Ardour");
1962 msg.set_position (Gtk::WIN_POS_MOUSE);
1964 switch (msg.run()) {
1966 load_session (session_path, session_name);
1970 response = RESPONSE_NONE;
1971 new_session_dialog->reset ();
1976 _session_is_new = true;
1978 std::string template_name = new_session_dialog->session_template_name();
1980 if (new_session_dialog->use_session_template()) {
1982 load_session (session_path, session_name, &template_name);
1988 AutoConnectOption iconnect;
1989 AutoConnectOption oconnect;
1991 if (new_session_dialog->create_control_bus()) {
1992 cchns = (uint32_t) new_session_dialog->control_channel_count();
1997 if (new_session_dialog->create_master_bus()) {
1998 mchns = (uint32_t) new_session_dialog->master_channel_count();
2003 if (new_session_dialog->connect_inputs()) {
2004 iconnect = AutoConnectPhysical;
2006 iconnect = AutoConnectOption (0);
2009 /// @todo some minor tweaks.
2011 if (new_session_dialog->connect_outs_to_master()) {
2012 oconnect = AutoConnectMaster;
2013 } else if (new_session_dialog->connect_outs_to_physical()) {
2014 oconnect = AutoConnectPhysical;
2016 oconnect = AutoConnectOption (0);
2019 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
2020 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
2022 if (!build_session (session_path,
2030 engine->frame_rate() * 60 * 5)) {
2032 response = Gtk::RESPONSE_NONE;
2033 new_session_dialog->reset ();
2040 } while (response == Gtk::RESPONSE_NONE);
2044 new_session_dialog->get_window()->set_cursor();
2045 new_session_dialog->hide();
2050 ARDOUR_UI::close_session()
2052 if (!check_audioengine()) {
2061 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2063 Session *new_session;
2064 session_loaded = false;
2066 if (!check_audioengine()) {
2070 if(!unload_session ()) return -1;
2072 /* if it already exists, we must have write access */
2074 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2075 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2076 "This prevents the session from being loaded."));
2082 new_session = new Session (*engine, path, snap_name, mix_template);
2087 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2091 connect_to_session (new_session);
2093 Config->set_current_owner (ConfigVariableBase::Interface);
2095 session_loaded = true;
2097 goto_editor_window ();
2100 session->set_clean ();
2103 editor->edit_cursor_position (true);
2108 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2109 uint32_t control_channels,
2110 uint32_t master_channels,
2111 AutoConnectOption input_connect,
2112 AutoConnectOption output_connect,
2115 nframes_t initial_length)
2117 Session *new_session;
2119 if (!check_audioengine()) {
2123 session_loaded = false;
2125 if (!unload_session ()) return false;
2127 _session_is_new = true;
2130 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2131 control_channels, master_channels, nphysin, nphysout, initial_length);
2136 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2141 connect_to_session (new_session);
2143 session_loaded = true;
2151 editor->show_window ();
2162 ARDOUR_UI::show_splash ()
2165 about = new About();
2166 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2173 ARDOUR_UI::about_signal_response(int response)
2179 ARDOUR_UI::hide_splash ()
2182 about->get_window()->set_cursor ();
2188 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2192 removed = rep.paths.size();
2195 MessageDialog msgd (*editor,
2196 _("No audio files were ready for cleanup"),
2199 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2200 msgd.set_secondary_text (_("If this seems suprising, \n\
2201 check for any existing snapshots.\n\
2202 These may still include regions that\n\
2203 require some unused files to continue to exist."));
2209 ArdourDialog results (_("ardour: cleanup"), true, false);
2211 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2212 CleanupResultsModelColumns() {
2216 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2217 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2221 CleanupResultsModelColumns results_columns;
2222 Glib::RefPtr<Gtk::ListStore> results_model;
2223 Gtk::TreeView results_display;
2225 results_model = ListStore::create (results_columns);
2226 results_display.set_model (results_model);
2227 results_display.append_column (list_title, results_columns.visible_name);
2229 results_display.set_name ("CleanupResultsList");
2230 results_display.set_headers_visible (true);
2231 results_display.set_headers_clickable (false);
2232 results_display.set_reorderable (false);
2234 Gtk::ScrolledWindow list_scroller;
2237 Gtk::HBox dhbox; // the hbox for the image and text
2238 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2239 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2241 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2243 const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2245 if (rep.space < 1048576.0f) {
2247 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2249 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1024.0f, "kilo"));
2253 txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2255 txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
2259 dhbox.pack_start (*dimage, true, false, 5);
2260 dhbox.pack_start (txt, true, false, 5);
2262 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2263 TreeModel::Row row = *(results_model->append());
2264 row[results_columns.visible_name] = *i;
2265 row[results_columns.fullpath] = *i;
2268 list_scroller.add (results_display);
2269 list_scroller.set_size_request (-1, 150);
2270 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2272 dvbox.pack_start (dhbox, true, false, 5);
2273 dvbox.pack_start (list_scroller, true, false, 5);
2274 ddhbox.pack_start (dvbox, true, false, 5);
2276 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2277 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2278 results.set_default_response (RESPONSE_CLOSE);
2279 results.set_position (Gtk::WIN_POS_MOUSE);
2280 results.show_all_children ();
2281 results.set_resizable (false);
2288 ARDOUR_UI::cleanup ()
2291 /* shouldn't happen: menu item is insensitive */
2296 MessageDialog checker (_("Are you sure you want to cleanup?"),
2298 Gtk::MESSAGE_QUESTION,
2299 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2301 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2302 ALL undo/redo information will be lost if you cleanup.\n\
2303 After cleanup, unused audio files will be moved to a \
2304 \"dead sounds\" location."));
2306 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2307 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2308 checker.set_default_response (RESPONSE_CANCEL);
2310 checker.set_name (_("CleanupDialog"));
2311 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2312 checker.set_position (Gtk::WIN_POS_MOUSE);
2314 switch (checker.run()) {
2315 case RESPONSE_ACCEPT:
2321 Session::cleanup_report rep;
2323 editor->prepare_for_cleanup ();
2325 /* do not allow flush until a session is reloaded */
2327 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2329 act->set_sensitive (false);
2332 if (session->cleanup_sources (rep)) {
2337 display_cleanup_results (rep,
2340 The following %1 %2 not in use and \n\
2341 have been moved to:\n\
2343 Flushing the wastebasket will \n\
2344 release an additional\n\
2345 %4 %5bytes of disk space.\n"
2353 ARDOUR_UI::flush_trash ()
2356 /* shouldn't happen: menu item is insensitive */
2360 Session::cleanup_report rep;
2362 if (session->cleanup_trash_sources (rep)) {
2366 display_cleanup_results (rep,
2368 _("The following %1 %2 deleted from\n\
2370 releasing %4 %5bytes of disk space"));
2374 ARDOUR_UI::add_route (Gtk::Window* float_window)
2382 if (add_route_dialog == 0) {
2383 add_route_dialog = new AddRouteDialog;
2385 add_route_dialog->set_transient_for (*float_window);
2389 if (add_route_dialog->is_visible()) {
2390 /* we're already doing this */
2394 ResponseType r = (ResponseType) add_route_dialog->run ();
2396 add_route_dialog->hide();
2399 case RESPONSE_ACCEPT:
2406 if ((count = add_route_dialog->count()) <= 0) {
2410 uint32_t input_chan = add_route_dialog->channels ();
2411 uint32_t output_chan;
2412 string name_template = add_route_dialog->name_template ();
2413 bool track = add_route_dialog->track ();
2415 AutoConnectOption oac = Config->get_output_auto_connect();
2417 if (oac & AutoConnectMaster) {
2418 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2420 output_chan = input_chan;
2423 /* XXX do something with name template */
2425 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2427 session_add_midi_track(count);
2429 MessageDialog msg (*editor,
2430 _("Sorry, MIDI Busses are not supported at this time."));
2432 //session_add_midi_bus();
2436 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2438 session_add_audio_bus (input_chan, output_chan, count);
2444 ARDOUR_UI::mixer_settings () const
2449 node = session->instant_xml(X_("Mixer"));
2451 node = Config->instant_xml(X_("Mixer"));
2455 node = new XMLNode (X_("Mixer"));
2462 ARDOUR_UI::editor_settings () const
2467 node = session->instant_xml(X_("Editor"));
2469 node = Config->instant_xml(X_("Editor"));
2473 node = new XMLNode (X_("Editor"));
2479 ARDOUR_UI::keyboard_settings () const
2483 node = Config->extra_xml(X_("Keyboard"));
2486 node = new XMLNode (X_("Keyboard"));
2492 ARDOUR_UI::halt_on_xrun_message ()
2494 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2496 MessageDialog msg (*editor,
2497 _("Recording was stopped because your system could not keep up."));
2502 ARDOUR_UI::disk_overrun_handler ()
2504 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2506 if (!have_disk_speed_dialog_displayed) {
2507 have_disk_speed_dialog_displayed = true;
2508 MessageDialog* msg = new MessageDialog (*editor, _("\
2509 The disk system on your computer\n\
2510 was not able to keep up with Ardour.\n\
2512 Specifically, it failed to write data to disk\n\
2513 quickly enough to keep up with recording.\n"));
2514 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2520 ARDOUR_UI::disk_underrun_handler ()
2522 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2524 if (!have_disk_speed_dialog_displayed) {
2525 have_disk_speed_dialog_displayed = true;
2526 MessageDialog* msg = new MessageDialog (*editor,
2527 _("The disk system on your computer\n\
2528 was not able to keep up with Ardour.\n\
2530 Specifically, it failed to read data from disk\n\
2531 quickly enough to keep up with playback.\n"));
2532 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2538 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2540 have_disk_speed_dialog_displayed = false;
2545 ARDOUR_UI::pending_state_dialog ()
2547 ArdourDialog dialog ("pending state dialog");
2549 This session appears to have been in\n\
2550 middle of recording when ardour or\n\
2551 the computer was shutdown.\n\
2553 Ardour can recover any captured audio for\n\
2554 you, or it can ignore it. Please decide\n\
2555 what you would like to do.\n"));
2557 dialog.get_vbox()->pack_start (message);
2558 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2559 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2561 dialog.set_position (WIN_POS_CENTER);
2564 switch (dialog.run ()) {
2565 case RESPONSE_ACCEPT:
2573 ARDOUR_UI::disconnect_from_jack ()
2576 if( engine->disconnect_from_jack ()) {
2577 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2581 update_sample_rate (0);
2586 ARDOUR_UI::reconnect_to_jack ()
2589 if (engine->reconnect_to_jack ()) {
2590 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2594 update_sample_rate (0);
2599 ARDOUR_UI::cmdline_new_session (string path)
2601 if (path[0] != '/') {
2602 char buf[PATH_MAX+1];
2605 getcwd (buf, sizeof (buf));
2614 return FALSE; /* don't call it again */
2618 ARDOUR_UI::use_config ()
2620 Glib::RefPtr<Action> act;
2622 switch (Config->get_native_file_data_format ()) {
2624 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2627 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2632 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2633 ract->set_active ();
2636 switch (Config->get_native_file_header_format ()) {
2638 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2641 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2644 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2647 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2650 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2653 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2656 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2661 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2662 ract->set_active ();
2665 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2667 set_transport_controllable_state (*node);
2672 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2674 if (Config->get_primary_clock_delta_edit_cursor()) {
2675 primary_clock.set (pos, false, editor->edit_cursor_position(false), 'p');
2677 primary_clock.set (pos, 0, true);
2680 if (Config->get_secondary_clock_delta_edit_cursor()) {
2681 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 's');
2683 secondary_clock.set (pos);
2686 if (big_clock_window) {
2687 big_clock.set (pos);
2692 ARDOUR_UI::record_state_changed ()
2694 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2696 if (!session || !big_clock_window) {
2697 /* why bother - the clock isn't visible */
2701 switch (session->record_status()) {
2702 case Session::Recording:
2703 big_clock.set_widget_name ("BigClockRecording");
2706 big_clock.set_widget_name ("BigClockNonRecording");
2712 ARDOUR_UI::set_keybindings_path (string path)
2714 keybindings_path = path;
2718 ARDOUR_UI::save_keybindings ()
2720 if (can_save_keybindings) {
2721 AccelMap::save (keybindings_path);
2726 ARDOUR_UI::first_idle ()
2729 session->allow_auto_play (true);
2731 can_save_keybindings = true;
2736 ARDOUR_UI::store_clock_modes ()
2738 XMLNode* node = new XMLNode(X_("ClockModes"));
2740 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2741 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2744 session->add_extra_xml (*node);
2745 session->set_dirty ();
2750 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2751 : Controllable (name), ui (u), type(tp)
2757 ARDOUR_UI::TransportControllable::set_value (float val)
2759 if (type == ShuttleControl) {
2766 fract = -((0.5f - val)/0.5f);
2768 fract = ((val - 0.5f)/0.5f);
2772 ui.set_shuttle_fract (fract);
2777 /* do nothing: these are radio-style actions */
2785 action = X_("Roll");
2788 action = X_("Stop");
2791 action = X_("Goto Start");
2794 action = X_("Goto End");
2797 action = X_("Loop");
2800 action = X_("Play Selection");
2803 action = X_("Record");
2813 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2821 ARDOUR_UI::TransportControllable::get_value (void) const
2840 case ShuttleControl:
2850 ARDOUR_UI::TransportControllable::set_id (const string& str)
2856 ARDOUR_UI::setup_profile ()
2858 if (gdk_screen_width() < 1200) {
2859 Profile->set_small_screen ();
2864 ARDOUR_UI::disable_all_plugins ()
2870 // session->begin_reversible_command (_("Disable all plugins"));
2872 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2874 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2875 // XMLNode& before = (*i)->get_redirect_state ();
2876 // session->add_command (new MementoCommand<Route>(**i, &before, 0));
2877 (*i)->disable_plugins ();
2878 // XMLNode& after = (*i)->get_redirect_state ();
2879 // session->add_command (new MementoCommand<Route>(**i, 0, &after));
2883 // session->commit_reversible_command ();
2887 ARDOUR_UI::ab_all_plugins ()
2893 boost::shared_ptr<Session::RouteList> routes = session->get_routes ();
2895 for (Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
2896 (*i)->ab_plugins (ab_direction);
2899 ab_direction = !ab_direction;