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::SuperRapidScreenUpdate;
92 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
94 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
96 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
98 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
99 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
100 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
101 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
105 adjuster_table (3, 3),
109 preroll_button (_("pre\nroll")),
110 postroll_button (_("post\nroll")),
114 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
118 roll_controllable ("transport roll", *this, TransportControllable::Roll),
119 stop_controllable ("transport stop", *this, TransportControllable::Stop),
120 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
121 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
122 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
123 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
124 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
125 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
126 shuttle_controller_binding_proxy (shuttle_controllable),
128 roll_button (roll_controllable),
129 stop_button (stop_controllable),
130 goto_start_button (goto_start_controllable),
131 goto_end_button (goto_end_controllable),
132 auto_loop_button (auto_loop_controllable),
133 play_selection_button (play_selection_controllable),
134 rec_button (rec_controllable),
136 shuttle_units_button (_("% ")),
138 punch_in_button (_("Punch In")),
139 punch_out_button (_("Punch Out")),
140 auto_return_button (_("Auto Return")),
141 auto_play_button (_("Auto Play")),
142 auto_input_button (_("Auto Input")),
143 click_button (_("Click")),
144 time_master_button (_("time\nmaster")),
146 auditioning_alert_button (_("AUDITION")),
147 solo_alert_button (_("SOLO")),
150 using namespace Gtk::Menu_Helpers;
156 if (theArdourUI == 0) {
162 color_manager = new ColorManager();
164 std::string color_file = ARDOUR::find_config_file("ardour.colors");
166 color_manager->load (color_file);
171 _session_is_new = false;
172 big_clock_window = 0;
173 session_selector_window = 0;
174 last_key_press_time = 0;
175 connection_editor = 0;
176 add_route_dialog = 0;
180 open_session_selector = 0;
181 have_configure_timeout = false;
182 have_disk_speed_dialog_displayed = false;
183 _will_create_new_session_automatically = false;
184 session_loaded = false;
185 last_speed_displayed = -1.0f;
186 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
188 can_save_keybindings = false;
189 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::first_idle));
191 last_configure_time.tv_sec = 0;
192 last_configure_time.tv_usec = 0;
194 shuttle_grabbed = false;
196 shuttle_max_speed = 8.0f;
198 shuttle_style_menu = 0;
199 shuttle_unit_menu = 0;
201 gettimeofday (&last_peak_grab, 0);
202 gettimeofday (&last_shuttle_request, 0);
204 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
205 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
207 /* handle pending state with a dialog */
209 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
211 /* have to wait for AudioEngine and Configuration before proceeding */
215 ARDOUR_UI::set_engine (AudioEngine& e)
219 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
220 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
221 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
222 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
224 ActionManager::init ();
225 new_session_dialog = new NewSessionDialog();
229 keyboard = new Keyboard;
231 if (setup_windows ()) {
232 throw failed_constructor ();
235 if (GTK_ARDOUR::show_key_actions) {
236 vector<string> names;
237 vector<string> paths;
239 vector<AccelKey> bindings;
241 ActionManager::get_all_actions (names, paths, keys, bindings);
243 vector<string>::iterator n;
244 vector<string>::iterator k;
245 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
246 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
252 /* start with timecode, metering enabled
255 blink_timeout_tag = -1;
257 /* the global configuration object is now valid */
261 /* this being a GUI and all, we want peakfiles */
263 AudioFileSource::set_build_peakfiles (true);
264 AudioFileSource::set_build_missing_peakfiles (true);
266 /* set default clock modes */
268 primary_clock.set_mode (AudioClock::SMPTE);
269 secondary_clock.set_mode (AudioClock::BBT);
271 /* start the time-of-day-clock */
273 update_wall_clock ();
274 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
276 update_disk_space ();
278 update_sample_rate (engine->frame_rate());
280 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
281 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
284 ARDOUR_UI::~ARDOUR_UI ()
286 save_ardour_state ();
300 if (add_route_dialog) {
301 delete add_route_dialog;
306 ARDOUR_UI::configure_timeout ()
311 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
312 /* no configure events yet */
316 gettimeofday (&now, 0);
317 timersub (&now, &last_configure_time, &diff);
319 /* force a gap of 0.5 seconds since the last configure event
322 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
325 have_configure_timeout = false;
326 save_ardour_state ();
332 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
334 if (have_configure_timeout) {
335 gettimeofday (&last_configure_time, 0);
337 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
338 have_configure_timeout = true;
345 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
347 const XMLProperty* prop;
349 if ((prop = node.property ("roll")) != 0) {
350 roll_controllable.set_id (prop->value());
352 if ((prop = node.property ("stop")) != 0) {
353 stop_controllable.set_id (prop->value());
355 if ((prop = node.property ("goto_start")) != 0) {
356 goto_start_controllable.set_id (prop->value());
358 if ((prop = node.property ("goto_end")) != 0) {
359 goto_end_controllable.set_id (prop->value());
361 if ((prop = node.property ("auto_loop")) != 0) {
362 auto_loop_controllable.set_id (prop->value());
364 if ((prop = node.property ("play_selection")) != 0) {
365 play_selection_controllable.set_id (prop->value());
367 if ((prop = node.property ("rec")) != 0) {
368 rec_controllable.set_id (prop->value());
370 if ((prop = node.property ("shuttle")) != 0) {
371 shuttle_controllable.set_id (prop->value());
376 ARDOUR_UI::get_transport_controllable_state ()
378 XMLNode* node = new XMLNode(X_("TransportControllables"));
381 roll_controllable.id().print (buf, sizeof (buf));
382 node->add_property (X_("roll"), buf);
383 stop_controllable.id().print (buf, sizeof (buf));
384 node->add_property (X_("stop"), buf);
385 goto_start_controllable.id().print (buf, sizeof (buf));
386 node->add_property (X_("goto_start"), buf);
387 goto_end_controllable.id().print (buf, sizeof (buf));
388 node->add_property (X_("goto_end"), buf);
389 auto_loop_controllable.id().print (buf, sizeof (buf));
390 node->add_property (X_("auto_loop"), buf);
391 play_selection_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("play_selection"), buf);
393 rec_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("rec"), buf);
395 shuttle_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("shuttle"), buf);
402 ARDOUR_UI::save_ardour_state ()
404 if (!keyboard || !mixer || !editor) {
408 /* XXX this is all a bit dubious. add_extra_xml() uses
409 a different lifetime model from add_instant_xml().
412 XMLNode* node = new XMLNode (keyboard->get_state());
413 Config->add_extra_xml (*node);
414 Config->add_extra_xml (get_transport_controllable_state());
415 Config->save_state();
417 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
418 XMLNode mnode(mixer->get_state());
421 session->add_instant_xml (enode, session->path());
422 session->add_instant_xml (mnode, session->path());
424 Config->add_instant_xml (enode, get_user_ardour_path());
425 Config->add_instant_xml (mnode, get_user_ardour_path());
432 ARDOUR_UI::startup ()
434 check_memory_locking();
438 ARDOUR_UI::no_memory_warning ()
440 XMLNode node (X_("no-memory-warning"));
441 Config->add_instant_xml (node, get_user_ardour_path());
445 ARDOUR_UI::check_memory_locking ()
448 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
452 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
454 if (engine->is_realtime() && memory_warning_node == 0) {
456 struct rlimit limits;
458 long pages, page_size;
460 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
463 ram = (int64_t) pages * (int64_t) page_size;
466 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
470 if (limits.rlim_cur != RLIM_INFINITY) {
472 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
475 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
476 "This might cause Ardour to run out of memory before your system "
477 "runs out of memory. \n\n"
478 "You can view the memory limit with 'ulimit -l', "
479 "and it is normally controlled by /etc/security/limits.conf"));
481 VBox* vbox = msg.get_vbox();
483 CheckButton cb (_("Do not show this window again"));
485 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
487 hbox.pack_start (cb, true, false);
488 vbox->pack_start (hbox);
491 editor->ensure_float (msg);
503 if (session && session->dirty()) {
504 switch (ask_about_saving_session(_("quit"))) {
509 /* use the default name */
510 if (save_state_canfail ("")) {
511 /* failed - don't quit */
512 MessageDialog msg (*editor,
514 Ardour was unable to save your session.\n\n\
515 If you still wish to quit, please use the\n\n\
516 \"Just quit\" option."));
527 session->set_deletion_in_progress ();
530 Config->save_state();
535 ARDOUR_UI::ask_about_saving_session (const string & what)
537 ArdourDialog window (_("ardour: save session?"));
538 Gtk::HBox dhbox; // the hbox for the image and text
539 Gtk::Label prompt_label;
540 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
544 msg = string_compose(_("Don't %1"), what);
545 window.add_button (msg, RESPONSE_REJECT);
546 msg = string_compose(_("Just %1"), what);
547 window.add_button (msg, RESPONSE_APPLY);
548 msg = string_compose(_("Save and %1"), what);
549 window.add_button (msg, RESPONSE_ACCEPT);
551 window.set_default_response (RESPONSE_ACCEPT);
553 Gtk::Button noquit_button (msg);
554 noquit_button.set_name ("EditorGTKButton");
559 if (session->snap_name() == session->name()) {
562 type = _("snapshot");
564 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?"),
565 type, session->snap_name());
567 prompt_label.set_text (prompt);
568 prompt_label.set_name (X_("PrompterLabel"));
569 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
571 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
573 dhbox.set_homogeneous (false);
574 dhbox.pack_start (*dimage, false, false, 5);
575 dhbox.pack_start (prompt_label, true, false, 5);
576 window.get_vbox()->pack_start (dhbox);
578 window.set_name (_("Prompter"));
579 window.set_position (Gtk::WIN_POS_MOUSE);
580 window.set_modal (true);
581 window.set_resizable (false);
584 save_the_session = 0;
586 window.set_keep_above (true);
589 ResponseType r = (ResponseType) window.run();
594 case RESPONSE_ACCEPT: // save and get out of here
596 case RESPONSE_APPLY: // get out of here
606 ARDOUR_UI::every_second ()
609 update_buffer_load ();
610 update_disk_space ();
615 ARDOUR_UI::every_point_one_seconds ()
617 update_speed_display ();
618 RapidScreenUpdate(); /* EMIT_SIGNAL */
623 ARDOUR_UI::every_point_zero_one_seconds ()
625 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
630 ARDOUR_UI::update_sample_rate (nframes_t ignored)
634 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
636 if (!engine->connected()) {
638 snprintf (buf, sizeof (buf), _("disconnected"));
642 nframes_t rate = engine->frame_rate();
644 if (fmod (rate, 1000.0) != 0.0) {
645 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"),
646 (float) rate/1000.0f,
647 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
649 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"),
651 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
655 sample_rate_label.set_text (buf);
659 ARDOUR_UI::update_cpu_load ()
662 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
663 cpu_load_label.set_text (buf);
667 ARDOUR_UI::update_buffer_load ()
672 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
673 session->playback_load(), session->capture_load());
674 buffer_load_label.set_text (buf);
676 buffer_load_label.set_text ("");
681 ARDOUR_UI::count_recenabled_streams (Route& route)
683 Track* track = dynamic_cast<Track*>(&route);
684 if (track && track->diskstream()->record_enabled()) {
685 rec_enabled_streams += track->n_inputs();
690 ARDOUR_UI::update_disk_space()
696 nframes_t frames = session->available_capture_duration();
699 if (frames == max_frames) {
700 strcpy (buf, _("Disk: 24hrs+"));
705 nframes_t fr = session->frame_rate();
707 rec_enabled_streams = 0;
708 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
710 if (rec_enabled_streams) {
711 frames /= rec_enabled_streams;
714 hrs = frames / (fr * 3600);
715 frames -= hrs * fr * 3600;
716 mins = frames / (fr * 60);
717 frames -= mins * fr * 60;
720 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
723 disk_space_label.set_text (buf);
727 ARDOUR_UI::update_wall_clock ()
734 tm_now = localtime (&now);
736 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
737 wall_clock_label.set_text (buf);
743 ARDOUR_UI::session_menu (GdkEventButton *ev)
745 session_popup_menu->popup (0, 0);
750 ARDOUR_UI::redisplay_recent_sessions ()
752 vector<string *> *sessions;
753 vector<string *>::iterator i;
754 RecentSessionsSorter cmp;
756 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
757 recent_session_model->clear ();
760 ARDOUR::read_recent_sessions (rs);
763 recent_session_display.set_model (recent_session_model);
767 /* sort them alphabetically */
768 sort (rs.begin(), rs.end(), cmp);
769 sessions = new vector<string*>;
771 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
772 sessions->push_back (new string ((*i).second));
775 for (i = sessions->begin(); i != sessions->end(); ++i) {
777 vector<string*>* states;
778 vector<const gchar*> item;
779 string fullpath = *(*i);
781 /* remove any trailing / */
783 if (fullpath[fullpath.length()-1] == '/') {
784 fullpath = fullpath.substr (0, fullpath.length()-1);
787 /* now get available states for this session */
789 if ((states = Session::possible_states (fullpath)) == 0) {
794 TreeModel::Row row = *(recent_session_model->append());
796 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
797 row[recent_session_columns.fullpath] = fullpath;
799 if (states->size() > 1) {
801 /* add the children */
803 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
805 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
807 child_row[recent_session_columns.visible_name] = **i2;
808 child_row[recent_session_columns.fullpath] = fullpath;
817 recent_session_display.set_model (recent_session_model);
822 ARDOUR_UI::build_session_selector ()
824 session_selector_window = new ArdourDialog ("session selector");
826 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
828 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
829 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
830 session_selector_window->set_default_response (RESPONSE_ACCEPT);
831 recent_session_model = TreeStore::create (recent_session_columns);
832 recent_session_display.set_model (recent_session_model);
833 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
834 recent_session_display.set_headers_visible (false);
835 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
837 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
839 scroller->add (recent_session_display);
840 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
842 session_selector_window->set_name ("SessionSelectorWindow");
843 session_selector_window->set_size_request (200, 400);
844 session_selector_window->get_vbox()->pack_start (*scroller);
845 session_selector_window->show_all_children();
849 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
851 session_selector_window->response (RESPONSE_ACCEPT);
855 ARDOUR_UI::open_recent_session ()
857 /* popup selector window */
859 if (session_selector_window == 0) {
860 build_session_selector ();
863 redisplay_recent_sessions ();
865 ResponseType r = (ResponseType) session_selector_window->run ();
867 session_selector_window->hide();
870 case RESPONSE_ACCEPT:
876 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
878 if (i == recent_session_model->children().end()) {
882 Glib::ustring path = (*i)[recent_session_columns.fullpath];
883 Glib::ustring state = (*i)[recent_session_columns.visible_name];
885 _session_is_new = false;
887 load_session (path, state);
891 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
895 if (stat (info.filename.c_str(), &statbuf) != 0) {
899 if (!S_ISDIR(statbuf.st_mode)) {
905 string session_file = info.filename;
907 session_file += Glib::path_get_basename (info.filename);
908 session_file += ".ardour";
910 if (stat (session_file.c_str(), &statbuf) != 0) {
914 return S_ISREG (statbuf.st_mode);
918 ARDOUR_UI::open_session ()
920 /* popup selector window */
922 if (open_session_selector == 0) {
924 /* ardour sessions are folders */
926 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
927 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
928 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
930 FileFilter session_filter;
931 session_filter.add_pattern ("*.ardour");
932 session_filter.set_name (_("Ardour sessions"));
933 open_session_selector->add_filter (session_filter);
934 open_session_selector->set_filter (session_filter);
937 int response = open_session_selector->run();
938 open_session_selector->hide ();
941 case RESPONSE_ACCEPT:
944 open_session_selector->hide();
948 open_session_selector->hide();
949 string session_path = open_session_selector->get_filename();
953 if (session_path.length() > 0) {
954 if (Session::find_session (session_path, path, name, isnew) == 0) {
955 _session_is_new = isnew;
956 load_session (path, name);
963 ARDOUR_UI::session_add_midi_track ()
965 cerr << _("Patience is a virtue.\n");
969 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
971 list<boost::shared_ptr<AudioTrack> > tracks;
972 Session::RouteList routes;
975 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
981 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
983 if (tracks.size() != how_many) {
985 error << _("could not create a new audio track") << endmsg;
987 error << string_compose (_("could only create %1 of %2 new audio %3"),
988 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
994 routes = session->new_audio_route (input_channels, output_channels, how_many);
996 if (routes.size() != how_many) {
998 error << _("could not create a new audio track") << endmsg;
1000 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1006 if (need_control_room_outs) {
1012 route->set_stereo_control_outs (control_lr_channels);
1013 route->control_outs()->set_stereo_pan (pans, this);
1015 #endif /* CONTROLOUTS */
1019 cerr << "About to complain about JACK\n";
1020 MessageDialog msg (*editor,
1021 _("There are insufficient JACK ports available\n\
1022 to create a new track or bus.\n\
1023 You should save Ardour, exit and\n\
1024 restart JACK with more ports."));
1030 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1032 nframes_t _preroll = 0;
1035 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1036 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1038 if (new_position > _preroll) {
1039 new_position -= _preroll;
1044 session->request_locate (new_position);
1049 ARDOUR_UI::transport_goto_start ()
1052 session->goto_start();
1055 /* force displayed area in editor to start no matter
1056 what "follow playhead" setting is.
1060 editor->reset_x_origin (session->current_start_frame());
1066 ARDOUR_UI::transport_goto_zero ()
1069 session->request_locate (0);
1072 /* force displayed area in editor to start no matter
1073 what "follow playhead" setting is.
1077 editor->reset_x_origin (0);
1083 ARDOUR_UI::transport_goto_end ()
1086 nframes_t frame = session->current_end_frame();
1087 session->request_locate (frame);
1089 /* force displayed area in editor to start no matter
1090 what "follow playhead" setting is.
1094 editor->reset_x_origin (frame);
1100 ARDOUR_UI::transport_stop ()
1106 if (session->is_auditioning()) {
1107 session->cancel_audition ();
1111 if (session->get_play_loop ()) {
1112 session->request_play_loop (false);
1115 session->request_stop ();
1119 ARDOUR_UI::transport_stop_and_forget_capture ()
1122 session->request_stop (true);
1127 ARDOUR_UI::remove_last_capture()
1130 editor->remove_last_capture();
1135 ARDOUR_UI::transport_record ()
1138 switch (session->record_status()) {
1139 case Session::Disabled:
1140 if (session->ntracks() == 0) {
1141 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1145 session->maybe_enable_record ();
1147 case Session::Recording:
1148 case Session::Enabled:
1149 session->disable_record (true);
1155 ARDOUR_UI::transport_roll ()
1163 rolling = session->transport_rolling ();
1165 if (session->get_play_loop()) {
1166 session->request_play_loop (false);
1167 auto_loop_button.set_visual_state (1);
1168 roll_button.set_visual_state (1);
1169 } else if (session->get_play_range ()) {
1170 session->request_play_range (false);
1171 play_selection_button.set_visual_state (0);
1172 } else if (rolling) {
1173 session->request_locate (session->last_transport_start(), true);
1176 session->request_transport_speed (1.0f);
1180 ARDOUR_UI::transport_loop()
1183 if (session->get_play_loop()) {
1184 if (session->transport_rolling()) {
1185 Location * looploc = session->locations()->auto_loop_location();
1187 session->request_locate (looploc->start(), true);
1192 session->request_play_loop (true);
1198 ARDOUR_UI::transport_play_selection ()
1204 if (!session->get_play_range()) {
1205 session->request_stop ();
1208 editor->play_selection ();
1212 ARDOUR_UI::transport_rewind (int option)
1214 float current_transport_speed;
1217 current_transport_speed = session->transport_speed();
1219 if (current_transport_speed >= 0.0f) {
1222 session->request_transport_speed (-1.0f);
1225 session->request_transport_speed (-4.0f);
1228 session->request_transport_speed (-0.5f);
1233 session->request_transport_speed (current_transport_speed * 1.5f);
1239 ARDOUR_UI::transport_forward (int option)
1241 float current_transport_speed;
1244 current_transport_speed = session->transport_speed();
1246 if (current_transport_speed <= 0.0f) {
1249 session->request_transport_speed (1.0f);
1252 session->request_transport_speed (4.0f);
1255 session->request_transport_speed (0.5f);
1260 session->request_transport_speed (current_transport_speed * 1.5f);
1266 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1272 boost::shared_ptr<Route> r;
1274 if ((r = session->route_by_remote_id (dstream)) != 0) {
1278 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1279 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1288 ARDOUR_UI::queue_transport_change ()
1290 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1294 ARDOUR_UI::map_transport_state ()
1296 float sp = session->transport_speed();
1299 transport_rolling ();
1300 } else if (sp < 0.0f) {
1301 transport_rewinding ();
1302 } else if (sp > 0.0f) {
1303 transport_forwarding ();
1305 transport_stopped ();
1310 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1312 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1313 (int) adj.get_value()].c_str());
1317 ARDOUR_UI::engine_stopped ()
1319 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1320 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1321 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1325 ARDOUR_UI::engine_running ()
1327 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1328 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1329 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1331 Glib::RefPtr<Action> action;
1332 char* action_name = 0;
1334 switch (engine->frames_per_cycle()) {
1336 action_name = X_("JACKLatency32");
1339 action_name = X_("JACKLatency64");
1342 action_name = X_("JACKLatency128");
1345 action_name = X_("JACKLatency512");
1348 action_name = X_("JACKLatency1024");
1351 action_name = X_("JACKLatency2048");
1354 action_name = X_("JACKLatency4096");
1357 action_name = X_("JACKLatency8192");
1360 /* XXX can we do anything useful ? */
1366 action = ActionManager::get_action (X_("JACK"), action_name);
1369 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1370 ract->set_active ();
1376 ARDOUR_UI::engine_halted ()
1378 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1380 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1381 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1383 update_sample_rate (0);
1385 MessageDialog msg (*editor,
1387 JACK has either been shutdown or it\n\
1388 disconnected Ardour because Ardour\n\
1389 was not fast enough. You can save the\n\
1390 session and/or try to reconnect to JACK ."));
1395 ARDOUR_UI::do_engine_start ()
1403 error << _("Unable to start the session running")
1413 ARDOUR_UI::start_engine ()
1415 if (do_engine_start () == 0) {
1416 if (session && _session_is_new) {
1417 /* we need to retain initial visual
1418 settings for a new session
1420 session->save_state ("");
1428 ARDOUR_UI::update_clocks ()
1430 if (!editor || !editor->dragging_playhead()) {
1431 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1436 ARDOUR_UI::start_clocking ()
1438 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1442 ARDOUR_UI::stop_clocking ()
1444 clock_signal_connection.disconnect ();
1448 ARDOUR_UI::toggle_clocking ()
1451 if (clock_button.get_active()) {
1460 ARDOUR_UI::_blink (void *arg)
1463 ((ARDOUR_UI *) arg)->blink ();
1470 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1474 ARDOUR_UI::start_blinking ()
1476 /* Start the blink signal. Everybody with a blinking widget
1477 uses Blink to drive the widget's state.
1480 if (blink_timeout_tag < 0) {
1482 blink_timeout_tag = g_timeout_add (240, _blink, this);
1487 ARDOUR_UI::stop_blinking ()
1489 if (blink_timeout_tag >= 0) {
1490 g_source_remove (blink_timeout_tag);
1491 blink_timeout_tag = -1;
1496 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1502 if (io.n_inputs() == 0) {
1507 /* XXX we're not handling multiple ports yet. */
1509 const char **connections = io.input(0)->get_connections();
1511 if (connections == 0 || connections[0] == '\0') {
1514 buf = connections[0];
1521 if (io.n_outputs() == 0) {
1526 /* XXX we're not handling multiple ports yet. */
1528 const char **connections = io.output(0)->get_connections();
1530 if (connections == 0 || connections[0] == '\0') {
1533 buf = connections[0];
1540 /** Ask the user for the name of a new shapshot and then take it.
1543 ARDOUR_UI::snapshot_session ()
1545 ArdourPrompter prompter (true);
1549 struct tm local_time;
1552 localtime_r (&n, &local_time);
1553 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1555 prompter.set_name ("Prompter");
1556 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1557 prompter.set_prompt (_("Name of New Snapshot"));
1558 prompter.set_initial_text (timebuf);
1560 switch (prompter.run()) {
1561 case RESPONSE_ACCEPT:
1562 prompter.get_result (snapname);
1563 if (snapname.length()){
1564 save_state (snapname);
1574 ARDOUR_UI::save_state (const string & name)
1576 (void) save_state_canfail (name);
1580 ARDOUR_UI::save_state_canfail (string name)
1585 if (name.length() == 0) {
1586 name = session->snap_name();
1589 if ((ret = session->save_state (name)) != 0) {
1593 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1598 ARDOUR_UI::restore_state (string name)
1601 if (name.length() == 0) {
1602 name = session->name();
1604 session->restore_state (name);
1609 ARDOUR_UI::primary_clock_value_changed ()
1612 session->request_locate (primary_clock.current_time ());
1617 ARDOUR_UI::secondary_clock_value_changed ()
1620 session->request_locate (secondary_clock.current_time ());
1625 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1627 if (session && dstream && dstream->record_enabled()) {
1629 Session::RecordState rs;
1631 rs = session->record_status ();
1634 case Session::Disabled:
1635 case Session::Enabled:
1636 if (w->get_state() != STATE_SELECTED) {
1637 w->set_state (STATE_SELECTED);
1641 case Session::Recording:
1642 if (w->get_state() != STATE_ACTIVE) {
1643 w->set_state (STATE_ACTIVE);
1649 if (w->get_state() != STATE_NORMAL) {
1650 w->set_state (STATE_NORMAL);
1656 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1662 switch (session->record_status()) {
1663 case Session::Enabled:
1665 rec_button.set_visual_state (2);
1667 rec_button.set_visual_state (0);
1671 case Session::Recording:
1672 rec_button.set_visual_state (1);
1676 rec_button.set_visual_state (0);
1682 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1690 ARDOUR_UI::save_template ()
1693 ArdourPrompter prompter (true);
1696 prompter.set_name (X_("Prompter"));
1697 prompter.set_prompt (_("Name for mix template:"));
1698 prompter.set_initial_text(session->name() + _("-template"));
1699 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1701 switch (prompter.run()) {
1702 case RESPONSE_ACCEPT:
1703 prompter.get_result (name);
1705 if (name.length()) {
1706 session->save_template (name);
1716 ARDOUR_UI::new_session (std::string predetermined_path)
1718 string session_name;
1719 string session_path;
1721 if (!engine->connected()) {
1722 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1727 int response = Gtk::RESPONSE_NONE;
1729 new_session_dialog->set_modal(true);
1730 new_session_dialog->set_name (predetermined_path);
1731 new_session_dialog->reset_recent();
1732 new_session_dialog->show();
1735 response = new_session_dialog->run ();
1737 if (!engine->connected()) {
1738 new_session_dialog->hide ();
1739 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1744 _session_is_new = false;
1746 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1751 new_session_dialog->hide ();
1754 } else if (response == Gtk::RESPONSE_NONE) {
1756 /* Clear was pressed */
1757 new_session_dialog->reset();
1759 } else if (response == Gtk::RESPONSE_YES) {
1761 /* YES == OPEN, but there's no enum for that */
1763 session_name = new_session_dialog->session_name();
1765 if (session_name.empty()) {
1766 response = Gtk::RESPONSE_NONE;
1770 if (session_name[0] == '/' ||
1771 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1772 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1773 load_session (Glib::path_get_dirname (session_name), session_name);
1775 session_path = new_session_dialog->session_folder();
1776 load_session (session_path, session_name);
1779 } else if (response == Gtk::RESPONSE_OK) {
1781 session_name = new_session_dialog->session_name();
1783 if (new_session_dialog->get_current_page() == 1) {
1785 /* XXX this is a bit of a hack..
1786 i really want the new sesion dialog to return RESPONSE_YES
1787 if we're on page 1 (the load page)
1788 Unfortunately i can't see how atm..
1791 if (session_name.empty()) {
1792 response = Gtk::RESPONSE_NONE;
1796 if (session_name[0] == '/' ||
1797 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1798 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1799 load_session (Glib::path_get_dirname (session_name), session_name);
1801 session_path = new_session_dialog->session_folder();
1802 load_session (session_path, session_name);
1807 if (session_name.empty()) {
1808 response = Gtk::RESPONSE_NONE;
1812 if (session_name[0] == '/' ||
1813 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1814 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1816 session_path = Glib::path_get_dirname (session_name);
1817 session_name = Glib::path_get_basename (session_name);
1821 session_path = new_session_dialog->session_folder();
1825 //XXX This is needed because session constructor wants a
1826 //non-existant path. hopefully this will be fixed at some point.
1828 session_path = Glib::build_filename (session_path, session_name);
1830 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1832 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1834 MessageDialog msg (str,
1836 Gtk::MESSAGE_WARNING,
1837 Gtk::BUTTONS_YES_NO,
1841 msg.set_name (X_("CleanupDialog"));
1842 msg.set_wmclass (X_("existing_session"), "Ardour");
1843 msg.set_position (Gtk::WIN_POS_MOUSE);
1845 switch (msg.run()) {
1847 load_session (session_path, session_name);
1851 response = RESPONSE_NONE;
1852 new_session_dialog->reset ();
1857 _session_is_new = true;
1859 std::string template_name = new_session_dialog->session_template_name();
1861 if (new_session_dialog->use_session_template()) {
1863 load_session (session_path, session_name, &template_name);
1869 AutoConnectOption iconnect;
1870 AutoConnectOption oconnect;
1872 if (new_session_dialog->create_control_bus()) {
1873 cchns = (uint32_t) new_session_dialog->control_channel_count();
1878 if (new_session_dialog->create_master_bus()) {
1879 mchns = (uint32_t) new_session_dialog->master_channel_count();
1884 if (new_session_dialog->connect_inputs()) {
1885 iconnect = AutoConnectPhysical;
1887 iconnect = AutoConnectOption (0);
1890 /// @todo some minor tweaks.
1892 if (new_session_dialog->connect_outs_to_master()) {
1893 oconnect = AutoConnectMaster;
1894 } else if (new_session_dialog->connect_outs_to_physical()) {
1895 oconnect = AutoConnectPhysical;
1897 oconnect = AutoConnectOption (0);
1900 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1901 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1903 if (build_session (session_path,
1911 engine->frame_rate() * 60 * 5)) {
1913 response = Gtk::RESPONSE_NONE;
1914 new_session_dialog->reset ();
1921 } while (response == Gtk::RESPONSE_NONE);
1925 new_session_dialog->get_window()->set_cursor();
1926 new_session_dialog->hide();
1931 ARDOUR_UI::close_session()
1938 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1940 Session *new_session;
1942 session_loaded = false;
1944 x = unload_session ();
1952 /* if it already exists, we must have write access */
1954 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1955 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1956 "This prevents the session from being loaded."));
1962 new_session = new Session (*engine, path, snap_name, mix_template);
1967 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1971 connect_to_session (new_session);
1973 Config->set_current_owner (ConfigVariableBase::Interface);
1975 session_loaded = true;
1977 goto_editor_window ();
1980 session->set_clean ();
1983 editor->edit_cursor_position (true);
1988 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1989 uint32_t control_channels,
1990 uint32_t master_channels,
1991 AutoConnectOption input_connect,
1992 AutoConnectOption output_connect,
1995 nframes_t initial_length)
1997 Session *new_session;
2000 session_loaded = false;
2001 x = unload_session ();
2008 _session_is_new = true;
2011 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2012 control_channels, master_channels, nphysin, nphysout, initial_length);
2017 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2022 connect_to_session (new_session);
2024 session_loaded = true;
2032 editor->show_window ();
2043 ARDOUR_UI::show_splash ()
2046 about = new About();
2047 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2054 ARDOUR_UI::about_signal_response(int response)
2060 ARDOUR_UI::hide_splash ()
2063 about->get_window()->set_cursor ();
2069 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2073 removed = rep.paths.size();
2076 MessageDialog msgd (*editor,
2077 _("No audio files were ready for cleanup"),
2080 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2081 msgd.set_secondary_text (_("If this seems suprising, \n\
2082 check for any existing snapshots.\n\
2083 These may still include regions that\n\
2084 require some unused files to continue to exist."));
2090 ArdourDialog results (_("ardour: cleanup"), true, false);
2092 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2093 CleanupResultsModelColumns() {
2097 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2098 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2102 CleanupResultsModelColumns results_columns;
2103 Glib::RefPtr<Gtk::ListStore> results_model;
2104 Gtk::TreeView results_display;
2106 results_model = ListStore::create (results_columns);
2107 results_display.set_model (results_model);
2108 results_display.append_column (list_title, results_columns.visible_name);
2110 results_display.set_name ("CleanupResultsList");
2111 results_display.set_headers_visible (true);
2112 results_display.set_headers_clickable (false);
2113 results_display.set_reorderable (false);
2115 Gtk::ScrolledWindow list_scroller;
2118 Gtk::HBox dhbox; // the hbox for the image and text
2119 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2120 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2122 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2124 if (rep.space < 1048576.0f) {
2126 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2128 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2132 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2134 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2138 dhbox.pack_start (*dimage, true, false, 5);
2139 dhbox.pack_start (txt, true, false, 5);
2141 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2142 TreeModel::Row row = *(results_model->append());
2143 row[results_columns.visible_name] = *i;
2144 row[results_columns.fullpath] = *i;
2147 list_scroller.add (results_display);
2148 list_scroller.set_size_request (-1, 150);
2149 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2151 dvbox.pack_start (dhbox, true, false, 5);
2152 dvbox.pack_start (list_scroller, true, false, 5);
2153 ddhbox.pack_start (dvbox, true, false, 5);
2155 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2156 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2157 results.set_default_response (RESPONSE_CLOSE);
2158 results.set_position (Gtk::WIN_POS_MOUSE);
2159 results.show_all_children ();
2160 results.set_resizable (false);
2167 ARDOUR_UI::cleanup ()
2170 /* shouldn't happen: menu item is insensitive */
2175 MessageDialog checker (_("Are you sure you want to cleanup?"),
2177 Gtk::MESSAGE_QUESTION,
2178 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2180 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2181 ALL undo/redo information will be lost if you cleanup.\n\
2182 After cleanup, unused audio files will be moved to a \
2183 \"dead sounds\" location."));
2185 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2186 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2187 checker.set_default_response (RESPONSE_CANCEL);
2189 checker.set_name (_("CleanupDialog"));
2190 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2191 checker.set_position (Gtk::WIN_POS_MOUSE);
2193 switch (checker.run()) {
2194 case RESPONSE_ACCEPT:
2200 Session::cleanup_report rep;
2202 editor->prepare_for_cleanup ();
2204 /* do not allow flush until a session is reloaded */
2206 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2208 act->set_sensitive (false);
2211 if (session->cleanup_sources (rep)) {
2216 display_cleanup_results (rep,
2219 The following %1 %2 not in use and \n\
2220 have been moved to:\n\
2222 Flushing the wastebasket will \n\
2223 release an additional\n\
2224 %4 %5bytes of disk space.\n"
2232 ARDOUR_UI::flush_trash ()
2235 /* shouldn't happen: menu item is insensitive */
2239 Session::cleanup_report rep;
2241 if (session->cleanup_trash_sources (rep)) {
2245 display_cleanup_results (rep,
2247 _("The following %1 %2 deleted from\n\
2249 releasing %4 %5bytes of disk space"));
2253 ARDOUR_UI::add_route (Gtk::Window* float_window)
2261 if (add_route_dialog == 0) {
2262 add_route_dialog = new AddRouteDialog;
2264 add_route_dialog->set_transient_for (*float_window);
2268 if (add_route_dialog->is_visible()) {
2269 /* we're already doing this */
2273 ResponseType r = (ResponseType) add_route_dialog->run ();
2275 add_route_dialog->hide();
2278 case RESPONSE_ACCEPT:
2285 if ((count = add_route_dialog->count()) <= 0) {
2289 uint32_t input_chan = add_route_dialog->channels ();
2290 uint32_t output_chan;
2291 string name_template = add_route_dialog->name_template ();
2292 bool track = add_route_dialog->track ();
2294 AutoConnectOption oac = Config->get_output_auto_connect();
2296 if (oac & AutoConnectMaster) {
2297 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2299 output_chan = input_chan;
2302 /* XXX do something with name template */
2305 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2307 session_add_audio_bus (input_chan, output_chan, count);
2312 ARDOUR_UI::mixer_settings () const
2317 node = session->instant_xml(X_("Mixer"), session->path());
2319 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2323 node = new XMLNode (X_("Mixer"));
2330 ARDOUR_UI::editor_settings () const
2335 node = session->instant_xml(X_("Editor"), session->path());
2337 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2341 node = new XMLNode (X_("Editor"));
2347 ARDOUR_UI::keyboard_settings () const
2351 node = Config->extra_xml(X_("Keyboard"));
2354 node = new XMLNode (X_("Keyboard"));
2360 ARDOUR_UI::halt_on_xrun_message ()
2362 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2364 MessageDialog msg (*editor,
2365 _("Recording was stopped because your system could not keep up."));
2370 ARDOUR_UI::disk_overrun_handler ()
2372 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2374 if (!have_disk_speed_dialog_displayed) {
2375 have_disk_speed_dialog_displayed = true;
2376 MessageDialog* msg = new MessageDialog (*editor, _("\
2377 The disk system on your computer\n\
2378 was not able to keep up with Ardour.\n\
2380 Specifically, it failed to write data to disk\n\
2381 quickly enough to keep up with recording.\n"));
2382 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2388 ARDOUR_UI::disk_underrun_handler ()
2390 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2392 if (!have_disk_speed_dialog_displayed) {
2393 have_disk_speed_dialog_displayed = true;
2394 MessageDialog* msg = new MessageDialog (*editor,
2395 _("The disk system on your computer\n\
2396 was not able to keep up with Ardour.\n\
2398 Specifically, it failed to read data from disk\n\
2399 quickly enough to keep up with playback.\n"));
2400 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2406 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2408 have_disk_speed_dialog_displayed = false;
2413 ARDOUR_UI::pending_state_dialog ()
2415 ArdourDialog dialog ("pending state dialog");
2417 This session appears to have been in\n\
2418 middle of recording when ardour or\n\
2419 the computer was shutdown.\n\
2421 Ardour can recover any captured audio for\n\
2422 you, or it can ignore it. Please decide\n\
2423 what you would like to do.\n"));
2425 dialog.get_vbox()->pack_start (message);
2426 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2427 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2429 dialog.set_position (WIN_POS_CENTER);
2432 switch (dialog.run ()) {
2433 case RESPONSE_ACCEPT:
2441 ARDOUR_UI::disconnect_from_jack ()
2444 if( engine->disconnect_from_jack ()) {
2445 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2449 update_sample_rate (0);
2454 ARDOUR_UI::reconnect_to_jack ()
2457 if (engine->reconnect_to_jack ()) {
2458 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2462 update_sample_rate (0);
2467 ARDOUR_UI::cmdline_new_session (string path)
2469 if (path[0] != '/') {
2470 char buf[PATH_MAX+1];
2473 getcwd (buf, sizeof (buf));
2482 _will_create_new_session_automatically = false; /* done it */
2483 return FALSE; /* don't call it again */
2487 ARDOUR_UI::use_config ()
2489 Glib::RefPtr<Action> act;
2491 switch (Config->get_native_file_data_format ()) {
2493 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2496 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2501 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2502 ract->set_active ();
2505 switch (Config->get_native_file_header_format ()) {
2507 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2510 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2513 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2516 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2519 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2522 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2525 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2530 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2531 ract->set_active ();
2534 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2536 set_transport_controllable_state (*node);
2541 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2543 primary_clock.set (pos);
2544 secondary_clock.set (pos);
2546 if (big_clock_window) {
2547 big_clock.set (pos);
2552 ARDOUR_UI::record_state_changed ()
2554 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2556 if (!session || !big_clock_window) {
2557 /* why bother - the clock isn't visible */
2561 switch (session->record_status()) {
2562 case Session::Recording:
2563 big_clock.set_widget_name ("BigClockRecording");
2566 big_clock.set_widget_name ("BigClockNonRecording");
2572 ARDOUR_UI::set_keybindings_path (string path)
2574 keybindings_path = path;
2578 ARDOUR_UI::save_keybindings ()
2580 if (can_save_keybindings) {
2581 AccelMap::save (keybindings_path);
2586 ARDOUR_UI::first_idle ()
2589 session->allow_auto_play (true);
2591 can_save_keybindings = true;
2596 ARDOUR_UI::store_clock_modes ()
2598 XMLNode* node = new XMLNode(X_("ClockModes"));
2600 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2601 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2604 session->add_extra_xml (*node);
2605 session->set_dirty ();
2610 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2611 : Controllable (name), ui (u), type(tp)
2617 ARDOUR_UI::TransportControllable::set_value (float val)
2619 if (type == ShuttleControl) {
2626 fract = -((0.5f - val)/0.5f);
2628 fract = ((val - 0.5f)/0.5f);
2632 ui.set_shuttle_fract (fract);
2637 /* do nothing: these are radio-style actions */
2645 action = X_("Roll");
2648 action = X_("Stop");
2651 action = X_("Goto Start");
2654 action = X_("Goto End");
2657 action = X_("Loop");
2660 action = X_("Play Selection");
2663 action = X_("Record");
2673 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2681 ARDOUR_UI::TransportControllable::get_value (void) const
2700 case ShuttleControl:
2710 ARDOUR_UI::TransportControllable::set_id (const string& str)