2 Copyright (C) 1999-2002 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.
31 #include <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
73 #include "gui_thread.h"
74 #include "meter_xpms.h"
75 #include "color_manager.h"
79 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
84 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
86 sigc::signal<void,bool> ARDOUR_UI::Blink;
87 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
88 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
89 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
91 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
93 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
95 primary_clock (X_("TransportClockDisplay"), true, false, true),
96 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
97 preroll_clock (X_("PreRollClock"), true, true),
98 postroll_clock (X_("PostRollClock"), true, true),
102 adjuster_table (3, 3),
106 preroll_button (_("pre\nroll")),
107 postroll_button (_("post\nroll")),
111 big_clock ("BigClockDisplay", true),
115 time_master_button (_("time\nmaster")),
117 shuttle_units_button (_("% ")),
119 punch_in_button (_("punch\nin")),
120 punch_out_button (_("punch\nout")),
121 auto_return_button (_("auto\nreturn")),
122 auto_play_button (_("auto\nplay")),
123 auto_input_button (_("auto\ninput")),
124 click_button (_("click")),
125 auditioning_alert_button (_("AUDITIONING")),
126 solo_alert_button (_("SOLO")),
130 using namespace Gtk::Menu_Helpers;
134 /* actually, its already loaded, but ... */
136 cerr << "Loading UI configuration file " << rcfile << endl;
140 if (theArdourUI == 0) {
144 ActionManager::init ();
148 color_manager = new ColorManager();
150 std::string color_file = Glib::getenv(X_("ARDOUR_COLORS"));
151 if(!Glib::file_test(color_file, Glib::FILE_TEST_EXISTS)) {
152 color_file = ARDOUR::find_config_file("ardour.colors");
154 color_manager->load (color_file);
156 m_new_session_dialog = 0;
157 m_new_session_dialog_ref = NewSessionDialogFactory::create();
158 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
162 _session_is_new = false;
163 big_clock_window = 0;
164 session_selector_window = 0;
165 last_key_press_time = 0;
166 connection_editor = 0;
167 add_route_dialog = 0;
172 open_session_selector = 0;
173 have_configure_timeout = false;
174 have_disk_overrun_displayed = false;
175 have_disk_underrun_displayed = false;
176 _will_create_new_session_automatically = false;
177 session_loaded = false;
178 last_speed_displayed = -1.0f;
180 last_configure_time.tv_sec = 0;
181 last_configure_time.tv_usec = 0;
183 shuttle_grabbed = false;
186 set_shuttle_units (Percentage);
187 set_shuttle_behaviour (Sprung);
189 shuttle_style_menu = 0;
190 shuttle_unit_menu = 0;
192 gettimeofday (&last_peak_grab, 0);
193 gettimeofday (&last_shuttle_request, 0);
195 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
196 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
197 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
198 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
200 /* handle pending state with a dialog */
202 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
204 /* have to wait for AudioEngine and Configuration before proceeding */
208 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
210 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
212 string msg = string_compose (_("\
213 You cannot record-enable\n\
215 because it has no input connections.\n\
216 You would be wasting space recording silence."),
219 ArdourMessage message (editor, X_("cannotrecord"), msg);
223 ARDOUR_UI::set_engine (AudioEngine& e)
227 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
228 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
229 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
230 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
234 keyboard = new Keyboard;
235 install_keybindings ();
237 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
238 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
240 if (setup_windows ()) {
241 throw failed_constructor ();
244 if (GTK_ARDOUR::show_key_actions) {
245 vector<string> names;
246 vector<string> paths;
248 vector<AccelKey> bindings;
250 ActionManager::get_all_actions (names, paths, keys, bindings);
252 vector<string>::iterator n;
253 vector<string>::iterator k;
254 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
255 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
261 /* start with timecode, metering enabled
264 blink_timeout_tag = -1;
266 /* this being a GUI and all, we want peakfiles */
268 FileSource::set_build_peakfiles (true);
269 FileSource::set_build_missing_peakfiles (true);
271 if (Source::start_peak_thread ()) {
272 throw failed_constructor();
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 Source::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::save_ardour_state ()
353 if (!keyboard || !mixer || !editor) {
357 /* XXX this is all a bit dubious. add_extra_xml() uses
358 a different lifetime model from add_instant_xml().
361 XMLNode* node = new XMLNode (keyboard->get_state());
362 Config->add_extra_xml (*node);
363 Config->save_state();
365 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
366 XMLNode& mnode (mixer->get_state());
369 session->add_instant_xml(enode, session->path());
370 session->add_instant_xml(mnode, session->path());
372 Config->add_instant_xml(enode, Config->get_user_ardour_path());
373 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
378 ARDOUR_UI::startup ()
380 /* Once the UI is up and running, start the audio engine. Doing
381 this before the UI is up and running can cause problems
382 when not running with SCHED_FIFO, because the amount of
383 CPU and disk work needed to get the UI started can interfere
384 with the scheduling of the audio thread.
387 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
393 if (session && session->dirty()) {
394 switch (ask_about_saving_session(_("quit"))) {
399 /* use the default name */
400 if (save_state_canfail ("")) {
401 /* failed - don't quit */
402 ArdourMessage (editor, X_("badsave dialog"),
404 Ardour was unable to save your session.\n\n\
405 If you still wish to quit, please use the\n\n\
406 \"Just quit\" option."));
419 ARDOUR_UI::ask_about_saving_session (const string & what)
421 ArdourDialog window (_("ardour: save session?"));
422 Gtk::Label prompt_label;
425 msg = string_compose(_("Save and %1"), what);
426 window.add_button (msg, RESPONSE_ACCEPT);
427 msg = string_compose(_("Just %1"), what);
428 window.add_button (msg, RESPONSE_APPLY);
429 msg = string_compose(_("Don't %1"), what);
430 window.add_button (msg, RESPONSE_REJECT);
432 Gtk::Button noquit_button (msg);
433 noquit_button.set_name ("EditorGTKButton");
438 if (session->snap_name() == session->name()) {
441 type = _("snapshot");
443 prompt = string_compose(_("The %1\n\"%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?"),
444 type, session->snap_name());
446 prompt_label.set_text (prompt);
447 prompt_label.set_alignment (0.5, 0.5);
448 prompt_label.set_name (X_("PrompterLabel"));
450 window.get_vbox()->pack_start (prompt_label);
452 window.set_name (_("Prompter"));
453 window.set_position (Gtk::WIN_POS_MOUSE);
454 window.set_modal (true);
457 save_the_session = 0;
459 editor->ensure_float (window);
461 ResponseType r = (ResponseType) window.run();
466 case RESPONSE_ACCEPT: // save and get out of here
468 case RESPONSE_APPLY: // get out of here
478 ARDOUR_UI::every_second ()
481 update_buffer_load ();
482 update_disk_space ();
483 // update_disk_rate ();
488 ARDOUR_UI::every_point_one_seconds ()
493 /* do not attempt to grab peak power more than once per cycle.
496 gettimeofday (&now, 0);
497 timersub (&now, &last_peak_grab, &diff);
499 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
500 IO::GrabPeakPower(); /* EMIT_SIGNAL */
501 last_peak_grab = now;
504 update_speed_display ();
505 RapidScreenUpdate(); /* EMIT_SIGNAL */
510 ARDOUR_UI::every_point_zero_one_seconds ()
512 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
517 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
521 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
523 if (!engine->connected()) {
525 snprintf (buf, sizeof (buf), _("disconnected"));
529 jack_nframes_t rate = engine->frame_rate();
531 if (fmod (rate, 1000.0) != 0.0) {
532 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
533 (float) rate/1000.0f,
534 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
536 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
538 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
542 sample_rate_label.set_text (buf);
546 ARDOUR_UI::update_cpu_load ()
549 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
550 cpu_load_label.set_text (buf);
554 ARDOUR_UI::update_disk_rate ()
559 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
560 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
561 disk_rate_label.set_text (buf);
563 disk_rate_label.set_text ("");
568 ARDOUR_UI::update_buffer_load ()
573 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
574 session->playback_load(), session->capture_load());
575 buffer_load_label.set_text (buf);
577 buffer_load_label.set_text ("");
582 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
584 if (ds.record_enabled()) {
585 rec_enabled_diskstreams++;
590 ARDOUR_UI::update_disk_space()
596 jack_nframes_t frames = session->available_capture_duration();
599 if (frames == max_frames) {
600 strcpy (buf, _("space: 24hrs+"));
605 jack_nframes_t fr = session->frame_rate();
607 if (session->actively_recording()){
609 rec_enabled_diskstreams = 0;
610 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
612 if (rec_enabled_diskstreams) {
613 frames /= rec_enabled_diskstreams;
618 /* hmmm. shall we divide by the route count? or the diskstream count?
619 or what? for now, do nothing ...
624 hrs = frames / (fr * 3600);
625 frames -= hrs * fr * 3600;
626 mins = frames / (fr * 60);
627 frames -= mins * fr * 60;
630 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
633 disk_space_label.set_text (buf);
637 ARDOUR_UI::update_wall_clock ()
644 tm_now = localtime (&now);
646 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
647 wall_clock_label.set_text (buf);
652 ARDOUR_UI::control_methods_adjusted ()
657 which_method = (int) online_control_button->adjustment.get_value();
658 switch (which_method) {
660 allow_mmc_and_local ();
669 fatal << _("programming error: impossible control method") << endmsg;
675 ARDOUR_UI::mmc_device_id_adjusted ()
680 int dev_id = (int) mmc_id_button->adjustment.get_value();
681 mmc->set_device_id (dev_id);
687 ARDOUR_UI::session_menu (GdkEventButton *ev)
689 session_popup_menu->popup (0, 0);
694 ARDOUR_UI::redisplay_recent_sessions ()
696 vector<string *> *sessions;
697 vector<string *>::iterator i;
698 RecentSessionsSorter cmp;
700 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
701 recent_session_model->clear ();
704 ARDOUR::read_recent_sessions (rs);
707 recent_session_display.set_model (recent_session_model);
711 /* sort them alphabetically */
712 sort (rs.begin(), rs.end(), cmp);
713 sessions = new vector<string*>;
715 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
716 sessions->push_back (new string ((*i).second));
719 for (i = sessions->begin(); i != sessions->end(); ++i) {
721 vector<string*>* states;
722 vector<const gchar*> item;
723 string fullpath = *(*i);
725 /* remove any trailing / */
727 if (fullpath[fullpath.length()-1] == '/') {
728 fullpath = fullpath.substr (0, fullpath.length()-1);
731 /* now get available states for this session */
733 if ((states = Session::possible_states (fullpath)) == 0) {
738 TreeModel::Row row = *(recent_session_model->append());
740 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
741 row[recent_session_columns.fullpath] = fullpath;
743 if (states->size() > 1) {
745 /* add the children */
747 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
749 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
751 child_row[recent_session_columns.visible_name] = **i2;
752 child_row[recent_session_columns.fullpath] = fullpath;
761 recent_session_display.set_model (recent_session_model);
766 ARDOUR_UI::build_session_selector ()
768 session_selector_window = new ArdourDialog ("session selector");
770 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
772 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
773 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
775 recent_session_model = TreeStore::create (recent_session_columns);
776 recent_session_display.set_model (recent_session_model);
777 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
778 recent_session_display.set_headers_visible (false);
780 scroller->add (recent_session_display);
781 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
783 session_selector_window->set_name ("SessionSelectorWindow");
784 session_selector_window->set_size_request (200, 400);
785 session_selector_window->get_vbox()->pack_start (*scroller);
786 session_selector_window->show_all_children();
790 ARDOUR_UI::open_recent_session ()
792 /* popup selector window */
794 if (session_selector_window == 0) {
795 build_session_selector ();
798 redisplay_recent_sessions ();
800 ResponseType r = (ResponseType) session_selector_window->run ();
802 session_selector_window->hide();
805 case RESPONSE_ACCEPT:
811 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
813 if (i == recent_session_model->children().end()) {
817 Glib::ustring path = (*i)[recent_session_columns.fullpath];
818 Glib::ustring state = (*i)[recent_session_columns.visible_name];
820 _session_is_new = false;
822 load_session (path, state);
826 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
830 if (stat (info.filename.c_str(), &statbuf) != 0) {
834 if (!S_ISDIR(statbuf.st_mode)) {
838 string session_file = info.filename;
840 session_file += PBD::basename (info.filename);
841 session_file += ".ardour";
843 if (stat (session_file.c_str(), &statbuf) != 0) {
847 return S_ISREG (statbuf.st_mode);
851 ARDOUR_UI::open_session ()
853 /* popup selector window */
855 if (open_session_selector == 0) {
857 /* ardour sessions are folders */
859 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
860 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
861 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
863 FileFilter session_filter;
864 session_filter.add_pattern ("*.ardour");
865 session_filter.set_name (_("Ardour sessions"));
866 open_session_selector->add_filter (session_filter);
867 open_session_selector->set_filter (session_filter);
870 int response = open_session_selector->run();
871 open_session_selector->hide ();
874 case RESPONSE_ACCEPT:
877 open_session_selector->hide();
881 open_session_selector->hide();
882 string session_path = open_session_selector->get_filename();
886 if (session_path.length() > 0) {
887 if (Session::find_session (session_path, path, name, isnew) == 0) {
888 _session_is_new = isnew;
889 load_session (path, name);
896 ARDOUR_UI::session_add_midi_track ()
898 cerr << _("Patience is a virtue.\n");
902 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
907 warning << _("You cannot add a track without a session already loaded.") << endmsg;
913 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
914 error << _("could not create new audio track") << endmsg;
917 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
918 error << _("could not create new audio bus") << endmsg;
923 if (need_control_room_outs) {
929 route->set_stereo_control_outs (control_lr_channels);
930 route->control_outs()->set_stereo_pan (pans, this);
932 #endif /* CONTROLOUTS */
936 ArdourMessage msg (editor, X_("noport dialog"),
937 _("There are insufficient JACK ports available\n\
938 to create a new track or bus.\n\
939 You should save Ardour, exit and\n\
940 restart JACK with more ports."));
945 ARDOUR_UI::diskstream_added (DiskStream* ds)
950 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
952 jack_nframes_t _preroll;
955 _preroll = session->convert_to_frames_at (new_position, session->preroll);
957 if (new_position > _preroll) {
958 new_position -= _preroll;
963 session->request_locate (new_position);
968 ARDOUR_UI::transport_goto_start ()
971 session->request_locate (0);
974 /* force displayed area in editor to start no matter
975 what "follow playhead" setting is.
979 editor->reposition_x_origin (0);
985 ARDOUR_UI::transport_goto_end ()
988 jack_nframes_t frame = session->current_end_frame();
989 session->request_locate (frame);
991 /* force displayed area in editor to start no matter
992 what "follow playhead" setting is.
996 editor->reposition_x_origin (frame);
1002 ARDOUR_UI::transport_stop ()
1008 if (session->is_auditioning()) {
1009 session->cancel_audition ();
1013 if (session->get_auto_loop()) {
1014 session->request_auto_loop (false);
1017 session->request_stop ();
1021 ARDOUR_UI::transport_stop_and_forget_capture ()
1024 session->request_stop (true);
1029 ARDOUR_UI::remove_last_capture()
1032 editor->remove_last_capture();
1037 ARDOUR_UI::transport_record ()
1040 switch (session->record_status()) {
1041 case Session::Disabled:
1042 if (session->ntracks() == 0) {
1043 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1044 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1047 session->maybe_enable_record ();
1049 case Session::Recording:
1050 case Session::Enabled:
1051 session->disable_record (true);
1057 ARDOUR_UI::transport_roll ()
1065 rolling = session->transport_rolling ();
1067 if (session->get_auto_loop()) {
1068 session->request_auto_loop (false);
1069 auto_loop_button.set_active (false);
1070 roll_button.set_active (true);
1071 } else if (session->get_play_range ()) {
1072 session->request_play_range (false);
1073 play_selection_button.set_active (false);
1074 } else if (rolling) {
1075 session->request_locate (session->last_transport_start(), true);
1078 session->request_transport_speed (1.0f);
1082 ARDOUR_UI::transport_loop()
1085 if (session->get_auto_loop()) {
1086 if (session->transport_rolling()) {
1087 Location * looploc = session->locations()->auto_loop_location();
1089 session->request_locate (looploc->start(), true);
1094 session->request_auto_loop (true);
1100 ARDOUR_UI::transport_play_selection ()
1106 if (!session->get_play_range()) {
1107 session->request_stop ();
1110 editor->play_selection ();
1114 ARDOUR_UI::transport_rewind (int option)
1116 float current_transport_speed;
1119 current_transport_speed = session->transport_speed();
1121 if (current_transport_speed >= 0.0f) {
1124 session->request_transport_speed (-1.0f);
1127 session->request_transport_speed (-4.0f);
1130 session->request_transport_speed (-0.5f);
1135 session->request_transport_speed (current_transport_speed * 1.5f);
1141 ARDOUR_UI::transport_forward (int option)
1143 float current_transport_speed;
1146 current_transport_speed = session->transport_speed();
1148 if (current_transport_speed <= 0.0f) {
1151 session->request_transport_speed (1.0f);
1154 session->request_transport_speed (4.0f);
1157 session->request_transport_speed (0.5f);
1162 session->request_transport_speed (current_transport_speed * 1.5f);
1168 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1176 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1177 Port *port = ds->io()->input (0);
1178 port->request_monitor_input (!port->monitoring_input());
1183 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1191 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1192 ds->set_record_enabled (!ds->record_enabled(), this);
1197 ARDOUR_UI::queue_transport_change ()
1199 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1203 ARDOUR_UI::map_transport_state ()
1205 float sp = session->transport_speed();
1208 transport_rolling ();
1209 } else if (sp < 0.0f) {
1210 transport_rewinding ();
1211 } else if (sp > 0.0f) {
1212 transport_forwarding ();
1214 transport_stopped ();
1219 ARDOUR_UI::send_all_midi_feedback ()
1222 session->send_all_midi_feedback();
1227 ARDOUR_UI::allow_local_only ()
1233 ARDOUR_UI::allow_mmc_only ()
1239 ARDOUR_UI::allow_mmc_and_local ()
1245 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1247 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1248 (int) adj.get_value()].c_str());
1252 ARDOUR_UI::engine_stopped ()
1254 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1255 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1256 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1261 ARDOUR_UI::engine_running ()
1263 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1264 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1265 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1269 ARDOUR_UI::engine_halted ()
1271 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1273 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1274 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1276 update_sample_rate (0);
1278 ArdourMessage msg (editor, X_("halted"),
1280 JACK has either been shutdown or it\n\
1281 disconnected Ardour because Ardour\n\
1282 was not fast enough. You can save the\n\
1283 session and/or try to reconnect to JACK ."));
1287 ARDOUR_UI::do_engine_start ()
1293 catch (AudioEngine::PortRegistrationFailure& err) {
1295 error << _("Unable to create all required ports")
1303 error << _("Unable to start the session running")
1313 ARDOUR_UI::start_engine ()
1315 if (do_engine_start () == 0) {
1316 if (session && _session_is_new) {
1317 /* we need to retain initial visual
1318 settings for a new session
1320 session->save_state ("");
1323 /* there is too much going on, in too many threads, for us to
1324 end up with a clean session. So wait 1 second after loading,
1325 and fix it up. its ugly, but until i come across a better
1326 solution, its what we have.
1329 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1336 ARDOUR_UI::update_clocks ()
1338 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1342 ARDOUR_UI::start_clocking ()
1344 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1348 ARDOUR_UI::stop_clocking ()
1350 clock_signal_connection.disconnect ();
1354 ARDOUR_UI::toggle_clocking ()
1357 if (clock_button.get_active()) {
1366 ARDOUR_UI::_blink (void *arg)
1369 ((ARDOUR_UI *) arg)->blink ();
1376 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1380 ARDOUR_UI::start_blinking ()
1382 /* Start the blink signal. Everybody with a blinking widget
1383 uses Blink to drive the widget's state.
1386 if (blink_timeout_tag < 0) {
1388 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1393 ARDOUR_UI::stop_blinking ()
1395 if (blink_timeout_tag >= 0) {
1396 gtk_timeout_remove (blink_timeout_tag);
1397 blink_timeout_tag = -1;
1403 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1405 using namespace Gtk;
1406 using namespace Menu_Helpers;
1408 if (dstream.hidden()) {
1412 MenuList& items = diskstream_menu->items();
1413 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1417 ARDOUR_UI::diskstream_selected (gint32 id)
1419 selected_dstream = id;
1424 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1426 using namespace Gtk;
1427 using namespace Menu_Helpers;
1433 diskstream_menu = new Menu();
1434 diskstream_menu->set_name ("ArdourContextMenu");
1435 using namespace Gtk;
1436 using namespace Menu_Helpers;
1438 MenuList& items = diskstream_menu->items();
1439 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1441 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1444 diskstream_menu->popup (ev->button, ev->time);
1446 diskstream_menu->popup (0, 0);
1449 selected_dstream = -1;
1453 delete diskstream_menu;
1455 return selected_dstream;
1459 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1465 if (io.n_inputs() == 0) {
1470 /* XXX we're not handling multiple ports yet. */
1472 const char **connections = io.input(0)->get_connections();
1474 if (connections == 0 || connections[0] == '\0') {
1477 buf = connections[0];
1484 if (io.n_outputs() == 0) {
1489 /* XXX we're not handling multiple ports yet. */
1491 const char **connections = io.output(0)->get_connections();
1493 if (connections == 0 || connections[0] == '\0') {
1496 buf = connections[0];
1504 ARDOUR_UI::snapshot_session ()
1506 ArdourPrompter prompter (true);
1513 now = now.substr (0, now.length() - 1);
1515 prompter.set_name ("Prompter");
1516 prompter.set_prompt (_("Name for snapshot"));
1517 prompter.set_initial_text (now);
1519 switch (prompter.run()) {
1520 case RESPONSE_ACCEPT:
1521 prompter.get_result (snapname);
1522 if (snapname.length()){
1523 save_state (snapname);
1533 ARDOUR_UI::save_state (const string & name)
1535 (void) save_state_canfail (name);
1539 ARDOUR_UI::save_state_canfail (string name)
1544 if (name.length() == 0) {
1545 name = session->snap_name();
1548 if ((ret = session->save_state (name)) != 0) {
1552 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1557 ARDOUR_UI::restore_state (string name)
1560 if (name.length() == 0) {
1561 name = session->name();
1563 session->restore_state (name);
1568 ARDOUR_UI::primary_clock_value_changed ()
1571 session->request_locate (primary_clock.current_time ());
1576 ARDOUR_UI::secondary_clock_value_changed ()
1579 session->request_locate (secondary_clock.current_time ());
1584 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1586 if (session && dstream && dstream->record_enabled()) {
1588 Session::RecordState rs;
1590 rs = session->record_status ();
1593 case Session::Disabled:
1594 case Session::Enabled:
1595 if (w->get_state() != STATE_SELECTED) {
1596 w->set_state (STATE_SELECTED);
1600 case Session::Recording:
1601 if (w->get_state() != STATE_ACTIVE) {
1602 w->set_state (STATE_ACTIVE);
1608 if (w->get_state() != STATE_NORMAL) {
1609 w->set_state (STATE_NORMAL);
1615 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1621 switch (session->record_status()) {
1622 case Session::Enabled:
1624 rec_button.set_state (1);
1626 rec_button.set_state (0);
1630 case Session::Recording:
1631 rec_button.set_state (2);
1635 rec_button.set_state (0);
1641 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1649 ARDOUR_UI::start_keyboard_prefix ()
1651 keyboard->start_prefix();
1655 ARDOUR_UI::save_template ()
1658 ArdourPrompter prompter (true);
1661 prompter.set_name (X_("Prompter"));
1662 prompter.set_prompt (_("Name for mix template:"));
1663 prompter.set_initial_text(session->name() + _("-template"));
1665 switch (prompter.run()) {
1666 case RESPONSE_ACCEPT:
1667 prompter.get_result (name);
1669 if (name.length()) {
1670 session->save_template (name);
1680 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1682 m_new_session_dialog->show_all();
1683 m_new_session_dialog->set_transient_for(*editor);
1684 m_new_session_dialog->set_name(predetermined_path);
1686 int response = Gtk::RESPONSE_CANCEL;
1689 response = m_new_session_dialog->run ();
1691 if(response == Gtk::RESPONSE_OK) {
1693 _session_is_new = true;
1695 std::string session_name = m_new_session_dialog->session_name();
1696 std::string session_path = m_new_session_dialog->session_folder();
1699 XXX This is needed because session constructor wants a
1700 non-existant path. hopefully this will be fixed at some point.
1702 session_path = Glib::build_filename(session_path, session_name);
1704 std::string template_name = m_new_session_dialog->session_template_name();
1706 if (m_new_session_dialog->use_session_template()) {
1708 load_session (session_path, session_name, &template_name);
1714 Session::AutoConnectOption iconnect;
1715 Session::AutoConnectOption oconnect;
1717 if (m_new_session_dialog->create_control_bus()) {
1718 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1723 if (m_new_session_dialog->create_master_bus()) {
1724 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1729 if (m_new_session_dialog->connect_inputs()) {
1730 iconnect = Session::AutoConnectPhysical;
1732 iconnect = Session::AutoConnectOption (0);
1735 /// @todo some minor tweaks.
1737 if (m_new_session_dialog->connect_outs_to_master()) {
1738 oconnect = Session::AutoConnectMaster;
1739 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1740 oconnect = Session::AutoConnectPhysical;
1742 oconnect = Session::AutoConnectOption (0);
1745 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1746 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1748 build_session (session_path,
1756 engine->frame_rate() * 60 * 5);
1760 } while(response == Gtk::RESPONSE_HELP);
1761 m_new_session_dialog->hide_all();
1765 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1767 Session *new_session;
1769 session_loaded = false;
1770 x = unload_session ();
1778 /* if it already exists, we must have write access */
1780 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1781 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
1782 You do not have write access to this session.\n\
1783 This prevents the session from being loaded."));
1788 new_session = new Session (*engine, path, snap_name, mix_template);
1793 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1797 connect_to_session (new_session);
1799 //if (engine->running()) {
1800 //mixer->show_window();
1802 session_loaded = true;
1807 ARDOUR_UI::make_session_clean ()
1810 session->set_clean ();
1817 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1818 uint32_t control_channels,
1819 uint32_t master_channels,
1820 Session::AutoConnectOption input_connect,
1821 Session::AutoConnectOption output_connect,
1824 jack_nframes_t initial_length)
1826 Session *new_session;
1829 session_loaded = false;
1830 x = unload_session ();
1837 _session_is_new = true;
1840 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1841 control_channels, master_channels, nphysin, nphysout, initial_length);
1846 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1850 connect_to_session (new_session);
1852 //if (engine->running()) {
1853 //mixer->show_window();
1855 session_loaded = true;
1863 editor->show_window ();
1867 if (session && mixer) {
1868 // mixer->show_window ();
1877 ARDOUR_UI::show_splash ()
1880 about = new About();
1886 ARDOUR_UI::hide_splash ()
1894 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1898 removed = rep.paths.size();
1901 ArdourMessage msg (editor, X_("cleanupresults"),
1903 No audio files were ready for cleanup\n\n\
1904 If this seems suprising, check for any existing\n\
1905 snapshots. These may still include regions that\n\
1906 require some unused files to continue to exist."));
1910 ArdourDialog results (_("ardour: cleanup"), true);
1912 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1913 CleanupResultsModelColumns() {
1917 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1918 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1922 Glib::RefPtr<Gtk::ListStore> results_model;
1923 CleanupResultsModelColumns results_columns;
1924 Gtk::TreeView results_display;
1926 results_model = ListStore::create (results_columns);
1927 results_display.set_model (results_model);
1928 results_display.append_column (list_title, results_columns.visible_name);
1929 results_display.set_headers_visible (true);
1931 Gtk::ScrolledWindow list_scroller;
1934 if (rep.space < 1048576.0f) {
1936 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1938 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1942 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1944 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1948 results.get_vbox()->pack_start (txt, false, false);
1950 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1951 TreeModel::Row row = *(results_model->append());
1952 row[results_columns.visible_name] = *i;
1953 row[results_columns.fullpath] = *i;
1956 list_scroller.add (results_display);
1957 list_scroller.set_size_request (-1, 250);
1958 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1960 results.get_vbox()->pack_start (list_scroller, true, true);
1961 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1962 results.set_position (Gtk::WIN_POS_MOUSE);
1968 ARDOUR_UI::cleanup ()
1971 /* shouldn't happen: menu item is insensitive */
1975 ArdourDialog checker (_("ardour cleanup"));
1976 Gtk::Label label (_("\
1977 Cleanup is a destructive operation.\n\
1978 ALL undo/redo information will be lost if you cleanup.\n\
1979 Unused audio files will be moved to a \"dead sounds\" location."));
1981 checker.get_vbox()->pack_start (label, false, false);
1982 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
1983 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1985 checker.set_name (_("CleanupDialog"));
1986 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1987 checker.set_position (Gtk::WIN_POS_MOUSE);
1989 switch (checker.run()) {
1990 case RESPONSE_ACCEPT:
1996 Session::cleanup_report rep;
1998 editor->prepare_for_cleanup ();
2000 if (session->cleanup_sources (rep)) {
2004 display_cleanup_results (rep,
2007 The following %1 %2 were not in use.\n\
2008 The next time you flush the wastebasket\n\
2009 it will release an additional %3 %4bytes\n\
2015 ARDOUR_UI::flush_trash ()
2018 /* shouldn't happen: menu item is insensitive */
2022 Session::cleanup_report rep;
2024 if (session->cleanup_trash_sources (rep)) {
2028 display_cleanup_results (rep,
2030 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2034 ARDOUR_UI::add_route ()
2042 if (add_route_dialog == 0) {
2043 add_route_dialog = new AddRouteDialog;
2044 editor->ensure_float (*add_route_dialog);
2047 if (add_route_dialog->is_visible()) {
2048 /* we're already doing this */
2052 ResponseType r = (ResponseType) add_route_dialog->run ();
2054 add_route_dialog->hide();
2057 case RESPONSE_ACCEPT:
2064 if ((count = add_route_dialog->count()) <= 0) {
2068 uint32_t input_chan = add_route_dialog->channels ();
2069 uint32_t output_chan;
2070 string name_template = add_route_dialog->name_template ();
2071 bool track = add_route_dialog->track ();
2073 Session::AutoConnectOption oac = session->get_output_auto_connect();
2075 if (oac & Session::AutoConnectMaster) {
2076 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2078 output_chan = input_chan;
2081 /* XXX do something with name template */
2085 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2087 session_add_audio_bus (input_chan, output_chan);
2091 while (Main::events_pending()) {
2098 ARDOUR_UI::mixer_settings () const
2103 node = session->instant_xml(X_("Mixer"), session->path());
2105 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2109 node = new XMLNode (X_("Mixer"));
2116 ARDOUR_UI::editor_settings () const
2121 node = session->instant_xml(X_("Editor"), session->path());
2123 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2127 node = new XMLNode (X_("Editor"));
2133 ARDOUR_UI::keyboard_settings () const
2137 node = Config->extra_xml(X_("Keyboard"));
2140 node = new XMLNode (X_("Keyboard"));
2146 ARDOUR_UI::halt_on_xrun_message ()
2148 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2150 ArdourMessage msg (editor, X_("haltonxrun"),
2151 _("Recording was stopped because your system could not keep up."));
2155 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2157 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2159 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2163 delete deletion_list;
2167 ARDOUR_UI::disk_overrun_handler ()
2169 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2171 if (!have_disk_overrun_displayed) {
2172 have_disk_overrun_displayed = true;
2173 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
2174 The disk system on your computer\n\
2175 was not able to keep up with Ardour.\n\
2177 Specifically, it failed to write data to disk\n\
2178 quickly enough to keep up with recording.\n"));
2179 have_disk_overrun_displayed = false;
2184 ARDOUR_UI::disk_underrun_handler ()
2186 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2188 if (!have_disk_underrun_displayed) {
2189 have_disk_underrun_displayed = true;
2190 ArdourMessage msg (editor, X_("diskrate2 dialog"),
2191 (_("The disk system on your computer\n\
2192 was not able to keep up with Ardour.\n\
2194 Specifically, it failed to read data from disk\n\
2195 quickly enough to keep up with playback.\n")));
2196 have_disk_underrun_displayed = false;
2201 ARDOUR_UI::disk_underrun_message_gone ()
2203 have_disk_underrun_displayed = false;
2207 ARDOUR_UI::disk_overrun_message_gone ()
2209 have_disk_underrun_displayed = false;
2213 ARDOUR_UI::pending_state_dialog ()
2215 ArdourDialog dialog ("pending state dialog");
2217 This session appears to have been in\n\
2218 middle of recording when ardour or\n\
2219 the computer was shutdown.\n\
2221 Ardour can recover any captured audio for\n\
2222 you, or it can ignore it. Please decide\n\
2223 what you would like to do.\n"));
2225 dialog.get_vbox()->pack_start (message);
2226 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2227 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2229 dialog.set_position (WIN_POS_CENTER);
2232 switch (dialog.run ()) {
2233 case RESPONSE_ACCEPT:
2244 ARDOUR_UI::disconnect_from_jack ()
2247 if( engine->disconnect_from_jack ()) {
2248 ArdourMessage msg (editor, X_("nojack dialog"),
2249 _("Could not disconnect from JACK"));
2252 update_sample_rate (0);
2257 ARDOUR_UI::reconnect_to_jack ()
2260 if (engine->reconnect_to_jack ()) {
2261 ArdourMessage msg (editor, X_("nojack dialog"),
2262 _("Could not reconnect to JACK"));
2265 update_sample_rate (0);
2270 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2272 engine->request_buffer_size (nframes);
2273 update_sample_rate (0);
2277 ARDOUR_UI::cmdline_new_session (string path)
2279 if (path[0] != '/') {
2280 char buf[PATH_MAX+1];
2283 getcwd (buf, sizeof (buf));
2290 new_session (false, path);
2292 _will_create_new_session_automatically = false; /* done it */
2293 return FALSE; /* don't call it again */