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>
48 #include <midi++/port.h>
49 #include <midi++/mmc.h>
51 #include <ardour/ardour.h>
52 #include <ardour/session_route.h>
53 #include <ardour/port.h>
54 #include <ardour/audioengine.h>
55 #include <ardour/playlist.h>
56 #include <ardour/utils.h>
57 #include <ardour/audio_diskstream.h>
58 #include <ardour/audiofilesource.h>
59 #include <ardour/recent_sessions.h>
60 #include <ardour/port.h>
61 #include <ardour/audio_track.h>
64 #include "ardour_ui.h"
65 #include "public_editor.h"
66 #include "audio_clock.h"
71 #include "add_route_dialog.h"
72 #include "new_session_dialog.h"
75 #include "gui_thread.h"
76 #include "color_manager.h"
80 using namespace ARDOUR;
82 using namespace Gtkmm2ext;
86 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
88 sigc::signal<void,bool> ARDOUR_UI::Blink;
89 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
90 sigc::signal<void> ARDOUR_UI::MidRapidScreenUpdate;
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 ("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 if (AudioSource::start_peak_thread ()) {
267 throw failed_constructor();
270 /* set default clock modes */
272 primary_clock.set_mode (AudioClock::SMPTE);
273 secondary_clock.set_mode (AudioClock::BBT);
275 /* start the time-of-day-clock */
277 update_wall_clock ();
278 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
280 update_disk_space ();
282 update_sample_rate (engine->frame_rate());
284 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
285 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
288 ARDOUR_UI::~ARDOUR_UI ()
290 save_ardour_state ();
304 if (add_route_dialog) {
305 delete add_route_dialog;
308 AudioSource::stop_peak_thread ();
312 ARDOUR_UI::configure_timeout ()
317 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
318 /* no configure events yet */
322 gettimeofday (&now, 0);
323 timersub (&now, &last_configure_time, &diff);
325 /* force a gap of 0.5 seconds since the last configure event
328 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
331 have_configure_timeout = false;
332 save_ardour_state ();
338 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
340 if (have_configure_timeout) {
341 gettimeofday (&last_configure_time, 0);
343 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
344 have_configure_timeout = true;
351 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
353 const XMLProperty* prop;
355 if ((prop = node.property ("roll")) != 0) {
356 roll_controllable.set_id (prop->value());
358 if ((prop = node.property ("stop")) != 0) {
359 stop_controllable.set_id (prop->value());
361 if ((prop = node.property ("goto_start")) != 0) {
362 goto_start_controllable.set_id (prop->value());
364 if ((prop = node.property ("goto_end")) != 0) {
365 goto_end_controllable.set_id (prop->value());
367 if ((prop = node.property ("auto_loop")) != 0) {
368 auto_loop_controllable.set_id (prop->value());
370 if ((prop = node.property ("play_selection")) != 0) {
371 play_selection_controllable.set_id (prop->value());
373 if ((prop = node.property ("rec")) != 0) {
374 rec_controllable.set_id (prop->value());
376 if ((prop = node.property ("shuttle")) != 0) {
377 shuttle_controllable.set_id (prop->value());
382 ARDOUR_UI::get_transport_controllable_state ()
384 XMLNode* node = new XMLNode(X_("TransportControllables"));
387 roll_controllable.id().print (buf, sizeof (buf));
388 node->add_property (X_("roll"), buf);
389 stop_controllable.id().print (buf, sizeof (buf));
390 node->add_property (X_("stop"), buf);
391 goto_start_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("goto_start"), buf);
393 goto_end_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("goto_end"), buf);
395 auto_loop_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("auto_loop"), buf);
397 play_selection_controllable.id().print (buf, sizeof (buf));
398 node->add_property (X_("play_selection"), buf);
399 rec_controllable.id().print (buf, sizeof (buf));
400 node->add_property (X_("rec"), buf);
401 shuttle_controllable.id().print (buf, sizeof (buf));
402 node->add_property (X_("shuttle"), buf);
408 ARDOUR_UI::save_ardour_state ()
410 if (!keyboard || !mixer || !editor) {
414 /* XXX this is all a bit dubious. add_extra_xml() uses
415 a different lifetime model from add_instant_xml().
418 XMLNode* node = new XMLNode (keyboard->get_state());
419 Config->add_extra_xml (*node);
420 Config->add_extra_xml (get_transport_controllable_state());
421 Config->save_state();
423 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
424 XMLNode mnode(mixer->get_state());
427 session->add_instant_xml (enode, session->path());
428 session->add_instant_xml (mnode, session->path());
430 Config->add_instant_xml (enode, get_user_ardour_path());
431 Config->add_instant_xml (mnode, get_user_ardour_path());
438 ARDOUR_UI::startup ()
440 if (engine->is_realtime()) {
442 struct rlimit limits;
444 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
448 if (limits.rlim_cur != RLIM_INFINITY) {
449 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
450 "This might cause Ardour to run out of memory before your system "
451 "runs out of memory. \n\n"
452 "You can view the memory limit with 'ulimit -l', "
453 "and it is normally controlled by /etc/security/limits.conf"));
455 editor->ensure_float (msg);
464 if (session && session->dirty()) {
465 switch (ask_about_saving_session(_("quit"))) {
470 /* use the default name */
471 if (save_state_canfail ("")) {
472 /* failed - don't quit */
473 MessageDialog msg (*editor,
475 Ardour was unable to save your session.\n\n\
476 If you still wish to quit, please use the\n\n\
477 \"Just quit\" option."));
488 session->set_deletion_in_progress ();
491 Config->save_state();
496 ARDOUR_UI::ask_about_saving_session (const string & what)
498 ArdourDialog window (_("ardour: save session?"));
499 Gtk::HBox dhbox; // the hbox for the image and text
500 Gtk::Label prompt_label;
501 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
505 msg = string_compose(_("Don't %1"), what);
506 window.add_button (msg, RESPONSE_REJECT);
507 msg = string_compose(_("Just %1"), what);
508 window.add_button (msg, RESPONSE_APPLY);
509 msg = string_compose(_("Save and %1"), what);
510 window.add_button (msg, RESPONSE_ACCEPT);
512 window.set_default_response (RESPONSE_ACCEPT);
514 Gtk::Button noquit_button (msg);
515 noquit_button.set_name ("EditorGTKButton");
520 if (session->snap_name() == session->name()) {
523 type = _("snapshot");
525 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?"),
526 type, session->snap_name());
528 prompt_label.set_text (prompt);
529 prompt_label.set_name (X_("PrompterLabel"));
530 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
532 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
534 dhbox.set_homogeneous (false);
535 dhbox.pack_start (*dimage, false, false, 5);
536 dhbox.pack_start (prompt_label, true, false, 5);
537 window.get_vbox()->pack_start (dhbox);
539 window.set_name (_("Prompter"));
540 window.set_position (Gtk::WIN_POS_MOUSE);
541 window.set_modal (true);
542 window.set_resizable (false);
545 save_the_session = 0;
547 window.set_keep_above (true);
550 ResponseType r = (ResponseType) window.run();
555 case RESPONSE_ACCEPT: // save and get out of here
557 case RESPONSE_APPLY: // get out of here
567 ARDOUR_UI::every_second ()
570 update_buffer_load ();
571 update_disk_space ();
576 ARDOUR_UI::every_point_one_seconds ()
578 update_speed_display ();
579 RapidScreenUpdate(); /* EMIT_SIGNAL */
584 ARDOUR_UI::every_point_oh_five_seconds ()
586 MidRapidScreenUpdate(); /* EMIT_SIGNAL */
591 ARDOUR_UI::every_point_zero_one_seconds ()
593 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
598 ARDOUR_UI::update_sample_rate (nframes_t ignored)
602 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
604 if (!engine->connected()) {
606 snprintf (buf, sizeof (buf), _("disconnected"));
610 nframes_t rate = engine->frame_rate();
612 if (fmod (rate, 1000.0) != 0.0) {
613 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f msecs"),
614 (float) rate/1000.0f,
615 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
617 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f msecs"),
619 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
623 sample_rate_label.set_text (buf);
627 ARDOUR_UI::update_cpu_load ()
630 snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), engine->get_cpu_load());
631 cpu_load_label.set_text (buf);
635 ARDOUR_UI::update_buffer_load ()
640 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
641 session->playback_load(), session->capture_load());
642 buffer_load_label.set_text (buf);
644 buffer_load_label.set_text ("");
649 ARDOUR_UI::count_recenabled_streams (Route& route)
651 Track* track = dynamic_cast<Track*>(&route);
652 if (track && track->diskstream()->record_enabled()) {
653 rec_enabled_streams += track->n_inputs();
658 ARDOUR_UI::update_disk_space()
664 nframes_t frames = session->available_capture_duration();
667 if (frames == max_frames) {
668 strcpy (buf, _("Disk: 24hrs+"));
673 nframes_t fr = session->frame_rate();
675 rec_enabled_streams = 0;
676 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
678 if (rec_enabled_streams) {
679 frames /= rec_enabled_streams;
682 hrs = frames / (fr * 3600);
683 frames -= hrs * fr * 3600;
684 mins = frames / (fr * 60);
685 frames -= mins * fr * 60;
688 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
691 disk_space_label.set_text (buf);
695 ARDOUR_UI::update_wall_clock ()
702 tm_now = localtime (&now);
704 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
705 wall_clock_label.set_text (buf);
711 ARDOUR_UI::session_menu (GdkEventButton *ev)
713 session_popup_menu->popup (0, 0);
718 ARDOUR_UI::redisplay_recent_sessions ()
720 vector<string *> *sessions;
721 vector<string *>::iterator i;
722 RecentSessionsSorter cmp;
724 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
725 recent_session_model->clear ();
728 ARDOUR::read_recent_sessions (rs);
731 recent_session_display.set_model (recent_session_model);
735 /* sort them alphabetically */
736 sort (rs.begin(), rs.end(), cmp);
737 sessions = new vector<string*>;
739 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
740 sessions->push_back (new string ((*i).second));
743 for (i = sessions->begin(); i != sessions->end(); ++i) {
745 vector<string*>* states;
746 vector<const gchar*> item;
747 string fullpath = *(*i);
749 /* remove any trailing / */
751 if (fullpath[fullpath.length()-1] == '/') {
752 fullpath = fullpath.substr (0, fullpath.length()-1);
755 /* now get available states for this session */
757 if ((states = Session::possible_states (fullpath)) == 0) {
762 TreeModel::Row row = *(recent_session_model->append());
764 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
765 row[recent_session_columns.fullpath] = fullpath;
767 if (states->size() > 1) {
769 /* add the children */
771 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
773 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
775 child_row[recent_session_columns.visible_name] = **i2;
776 child_row[recent_session_columns.fullpath] = fullpath;
785 recent_session_display.set_model (recent_session_model);
790 ARDOUR_UI::build_session_selector ()
792 session_selector_window = new ArdourDialog ("session selector");
794 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
796 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
797 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
798 session_selector_window->set_default_response (RESPONSE_ACCEPT);
799 recent_session_model = TreeStore::create (recent_session_columns);
800 recent_session_display.set_model (recent_session_model);
801 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
802 recent_session_display.set_headers_visible (false);
803 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
805 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
807 scroller->add (recent_session_display);
808 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
810 session_selector_window->set_name ("SessionSelectorWindow");
811 session_selector_window->set_size_request (200, 400);
812 session_selector_window->get_vbox()->pack_start (*scroller);
813 session_selector_window->show_all_children();
817 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
819 session_selector_window->response (RESPONSE_ACCEPT);
823 ARDOUR_UI::open_recent_session ()
825 /* popup selector window */
827 if (session_selector_window == 0) {
828 build_session_selector ();
831 redisplay_recent_sessions ();
833 ResponseType r = (ResponseType) session_selector_window->run ();
835 session_selector_window->hide();
838 case RESPONSE_ACCEPT:
844 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
846 if (i == recent_session_model->children().end()) {
850 Glib::ustring path = (*i)[recent_session_columns.fullpath];
851 Glib::ustring state = (*i)[recent_session_columns.visible_name];
853 _session_is_new = false;
855 load_session (path, state);
859 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
863 if (stat (info.filename.c_str(), &statbuf) != 0) {
867 if (!S_ISDIR(statbuf.st_mode)) {
873 string session_file = info.filename;
875 session_file += Glib::path_get_basename (info.filename);
876 session_file += ".ardour";
878 if (stat (session_file.c_str(), &statbuf) != 0) {
882 return S_ISREG (statbuf.st_mode);
886 ARDOUR_UI::open_session ()
888 /* popup selector window */
890 if (open_session_selector == 0) {
892 /* ardour sessions are folders */
894 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
895 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
896 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
898 FileFilter session_filter;
899 session_filter.add_pattern ("*.ardour");
900 session_filter.set_name (_("Ardour sessions"));
901 open_session_selector->add_filter (session_filter);
902 open_session_selector->set_filter (session_filter);
905 int response = open_session_selector->run();
906 open_session_selector->hide ();
909 case RESPONSE_ACCEPT:
912 open_session_selector->hide();
916 open_session_selector->hide();
917 string session_path = open_session_selector->get_filename();
921 if (session_path.length() > 0) {
922 if (Session::find_session (session_path, path, name, isnew) == 0) {
923 _session_is_new = isnew;
924 load_session (path, name);
931 ARDOUR_UI::session_add_midi_track ()
933 cerr << _("Patience is a virtue.\n");
937 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
939 list<boost::shared_ptr<AudioTrack> > tracks;
940 Session::RouteList routes;
943 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
949 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
951 if (tracks.size() != how_many) {
953 error << _("could not create a new audio track") << endmsg;
955 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
961 routes = session->new_audio_route (input_channels, output_channels, how_many);
963 if (routes.size() != how_many) {
965 error << _("could not create a new audio track") << endmsg;
967 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
973 if (need_control_room_outs) {
979 route->set_stereo_control_outs (control_lr_channels);
980 route->control_outs()->set_stereo_pan (pans, this);
982 #endif /* CONTROLOUTS */
986 MessageDialog msg (*editor,
987 _("There are insufficient JACK ports available\n\
988 to create a new track or bus.\n\
989 You should save Ardour, exit and\n\
990 restart JACK with more ports."));
996 ARDOUR_UI::do_transport_locate (nframes_t new_position)
998 nframes_t _preroll = 0;
1001 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1002 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1004 if (new_position > _preroll) {
1005 new_position -= _preroll;
1010 session->request_locate (new_position);
1015 ARDOUR_UI::transport_goto_start ()
1018 session->goto_start();
1021 /* force displayed area in editor to start no matter
1022 what "follow playhead" setting is.
1026 editor->reset_x_origin (session->current_start_frame());
1032 ARDOUR_UI::transport_goto_zero ()
1035 session->request_locate (0);
1038 /* force displayed area in editor to start no matter
1039 what "follow playhead" setting is.
1043 editor->reset_x_origin (0);
1049 ARDOUR_UI::transport_goto_end ()
1052 nframes_t frame = session->current_end_frame();
1053 session->request_locate (frame);
1055 /* force displayed area in editor to start no matter
1056 what "follow playhead" setting is.
1060 editor->reset_x_origin (frame);
1066 ARDOUR_UI::transport_stop ()
1072 if (session->is_auditioning()) {
1073 session->cancel_audition ();
1077 if (session->get_play_loop ()) {
1078 session->request_play_loop (false);
1081 session->request_stop ();
1085 ARDOUR_UI::transport_stop_and_forget_capture ()
1088 session->request_stop (true);
1093 ARDOUR_UI::remove_last_capture()
1096 editor->remove_last_capture();
1101 ARDOUR_UI::transport_record ()
1103 cerr << "transport record\n";
1106 switch (session->record_status()) {
1107 case Session::Disabled:
1108 if (session->ntracks() == 0) {
1109 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1113 session->maybe_enable_record ();
1115 case Session::Recording:
1116 case Session::Enabled:
1117 session->disable_record (true);
1123 ARDOUR_UI::transport_roll ()
1131 rolling = session->transport_rolling ();
1133 if (session->get_play_loop()) {
1134 session->request_play_loop (false);
1135 auto_loop_button.set_visual_state (1);
1136 roll_button.set_visual_state (1);
1137 } else if (session->get_play_range ()) {
1138 session->request_play_range (false);
1139 play_selection_button.set_visual_state (0);
1140 } else if (rolling) {
1141 session->request_locate (session->last_transport_start(), true);
1144 session->request_transport_speed (1.0f);
1148 ARDOUR_UI::transport_loop()
1151 if (session->get_play_loop()) {
1152 if (session->transport_rolling()) {
1153 Location * looploc = session->locations()->auto_loop_location();
1155 session->request_locate (looploc->start(), true);
1160 session->request_play_loop (true);
1166 ARDOUR_UI::transport_play_selection ()
1172 if (!session->get_play_range()) {
1173 session->request_stop ();
1176 editor->play_selection ();
1180 ARDOUR_UI::transport_rewind (int option)
1182 float current_transport_speed;
1185 current_transport_speed = session->transport_speed();
1187 if (current_transport_speed >= 0.0f) {
1190 session->request_transport_speed (-1.0f);
1193 session->request_transport_speed (-4.0f);
1196 session->request_transport_speed (-0.5f);
1201 session->request_transport_speed (current_transport_speed * 1.5f);
1207 ARDOUR_UI::transport_forward (int option)
1209 float current_transport_speed;
1212 current_transport_speed = session->transport_speed();
1214 if (current_transport_speed <= 0.0f) {
1217 session->request_transport_speed (1.0f);
1220 session->request_transport_speed (4.0f);
1223 session->request_transport_speed (0.5f);
1228 session->request_transport_speed (current_transport_speed * 1.5f);
1234 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1240 boost::shared_ptr<Route> r;
1242 if ((r = session->route_by_remote_id (dstream)) != 0) {
1246 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1247 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1256 ARDOUR_UI::queue_transport_change ()
1258 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1262 ARDOUR_UI::map_transport_state ()
1264 float sp = session->transport_speed();
1267 transport_rolling ();
1268 } else if (sp < 0.0f) {
1269 transport_rewinding ();
1270 } else if (sp > 0.0f) {
1271 transport_forwarding ();
1273 transport_stopped ();
1278 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1280 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1281 (int) adj.get_value()].c_str());
1285 ARDOUR_UI::engine_stopped ()
1287 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1288 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1289 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1293 ARDOUR_UI::engine_running ()
1295 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1296 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1297 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1299 Glib::RefPtr<Action> action;
1300 char* action_name = 0;
1302 switch (engine->frames_per_cycle()) {
1304 action_name = X_("JACKLatency32");
1307 action_name = X_("JACKLatency64");
1310 action_name = X_("JACKLatency128");
1313 action_name = X_("JACKLatency512");
1316 action_name = X_("JACKLatency1024");
1319 action_name = X_("JACKLatency2048");
1322 action_name = X_("JACKLatency4096");
1325 action_name = X_("JACKLatency8192");
1328 /* XXX can we do anything useful ? */
1334 action = ActionManager::get_action (X_("JACK"), action_name);
1337 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1338 ract->set_active ();
1344 ARDOUR_UI::engine_halted ()
1346 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1348 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1349 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1351 update_sample_rate (0);
1353 MessageDialog msg (*editor,
1355 JACK has either been shutdown or it\n\
1356 disconnected Ardour because Ardour\n\
1357 was not fast enough. You can save the\n\
1358 session and/or try to reconnect to JACK ."));
1363 ARDOUR_UI::do_engine_start ()
1371 error << _("Unable to start the session running")
1381 ARDOUR_UI::start_engine ()
1383 if (do_engine_start () == 0) {
1384 if (session && _session_is_new) {
1385 /* we need to retain initial visual
1386 settings for a new session
1388 session->save_state ("");
1396 ARDOUR_UI::update_clocks ()
1398 if (!editor || !editor->dragging_playhead()) {
1399 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1404 ARDOUR_UI::start_clocking ()
1406 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1410 ARDOUR_UI::stop_clocking ()
1412 clock_signal_connection.disconnect ();
1416 ARDOUR_UI::toggle_clocking ()
1419 if (clock_button.get_active()) {
1428 ARDOUR_UI::_blink (void *arg)
1431 ((ARDOUR_UI *) arg)->blink ();
1438 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1442 ARDOUR_UI::start_blinking ()
1444 /* Start the blink signal. Everybody with a blinking widget
1445 uses Blink to drive the widget's state.
1448 if (blink_timeout_tag < 0) {
1450 blink_timeout_tag = g_timeout_add (240, _blink, this);
1455 ARDOUR_UI::stop_blinking ()
1457 if (blink_timeout_tag >= 0) {
1458 g_source_remove (blink_timeout_tag);
1459 blink_timeout_tag = -1;
1464 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1470 if (io.n_inputs() == 0) {
1475 /* XXX we're not handling multiple ports yet. */
1477 const char **connections = io.input(0)->get_connections();
1479 if (connections == 0 || connections[0] == '\0') {
1482 buf = connections[0];
1489 if (io.n_outputs() == 0) {
1494 /* XXX we're not handling multiple ports yet. */
1496 const char **connections = io.output(0)->get_connections();
1498 if (connections == 0 || connections[0] == '\0') {
1501 buf = connections[0];
1509 ARDOUR_UI::snapshot_session ()
1511 ArdourPrompter prompter (true);
1515 struct tm local_time;
1518 localtime_r (&n, &local_time);
1519 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1521 prompter.set_name ("Prompter");
1522 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1523 prompter.set_prompt (_("Name of New Snapshot"));
1524 prompter.set_initial_text (timebuf);
1526 switch (prompter.run()) {
1527 case RESPONSE_ACCEPT:
1528 prompter.get_result (snapname);
1529 if (snapname.length()){
1530 save_state (snapname);
1540 ARDOUR_UI::save_state (const string & name)
1542 (void) save_state_canfail (name);
1546 ARDOUR_UI::save_state_canfail (string name)
1551 if (name.length() == 0) {
1552 name = session->snap_name();
1555 if ((ret = session->save_state (name)) != 0) {
1559 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1564 ARDOUR_UI::restore_state (string name)
1567 if (name.length() == 0) {
1568 name = session->name();
1570 session->restore_state (name);
1575 ARDOUR_UI::primary_clock_value_changed ()
1578 session->request_locate (primary_clock.current_time ());
1583 ARDOUR_UI::secondary_clock_value_changed ()
1586 session->request_locate (secondary_clock.current_time ());
1591 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1593 if (session && dstream && dstream->record_enabled()) {
1595 Session::RecordState rs;
1597 rs = session->record_status ();
1600 case Session::Disabled:
1601 case Session::Enabled:
1602 if (w->get_state() != STATE_SELECTED) {
1603 w->set_state (STATE_SELECTED);
1607 case Session::Recording:
1608 if (w->get_state() != STATE_ACTIVE) {
1609 w->set_state (STATE_ACTIVE);
1615 if (w->get_state() != STATE_NORMAL) {
1616 w->set_state (STATE_NORMAL);
1622 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1628 switch (session->record_status()) {
1629 case Session::Enabled:
1631 rec_button.set_visual_state (2);
1633 rec_button.set_visual_state (0);
1637 case Session::Recording:
1638 rec_button.set_visual_state (1);
1642 rec_button.set_visual_state (0);
1648 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1656 ARDOUR_UI::save_template ()
1659 ArdourPrompter prompter (true);
1662 prompter.set_name (X_("Prompter"));
1663 prompter.set_prompt (_("Name for mix template:"));
1664 prompter.set_initial_text(session->name() + _("-template"));
1665 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1667 switch (prompter.run()) {
1668 case RESPONSE_ACCEPT:
1669 prompter.get_result (name);
1671 if (name.length()) {
1672 session->save_template (name);
1682 ARDOUR_UI::new_session (std::string predetermined_path)
1684 string session_name;
1685 string session_path;
1687 if (!engine->connected()) {
1688 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1693 int response = Gtk::RESPONSE_NONE;
1695 new_session_dialog->set_modal(true);
1696 new_session_dialog->set_name (predetermined_path);
1697 new_session_dialog->reset_recent();
1698 new_session_dialog->show();
1701 response = new_session_dialog->run ();
1703 if (!engine->connected()) {
1704 new_session_dialog->hide ();
1705 MessageDialog msg (_("Ardour is no longer connected to JACK. Creating a new session is not possible."));
1710 _session_is_new = false;
1712 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1717 new_session_dialog->hide ();
1720 } else if (response == Gtk::RESPONSE_NONE) {
1722 /* Clear was pressed */
1723 new_session_dialog->reset();
1725 } else if (response == Gtk::RESPONSE_YES) {
1727 /* YES == OPEN, but there's no enum for that */
1729 session_name = new_session_dialog->session_name();
1731 if (session_name.empty()) {
1732 response = Gtk::RESPONSE_NONE;
1736 if (session_name[0] == '/' ||
1737 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1738 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1739 load_session (Glib::path_get_dirname (session_name), session_name);
1741 session_path = new_session_dialog->session_folder();
1742 load_session (session_path, session_name);
1745 } else if (response == Gtk::RESPONSE_OK) {
1747 session_name = new_session_dialog->session_name();
1749 if (new_session_dialog->get_current_page() == 1) {
1751 /* XXX this is a bit of a hack..
1752 i really want the new sesion dialog to return RESPONSE_YES
1753 if we're on page 1 (the load page)
1754 Unfortunately i can't see how atm..
1757 if (session_name.empty()) {
1758 response = Gtk::RESPONSE_NONE;
1762 if (session_name[0] == '/' ||
1763 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1764 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1765 load_session (Glib::path_get_dirname (session_name), session_name);
1767 session_path = new_session_dialog->session_folder();
1768 load_session (session_path, session_name);
1773 if (session_name.empty()) {
1774 response = Gtk::RESPONSE_NONE;
1778 if (session_name[0] == '/' ||
1779 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1780 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1782 session_path = Glib::path_get_dirname (session_name);
1783 session_name = Glib::path_get_basename (session_name);
1787 session_path = new_session_dialog->session_folder();
1791 //XXX This is needed because session constructor wants a
1792 //non-existant path. hopefully this will be fixed at some point.
1794 session_path = Glib::build_filename (session_path, session_name);
1796 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1798 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1800 MessageDialog msg (str,
1802 Gtk::MESSAGE_WARNING,
1803 Gtk::BUTTONS_YES_NO,
1807 msg.set_name (X_("CleanupDialog"));
1808 msg.set_wmclass (X_("existing_session"), "Ardour");
1809 msg.set_position (Gtk::WIN_POS_MOUSE);
1811 switch (msg.run()) {
1813 load_session (session_path, session_name);
1817 response = RESPONSE_NONE;
1818 new_session_dialog->reset ();
1823 _session_is_new = true;
1825 std::string template_name = new_session_dialog->session_template_name();
1827 if (new_session_dialog->use_session_template()) {
1829 load_session (session_path, session_name, &template_name);
1835 AutoConnectOption iconnect;
1836 AutoConnectOption oconnect;
1838 if (new_session_dialog->create_control_bus()) {
1839 cchns = (uint32_t) new_session_dialog->control_channel_count();
1844 if (new_session_dialog->create_master_bus()) {
1845 mchns = (uint32_t) new_session_dialog->master_channel_count();
1850 if (new_session_dialog->connect_inputs()) {
1851 iconnect = AutoConnectPhysical;
1853 iconnect = AutoConnectOption (0);
1856 /// @todo some minor tweaks.
1858 if (new_session_dialog->connect_outs_to_master()) {
1859 oconnect = AutoConnectMaster;
1860 } else if (new_session_dialog->connect_outs_to_physical()) {
1861 oconnect = AutoConnectPhysical;
1863 oconnect = AutoConnectOption (0);
1866 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1867 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1869 if (build_session (session_path,
1877 engine->frame_rate() * 60 * 5)) {
1879 response = Gtk::RESPONSE_NONE;
1880 new_session_dialog->reset ();
1887 } while (response == Gtk::RESPONSE_NONE);
1891 new_session_dialog->get_window()->set_cursor();
1892 new_session_dialog->hide();
1896 ARDOUR_UI::close_session()
1903 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1905 Session *new_session;
1907 session_loaded = false;
1909 x = unload_session ();
1917 /* if it already exists, we must have write access */
1919 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1920 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
1921 "This prevents the session from being loaded."));
1927 new_session = new Session (*engine, path, snap_name, mix_template);
1932 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1936 connect_to_session (new_session);
1938 Config->set_current_owner (ConfigVariableBase::Interface);
1940 session_loaded = true;
1942 goto_editor_window ();
1945 session->set_clean ();
1952 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1953 uint32_t control_channels,
1954 uint32_t master_channels,
1955 AutoConnectOption input_connect,
1956 AutoConnectOption output_connect,
1959 nframes_t initial_length)
1961 Session *new_session;
1964 session_loaded = false;
1965 x = unload_session ();
1972 _session_is_new = true;
1975 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1976 control_channels, master_channels, nphysin, nphysout, initial_length);
1981 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
1986 connect_to_session (new_session);
1988 session_loaded = true;
1996 editor->show_window ();
2007 ARDOUR_UI::show_splash ()
2010 about = new About();
2011 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2018 ARDOUR_UI::about_signal_response(int response)
2024 ARDOUR_UI::hide_splash ()
2027 about->get_window()->set_cursor ();
2033 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2037 removed = rep.paths.size();
2040 MessageDialog msgd (*editor,
2041 _("No audio files were ready for cleanup"),
2044 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2045 msgd.set_secondary_text (_("If this seems suprising, \n\
2046 check for any existing snapshots.\n\
2047 These may still include regions that\n\
2048 require some unused files to continue to exist."));
2054 ArdourDialog results (_("ardour: cleanup"), true, false);
2056 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2057 CleanupResultsModelColumns() {
2061 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2062 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2066 CleanupResultsModelColumns results_columns;
2067 Glib::RefPtr<Gtk::ListStore> results_model;
2068 Gtk::TreeView results_display;
2070 results_model = ListStore::create (results_columns);
2071 results_display.set_model (results_model);
2072 results_display.append_column (list_title, results_columns.visible_name);
2074 results_display.set_name ("CleanupResultsList");
2075 results_display.set_headers_visible (true);
2076 results_display.set_headers_clickable (false);
2077 results_display.set_reorderable (false);
2079 Gtk::ScrolledWindow list_scroller;
2082 Gtk::HBox dhbox; // the hbox for the image and text
2083 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2084 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2086 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2088 if (rep.space < 1048576.0f) {
2090 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2092 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2096 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2098 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2102 dhbox.pack_start (*dimage, true, false, 5);
2103 dhbox.pack_start (txt, true, false, 5);
2105 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2106 TreeModel::Row row = *(results_model->append());
2107 row[results_columns.visible_name] = *i;
2108 row[results_columns.fullpath] = *i;
2111 list_scroller.add (results_display);
2112 list_scroller.set_size_request (-1, 150);
2113 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2115 dvbox.pack_start (dhbox, true, false, 5);
2116 dvbox.pack_start (list_scroller, true, false, 5);
2117 ddhbox.pack_start (dvbox, true, false, 5);
2119 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2120 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2121 results.set_default_response (RESPONSE_CLOSE);
2122 results.set_position (Gtk::WIN_POS_MOUSE);
2123 results.show_all_children ();
2124 results.set_resizable (false);
2131 ARDOUR_UI::cleanup ()
2134 /* shouldn't happen: menu item is insensitive */
2139 MessageDialog checker (_("Are you sure you want to cleanup?"),
2141 Gtk::MESSAGE_QUESTION,
2142 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2144 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2145 ALL undo/redo information will be lost if you cleanup.\n\
2146 After cleanup, unused audio files will be moved to a \
2147 \"dead sounds\" location."));
2149 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2150 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2151 checker.set_default_response (RESPONSE_CANCEL);
2153 checker.set_name (_("CleanupDialog"));
2154 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2155 checker.set_position (Gtk::WIN_POS_MOUSE);
2157 switch (checker.run()) {
2158 case RESPONSE_ACCEPT:
2164 Session::cleanup_report rep;
2166 editor->prepare_for_cleanup ();
2168 /* do not allow flush until a session is reloaded */
2170 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2172 act->set_sensitive (false);
2175 if (session->cleanup_sources (rep)) {
2180 display_cleanup_results (rep,
2183 The following %1 %2 not in use and \n\
2184 have been moved to:\n\
2186 Flushing the wastebasket will \n\
2187 release an additional\n\
2188 %4 %5bytes of disk space.\n"
2196 ARDOUR_UI::flush_trash ()
2199 /* shouldn't happen: menu item is insensitive */
2203 Session::cleanup_report rep;
2205 if (session->cleanup_trash_sources (rep)) {
2209 display_cleanup_results (rep,
2211 _("The following %1 %2 deleted from\n\
2213 releasing %4 %5bytes of disk space"));
2217 ARDOUR_UI::add_route ()
2225 if (add_route_dialog == 0) {
2226 add_route_dialog = new AddRouteDialog;
2227 editor->ensure_float (*add_route_dialog);
2230 if (add_route_dialog->is_visible()) {
2231 /* we're already doing this */
2235 ResponseType r = (ResponseType) add_route_dialog->run ();
2237 add_route_dialog->hide();
2240 case RESPONSE_ACCEPT:
2247 if ((count = add_route_dialog->count()) <= 0) {
2251 uint32_t input_chan = add_route_dialog->channels ();
2252 uint32_t output_chan;
2253 string name_template = add_route_dialog->name_template ();
2254 bool track = add_route_dialog->track ();
2256 AutoConnectOption oac = Config->get_output_auto_connect();
2258 if (oac & AutoConnectMaster) {
2259 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2261 output_chan = input_chan;
2264 /* XXX do something with name template */
2267 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2269 session_add_audio_bus (input_chan, output_chan, count);
2274 ARDOUR_UI::mixer_settings () const
2279 node = session->instant_xml(X_("Mixer"), session->path());
2281 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2285 node = new XMLNode (X_("Mixer"));
2292 ARDOUR_UI::editor_settings () const
2297 node = session->instant_xml(X_("Editor"), session->path());
2299 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2303 node = new XMLNode (X_("Editor"));
2309 ARDOUR_UI::keyboard_settings () const
2313 node = Config->extra_xml(X_("Keyboard"));
2316 node = new XMLNode (X_("Keyboard"));
2322 ARDOUR_UI::halt_on_xrun_message ()
2324 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2326 MessageDialog msg (*editor,
2327 _("Recording was stopped because your system could not keep up."));
2332 ARDOUR_UI::disk_overrun_handler ()
2334 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2336 if (!have_disk_speed_dialog_displayed) {
2337 have_disk_speed_dialog_displayed = true;
2338 MessageDialog* msg = new MessageDialog (*editor, X_("diskrate dialog"), _("\
2339 The disk system on your computer\n\
2340 was not able to keep up with Ardour.\n\
2342 Specifically, it failed to write data to disk\n\
2343 quickly enough to keep up with recording.\n"));
2344 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2350 ARDOUR_UI::disk_underrun_handler ()
2352 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2354 if (!have_disk_speed_dialog_displayed) {
2355 have_disk_speed_dialog_displayed = true;
2356 MessageDialog* msg = new MessageDialog (*editor,
2357 _("The disk system on your computer\n\
2358 was not able to keep up with Ardour.\n\
2360 Specifically, it failed to read data from disk\n\
2361 quickly enough to keep up with playback.\n"));
2362 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2368 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2370 have_disk_speed_dialog_displayed = false;
2375 ARDOUR_UI::pending_state_dialog ()
2377 ArdourDialog dialog ("pending state dialog");
2379 This session appears to have been in\n\
2380 middle of recording when ardour or\n\
2381 the computer was shutdown.\n\
2383 Ardour can recover any captured audio for\n\
2384 you, or it can ignore it. Please decide\n\
2385 what you would like to do.\n"));
2387 dialog.get_vbox()->pack_start (message);
2388 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2389 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2391 dialog.set_position (WIN_POS_CENTER);
2394 switch (dialog.run ()) {
2395 case RESPONSE_ACCEPT:
2403 ARDOUR_UI::disconnect_from_jack ()
2406 if( engine->disconnect_from_jack ()) {
2407 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2411 update_sample_rate (0);
2416 ARDOUR_UI::reconnect_to_jack ()
2419 if (engine->reconnect_to_jack ()) {
2420 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2424 update_sample_rate (0);
2429 ARDOUR_UI::cmdline_new_session (string path)
2431 if (path[0] != '/') {
2432 char buf[PATH_MAX+1];
2435 getcwd (buf, sizeof (buf));
2444 _will_create_new_session_automatically = false; /* done it */
2445 return FALSE; /* don't call it again */
2449 ARDOUR_UI::use_config ()
2451 Glib::RefPtr<Action> act;
2453 switch (Config->get_native_file_data_format ()) {
2455 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2458 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2463 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2464 ract->set_active ();
2467 switch (Config->get_native_file_header_format ()) {
2469 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2472 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2475 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2478 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2481 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2484 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2487 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2492 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2493 ract->set_active ();
2496 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2498 set_transport_controllable_state (*node);
2503 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2505 primary_clock.set (pos);
2506 secondary_clock.set (pos);
2508 if (big_clock_window) {
2509 big_clock.set (pos);
2514 ARDOUR_UI::record_state_changed ()
2516 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2518 if (!session || !big_clock_window) {
2519 /* why bother - the clock isn't visible */
2523 switch (session->record_status()) {
2524 case Session::Recording:
2525 big_clock.set_widget_name ("BigClockRecording");
2528 big_clock.set_widget_name ("BigClockNonRecording");
2534 ARDOUR_UI::set_keybindings_path (string path)
2536 keybindings_path = path;
2540 ARDOUR_UI::save_keybindings ()
2542 if (can_save_keybindings) {
2543 AccelMap::save (keybindings_path);
2548 ARDOUR_UI::first_idle ()
2550 can_save_keybindings = true;
2555 ARDOUR_UI::store_clock_modes ()
2557 XMLNode* node = new XMLNode(X_("ClockModes"));
2559 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2560 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2563 session->add_extra_xml (*node);
2564 session->set_dirty ();
2569 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2570 : Controllable (name), ui (u), type(tp)
2576 ARDOUR_UI::TransportControllable::set_value (float val)
2578 if (type == ShuttleControl) {
2585 fract = -((0.5f - val)/0.5f);
2587 fract = ((val - 0.5f)/0.5f);
2591 ui.set_shuttle_fract (fract);
2596 /* do nothing: these are radio-style actions */
2604 action = X_("Roll");
2607 action = X_("Stop");
2610 action = X_("Goto Start");
2613 action = X_("Goto End");
2616 action = X_("Loop");
2619 action = X_("Play Selection");
2622 action = X_("Record");
2632 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2640 ARDOUR_UI::TransportControllable::get_value (void) const
2659 case ShuttleControl:
2669 ARDOUR_UI::TransportControllable::set_id (const string& str)