2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/resource.h>
32 #include <gtkmm/messagedialog.h>
33 #include <gtkmm/accelmap.h>
35 #include <pbd/error.h>
36 #include <pbd/compose.h>
37 #include <pbd/pathscanner.h>
38 #include <pbd/failed_constructor.h>
39 #include <pbd/enumwriter.h>
40 #include <pbd/stacktrace.h>
41 #include <gtkmm2ext/gtk_ui.h>
42 #include <gtkmm2ext/utils.h>
43 #include <gtkmm2ext/click_box.h>
44 #include <gtkmm2ext/fastmeter.h>
45 #include <gtkmm2ext/stop_signal.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/window_title.h>
49 #include <midi++/port.h>
50 #include <midi++/mmc.h>
52 #include <ardour/ardour.h>
53 #include <ardour/session_route.h>
54 #include <ardour/port.h>
55 #include <ardour/audioengine.h>
56 #include <ardour/playlist.h>
57 #include <ardour/utils.h>
58 #include <ardour/audio_diskstream.h>
59 #include <ardour/audiofilesource.h>
60 #include <ardour/recent_sessions.h>
61 #include <ardour/port.h>
62 #include <ardour/audio_track.h>
65 #include "ardour_ui.h"
66 #include "public_editor.h"
67 #include "audio_clock.h"
72 #include "add_route_dialog.h"
73 #include "new_session_dialog.h"
76 #include "gui_thread.h"
77 #include "color_manager.h"
81 using namespace ARDOUR;
83 using namespace Gtkmm2ext;
87 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
89 sigc::signal<void,bool> ARDOUR_UI::Blink;
90 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
91 sigc::signal<void> ARDOUR_UI::MidRapidScreenUpdate;
92 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
93 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
95 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
97 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
99 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
100 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
101 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
102 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
106 adjuster_table (3, 3),
110 preroll_button (_("pre\nroll")),
111 postroll_button (_("post\nroll")),
115 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
119 roll_controllable ("transport roll", *this, TransportControllable::Roll),
120 stop_controllable ("transport stop", *this, TransportControllable::Stop),
121 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
122 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
123 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
124 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
125 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
126 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
127 shuttle_controller_binding_proxy (shuttle_controllable),
129 roll_button (roll_controllable),
130 stop_button (stop_controllable),
131 goto_start_button (goto_start_controllable),
132 goto_end_button (goto_end_controllable),
133 auto_loop_button (auto_loop_controllable),
134 play_selection_button (play_selection_controllable),
135 rec_button (rec_controllable),
137 shuttle_units_button (_("% ")),
139 punch_in_button (_("Punch In")),
140 punch_out_button (_("Punch Out")),
141 auto_return_button (_("Auto Return")),
142 auto_play_button (_("Auto Play")),
143 auto_input_button (_("Auto Input")),
144 click_button (_("Click")),
145 time_master_button (_("time\nmaster")),
147 auditioning_alert_button (_("AUDITION")),
148 solo_alert_button (_("SOLO")),
151 using namespace Gtk::Menu_Helpers;
157 if (theArdourUI == 0) {
163 color_manager = new ColorManager();
165 std::string color_file = ARDOUR::find_config_file("ardour.colors");
167 color_manager->load (color_file);
172 _session_is_new = false;
173 big_clock_window = 0;
174 session_selector_window = 0;
175 last_key_press_time = 0;
176 connection_editor = 0;
177 add_route_dialog = 0;
181 open_session_selector = 0;
182 have_configure_timeout = false;
183 have_disk_speed_dialog_displayed = false;
184 _will_create_new_session_automatically = false;
185 session_loaded = false;
186 last_speed_displayed = -1.0f;
187 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
189 can_save_keybindings = false;
190 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
192 last_configure_time.tv_sec = 0;
193 last_configure_time.tv_usec = 0;
195 shuttle_grabbed = false;
197 shuttle_max_speed = 8.0f;
199 shuttle_style_menu = 0;
200 shuttle_unit_menu = 0;
202 gettimeofday (&last_peak_grab, 0);
203 gettimeofday (&last_shuttle_request, 0);
205 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
206 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
208 /* handle pending state with a dialog */
210 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
212 /* have to wait for AudioEngine and Configuration before proceeding */
216 ARDOUR_UI::set_engine (AudioEngine& e)
220 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
221 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
222 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
223 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
225 ActionManager::init ();
226 new_session_dialog = new NewSessionDialog();
230 keyboard = new Keyboard;
232 if (setup_windows ()) {
233 throw failed_constructor ();
236 if (GTK_ARDOUR::show_key_actions) {
237 vector<string> names;
238 vector<string> paths;
240 vector<AccelKey> bindings;
242 ActionManager::get_all_actions (names, paths, keys, bindings);
244 vector<string>::iterator n;
245 vector<string>::iterator k;
246 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
247 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
253 /* start with timecode, metering enabled
256 blink_timeout_tag = -1;
258 /* the global configuration object is now valid */
262 /* this being a GUI and all, we want peakfiles */
264 AudioFileSource::set_build_peakfiles (true);
265 AudioFileSource::set_build_missing_peakfiles (true);
267 /* set default clock modes */
269 primary_clock.set_mode (AudioClock::SMPTE);
270 secondary_clock.set_mode (AudioClock::BBT);
272 /* start the time-of-day-clock */
274 update_wall_clock ();
275 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
277 update_disk_space ();
279 update_sample_rate (engine->frame_rate());
281 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
282 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
285 ARDOUR_UI::~ARDOUR_UI ()
287 save_ardour_state ();
301 if (add_route_dialog) {
302 delete add_route_dialog;
307 ARDOUR_UI::configure_timeout ()
312 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
313 /* no configure events yet */
317 gettimeofday (&now, 0);
318 timersub (&now, &last_configure_time, &diff);
320 /* force a gap of 0.5 seconds since the last configure event
323 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
326 have_configure_timeout = false;
327 save_ardour_state ();
333 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
335 if (have_configure_timeout) {
336 gettimeofday (&last_configure_time, 0);
338 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
339 have_configure_timeout = true;
346 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
348 const XMLProperty* prop;
350 if ((prop = node.property ("roll")) != 0) {
351 roll_controllable.set_id (prop->value());
353 if ((prop = node.property ("stop")) != 0) {
354 stop_controllable.set_id (prop->value());
356 if ((prop = node.property ("goto_start")) != 0) {
357 goto_start_controllable.set_id (prop->value());
359 if ((prop = node.property ("goto_end")) != 0) {
360 goto_end_controllable.set_id (prop->value());
362 if ((prop = node.property ("auto_loop")) != 0) {
363 auto_loop_controllable.set_id (prop->value());
365 if ((prop = node.property ("play_selection")) != 0) {
366 play_selection_controllable.set_id (prop->value());
368 if ((prop = node.property ("rec")) != 0) {
369 rec_controllable.set_id (prop->value());
371 if ((prop = node.property ("shuttle")) != 0) {
372 shuttle_controllable.set_id (prop->value());
377 ARDOUR_UI::get_transport_controllable_state ()
379 XMLNode* node = new XMLNode(X_("TransportControllables"));
382 roll_controllable.id().print (buf, sizeof (buf));
383 node->add_property (X_("roll"), buf);
384 stop_controllable.id().print (buf, sizeof (buf));
385 node->add_property (X_("stop"), buf);
386 goto_start_controllable.id().print (buf, sizeof (buf));
387 node->add_property (X_("goto_start"), buf);
388 goto_end_controllable.id().print (buf, sizeof (buf));
389 node->add_property (X_("goto_end"), buf);
390 auto_loop_controllable.id().print (buf, sizeof (buf));
391 node->add_property (X_("auto_loop"), buf);
392 play_selection_controllable.id().print (buf, sizeof (buf));
393 node->add_property (X_("play_selection"), buf);
394 rec_controllable.id().print (buf, sizeof (buf));
395 node->add_property (X_("rec"), buf);
396 shuttle_controllable.id().print (buf, sizeof (buf));
397 node->add_property (X_("shuttle"), buf);
403 ARDOUR_UI::save_ardour_state ()
405 if (!keyboard || !mixer || !editor) {
409 /* XXX this is all a bit dubious. add_extra_xml() uses
410 a different lifetime model from add_instant_xml().
413 XMLNode* node = new XMLNode (keyboard->get_state());
414 Config->add_extra_xml (*node);
415 Config->add_extra_xml (get_transport_controllable_state());
416 Config->save_state();
418 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
419 XMLNode mnode(mixer->get_state());
422 session->add_instant_xml (enode, session->path());
423 session->add_instant_xml (mnode, session->path());
425 Config->add_instant_xml (enode, get_user_ardour_path());
426 Config->add_instant_xml (mnode, get_user_ardour_path());
433 ARDOUR_UI::startup ()
435 check_memory_locking();
439 ARDOUR_UI::no_memory_warning ()
441 XMLNode node (X_("no-memory-warning"));
442 Config->add_instant_xml (node, get_user_ardour_path());
446 ARDOUR_UI::check_memory_locking ()
449 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
453 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
455 if (engine->is_realtime() && memory_warning_node == 0) {
457 struct rlimit limits;
459 long pages, page_size;
461 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
464 ram = (int64_t) pages * (int64_t) page_size;
467 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
471 if (limits.rlim_cur != RLIM_INFINITY) {
473 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
476 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
477 "This might cause Ardour to run out of memory before your system "
478 "runs out of memory. \n\n"
479 "You can view the memory limit with 'ulimit -l', "
480 "and it is normally controlled by /etc/security/limits.conf"));
482 VBox* vbox = msg.get_vbox();
484 CheckButton cb (_("Do not show this window again"));
486 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
488 hbox.pack_start (cb, true, false);
489 vbox->pack_start (hbox);
492 editor->ensure_float (msg);
504 if (session && session->dirty()) {
505 switch (ask_about_saving_session(_("quit"))) {
510 /* use the default name */
511 if (save_state_canfail ("")) {
512 /* failed - don't quit */
513 MessageDialog msg (*editor,
515 Ardour was unable to save your session.\n\n\
516 If you still wish to quit, please use the\n\n\
517 \"Just quit\" option."));
528 session->set_deletion_in_progress ();
530 cerr << "Stopping engine\n";
532 Config->save_state();
537 ARDOUR_UI::ask_about_saving_session (const string & what)
539 ArdourDialog window (_("ardour: save session?"));
540 Gtk::HBox dhbox; // the hbox for the image and text
541 Gtk::Label prompt_label;
542 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
546 msg = string_compose(_("Don't %1"), what);
547 window.add_button (msg, RESPONSE_REJECT);
548 msg = string_compose(_("Just %1"), what);
549 window.add_button (msg, RESPONSE_APPLY);
550 msg = string_compose(_("Save and %1"), what);
551 window.add_button (msg, RESPONSE_ACCEPT);
553 window.set_default_response (RESPONSE_ACCEPT);
555 Gtk::Button noquit_button (msg);
556 noquit_button.set_name ("EditorGTKButton");
561 if (session->snap_name() == session->name()) {
564 type = _("snapshot");
566 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?"),
567 type, session->snap_name());
569 prompt_label.set_text (prompt);
570 prompt_label.set_name (X_("PrompterLabel"));
571 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
573 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
575 dhbox.set_homogeneous (false);
576 dhbox.pack_start (*dimage, false, false, 5);
577 dhbox.pack_start (prompt_label, true, false, 5);
578 window.get_vbox()->pack_start (dhbox);
580 window.set_name (_("Prompter"));
581 window.set_position (Gtk::WIN_POS_MOUSE);
582 window.set_modal (true);
583 window.set_resizable (false);
586 save_the_session = 0;
588 window.set_keep_above (true);
591 ResponseType r = (ResponseType) window.run();
596 case RESPONSE_ACCEPT: // save and get out of here
598 case RESPONSE_APPLY: // get out of here
608 ARDOUR_UI::every_second ()
611 update_buffer_load ();
612 update_disk_space ();
617 ARDOUR_UI::every_point_one_seconds ()
619 update_speed_display ();
620 RapidScreenUpdate(); /* EMIT_SIGNAL */
625 ARDOUR_UI::every_point_oh_five_seconds ()
627 MidRapidScreenUpdate(); /* EMIT_SIGNAL */
632 ARDOUR_UI::every_point_zero_one_seconds ()
634 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
639 ARDOUR_UI::update_sample_rate (nframes_t ignored)
643 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
645 if (!engine->connected()) {
647 snprintf (buf, sizeof (buf), _("disconnected"));
651 nframes_t rate = engine->frame_rate();
653 if (fmod (rate, 1000.0) != 0.0) {
654 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"),
655 (float) rate/1000.0f,
656 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
658 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"),
660 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
664 sample_rate_label.set_text (buf);
668 ARDOUR_UI::update_cpu_load ()
671 snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
672 cpu_load_label.set_text (buf);
676 ARDOUR_UI::update_buffer_load ()
681 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
682 session->playback_load(), session->capture_load());
683 buffer_load_label.set_text (buf);
685 buffer_load_label.set_text ("");
690 ARDOUR_UI::count_recenabled_streams (Route& route)
692 Track* track = dynamic_cast<Track*>(&route);
693 if (track && track->diskstream()->record_enabled()) {
694 rec_enabled_streams += track->n_inputs();
699 ARDOUR_UI::update_disk_space()
705 nframes_t frames = session->available_capture_duration();
708 if (frames == max_frames) {
709 strcpy (buf, _("Disk: 24hrs+"));
714 nframes_t fr = session->frame_rate();
716 rec_enabled_streams = 0;
717 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
719 if (rec_enabled_streams) {
720 frames /= rec_enabled_streams;
723 hrs = frames / (fr * 3600);
724 frames -= hrs * fr * 3600;
725 mins = frames / (fr * 60);
726 frames -= mins * fr * 60;
729 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
732 disk_space_label.set_text (buf);
736 ARDOUR_UI::update_wall_clock ()
743 tm_now = localtime (&now);
745 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
746 wall_clock_label.set_text (buf);
752 ARDOUR_UI::session_menu (GdkEventButton *ev)
754 session_popup_menu->popup (0, 0);
759 ARDOUR_UI::redisplay_recent_sessions ()
761 vector<string *> *sessions;
762 vector<string *>::iterator i;
763 RecentSessionsSorter cmp;
765 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
766 recent_session_model->clear ();
769 ARDOUR::read_recent_sessions (rs);
772 recent_session_display.set_model (recent_session_model);
776 /* sort them alphabetically */
777 sort (rs.begin(), rs.end(), cmp);
778 sessions = new vector<string*>;
780 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
781 sessions->push_back (new string ((*i).second));
784 for (i = sessions->begin(); i != sessions->end(); ++i) {
786 vector<string*>* states;
787 vector<const gchar*> item;
788 string fullpath = *(*i);
790 /* remove any trailing / */
792 if (fullpath[fullpath.length()-1] == '/') {
793 fullpath = fullpath.substr (0, fullpath.length()-1);
796 /* now get available states for this session */
798 if ((states = Session::possible_states (fullpath)) == 0) {
803 TreeModel::Row row = *(recent_session_model->append());
805 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
806 row[recent_session_columns.fullpath] = fullpath;
808 if (states->size() > 1) {
810 /* add the children */
812 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
814 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
816 child_row[recent_session_columns.visible_name] = **i2;
817 child_row[recent_session_columns.fullpath] = fullpath;
826 recent_session_display.set_model (recent_session_model);
831 ARDOUR_UI::build_session_selector ()
833 session_selector_window = new ArdourDialog ("session selector");
835 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
837 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
838 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
839 session_selector_window->set_default_response (RESPONSE_ACCEPT);
840 recent_session_model = TreeStore::create (recent_session_columns);
841 recent_session_display.set_model (recent_session_model);
842 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
843 recent_session_display.set_headers_visible (false);
844 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
846 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
848 scroller->add (recent_session_display);
849 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
851 session_selector_window->set_name ("SessionSelectorWindow");
852 session_selector_window->set_size_request (200, 400);
853 session_selector_window->get_vbox()->pack_start (*scroller);
854 session_selector_window->show_all_children();
858 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
860 session_selector_window->response (RESPONSE_ACCEPT);
864 ARDOUR_UI::open_recent_session ()
866 /* popup selector window */
868 if (session_selector_window == 0) {
869 build_session_selector ();
872 redisplay_recent_sessions ();
874 ResponseType r = (ResponseType) session_selector_window->run ();
876 session_selector_window->hide();
879 case RESPONSE_ACCEPT:
885 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
887 if (i == recent_session_model->children().end()) {
891 Glib::ustring path = (*i)[recent_session_columns.fullpath];
892 Glib::ustring state = (*i)[recent_session_columns.visible_name];
894 _session_is_new = false;
896 load_session (path, state);
900 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
904 if (stat (info.filename.c_str(), &statbuf) != 0) {
908 if (!S_ISDIR(statbuf.st_mode)) {
914 string session_file = info.filename;
916 session_file += Glib::path_get_basename (info.filename);
917 session_file += ".ardour";
919 if (stat (session_file.c_str(), &statbuf) != 0) {
923 return S_ISREG (statbuf.st_mode);
927 ARDOUR_UI::open_session ()
929 /* popup selector window */
931 if (open_session_selector == 0) {
933 /* ardour sessions are folders */
935 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
936 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
937 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
939 FileFilter session_filter;
940 session_filter.add_pattern ("*.ardour");
941 session_filter.set_name (_("Ardour sessions"));
942 open_session_selector->add_filter (session_filter);
943 open_session_selector->set_filter (session_filter);
946 int response = open_session_selector->run();
947 open_session_selector->hide ();
950 case RESPONSE_ACCEPT:
953 open_session_selector->hide();
957 open_session_selector->hide();
958 string session_path = open_session_selector->get_filename();
962 if (session_path.length() > 0) {
963 if (Session::find_session (session_path, path, name, isnew) == 0) {
964 _session_is_new = isnew;
965 load_session (path, name);
972 ARDOUR_UI::session_add_midi_track ()
974 cerr << _("Patience is a virtue.\n");
978 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
980 list<boost::shared_ptr<AudioTrack> > tracks;
981 Session::RouteList routes;
984 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
990 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
992 if (tracks.size() != how_many) {
994 error << _("could not create a new audio track") << endmsg;
996 error << string_compose (_("could only create %1 of %2 new audio %3"),
997 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1003 routes = session->new_audio_route (input_channels, output_channels, how_many);
1005 if (routes.size() != how_many) {
1006 if (how_many == 1) {
1007 error << _("could not create a new audio track") << endmsg;
1009 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1015 if (need_control_room_outs) {
1021 route->set_stereo_control_outs (control_lr_channels);
1022 route->control_outs()->set_stereo_pan (pans, this);
1024 #endif /* CONTROLOUTS */
1028 cerr << "About to complain about JACK\n";
1029 MessageDialog msg (*editor,
1030 _("There are insufficient JACK ports available\n\
1031 to create a new track or bus.\n\
1032 You should save Ardour, exit and\n\
1033 restart JACK with more ports."));
1039 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1041 nframes_t _preroll = 0;
1044 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1045 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1047 if (new_position > _preroll) {
1048 new_position -= _preroll;
1053 session->request_locate (new_position);
1058 ARDOUR_UI::transport_goto_start ()
1061 session->goto_start();
1064 /* force displayed area in editor to start no matter
1065 what "follow playhead" setting is.
1069 editor->reset_x_origin (session->current_start_frame());
1075 ARDOUR_UI::transport_goto_zero ()
1078 session->request_locate (0);
1081 /* force displayed area in editor to start no matter
1082 what "follow playhead" setting is.
1086 editor->reset_x_origin (0);
1092 ARDOUR_UI::transport_goto_end ()
1095 nframes_t frame = session->current_end_frame();
1096 session->request_locate (frame);
1098 /* force displayed area in editor to start no matter
1099 what "follow playhead" setting is.
1103 editor->reset_x_origin (frame);
1109 ARDOUR_UI::transport_stop ()
1115 if (session->is_auditioning()) {
1116 session->cancel_audition ();
1120 if (session->get_play_loop ()) {
1121 session->request_play_loop (false);
1124 session->request_stop ();
1128 ARDOUR_UI::transport_stop_and_forget_capture ()
1131 session->request_stop (true);
1136 ARDOUR_UI::remove_last_capture()
1139 editor->remove_last_capture();
1144 ARDOUR_UI::transport_record ()
1147 switch (session->record_status()) {
1148 case Session::Disabled:
1149 if (session->ntracks() == 0) {
1150 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1154 session->maybe_enable_record ();
1156 case Session::Recording:
1157 case Session::Enabled:
1158 session->disable_record (true);
1164 ARDOUR_UI::transport_roll ()
1172 rolling = session->transport_rolling ();
1174 if (session->get_play_loop()) {
1175 session->request_play_loop (false);
1176 auto_loop_button.set_visual_state (1);
1177 roll_button.set_visual_state (1);
1178 } else if (session->get_play_range ()) {
1179 session->request_play_range (false);
1180 play_selection_button.set_visual_state (0);
1181 } else if (rolling) {
1182 session->request_locate (session->last_transport_start(), true);
1185 session->request_transport_speed (1.0f);
1189 ARDOUR_UI::transport_loop()
1192 if (session->get_play_loop()) {
1193 if (session->transport_rolling()) {
1194 Location * looploc = session->locations()->auto_loop_location();
1196 session->request_locate (looploc->start(), true);
1201 session->request_play_loop (true);
1207 ARDOUR_UI::transport_play_selection ()
1213 if (!session->get_play_range()) {
1214 session->request_stop ();
1217 editor->play_selection ();
1221 ARDOUR_UI::transport_rewind (int option)
1223 float current_transport_speed;
1226 current_transport_speed = session->transport_speed();
1228 if (current_transport_speed >= 0.0f) {
1231 session->request_transport_speed (-1.0f);
1234 session->request_transport_speed (-4.0f);
1237 session->request_transport_speed (-0.5f);
1242 session->request_transport_speed (current_transport_speed * 1.5f);
1248 ARDOUR_UI::transport_forward (int option)
1250 float current_transport_speed;
1253 current_transport_speed = session->transport_speed();
1255 if (current_transport_speed <= 0.0f) {
1258 session->request_transport_speed (1.0f);
1261 session->request_transport_speed (4.0f);
1264 session->request_transport_speed (0.5f);
1269 session->request_transport_speed (current_transport_speed * 1.5f);
1275 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1281 boost::shared_ptr<Route> r;
1283 if ((r = session->route_by_remote_id (dstream)) != 0) {
1287 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1288 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1297 ARDOUR_UI::queue_transport_change ()
1299 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1303 ARDOUR_UI::map_transport_state ()
1305 float sp = session->transport_speed();
1308 transport_rolling ();
1309 } else if (sp < 0.0f) {
1310 transport_rewinding ();
1311 } else if (sp > 0.0f) {
1312 transport_forwarding ();
1314 transport_stopped ();
1319 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1321 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1322 (int) adj.get_value()].c_str());
1326 ARDOUR_UI::engine_stopped ()
1328 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1329 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1330 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1334 ARDOUR_UI::engine_running ()
1336 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1337 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1338 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1340 Glib::RefPtr<Action> action;
1341 char* action_name = 0;
1343 switch (engine->frames_per_cycle()) {
1345 action_name = X_("JACKLatency32");
1348 action_name = X_("JACKLatency64");
1351 action_name = X_("JACKLatency128");
1354 action_name = X_("JACKLatency512");
1357 action_name = X_("JACKLatency1024");
1360 action_name = X_("JACKLatency2048");
1363 action_name = X_("JACKLatency4096");
1366 action_name = X_("JACKLatency8192");
1369 /* XXX can we do anything useful ? */
1375 action = ActionManager::get_action (X_("JACK"), action_name);
1378 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1379 ract->set_active ();
1385 ARDOUR_UI::engine_halted ()
1387 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1389 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1390 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1392 update_sample_rate (0);
1394 MessageDialog msg (*editor,
1396 JACK has either been shutdown or it\n\
1397 disconnected Ardour because Ardour\n\
1398 was not fast enough. You can save the\n\
1399 session and/or try to reconnect to JACK ."));
1404 ARDOUR_UI::do_engine_start ()
1412 error << _("Unable to start the session running")
1422 ARDOUR_UI::start_engine ()
1424 if (do_engine_start () == 0) {
1425 if (session && _session_is_new) {
1426 /* we need to retain initial visual
1427 settings for a new session
1429 session->save_state ("");
1437 ARDOUR_UI::update_clocks ()
1439 if (!editor || !editor->dragging_playhead()) {
1440 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1445 ARDOUR_UI::start_clocking ()
1447 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1451 ARDOUR_UI::stop_clocking ()
1453 clock_signal_connection.disconnect ();
1457 ARDOUR_UI::toggle_clocking ()
1460 if (clock_button.get_active()) {
1469 ARDOUR_UI::_blink (void *arg)
1472 ((ARDOUR_UI *) arg)->blink ();
1479 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1483 ARDOUR_UI::start_blinking ()
1485 /* Start the blink signal. Everybody with a blinking widget
1486 uses Blink to drive the widget's state.
1489 if (blink_timeout_tag < 0) {
1491 blink_timeout_tag = g_timeout_add (240, _blink, this);
1496 ARDOUR_UI::stop_blinking ()
1498 if (blink_timeout_tag >= 0) {
1499 g_source_remove (blink_timeout_tag);
1500 blink_timeout_tag = -1;
1505 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1511 if (io.n_inputs() == 0) {
1516 /* XXX we're not handling multiple ports yet. */
1518 const char **connections = io.input(0)->get_connections();
1520 if (connections == 0 || connections[0] == '\0') {
1523 buf = connections[0];
1530 if (io.n_outputs() == 0) {
1535 /* XXX we're not handling multiple ports yet. */
1537 const char **connections = io.output(0)->get_connections();
1539 if (connections == 0 || connections[0] == '\0') {
1542 buf = connections[0];
1550 ARDOUR_UI::snapshot_session ()
1552 ArdourPrompter prompter (true);
1556 struct tm local_time;
1559 localtime_r (&n, &local_time);
1560 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1562 prompter.set_name ("Prompter");
1563 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1564 prompter.set_prompt (_("Name of New Snapshot"));
1565 prompter.set_initial_text (timebuf);
1567 switch (prompter.run()) {
1568 case RESPONSE_ACCEPT:
1569 prompter.get_result (snapname);
1570 if (snapname.length()){
1571 save_state (snapname);
1581 ARDOUR_UI::save_state (const string & name)
1583 (void) save_state_canfail (name);
1587 ARDOUR_UI::save_state_canfail (string name)
1592 if (name.length() == 0) {
1593 name = session->snap_name();
1596 if ((ret = session->save_state (name)) != 0) {
1600 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1605 ARDOUR_UI::restore_state (string name)
1608 if (name.length() == 0) {
1609 name = session->name();
1611 session->restore_state (name);
1616 ARDOUR_UI::primary_clock_value_changed ()
1619 session->request_locate (primary_clock.current_time ());
1624 ARDOUR_UI::secondary_clock_value_changed ()
1627 session->request_locate (secondary_clock.current_time ());
1632 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1634 if (session && dstream && dstream->record_enabled()) {
1636 Session::RecordState rs;
1638 rs = session->record_status ();
1641 case Session::Disabled:
1642 case Session::Enabled:
1643 if (w->get_state() != STATE_SELECTED) {
1644 w->set_state (STATE_SELECTED);
1648 case Session::Recording:
1649 if (w->get_state() != STATE_ACTIVE) {
1650 w->set_state (STATE_ACTIVE);
1656 if (w->get_state() != STATE_NORMAL) {
1657 w->set_state (STATE_NORMAL);
1663 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1669 switch (session->record_status()) {
1670 case Session::Enabled:
1672 rec_button.set_visual_state (2);
1674 rec_button.set_visual_state (0);
1678 case Session::Recording:
1679 rec_button.set_visual_state (1);
1683 rec_button.set_visual_state (0);
1689 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1697 ARDOUR_UI::save_template ()
1700 ArdourPrompter prompter (true);
1703 prompter.set_name (X_("Prompter"));
1704 prompter.set_prompt (_("Name for mix template:"));
1705 prompter.set_initial_text(session->name() + _("-template"));
1706 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1708 switch (prompter.run()) {
1709 case RESPONSE_ACCEPT:
1710 prompter.get_result (name);
1712 if (name.length()) {
1713 session->save_template (name);
1723 ARDOUR_UI::new_session (std::string predetermined_path)
1725 string session_name;
1726 string session_path;
1728 if (!engine->connected()) {
1729 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1734 int response = Gtk::RESPONSE_NONE;
1736 new_session_dialog->set_modal(true);
1737 new_session_dialog->set_name (predetermined_path);
1738 new_session_dialog->reset_recent();
1739 new_session_dialog->show();
1742 response = new_session_dialog->run ();
1744 if (!engine->connected()) {
1745 new_session_dialog->hide ();
1746 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1751 _session_is_new = false;
1753 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1758 new_session_dialog->hide ();
1761 } else if (response == Gtk::RESPONSE_NONE) {
1763 /* Clear was pressed */
1764 new_session_dialog->reset();
1766 } else if (response == Gtk::RESPONSE_YES) {
1768 /* YES == OPEN, but there's no enum for that */
1770 session_name = new_session_dialog->session_name();
1772 if (session_name.empty()) {
1773 response = Gtk::RESPONSE_NONE;
1777 if (session_name[0] == '/' ||
1778 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1779 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1780 load_session (Glib::path_get_dirname (session_name), session_name);
1782 session_path = new_session_dialog->session_folder();
1783 load_session (session_path, session_name);
1786 } else if (response == Gtk::RESPONSE_OK) {
1788 session_name = new_session_dialog->session_name();
1790 if (new_session_dialog->get_current_page() == 1) {
1792 /* XXX this is a bit of a hack..
1793 i really want the new sesion dialog to return RESPONSE_YES
1794 if we're on page 1 (the load page)
1795 Unfortunately i can't see how atm..
1798 if (session_name.empty()) {
1799 response = Gtk::RESPONSE_NONE;
1803 if (session_name[0] == '/' ||
1804 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1805 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1806 load_session (Glib::path_get_dirname (session_name), session_name);
1808 session_path = new_session_dialog->session_folder();
1809 load_session (session_path, session_name);
1814 if (session_name.empty()) {
1815 response = Gtk::RESPONSE_NONE;
1819 if (session_name[0] == '/' ||
1820 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1821 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1823 session_path = Glib::path_get_dirname (session_name);
1824 session_name = Glib::path_get_basename (session_name);
1828 session_path = new_session_dialog->session_folder();
1832 //XXX This is needed because session constructor wants a
1833 //non-existant path. hopefully this will be fixed at some point.
1835 session_path = Glib::build_filename (session_path, session_name);
1837 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1839 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1841 MessageDialog msg (str,
1843 Gtk::MESSAGE_WARNING,
1844 Gtk::BUTTONS_YES_NO,
1848 msg.set_name (X_("CleanupDialog"));
1849 msg.set_wmclass (X_("existing_session"), "Ardour");
1850 msg.set_position (Gtk::WIN_POS_MOUSE);
1852 switch (msg.run()) {
1854 load_session (session_path, session_name);
1858 response = RESPONSE_NONE;
1859 new_session_dialog->reset ();
1864 _session_is_new = true;
1866 std::string template_name = new_session_dialog->session_template_name();
1868 if (new_session_dialog->use_session_template()) {
1870 load_session (session_path, session_name, &template_name);
1876 AutoConnectOption iconnect;
1877 AutoConnectOption oconnect;
1879 if (new_session_dialog->create_control_bus()) {
1880 cchns = (uint32_t) new_session_dialog->control_channel_count();
1885 if (new_session_dialog->create_master_bus()) {
1886 mchns = (uint32_t) new_session_dialog->master_channel_count();
1891 if (new_session_dialog->connect_inputs()) {
1892 iconnect = AutoConnectPhysical;
1894 iconnect = AutoConnectOption (0);
1897 /// @todo some minor tweaks.
1899 if (new_session_dialog->connect_outs_to_master()) {
1900 oconnect = AutoConnectMaster;
1901 } else if (new_session_dialog->connect_outs_to_physical()) {
1902 oconnect = AutoConnectPhysical;
1904 oconnect = AutoConnectOption (0);
1907 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1908 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1910 if (build_session (session_path,
1918 engine->frame_rate() * 60 * 5)) {
1920 response = Gtk::RESPONSE_NONE;
1921 new_session_dialog->reset ();
1928 } while (response == Gtk::RESPONSE_NONE);
1932 new_session_dialog->get_window()->set_cursor();
1933 new_session_dialog->hide();
1938 ARDOUR_UI::close_session()
1945 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1947 Session *new_session;
1949 session_loaded = false;
1951 x = unload_session ();
1959 /* if it already exists, we must have write access */
1961 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1962 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1963 "This prevents the session from being loaded."));
1969 new_session = new Session (*engine, path, snap_name, mix_template);
1974 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1978 connect_to_session (new_session);
1980 Config->set_current_owner (ConfigVariableBase::Interface);
1982 session_loaded = true;
1984 goto_editor_window ();
1987 session->set_clean ();
1990 editor->edit_cursor_position (true);
1995 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1996 uint32_t control_channels,
1997 uint32_t master_channels,
1998 AutoConnectOption input_connect,
1999 AutoConnectOption output_connect,
2002 nframes_t initial_length)
2004 Session *new_session;
2007 session_loaded = false;
2008 x = unload_session ();
2015 _session_is_new = true;
2018 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2019 control_channels, master_channels, nphysin, nphysout, initial_length);
2024 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2029 connect_to_session (new_session);
2031 session_loaded = true;
2039 editor->show_window ();
2050 ARDOUR_UI::show_splash ()
2053 about = new About();
2054 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2061 ARDOUR_UI::about_signal_response(int response)
2067 ARDOUR_UI::hide_splash ()
2070 about->get_window()->set_cursor ();
2076 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2080 removed = rep.paths.size();
2083 MessageDialog msgd (*editor,
2084 _("No audio files were ready for cleanup"),
2087 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2088 msgd.set_secondary_text (_("If this seems suprising, \n\
2089 check for any existing snapshots.\n\
2090 These may still include regions that\n\
2091 require some unused files to continue to exist."));
2097 ArdourDialog results (_("ardour: cleanup"), true, false);
2099 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2100 CleanupResultsModelColumns() {
2104 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2105 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2109 CleanupResultsModelColumns results_columns;
2110 Glib::RefPtr<Gtk::ListStore> results_model;
2111 Gtk::TreeView results_display;
2113 results_model = ListStore::create (results_columns);
2114 results_display.set_model (results_model);
2115 results_display.append_column (list_title, results_columns.visible_name);
2117 results_display.set_name ("CleanupResultsList");
2118 results_display.set_headers_visible (true);
2119 results_display.set_headers_clickable (false);
2120 results_display.set_reorderable (false);
2122 Gtk::ScrolledWindow list_scroller;
2125 Gtk::HBox dhbox; // the hbox for the image and text
2126 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2127 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2129 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2131 if (rep.space < 1048576.0f) {
2133 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2135 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2139 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2141 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2145 dhbox.pack_start (*dimage, true, false, 5);
2146 dhbox.pack_start (txt, true, false, 5);
2148 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2149 TreeModel::Row row = *(results_model->append());
2150 row[results_columns.visible_name] = *i;
2151 row[results_columns.fullpath] = *i;
2154 list_scroller.add (results_display);
2155 list_scroller.set_size_request (-1, 150);
2156 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2158 dvbox.pack_start (dhbox, true, false, 5);
2159 dvbox.pack_start (list_scroller, true, false, 5);
2160 ddhbox.pack_start (dvbox, true, false, 5);
2162 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2163 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2164 results.set_default_response (RESPONSE_CLOSE);
2165 results.set_position (Gtk::WIN_POS_MOUSE);
2166 results.show_all_children ();
2167 results.set_resizable (false);
2174 ARDOUR_UI::cleanup ()
2177 /* shouldn't happen: menu item is insensitive */
2182 MessageDialog checker (_("Are you sure you want to cleanup?"),
2184 Gtk::MESSAGE_QUESTION,
2185 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2187 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2188 ALL undo/redo information will be lost if you cleanup.\n\
2189 After cleanup, unused audio files will be moved to a \
2190 \"dead sounds\" location."));
2192 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2193 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2194 checker.set_default_response (RESPONSE_CANCEL);
2196 checker.set_name (_("CleanupDialog"));
2197 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2198 checker.set_position (Gtk::WIN_POS_MOUSE);
2200 switch (checker.run()) {
2201 case RESPONSE_ACCEPT:
2207 Session::cleanup_report rep;
2209 editor->prepare_for_cleanup ();
2211 /* do not allow flush until a session is reloaded */
2213 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2215 act->set_sensitive (false);
2218 if (session->cleanup_sources (rep)) {
2223 display_cleanup_results (rep,
2226 The following %1 %2 not in use and \n\
2227 have been moved to:\n\
2229 Flushing the wastebasket will \n\
2230 release an additional\n\
2231 %4 %5bytes of disk space.\n"
2239 ARDOUR_UI::flush_trash ()
2242 /* shouldn't happen: menu item is insensitive */
2246 Session::cleanup_report rep;
2248 if (session->cleanup_trash_sources (rep)) {
2252 display_cleanup_results (rep,
2254 _("The following %1 %2 deleted from\n\
2256 releasing %4 %5bytes of disk space"));
2260 ARDOUR_UI::add_route (Gtk::Window* float_window)
2268 if (add_route_dialog == 0) {
2269 add_route_dialog = new AddRouteDialog;
2271 add_route_dialog->set_transient_for (*float_window);
2275 if (add_route_dialog->is_visible()) {
2276 /* we're already doing this */
2280 ResponseType r = (ResponseType) add_route_dialog->run ();
2282 add_route_dialog->hide();
2285 case RESPONSE_ACCEPT:
2292 if ((count = add_route_dialog->count()) <= 0) {
2296 uint32_t input_chan = add_route_dialog->channels ();
2297 uint32_t output_chan;
2298 string name_template = add_route_dialog->name_template ();
2299 bool track = add_route_dialog->track ();
2301 AutoConnectOption oac = Config->get_output_auto_connect();
2303 if (oac & AutoConnectMaster) {
2304 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2306 output_chan = input_chan;
2309 /* XXX do something with name template */
2312 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2314 session_add_audio_bus (input_chan, output_chan, count);
2319 ARDOUR_UI::mixer_settings () const
2324 node = session->instant_xml(X_("Mixer"), session->path());
2326 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2330 node = new XMLNode (X_("Mixer"));
2337 ARDOUR_UI::editor_settings () const
2342 node = session->instant_xml(X_("Editor"), session->path());
2344 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2348 node = new XMLNode (X_("Editor"));
2354 ARDOUR_UI::keyboard_settings () const
2358 node = Config->extra_xml(X_("Keyboard"));
2361 node = new XMLNode (X_("Keyboard"));
2367 ARDOUR_UI::halt_on_xrun_message ()
2369 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2371 MessageDialog msg (*editor,
2372 _("Recording was stopped because your system could not keep up."));
2377 ARDOUR_UI::disk_overrun_handler ()
2379 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2381 if (!have_disk_speed_dialog_displayed) {
2382 have_disk_speed_dialog_displayed = true;
2383 MessageDialog* msg = new MessageDialog (*editor, _("\
2384 The disk system on your computer\n\
2385 was not able to keep up with Ardour.\n\
2387 Specifically, it failed to write data to disk\n\
2388 quickly enough to keep up with recording.\n"));
2389 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2395 ARDOUR_UI::disk_underrun_handler ()
2397 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2399 if (!have_disk_speed_dialog_displayed) {
2400 have_disk_speed_dialog_displayed = true;
2401 MessageDialog* msg = new MessageDialog (*editor,
2402 _("The disk system on your computer\n\
2403 was not able to keep up with Ardour.\n\
2405 Specifically, it failed to read data from disk\n\
2406 quickly enough to keep up with playback.\n"));
2407 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2413 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2415 have_disk_speed_dialog_displayed = false;
2420 ARDOUR_UI::pending_state_dialog ()
2422 ArdourDialog dialog ("pending state dialog");
2424 This session appears to have been in\n\
2425 middle of recording when ardour or\n\
2426 the computer was shutdown.\n\
2428 Ardour can recover any captured audio for\n\
2429 you, or it can ignore it. Please decide\n\
2430 what you would like to do.\n"));
2432 dialog.get_vbox()->pack_start (message);
2433 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2434 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2436 dialog.set_position (WIN_POS_CENTER);
2439 switch (dialog.run ()) {
2440 case RESPONSE_ACCEPT:
2448 ARDOUR_UI::disconnect_from_jack ()
2451 if( engine->disconnect_from_jack ()) {
2452 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2456 update_sample_rate (0);
2461 ARDOUR_UI::reconnect_to_jack ()
2464 if (engine->reconnect_to_jack ()) {
2465 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2469 update_sample_rate (0);
2474 ARDOUR_UI::cmdline_new_session (string path)
2476 if (path[0] != '/') {
2477 char buf[PATH_MAX+1];
2480 getcwd (buf, sizeof (buf));
2489 _will_create_new_session_automatically = false; /* done it */
2490 return FALSE; /* don't call it again */
2494 ARDOUR_UI::use_config ()
2496 Glib::RefPtr<Action> act;
2498 switch (Config->get_native_file_data_format ()) {
2500 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2503 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2508 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2509 ract->set_active ();
2512 switch (Config->get_native_file_header_format ()) {
2514 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2517 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2520 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2523 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2526 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2529 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2532 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2537 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2538 ract->set_active ();
2541 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2543 set_transport_controllable_state (*node);
2548 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2550 primary_clock.set (pos);
2551 secondary_clock.set (pos);
2553 if (big_clock_window) {
2554 big_clock.set (pos);
2559 ARDOUR_UI::record_state_changed ()
2561 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2563 if (!session || !big_clock_window) {
2564 /* why bother - the clock isn't visible */
2568 switch (session->record_status()) {
2569 case Session::Recording:
2570 big_clock.set_widget_name ("BigClockRecording");
2573 big_clock.set_widget_name ("BigClockNonRecording");
2579 ARDOUR_UI::set_keybindings_path (string path)
2581 keybindings_path = path;
2585 ARDOUR_UI::save_keybindings ()
2587 if (can_save_keybindings) {
2588 AccelMap::save (keybindings_path);
2593 ARDOUR_UI::first_idle ()
2595 can_save_keybindings = true;
2600 ARDOUR_UI::store_clock_modes ()
2602 XMLNode* node = new XMLNode(X_("ClockModes"));
2604 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2605 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2608 session->add_extra_xml (*node);
2609 session->set_dirty ();
2614 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2615 : Controllable (name), ui (u), type(tp)
2621 ARDOUR_UI::TransportControllable::set_value (float val)
2623 if (type == ShuttleControl) {
2630 fract = -((0.5f - val)/0.5f);
2632 fract = ((val - 0.5f)/0.5f);
2636 ui.set_shuttle_fract (fract);
2641 /* do nothing: these are radio-style actions */
2649 action = X_("Roll");
2652 action = X_("Stop");
2655 action = X_("Goto Start");
2658 action = X_("Goto End");
2661 action = X_("Loop");
2664 action = X_("Play Selection");
2667 action = X_("Record");
2677 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2685 ARDOUR_UI::TransportControllable::get_value (void) const
2704 case ShuttleControl:
2714 ARDOUR_UI::TransportControllable::set_id (const string& str)