2 Copyright (C) 1999-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #define __STDC_FORMAT_MACROS 1
33 #include <sys/resource.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/accelmap.h>
38 #include <pbd/error.h>
39 #include <pbd/compose.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/failed_constructor.h>
42 #include <pbd/enumwriter.h>
43 #include <pbd/stacktrace.h>
44 #include <gtkmm2ext/gtk_ui.h>
45 #include <gtkmm2ext/utils.h>
46 #include <gtkmm2ext/click_box.h>
47 #include <gtkmm2ext/fastmeter.h>
48 #include <gtkmm2ext/stop_signal.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/window_title.h>
52 #include <midi++/port.h>
53 #include <midi++/mmc.h>
55 #include <ardour/ardour.h>
56 #include <ardour/profile.h>
57 #include <ardour/session_route.h>
58 #include <ardour/port.h>
59 #include <ardour/audioengine.h>
60 #include <ardour/playlist.h>
61 #include <ardour/utils.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/audiofilesource.h>
64 #include <ardour/recent_sessions.h>
65 #include <ardour/port.h>
66 #include <ardour/audio_track.h>
67 #include <ardour/midi_track.h>
70 #include "ardour_ui.h"
71 #include "public_editor.h"
72 #include "audio_clock.h"
77 #include "add_route_dialog.h"
78 #include "new_session_dialog.h"
81 #include "gui_thread.h"
82 #include "color_manager.h"
86 using namespace ARDOUR;
88 using namespace Gtkmm2ext;
92 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
94 sigc::signal<void,bool> ARDOUR_UI::Blink;
95 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
96 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
97 sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
99 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
101 : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp, rcfile),
103 primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
104 secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
105 preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
106 postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
110 adjuster_table (3, 3),
114 preroll_button (_("pre\nroll")),
115 postroll_button (_("post\nroll")),
119 big_clock (X_("bigclock"), false, "BigClockNonRecording", false, false, true),
123 roll_controllable ("transport roll", *this, TransportControllable::Roll),
124 stop_controllable ("transport stop", *this, TransportControllable::Stop),
125 goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
126 goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
127 auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
128 play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
129 rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
130 shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
131 shuttle_controller_binding_proxy (shuttle_controllable),
133 roll_button (roll_controllable),
134 stop_button (stop_controllable),
135 goto_start_button (goto_start_controllable),
136 goto_end_button (goto_end_controllable),
137 auto_loop_button (auto_loop_controllable),
138 play_selection_button (play_selection_controllable),
139 rec_button (rec_controllable),
141 shuttle_units_button (_("% ")),
143 punch_in_button (_("Punch In")),
144 punch_out_button (_("Punch Out")),
145 auto_return_button (_("Auto Return")),
146 auto_play_button (_("Auto Play")),
147 auto_input_button (_("Auto Input")),
148 click_button (_("Click")),
149 time_master_button (_("time\nmaster")),
151 auditioning_alert_button (_("AUDITION")),
152 solo_alert_button (_("SOLO")),
155 using namespace Gtk::Menu_Helpers;
161 if (theArdourUI == 0) {
167 color_manager = new ColorManager();
169 std::string color_file = ARDOUR::find_config_file("ardour.colors");
171 color_manager->load (color_file);
176 _session_is_new = false;
177 big_clock_window = 0;
178 session_selector_window = 0;
179 last_key_press_time = 0;
180 connection_editor = 0;
181 add_route_dialog = 0;
185 open_session_selector = 0;
186 have_configure_timeout = false;
187 have_disk_speed_dialog_displayed = false;
188 _will_create_new_session_automatically = false;
189 session_loaded = false;
190 last_speed_displayed = -1.0f;
191 keybindings_path = ARDOUR::find_config_file ("ardour.bindings");
193 can_save_keybindings = false;
195 last_configure_time.tv_sec = 0;
196 last_configure_time.tv_usec = 0;
198 shuttle_grabbed = false;
200 shuttle_max_speed = 8.0f;
202 shuttle_style_menu = 0;
203 shuttle_unit_menu = 0;
205 gettimeofday (&last_peak_grab, 0);
206 gettimeofday (&last_shuttle_request, 0);
208 ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
209 ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
211 /* handle pending state with a dialog */
213 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
215 /* have to wait for AudioEngine and Configuration before proceeding */
219 ARDOUR_UI::set_engine (AudioEngine& e)
223 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
224 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
225 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
226 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
228 ActionManager::init ();
229 new_session_dialog = new NewSessionDialog();
233 keyboard = new Keyboard;
235 if (setup_windows ()) {
236 throw failed_constructor ();
239 if (GTK_ARDOUR::show_key_actions) {
240 vector<string> names;
241 vector<string> paths;
243 vector<AccelKey> bindings;
245 ActionManager::get_all_actions (names, paths, keys, bindings);
247 vector<string>::iterator n;
248 vector<string>::iterator k;
249 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
250 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
256 /* start with timecode, metering enabled
259 blink_timeout_tag = -1;
261 /* the global configuration object is now valid */
265 /* this being a GUI and all, we want peakfiles */
267 AudioFileSource::set_build_peakfiles (true);
268 AudioFileSource::set_build_missing_peakfiles (true);
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;
310 ARDOUR_UI::configure_timeout ()
315 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
316 /* no configure events yet */
320 gettimeofday (&now, 0);
321 timersub (&now, &last_configure_time, &diff);
323 /* force a gap of 0.5 seconds since the last configure event
326 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
329 have_configure_timeout = false;
330 save_ardour_state ();
336 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
338 if (have_configure_timeout) {
339 gettimeofday (&last_configure_time, 0);
341 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
342 have_configure_timeout = true;
349 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
351 const XMLProperty* prop;
353 if ((prop = node.property ("roll")) != 0) {
354 roll_controllable.set_id (prop->value());
356 if ((prop = node.property ("stop")) != 0) {
357 stop_controllable.set_id (prop->value());
359 if ((prop = node.property ("goto_start")) != 0) {
360 goto_start_controllable.set_id (prop->value());
362 if ((prop = node.property ("goto_end")) != 0) {
363 goto_end_controllable.set_id (prop->value());
365 if ((prop = node.property ("auto_loop")) != 0) {
366 auto_loop_controllable.set_id (prop->value());
368 if ((prop = node.property ("play_selection")) != 0) {
369 play_selection_controllable.set_id (prop->value());
371 if ((prop = node.property ("rec")) != 0) {
372 rec_controllable.set_id (prop->value());
374 if ((prop = node.property ("shuttle")) != 0) {
375 shuttle_controllable.set_id (prop->value());
380 ARDOUR_UI::get_transport_controllable_state ()
382 XMLNode* node = new XMLNode(X_("TransportControllables"));
385 roll_controllable.id().print (buf, sizeof (buf));
386 node->add_property (X_("roll"), buf);
387 stop_controllable.id().print (buf, sizeof (buf));
388 node->add_property (X_("stop"), buf);
389 goto_start_controllable.id().print (buf, sizeof (buf));
390 node->add_property (X_("goto_start"), buf);
391 goto_end_controllable.id().print (buf, sizeof (buf));
392 node->add_property (X_("goto_end"), buf);
393 auto_loop_controllable.id().print (buf, sizeof (buf));
394 node->add_property (X_("auto_loop"), buf);
395 play_selection_controllable.id().print (buf, sizeof (buf));
396 node->add_property (X_("play_selection"), buf);
397 rec_controllable.id().print (buf, sizeof (buf));
398 node->add_property (X_("rec"), buf);
399 shuttle_controllable.id().print (buf, sizeof (buf));
400 node->add_property (X_("shuttle"), buf);
406 ARDOUR_UI::save_ardour_state ()
408 if (!keyboard || !mixer || !editor) {
412 /* XXX this is all a bit dubious. add_extra_xml() uses
413 a different lifetime model from add_instant_xml().
416 XMLNode* node = new XMLNode (keyboard->get_state());
417 Config->add_extra_xml (*node);
418 Config->add_extra_xml (get_transport_controllable_state());
419 Config->save_state();
421 XMLNode enode(static_cast<Stateful*>(editor)->get_state());
422 XMLNode mnode(mixer->get_state());
425 session->add_instant_xml (enode, session->path());
426 session->add_instant_xml (mnode, session->path());
428 Config->add_instant_xml (enode, get_user_ardour_path());
429 Config->add_instant_xml (mnode, get_user_ardour_path());
436 ARDOUR_UI::autosave_session ()
438 if (!Config->get_periodic_safety_backups())
442 session->maybe_write_autosave();
449 ARDOUR_UI::update_autosave ()
451 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
453 if (session->dirty()) {
454 if (_autosave_connection.connected()) {
455 _autosave_connection.disconnect();
458 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
459 Config->get_periodic_safety_backup_interval() * 1000);
462 if (_autosave_connection.connected()) {
463 _autosave_connection.disconnect();
469 ARDOUR_UI::startup ()
471 check_memory_locking();
475 ARDOUR_UI::no_memory_warning ()
477 XMLNode node (X_("no-memory-warning"));
478 Config->add_instant_xml (node, get_user_ardour_path());
482 ARDOUR_UI::check_memory_locking ()
485 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
489 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
491 if (engine->is_realtime() && memory_warning_node == 0) {
493 struct rlimit limits;
495 long pages, page_size;
497 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
500 ram = (int64_t) pages * (int64_t) page_size;
503 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
507 if (limits.rlim_cur != RLIM_INFINITY) {
509 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
512 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
513 "This might cause Ardour to run out of memory before your system "
514 "runs out of memory. \n\n"
515 "You can view the memory limit with 'ulimit -l', "
516 "and it is normally controlled by /etc/security/limits.conf"));
518 VBox* vbox = msg.get_vbox();
520 CheckButton cb (_("Do not show this window again"));
522 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
524 hbox.pack_start (cb, true, false);
525 vbox->pack_start (hbox);
528 editor->ensure_float (msg);
540 if (session && session->dirty()) {
541 switch (ask_about_saving_session(_("quit"))) {
546 /* use the default name */
547 if (save_state_canfail ("")) {
548 /* failed - don't quit */
549 MessageDialog msg (*editor,
551 Ardour was unable to save your session.\n\n\
552 If you still wish to quit, please use the\n\n\
553 \"Just quit\" option."));
564 session->set_deletion_in_progress ();
567 Config->save_state();
572 ARDOUR_UI::ask_about_saving_session (const string & what)
574 ArdourDialog window (_("ardour: save session?"));
575 Gtk::HBox dhbox; // the hbox for the image and text
576 Gtk::Label prompt_label;
577 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
581 msg = string_compose(_("Don't %1"), what);
582 window.add_button (msg, RESPONSE_REJECT);
583 msg = string_compose(_("Just %1"), what);
584 window.add_button (msg, RESPONSE_APPLY);
585 msg = string_compose(_("Save and %1"), what);
586 window.add_button (msg, RESPONSE_ACCEPT);
588 window.set_default_response (RESPONSE_ACCEPT);
590 Gtk::Button noquit_button (msg);
591 noquit_button.set_name ("EditorGTKButton");
596 if (session->snap_name() == session->name()) {
599 type = _("snapshot");
601 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?"),
602 type, session->snap_name());
604 prompt_label.set_text (prompt);
605 prompt_label.set_name (X_("PrompterLabel"));
606 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
608 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP)
610 dhbox.set_homogeneous (false);
611 dhbox.pack_start (*dimage, false, false, 5);
612 dhbox.pack_start (prompt_label, true, false, 5);
613 window.get_vbox()->pack_start (dhbox);
615 window.set_name (_("Prompter"));
616 window.set_position (Gtk::WIN_POS_MOUSE);
617 window.set_modal (true);
618 window.set_resizable (false);
621 save_the_session = 0;
623 window.set_keep_above (true);
626 ResponseType r = (ResponseType) window.run();
631 case RESPONSE_ACCEPT: // save and get out of here
633 case RESPONSE_APPLY: // get out of here
643 ARDOUR_UI::every_second ()
646 update_buffer_load ();
647 update_disk_space ();
652 ARDOUR_UI::every_point_one_seconds ()
654 update_speed_display ();
655 RapidScreenUpdate(); /* EMIT_SIGNAL */
660 ARDOUR_UI::every_point_zero_one_seconds ()
662 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
667 ARDOUR_UI::update_sample_rate (nframes_t ignored)
671 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
673 if (!engine->connected()) {
675 snprintf (buf, sizeof (buf), _("disconnected"));
679 nframes_t rate = engine->frame_rate();
681 if (fmod (rate, 1000.0) != 0.0) {
682 snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
683 (float) rate/1000.0f,
684 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
686 snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
688 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
692 sample_rate_label.set_text (buf);
696 ARDOUR_UI::update_cpu_load ()
699 snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
700 cpu_load_label.set_text (buf);
704 ARDOUR_UI::update_buffer_load ()
709 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
710 session->playback_load(), session->capture_load());
711 buffer_load_label.set_text (buf);
713 buffer_load_label.set_text ("");
718 ARDOUR_UI::count_recenabled_streams (Route& route)
720 Track* track = dynamic_cast<Track*>(&route);
721 if (track && track->diskstream()->record_enabled()) {
722 rec_enabled_streams += track->n_inputs().get_total();
727 ARDOUR_UI::update_disk_space()
733 nframes_t frames = session->available_capture_duration();
736 if (frames == max_frames) {
737 strcpy (buf, _("Disk: 24hrs+"));
742 nframes_t fr = session->frame_rate();
744 rec_enabled_streams = 0;
745 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
747 if (rec_enabled_streams) {
748 frames /= rec_enabled_streams;
751 hrs = frames / (fr * 3600);
752 frames -= hrs * fr * 3600;
753 mins = frames / (fr * 60);
754 frames -= mins * fr * 60;
757 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
760 disk_space_label.set_text (buf);
764 ARDOUR_UI::update_wall_clock ()
771 tm_now = localtime (&now);
773 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
774 wall_clock_label.set_text (buf);
780 ARDOUR_UI::session_menu (GdkEventButton *ev)
782 session_popup_menu->popup (0, 0);
787 ARDOUR_UI::redisplay_recent_sessions ()
789 vector<string *> *sessions;
790 vector<string *>::iterator i;
791 RecentSessionsSorter cmp;
793 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
794 recent_session_model->clear ();
797 ARDOUR::read_recent_sessions (rs);
800 recent_session_display.set_model (recent_session_model);
804 /* sort them alphabetically */
805 sort (rs.begin(), rs.end(), cmp);
806 sessions = new vector<string*>;
808 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
809 sessions->push_back (new string ((*i).second));
812 for (i = sessions->begin(); i != sessions->end(); ++i) {
814 vector<string*>* states;
815 vector<const gchar*> item;
816 string fullpath = *(*i);
818 /* remove any trailing / */
820 if (fullpath[fullpath.length()-1] == '/') {
821 fullpath = fullpath.substr (0, fullpath.length()-1);
824 /* now get available states for this session */
826 if ((states = Session::possible_states (fullpath)) == 0) {
831 TreeModel::Row row = *(recent_session_model->append());
833 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
834 row[recent_session_columns.fullpath] = fullpath;
836 if (states->size() > 1) {
838 /* add the children */
840 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
842 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
844 child_row[recent_session_columns.visible_name] = **i2;
845 child_row[recent_session_columns.fullpath] = fullpath;
854 recent_session_display.set_model (recent_session_model);
859 ARDOUR_UI::build_session_selector ()
861 session_selector_window = new ArdourDialog ("session selector");
863 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
865 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
866 session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
867 session_selector_window->set_default_response (RESPONSE_ACCEPT);
868 recent_session_model = TreeStore::create (recent_session_columns);
869 recent_session_display.set_model (recent_session_model);
870 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
871 recent_session_display.set_headers_visible (false);
872 recent_session_display.get_selection()->set_mode (SELECTION_SINGLE);
874 recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
876 scroller->add (recent_session_display);
877 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
879 session_selector_window->set_name ("SessionSelectorWindow");
880 session_selector_window->set_size_request (200, 400);
881 session_selector_window->get_vbox()->pack_start (*scroller);
882 session_selector_window->show_all_children();
886 ARDOUR_UI::recent_session_row_activated (const TreePath& path, TreeViewColumn* col)
888 session_selector_window->response (RESPONSE_ACCEPT);
892 ARDOUR_UI::open_recent_session ()
894 /* popup selector window */
896 if (session_selector_window == 0) {
897 build_session_selector ();
900 redisplay_recent_sessions ();
902 ResponseType r = (ResponseType) session_selector_window->run ();
904 session_selector_window->hide();
907 case RESPONSE_ACCEPT:
913 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
915 if (i == recent_session_model->children().end()) {
919 Glib::ustring path = (*i)[recent_session_columns.fullpath];
920 Glib::ustring state = (*i)[recent_session_columns.visible_name];
922 _session_is_new = false;
924 load_session (path, state);
928 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
932 if (stat (info.filename.c_str(), &statbuf) != 0) {
936 if (!S_ISDIR(statbuf.st_mode)) {
942 string session_file = info.filename;
944 session_file += Glib::path_get_basename (info.filename);
945 session_file += ".ardour";
947 if (stat (session_file.c_str(), &statbuf) != 0) {
951 return S_ISREG (statbuf.st_mode);
955 ARDOUR_UI::open_session ()
957 /* popup selector window */
959 if (open_session_selector == 0) {
961 /* ardour sessions are folders */
963 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
964 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
965 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
967 FileFilter session_filter;
968 session_filter.add_pattern ("*.ardour");
969 session_filter.set_name (_("Ardour sessions"));
970 open_session_selector->add_filter (session_filter);
971 open_session_selector->set_filter (session_filter);
974 int response = open_session_selector->run();
975 open_session_selector->hide ();
978 case RESPONSE_ACCEPT:
981 open_session_selector->hide();
985 open_session_selector->hide();
986 string session_path = open_session_selector->get_filename();
990 if (session_path.length() > 0) {
991 if (Session::find_session (session_path, path, name, isnew) == 0) {
992 _session_is_new = isnew;
993 load_session (path, name);
1000 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1002 list<boost::shared_ptr<MidiTrack> > tracks;
1005 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1012 tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1014 if (tracks.size() != how_many) {
1015 if (how_many == 1) {
1016 error << _("could not create a new midi track") << endmsg;
1018 error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1022 if ((route = session->new_midi_route ()) == 0) {
1023 error << _("could not create new midi bus") << endmsg;
1029 MessageDialog msg (*editor,
1030 _("There are insufficient JACK ports available\n\
1031 to create a new track or bus.\n\
1032 You should save Ardour, exit and\n\
1033 restart JACK with more ports."));
1040 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1042 list<boost::shared_ptr<AudioTrack> > tracks;
1043 Session::RouteList routes;
1046 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1052 tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1054 if (tracks.size() != how_many) {
1055 if (how_many == 1) {
1056 error << _("could not create a new audio track") << endmsg;
1058 error << string_compose (_("could only create %1 of %2 new audio %3"),
1059 tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1065 routes = session->new_audio_route (input_channels, output_channels, how_many);
1067 if (routes.size() != how_many) {
1068 if (how_many == 1) {
1069 error << _("could not create a new audio track") << endmsg;
1071 error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1077 if (need_control_room_outs) {
1083 route->set_stereo_control_outs (control_lr_channels);
1084 route->control_outs()->set_stereo_pan (pans, this);
1086 #endif /* CONTROLOUTS */
1090 cerr << "About to complain about JACK\n";
1091 MessageDialog msg (*editor,
1092 _("There are insufficient JACK ports available\n\
1093 to create a new track or bus.\n\
1094 You should save Ardour, exit and\n\
1095 restart JACK with more ports."));
1101 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1103 nframes_t _preroll = 0;
1106 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1107 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1109 if (new_position > _preroll) {
1110 new_position -= _preroll;
1115 session->request_locate (new_position);
1120 ARDOUR_UI::transport_goto_start ()
1123 session->goto_start();
1126 /* force displayed area in editor to start no matter
1127 what "follow playhead" setting is.
1131 editor->reset_x_origin (session->current_start_frame());
1137 ARDOUR_UI::transport_goto_zero ()
1140 session->request_locate (0);
1143 /* force displayed area in editor to start no matter
1144 what "follow playhead" setting is.
1148 editor->reset_x_origin (0);
1154 ARDOUR_UI::transport_goto_end ()
1157 nframes_t frame = session->current_end_frame();
1158 session->request_locate (frame);
1160 /* force displayed area in editor to start no matter
1161 what "follow playhead" setting is.
1165 editor->reset_x_origin (frame);
1171 ARDOUR_UI::transport_stop ()
1177 if (session->is_auditioning()) {
1178 session->cancel_audition ();
1182 if (session->get_play_loop ()) {
1183 session->request_play_loop (false);
1186 session->request_stop ();
1190 ARDOUR_UI::transport_stop_and_forget_capture ()
1193 session->request_stop (true);
1198 ARDOUR_UI::remove_last_capture()
1201 editor->remove_last_capture();
1206 ARDOUR_UI::transport_record ()
1209 switch (session->record_status()) {
1210 case Session::Disabled:
1211 if (session->ntracks() == 0) {
1212 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1216 session->maybe_enable_record ();
1218 case Session::Recording:
1219 case Session::Enabled:
1220 session->disable_record (true);
1226 ARDOUR_UI::transport_roll ()
1234 rolling = session->transport_rolling ();
1236 if (session->get_play_loop()) {
1237 session->request_play_loop (false);
1238 auto_loop_button.set_visual_state (1);
1239 roll_button.set_visual_state (1);
1240 } else if (session->get_play_range ()) {
1241 session->request_play_range (false);
1242 play_selection_button.set_visual_state (0);
1243 } else if (rolling) {
1244 session->request_locate (session->last_transport_start(), true);
1247 session->request_transport_speed (1.0f);
1251 ARDOUR_UI::transport_loop()
1254 if (session->get_play_loop()) {
1255 if (session->transport_rolling()) {
1256 Location * looploc = session->locations()->auto_loop_location();
1258 session->request_locate (looploc->start(), true);
1263 session->request_play_loop (true);
1269 ARDOUR_UI::transport_play_selection ()
1275 if (!session->get_play_range()) {
1276 session->request_stop ();
1279 editor->play_selection ();
1283 ARDOUR_UI::transport_rewind (int option)
1285 float current_transport_speed;
1288 current_transport_speed = session->transport_speed();
1290 if (current_transport_speed >= 0.0f) {
1293 session->request_transport_speed (-1.0f);
1296 session->request_transport_speed (-4.0f);
1299 session->request_transport_speed (-0.5f);
1304 session->request_transport_speed (current_transport_speed * 1.5f);
1310 ARDOUR_UI::transport_forward (int option)
1312 float current_transport_speed;
1315 current_transport_speed = session->transport_speed();
1317 if (current_transport_speed <= 0.0f) {
1320 session->request_transport_speed (1.0f);
1323 session->request_transport_speed (4.0f);
1326 session->request_transport_speed (0.5f);
1331 session->request_transport_speed (current_transport_speed * 1.5f);
1337 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1343 boost::shared_ptr<Route> r;
1345 if ((r = session->route_by_remote_id (dstream)) != 0) {
1349 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1350 t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1359 ARDOUR_UI::queue_transport_change ()
1361 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1365 ARDOUR_UI::map_transport_state ()
1367 float sp = session->transport_speed();
1370 transport_rolling ();
1371 } else if (sp < 0.0f) {
1372 transport_rewinding ();
1373 } else if (sp > 0.0f) {
1374 transport_forwarding ();
1376 transport_stopped ();
1381 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1383 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1384 (int) adj.get_value()].c_str());
1388 ARDOUR_UI::engine_stopped ()
1390 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1391 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1392 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1396 ARDOUR_UI::engine_running ()
1398 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1399 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1400 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1402 Glib::RefPtr<Action> action;
1403 char* action_name = 0;
1405 switch (engine->frames_per_cycle()) {
1407 action_name = X_("JACKLatency32");
1410 action_name = X_("JACKLatency64");
1413 action_name = X_("JACKLatency128");
1416 action_name = X_("JACKLatency512");
1419 action_name = X_("JACKLatency1024");
1422 action_name = X_("JACKLatency2048");
1425 action_name = X_("JACKLatency4096");
1428 action_name = X_("JACKLatency8192");
1431 /* XXX can we do anything useful ? */
1437 action = ActionManager::get_action (X_("JACK"), action_name);
1440 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1441 ract->set_active ();
1447 ARDOUR_UI::engine_halted ()
1449 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1451 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1452 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1454 update_sample_rate (0);
1456 MessageDialog msg (*editor,
1458 JACK has either been shutdown or it\n\
1459 disconnected Ardour because Ardour\n\
1460 was not fast enough. You can save the\n\
1461 session and/or try to reconnect to JACK ."));
1466 ARDOUR_UI::do_engine_start ()
1474 error << _("Unable to start the session running")
1484 ARDOUR_UI::start_engine ()
1486 if (do_engine_start () == 0) {
1487 if (session && _session_is_new) {
1488 /* we need to retain initial visual
1489 settings for a new session
1491 session->save_state ("");
1499 ARDOUR_UI::update_clocks ()
1501 if (!editor || !editor->dragging_playhead()) {
1502 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1507 ARDOUR_UI::start_clocking ()
1509 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1513 ARDOUR_UI::stop_clocking ()
1515 clock_signal_connection.disconnect ();
1519 ARDOUR_UI::toggle_clocking ()
1522 if (clock_button.get_active()) {
1531 ARDOUR_UI::_blink (void *arg)
1534 ((ARDOUR_UI *) arg)->blink ();
1541 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1545 ARDOUR_UI::start_blinking ()
1547 /* Start the blink signal. Everybody with a blinking widget
1548 uses Blink to drive the widget's state.
1551 if (blink_timeout_tag < 0) {
1553 blink_timeout_tag = g_timeout_add (240, _blink, this);
1558 ARDOUR_UI::stop_blinking ()
1560 if (blink_timeout_tag >= 0) {
1561 g_source_remove (blink_timeout_tag);
1562 blink_timeout_tag = -1;
1567 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1573 if (io.n_inputs().get_total() == 0) {
1578 /* XXX we're not handling multiple ports yet. */
1580 const char **connections = io.input(0)->get_connections();
1582 if (connections == 0 || connections[0] == '\0') {
1585 buf = connections[0];
1592 if (io.n_outputs().get_total() == 0) {
1597 /* XXX we're not handling multiple ports yet. */
1599 const char **connections = io.output(0)->get_connections();
1601 if (connections == 0 || connections[0] == '\0') {
1604 buf = connections[0];
1611 /** Ask the user for the name of a new shapshot and then take it.
1614 ARDOUR_UI::snapshot_session ()
1616 ArdourPrompter prompter (true);
1620 struct tm local_time;
1623 localtime_r (&n, &local_time);
1624 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1626 prompter.set_name ("Prompter");
1627 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1628 prompter.set_prompt (_("Name of New Snapshot"));
1629 prompter.set_initial_text (timebuf);
1631 switch (prompter.run()) {
1632 case RESPONSE_ACCEPT:
1633 prompter.get_result (snapname);
1634 if (snapname.length()){
1635 save_state (snapname);
1645 ARDOUR_UI::save_state (const string & name)
1647 (void) save_state_canfail (name);
1651 ARDOUR_UI::save_state_canfail (string name)
1656 if (name.length() == 0) {
1657 name = session->snap_name();
1660 if ((ret = session->save_state (name)) != 0) {
1664 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1669 ARDOUR_UI::restore_state (string name)
1672 if (name.length() == 0) {
1673 name = session->name();
1675 session->restore_state (name);
1680 ARDOUR_UI::primary_clock_value_changed ()
1683 session->request_locate (primary_clock.current_time ());
1688 ARDOUR_UI::secondary_clock_value_changed ()
1691 session->request_locate (secondary_clock.current_time ());
1696 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1698 if (session && dstream && dstream->record_enabled()) {
1700 Session::RecordState rs;
1702 rs = session->record_status ();
1705 case Session::Disabled:
1706 case Session::Enabled:
1707 if (w->get_state() != STATE_SELECTED) {
1708 w->set_state (STATE_SELECTED);
1712 case Session::Recording:
1713 if (w->get_state() != STATE_ACTIVE) {
1714 w->set_state (STATE_ACTIVE);
1720 if (w->get_state() != STATE_NORMAL) {
1721 w->set_state (STATE_NORMAL);
1727 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1733 switch (session->record_status()) {
1734 case Session::Enabled:
1736 rec_button.set_visual_state (2);
1738 rec_button.set_visual_state (0);
1742 case Session::Recording:
1743 rec_button.set_visual_state (1);
1747 rec_button.set_visual_state (0);
1753 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1761 ARDOUR_UI::save_template ()
1764 ArdourPrompter prompter (true);
1767 prompter.set_name (X_("Prompter"));
1768 prompter.set_prompt (_("Name for mix template:"));
1769 prompter.set_initial_text(session->name() + _("-template"));
1770 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1772 switch (prompter.run()) {
1773 case RESPONSE_ACCEPT:
1774 prompter.get_result (name);
1776 if (name.length()) {
1777 session->save_template (name);
1787 ARDOUR_UI::new_session (std::string predetermined_path)
1789 string session_name;
1790 string session_path;
1792 if (!engine->connected()) {
1793 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1798 int response = Gtk::RESPONSE_NONE;
1800 new_session_dialog->set_modal(true);
1801 new_session_dialog->set_name (predetermined_path);
1802 new_session_dialog->reset_recent();
1803 new_session_dialog->show();
1806 response = new_session_dialog->run ();
1808 if (!engine->connected()) {
1809 new_session_dialog->hide ();
1810 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1815 _session_is_new = false;
1817 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1822 new_session_dialog->hide ();
1825 } else if (response == Gtk::RESPONSE_NONE) {
1827 /* Clear was pressed */
1828 new_session_dialog->reset();
1830 } else if (response == Gtk::RESPONSE_YES) {
1832 /* YES == OPEN, but there's no enum for that */
1834 session_name = new_session_dialog->session_name();
1836 if (session_name.empty()) {
1837 response = Gtk::RESPONSE_NONE;
1841 if (session_name[0] == '/' ||
1842 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1843 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1844 load_session (Glib::path_get_dirname (session_name), session_name);
1846 session_path = new_session_dialog->session_folder();
1847 load_session (session_path, session_name);
1850 } else if (response == Gtk::RESPONSE_OK) {
1852 session_name = new_session_dialog->session_name();
1854 if (new_session_dialog->get_current_page() == 1) {
1856 /* XXX this is a bit of a hack..
1857 i really want the new sesion dialog to return RESPONSE_YES
1858 if we're on page 1 (the load page)
1859 Unfortunately i can't see how atm..
1862 if (session_name.empty()) {
1863 response = Gtk::RESPONSE_NONE;
1867 if (session_name[0] == '/' ||
1868 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1869 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1870 load_session (Glib::path_get_dirname (session_name), session_name);
1872 session_path = new_session_dialog->session_folder();
1873 load_session (session_path, session_name);
1878 if (session_name.empty()) {
1879 response = Gtk::RESPONSE_NONE;
1883 if (session_name[0] == '/' ||
1884 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1885 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1887 session_path = Glib::path_get_dirname (session_name);
1888 session_name = Glib::path_get_basename (session_name);
1892 session_path = new_session_dialog->session_folder();
1896 //XXX This is needed because session constructor wants a
1897 //non-existant path. hopefully this will be fixed at some point.
1899 session_path = Glib::build_filename (session_path, session_name);
1901 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1903 Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1905 MessageDialog msg (str,
1907 Gtk::MESSAGE_WARNING,
1908 Gtk::BUTTONS_YES_NO,
1912 msg.set_name (X_("CleanupDialog"));
1913 msg.set_wmclass (X_("existing_session"), "Ardour");
1914 msg.set_position (Gtk::WIN_POS_MOUSE);
1916 switch (msg.run()) {
1918 load_session (session_path, session_name);
1922 response = RESPONSE_NONE;
1923 new_session_dialog->reset ();
1928 _session_is_new = true;
1930 std::string template_name = new_session_dialog->session_template_name();
1932 if (new_session_dialog->use_session_template()) {
1934 load_session (session_path, session_name, &template_name);
1940 AutoConnectOption iconnect;
1941 AutoConnectOption oconnect;
1943 if (new_session_dialog->create_control_bus()) {
1944 cchns = (uint32_t) new_session_dialog->control_channel_count();
1949 if (new_session_dialog->create_master_bus()) {
1950 mchns = (uint32_t) new_session_dialog->master_channel_count();
1955 if (new_session_dialog->connect_inputs()) {
1956 iconnect = AutoConnectPhysical;
1958 iconnect = AutoConnectOption (0);
1961 /// @todo some minor tweaks.
1963 if (new_session_dialog->connect_outs_to_master()) {
1964 oconnect = AutoConnectMaster;
1965 } else if (new_session_dialog->connect_outs_to_physical()) {
1966 oconnect = AutoConnectPhysical;
1968 oconnect = AutoConnectOption (0);
1971 uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1972 uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1974 if (build_session (session_path,
1982 engine->frame_rate() * 60 * 5)) {
1984 response = Gtk::RESPONSE_NONE;
1985 new_session_dialog->reset ();
1992 } while (response == Gtk::RESPONSE_NONE);
1996 new_session_dialog->get_window()->set_cursor();
1997 new_session_dialog->hide();
2002 ARDOUR_UI::close_session()
2009 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2011 Session *new_session;
2013 session_loaded = false;
2015 x = unload_session ();
2023 /* if it already exists, we must have write access */
2025 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2026 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2027 "This prevents the session from being loaded."));
2033 new_session = new Session (*engine, path, snap_name, mix_template);
2038 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2042 connect_to_session (new_session);
2044 Config->set_current_owner (ConfigVariableBase::Interface);
2046 session_loaded = true;
2048 goto_editor_window ();
2051 session->set_clean ();
2054 editor->edit_cursor_position (true);
2059 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2060 uint32_t control_channels,
2061 uint32_t master_channels,
2062 AutoConnectOption input_connect,
2063 AutoConnectOption output_connect,
2066 nframes_t initial_length)
2068 Session *new_session;
2071 session_loaded = false;
2072 x = unload_session ();
2079 _session_is_new = true;
2082 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2083 control_channels, master_channels, nphysin, nphysout, initial_length);
2088 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2093 connect_to_session (new_session);
2095 session_loaded = true;
2103 editor->show_window ();
2114 ARDOUR_UI::show_splash ()
2117 about = new About();
2118 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2125 ARDOUR_UI::about_signal_response(int response)
2131 ARDOUR_UI::hide_splash ()
2134 about->get_window()->set_cursor ();
2140 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2144 removed = rep.paths.size();
2147 MessageDialog msgd (*editor,
2148 _("No audio files were ready for cleanup"),
2151 (Gtk::ButtonsType)(Gtk::BUTTONS_OK) );
2152 msgd.set_secondary_text (_("If this seems suprising, \n\
2153 check for any existing snapshots.\n\
2154 These may still include regions that\n\
2155 require some unused files to continue to exist."));
2161 ArdourDialog results (_("ardour: cleanup"), true, false);
2163 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2164 CleanupResultsModelColumns() {
2168 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2169 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2173 CleanupResultsModelColumns results_columns;
2174 Glib::RefPtr<Gtk::ListStore> results_model;
2175 Gtk::TreeView results_display;
2177 results_model = ListStore::create (results_columns);
2178 results_display.set_model (results_model);
2179 results_display.append_column (list_title, results_columns.visible_name);
2181 results_display.set_name ("CleanupResultsList");
2182 results_display.set_headers_visible (true);
2183 results_display.set_headers_clickable (false);
2184 results_display.set_reorderable (false);
2186 Gtk::ScrolledWindow list_scroller;
2189 Gtk::HBox dhbox; // the hbox for the image and text
2190 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2191 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
2193 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2195 if (rep.space < 1048576.0f) {
2197 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2199 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2203 txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2205 txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2209 dhbox.pack_start (*dimage, true, false, 5);
2210 dhbox.pack_start (txt, true, false, 5);
2212 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2213 TreeModel::Row row = *(results_model->append());
2214 row[results_columns.visible_name] = *i;
2215 row[results_columns.fullpath] = *i;
2218 list_scroller.add (results_display);
2219 list_scroller.set_size_request (-1, 150);
2220 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2222 dvbox.pack_start (dhbox, true, false, 5);
2223 dvbox.pack_start (list_scroller, true, false, 5);
2224 ddhbox.pack_start (dvbox, true, false, 5);
2226 results.get_vbox()->pack_start (ddhbox, true, false, 5);
2227 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2228 results.set_default_response (RESPONSE_CLOSE);
2229 results.set_position (Gtk::WIN_POS_MOUSE);
2230 results.show_all_children ();
2231 results.set_resizable (false);
2238 ARDOUR_UI::cleanup ()
2241 /* shouldn't happen: menu item is insensitive */
2246 MessageDialog checker (_("Are you sure you want to cleanup?"),
2248 Gtk::MESSAGE_QUESTION,
2249 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2251 checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2252 ALL undo/redo information will be lost if you cleanup.\n\
2253 After cleanup, unused audio files will be moved to a \
2254 \"dead sounds\" location."));
2256 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2257 checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2258 checker.set_default_response (RESPONSE_CANCEL);
2260 checker.set_name (_("CleanupDialog"));
2261 checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2262 checker.set_position (Gtk::WIN_POS_MOUSE);
2264 switch (checker.run()) {
2265 case RESPONSE_ACCEPT:
2271 Session::cleanup_report rep;
2273 editor->prepare_for_cleanup ();
2275 /* do not allow flush until a session is reloaded */
2277 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2279 act->set_sensitive (false);
2282 if (session->cleanup_sources (rep)) {
2287 display_cleanup_results (rep,
2290 The following %1 %2 not in use and \n\
2291 have been moved to:\n\
2293 Flushing the wastebasket will \n\
2294 release an additional\n\
2295 %4 %5bytes of disk space.\n"
2303 ARDOUR_UI::flush_trash ()
2306 /* shouldn't happen: menu item is insensitive */
2310 Session::cleanup_report rep;
2312 if (session->cleanup_trash_sources (rep)) {
2316 display_cleanup_results (rep,
2318 _("The following %1 %2 deleted from\n\
2320 releasing %4 %5bytes of disk space"));
2324 ARDOUR_UI::add_route (Gtk::Window* float_window)
2332 if (add_route_dialog == 0) {
2333 add_route_dialog = new AddRouteDialog;
2335 add_route_dialog->set_transient_for (*float_window);
2339 if (add_route_dialog->is_visible()) {
2340 /* we're already doing this */
2344 ResponseType r = (ResponseType) add_route_dialog->run ();
2346 add_route_dialog->hide();
2349 case RESPONSE_ACCEPT:
2356 if ((count = add_route_dialog->count()) <= 0) {
2360 uint32_t input_chan = add_route_dialog->channels ();
2361 uint32_t output_chan;
2362 string name_template = add_route_dialog->name_template ();
2363 bool track = add_route_dialog->track ();
2365 AutoConnectOption oac = Config->get_output_auto_connect();
2367 if (oac & AutoConnectMaster) {
2368 output_chan = (session->master_out() ? session->master_out()->n_inputs().get(DataType::AUDIO) : input_chan);
2370 output_chan = input_chan;
2373 /* XXX do something with name template */
2375 if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2377 session_add_midi_track(count);
2379 MessageDialog msg (*editor,
2380 _("Sorry, MIDI Busses are not supported at this time."));
2382 //session_add_midi_bus();
2386 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2388 session_add_audio_bus (input_chan, output_chan, count);
2394 ARDOUR_UI::mixer_settings () const
2399 node = session->instant_xml(X_("Mixer"), session->path());
2401 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2405 node = new XMLNode (X_("Mixer"));
2412 ARDOUR_UI::editor_settings () const
2417 node = session->instant_xml(X_("Editor"), session->path());
2419 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2423 node = new XMLNode (X_("Editor"));
2429 ARDOUR_UI::keyboard_settings () const
2433 node = Config->extra_xml(X_("Keyboard"));
2436 node = new XMLNode (X_("Keyboard"));
2442 ARDOUR_UI::halt_on_xrun_message ()
2444 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2446 MessageDialog msg (*editor,
2447 _("Recording was stopped because your system could not keep up."));
2452 ARDOUR_UI::disk_overrun_handler ()
2454 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2456 if (!have_disk_speed_dialog_displayed) {
2457 have_disk_speed_dialog_displayed = true;
2458 MessageDialog* msg = new MessageDialog (*editor, _("\
2459 The disk system on your computer\n\
2460 was not able to keep up with Ardour.\n\
2462 Specifically, it failed to write data to disk\n\
2463 quickly enough to keep up with recording.\n"));
2464 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2470 ARDOUR_UI::disk_underrun_handler ()
2472 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2474 if (!have_disk_speed_dialog_displayed) {
2475 have_disk_speed_dialog_displayed = true;
2476 MessageDialog* msg = new MessageDialog (*editor,
2477 _("The disk system on your computer\n\
2478 was not able to keep up with Ardour.\n\
2480 Specifically, it failed to read data from disk\n\
2481 quickly enough to keep up with playback.\n"));
2482 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2488 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2490 have_disk_speed_dialog_displayed = false;
2495 ARDOUR_UI::pending_state_dialog ()
2497 ArdourDialog dialog ("pending state dialog");
2499 This session appears to have been in\n\
2500 middle of recording when ardour or\n\
2501 the computer was shutdown.\n\
2503 Ardour can recover any captured audio for\n\
2504 you, or it can ignore it. Please decide\n\
2505 what you would like to do.\n"));
2507 dialog.get_vbox()->pack_start (message);
2508 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2509 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2511 dialog.set_position (WIN_POS_CENTER);
2514 switch (dialog.run ()) {
2515 case RESPONSE_ACCEPT:
2523 ARDOUR_UI::disconnect_from_jack ()
2526 if( engine->disconnect_from_jack ()) {
2527 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2531 update_sample_rate (0);
2536 ARDOUR_UI::reconnect_to_jack ()
2539 if (engine->reconnect_to_jack ()) {
2540 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2544 update_sample_rate (0);
2549 ARDOUR_UI::cmdline_new_session (string path)
2551 if (path[0] != '/') {
2552 char buf[PATH_MAX+1];
2555 getcwd (buf, sizeof (buf));
2564 _will_create_new_session_automatically = false; /* done it */
2565 return FALSE; /* don't call it again */
2569 ARDOUR_UI::use_config ()
2571 Glib::RefPtr<Action> act;
2573 switch (Config->get_native_file_data_format ()) {
2575 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2578 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2583 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2584 ract->set_active ();
2587 switch (Config->get_native_file_header_format ()) {
2589 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2592 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2595 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2598 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2601 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2604 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2607 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2612 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2613 ract->set_active ();
2616 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2618 set_transport_controllable_state (*node);
2623 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2625 primary_clock.set (pos);
2626 secondary_clock.set (pos);
2628 if (big_clock_window) {
2629 big_clock.set (pos);
2634 ARDOUR_UI::record_state_changed ()
2636 ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2638 if (!session || !big_clock_window) {
2639 /* why bother - the clock isn't visible */
2643 switch (session->record_status()) {
2644 case Session::Recording:
2645 big_clock.set_widget_name ("BigClockRecording");
2648 big_clock.set_widget_name ("BigClockNonRecording");
2654 ARDOUR_UI::set_keybindings_path (string path)
2656 keybindings_path = path;
2660 ARDOUR_UI::save_keybindings ()
2662 if (can_save_keybindings) {
2663 AccelMap::save (keybindings_path);
2668 ARDOUR_UI::first_idle ()
2671 session->allow_auto_play (true);
2673 can_save_keybindings = true;
2678 ARDOUR_UI::store_clock_modes ()
2680 XMLNode* node = new XMLNode(X_("ClockModes"));
2682 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2683 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2686 session->add_extra_xml (*node);
2687 session->set_dirty ();
2692 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2693 : Controllable (name), ui (u), type(tp)
2699 ARDOUR_UI::TransportControllable::set_value (float val)
2701 if (type == ShuttleControl) {
2708 fract = -((0.5f - val)/0.5f);
2710 fract = ((val - 0.5f)/0.5f);
2714 ui.set_shuttle_fract (fract);
2719 /* do nothing: these are radio-style actions */
2727 action = X_("Roll");
2730 action = X_("Stop");
2733 action = X_("Goto Start");
2736 action = X_("Goto End");
2739 action = X_("Loop");
2742 action = X_("Play Selection");
2745 action = X_("Record");
2755 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2763 ARDOUR_UI::TransportControllable::get_value (void) const
2782 case ShuttleControl:
2792 ARDOUR_UI::TransportControllable::set_id (const string& str)
2798 ARDOUR_UI::setup_profile ()
2800 if (gdk_screen_width() < 1200) {
2801 Profile->set_small_screen ();