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"
78 using namespace ARDOUR;
79 using namespace Gtkmm2ext;
83 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
85 sigc::signal<void,bool> ARDOUR_UI::Blink;
86 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
87 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
88 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
90 static const char* channel_setup_names[] = {
101 vector<string> channel_combo_strings;
103 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
105 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
107 primary_clock (X_("TransportClockDisplay"), true, false, true),
108 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
109 preroll_clock (X_("PreRollClock"), true, true),
110 postroll_clock (X_("PostRollClock"), true, true),
114 adjuster_table (3, 3),
118 preroll_button (_("pre\nroll")),
119 postroll_button (_("post\nroll")),
123 big_clock ("BigClockDisplay", true),
127 time_master_button (_("time\nmaster")),
129 shuttle_units_button (_("% ")),
131 punch_in_button (_("punch\nin")),
132 punch_out_button (_("punch\nout")),
133 auto_return_button (_("auto\nreturn")),
134 auto_play_button (_("auto\nplay")),
135 auto_input_button (_("auto\ninput")),
136 click_button (_("click")),
137 auditioning_alert_button (_("AUDITIONING")),
138 solo_alert_button (_("SOLO")),
142 using namespace Gtk::Menu_Helpers;
146 /* actually, its already loaded, but ... */
148 cerr << "Loading UI configuration file " << rcfile << endl;
152 if (theArdourUI == 0) {
156 ActionManager::init ();
158 m_new_session_dialog = 0;
159 m_new_session_dialog_ref = NewSessionDialogFactory::create();
160 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
164 _session_is_new = false;
165 big_clock_window = 0;
166 session_selector_window = 0;
167 last_key_press_time = 0;
168 connection_editor = 0;
169 add_route_dialog = 0;
174 open_session_selector = 0;
175 have_configure_timeout = false;
176 have_disk_overrun_displayed = false;
177 have_disk_underrun_displayed = false;
178 _will_create_new_session_automatically = false;
179 session_loaded = false;
180 last_speed_displayed = -1.0f;
182 last_configure_time.tv_sec = 0;
183 last_configure_time.tv_usec = 0;
185 shuttle_grabbed = false;
188 set_shuttle_units (Percentage);
189 set_shuttle_behaviour (Sprung);
191 shuttle_style_menu = 0;
192 shuttle_unit_menu = 0;
194 gettimeofday (&last_peak_grab, 0);
195 gettimeofday (&last_shuttle_request, 0);
197 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
198 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
199 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
200 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
202 /* handle pending state with a dialog */
204 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
206 channel_combo_strings = internationalize (channel_setup_names);
208 /* have to wait for AudioEngine and Configuration before proceeding */
212 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
214 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
216 string msg = string_compose (_("\
217 You cannot record-enable\n\
219 because it has no input connections.\n\
220 You would be wasting space recording silence."),
223 ArdourMessage message (editor, X_("cannotrecord"), msg);
227 ARDOUR_UI::set_engine (AudioEngine& e)
231 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
232 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
233 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
234 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
238 keyboard = new Keyboard;
239 install_keybindings ();
241 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
242 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
244 if (setup_windows ()) {
245 throw failed_constructor ();
248 if (GTK_ARDOUR::show_key_actions) {
249 vector<string> names;
250 vector<string> paths;
252 vector<AccelKey> bindings;
254 ActionManager::get_all_actions (names, paths, keys, bindings);
256 vector<string>::iterator n;
257 vector<string>::iterator k;
258 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
259 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
265 /* start with timecode, metering enabled
268 blink_timeout_tag = -1;
270 /* this being a GUI and all, we want peakfiles */
272 FileSource::set_build_peakfiles (true);
273 FileSource::set_build_missing_peakfiles (true);
275 if (Source::start_peak_thread ()) {
276 throw failed_constructor();
279 /* start the time-of-day-clock */
281 update_wall_clock ();
282 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
284 update_disk_space ();
286 update_sample_rate (engine->frame_rate());
288 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
289 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
292 ARDOUR_UI::~ARDOUR_UI ()
294 save_ardour_state ();
308 if (add_route_dialog) {
309 delete add_route_dialog;
312 Source::stop_peak_thread ();
316 ARDOUR_UI::configure_timeout ()
321 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
322 /* no configure events yet */
326 gettimeofday (&now, 0);
327 timersub (&now, &last_configure_time, &diff);
329 /* force a gap of 0.5 seconds since the last configure event
332 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
335 have_configure_timeout = false;
336 save_ardour_state ();
342 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
344 if (have_configure_timeout) {
345 gettimeofday (&last_configure_time, 0);
347 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
348 have_configure_timeout = true;
355 ARDOUR_UI::save_ardour_state ()
357 if (!keyboard || !mixer || !editor) {
361 /* XXX this is all a bit dubious. add_extra_xml() uses
362 a different lifetime model from add_instant_xml().
365 XMLNode* node = new XMLNode (keyboard->get_state());
366 Config->add_extra_xml (*node);
367 Config->save_state();
369 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
370 XMLNode& mnode (mixer->get_state());
373 session->add_instant_xml(enode, session->path());
374 session->add_instant_xml(mnode, session->path());
376 Config->add_instant_xml(enode, Config->get_user_ardour_path());
377 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
382 ARDOUR_UI::startup ()
384 /* Once the UI is up and running, start the audio engine. Doing
385 this before the UI is up and running can cause problems
386 when not running with SCHED_FIFO, because the amount of
387 CPU and disk work needed to get the UI started can interfere
388 with the scheduling of the audio thread.
391 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
397 if (session && session->dirty()) {
398 switch (ask_about_saving_session(_("quit"))) {
403 /* use the default name */
404 if (save_state_canfail ("")) {
405 /* failed - don't quit */
406 ArdourMessage (editor, X_("badsave dialog"),
408 Ardour was unable to save your session.\n\n\
409 If you still wish to quit, please use the\n\n\
410 \"Just quit\" option."));
423 ARDOUR_UI::ask_about_saving_session (const string & what)
425 ArdourDialog window (_("ardour: save session?"));
426 Gtk::Label prompt_label;
429 msg = string_compose(_("Save and %1"), what);
430 window.add_button (msg, RESPONSE_ACCEPT);
431 msg = string_compose(_("Just %1"), what);
432 window.add_button (msg, RESPONSE_APPLY);
433 msg = string_compose(_("Don't %1"), what);
434 window.add_button (msg, RESPONSE_REJECT);
436 Gtk::Button noquit_button (msg);
437 noquit_button.set_name ("EditorGTKButton");
442 if (session->snap_name() == session->name()) {
445 type = _("snapshot");
447 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?"),
448 type, session->snap_name());
450 prompt_label.set_text (prompt);
451 prompt_label.set_alignment (0.5, 0.5);
452 prompt_label.set_name (X_("PrompterLabel"));
454 window.get_vbox()->pack_start (prompt_label);
456 window.set_name (_("Prompter"));
457 window.set_position (Gtk::WIN_POS_MOUSE);
458 window.set_modal (true);
461 save_the_session = 0;
463 editor->ensure_float (window);
465 ResponseType r = (ResponseType) window.run();
470 case RESPONSE_ACCEPT: // save and get out of here
472 case RESPONSE_APPLY: // get out of here
482 ARDOUR_UI::every_second ()
485 update_buffer_load ();
486 update_disk_space ();
487 // update_disk_rate ();
492 ARDOUR_UI::every_point_one_seconds ()
497 /* do not attempt to grab peak power more than once per cycle.
500 gettimeofday (&now, 0);
501 timersub (&now, &last_peak_grab, &diff);
503 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
504 IO::GrabPeakPower(); /* EMIT_SIGNAL */
505 last_peak_grab = now;
508 update_speed_display ();
509 RapidScreenUpdate(); /* EMIT_SIGNAL */
514 ARDOUR_UI::every_point_zero_one_seconds ()
516 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
521 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
525 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
527 if (!engine->connected()) {
529 snprintf (buf, sizeof (buf), _("disconnected"));
533 jack_nframes_t rate = engine->frame_rate();
535 if (fmod (rate, 1000.0) != 0.0) {
536 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
537 (float) rate/1000.0f,
538 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
540 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
542 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
546 sample_rate_label.set_text (buf);
550 ARDOUR_UI::update_cpu_load ()
553 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
554 cpu_load_label.set_text (buf);
558 ARDOUR_UI::update_disk_rate ()
563 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
564 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
565 disk_rate_label.set_text (buf);
567 disk_rate_label.set_text ("");
572 ARDOUR_UI::update_buffer_load ()
577 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
578 session->playback_load(), session->capture_load());
579 buffer_load_label.set_text (buf);
581 buffer_load_label.set_text ("");
586 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
588 if (ds.record_enabled()) {
589 rec_enabled_diskstreams++;
594 ARDOUR_UI::update_disk_space()
600 jack_nframes_t frames = session->available_capture_duration();
603 if (frames == max_frames) {
604 strcpy (buf, _("space: 24hrs+"));
609 jack_nframes_t fr = session->frame_rate();
611 if (session->actively_recording()){
613 rec_enabled_diskstreams = 0;
614 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
616 if (rec_enabled_diskstreams) {
617 frames /= rec_enabled_diskstreams;
622 /* hmmm. shall we divide by the route count? or the diskstream count?
623 or what? for now, do nothing ...
628 hrs = frames / (fr * 3600);
629 frames -= hrs * fr * 3600;
630 mins = frames / (fr * 60);
631 frames -= mins * fr * 60;
634 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
637 disk_space_label.set_text (buf);
641 ARDOUR_UI::update_wall_clock ()
648 tm_now = localtime (&now);
650 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
651 wall_clock_label.set_text (buf);
656 ARDOUR_UI::control_methods_adjusted ()
661 which_method = (int) online_control_button->adjustment.get_value();
662 switch (which_method) {
664 allow_mmc_and_local ();
673 fatal << _("programming error: impossible control method") << endmsg;
679 ARDOUR_UI::mmc_device_id_adjusted ()
684 int dev_id = (int) mmc_id_button->adjustment.get_value();
685 mmc->set_device_id (dev_id);
691 ARDOUR_UI::session_menu (GdkEventButton *ev)
693 session_popup_menu->popup (0, 0);
698 ARDOUR_UI::redisplay_recent_sessions ()
700 vector<string *> *sessions;
701 vector<string *>::iterator i;
702 RecentSessionsSorter cmp;
704 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
705 recent_session_model->clear ();
708 ARDOUR::read_recent_sessions (rs);
711 recent_session_display.set_model (recent_session_model);
715 /* sort them alphabetically */
716 sort (rs.begin(), rs.end(), cmp);
717 sessions = new vector<string*>;
719 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
720 sessions->push_back (new string ((*i).second));
723 for (i = sessions->begin(); i != sessions->end(); ++i) {
725 vector<string*>* states;
726 vector<const gchar*> item;
727 string fullpath = *(*i);
729 /* remove any trailing / */
731 if (fullpath[fullpath.length()-1] == '/') {
732 fullpath = fullpath.substr (0, fullpath.length()-1);
735 /* now get available states for this session */
737 if ((states = Session::possible_states (fullpath)) == 0) {
742 TreeModel::Row row = *(recent_session_model->append());
744 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
745 row[recent_session_columns.fullpath] = fullpath;
747 if (states->size() > 1) {
749 /* add the children */
751 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
753 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
755 child_row[recent_session_columns.visible_name] = **i2;
756 child_row[recent_session_columns.fullpath] = fullpath;
765 recent_session_display.set_model (recent_session_model);
770 ARDOUR_UI::build_session_selector ()
772 session_selector_window = new ArdourDialog ("session selector");
774 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
776 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
777 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
779 recent_session_model = TreeStore::create (recent_session_columns);
780 recent_session_display.set_model (recent_session_model);
781 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
782 recent_session_display.set_headers_visible (false);
784 scroller->add (recent_session_display);
785 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
787 session_selector_window->set_name ("SessionSelectorWindow");
788 session_selector_window->set_size_request (200, 400);
789 session_selector_window->get_vbox()->pack_start (*scroller);
790 session_selector_window->show_all_children();
794 ARDOUR_UI::open_recent_session ()
796 /* popup selector window */
798 if (session_selector_window == 0) {
799 build_session_selector ();
802 redisplay_recent_sessions ();
804 ResponseType r = (ResponseType) session_selector_window->run ();
806 session_selector_window->hide();
809 case RESPONSE_ACCEPT:
815 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
817 if (i == recent_session_model->children().end()) {
821 Glib::ustring path = (*i)[recent_session_columns.fullpath];
822 Glib::ustring state = (*i)[recent_session_columns.visible_name];
824 _session_is_new = false;
826 load_session (path, state);
830 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
834 if (stat (info.filename.c_str(), &statbuf) != 0) {
838 if (!S_ISDIR(statbuf.st_mode)) {
842 string session_file = info.filename;
844 session_file += PBD::basename (info.filename);
845 session_file += ".ardour";
847 if (stat (session_file.c_str(), &statbuf) != 0) {
851 return S_ISREG (statbuf.st_mode);
855 ARDOUR_UI::open_session ()
857 /* popup selector window */
859 if (open_session_selector == 0) {
861 /* ardour sessions are folders */
863 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
864 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
865 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
867 FileFilter session_filter;
868 session_filter.add_pattern ("*.ardour");
869 session_filter.set_name (_("Ardour sessions"));
870 open_session_selector->add_filter (session_filter);
871 open_session_selector->set_filter (session_filter);
874 int response = open_session_selector->run();
875 open_session_selector->hide ();
878 case RESPONSE_ACCEPT:
881 open_session_selector->hide();
885 open_session_selector->hide();
886 string session_path = open_session_selector->get_filename();
890 if (session_path.length() > 0) {
891 if (Session::find_session (session_path, path, name, isnew) == 0) {
892 _session_is_new = isnew;
893 load_session (path, name);
900 ARDOUR_UI::session_add_midi_track ()
902 cerr << _("Patience is a virtue.\n");
906 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
911 warning << _("You cannot add a track without a session already loaded.") << endmsg;
917 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
918 error << _("could not create new audio track") << endmsg;
921 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
922 error << _("could not create new audio bus") << endmsg;
927 if (need_control_room_outs) {
933 route->set_stereo_control_outs (control_lr_channels);
934 route->control_outs()->set_stereo_pan (pans, this);
936 #endif /* CONTROLOUTS */
940 ArdourMessage msg (editor, X_("noport dialog"),
941 _("There are insufficient JACK ports available\n\
942 to create a new track or bus.\n\
943 You should save Ardour, exit and\n\
944 restart JACK with more ports."));
949 ARDOUR_UI::diskstream_added (DiskStream* ds)
954 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
956 jack_nframes_t _preroll;
959 _preroll = session->convert_to_frames_at (new_position, session->preroll);
961 if (new_position > _preroll) {
962 new_position -= _preroll;
967 session->request_locate (new_position);
972 ARDOUR_UI::transport_goto_start ()
975 session->request_locate (0);
978 /* force displayed area in editor to start no matter
979 what "follow playhead" setting is.
983 editor->reposition_x_origin (0);
989 ARDOUR_UI::transport_goto_end ()
992 jack_nframes_t frame = session->current_end_frame();
993 session->request_locate (frame);
995 /* force displayed area in editor to start no matter
996 what "follow playhead" setting is.
1000 editor->reposition_x_origin (frame);
1006 ARDOUR_UI::transport_stop ()
1012 if (session->is_auditioning()) {
1013 session->cancel_audition ();
1017 if (session->get_auto_loop()) {
1018 session->request_auto_loop (false);
1021 session->request_stop ();
1025 ARDOUR_UI::transport_stop_and_forget_capture ()
1028 session->request_stop (true);
1033 ARDOUR_UI::remove_last_capture()
1036 editor->remove_last_capture();
1041 ARDOUR_UI::transport_record ()
1044 switch (session->record_status()) {
1045 case Session::Disabled:
1046 if (session->ntracks() == 0) {
1047 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1048 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1051 session->maybe_enable_record ();
1053 case Session::Recording:
1054 case Session::Enabled:
1055 session->disable_record ();
1061 ARDOUR_UI::transport_roll ()
1069 rolling = session->transport_rolling ();
1071 if (session->get_auto_loop()) {
1072 session->request_auto_loop (false);
1073 auto_loop_button.set_active (false);
1074 roll_button.set_active (true);
1075 } else if (session->get_play_range ()) {
1076 session->request_play_range (false);
1077 play_selection_button.set_active (false);
1078 } else if (rolling) {
1079 session->request_locate (session->last_transport_start(), true);
1082 session->request_transport_speed (1.0f);
1086 ARDOUR_UI::transport_loop()
1089 if (session->get_auto_loop()) {
1090 if (session->transport_rolling()) {
1091 Location * looploc = session->locations()->auto_loop_location();
1093 session->request_locate (looploc->start(), true);
1098 session->request_auto_loop (true);
1104 ARDOUR_UI::transport_play_selection ()
1110 if (!session->get_play_range()) {
1111 session->request_stop ();
1114 editor->play_selection ();
1118 ARDOUR_UI::transport_rewind (int option)
1120 float current_transport_speed;
1123 current_transport_speed = session->transport_speed();
1125 if (current_transport_speed >= 0.0f) {
1128 session->request_transport_speed (-1.0f);
1131 session->request_transport_speed (-4.0f);
1134 session->request_transport_speed (-0.5f);
1139 session->request_transport_speed (current_transport_speed * 1.5f);
1145 ARDOUR_UI::transport_forward (int option)
1147 float current_transport_speed;
1150 current_transport_speed = session->transport_speed();
1152 if (current_transport_speed <= 0.0f) {
1155 session->request_transport_speed (1.0f);
1158 session->request_transport_speed (4.0f);
1161 session->request_transport_speed (0.5f);
1166 session->request_transport_speed (current_transport_speed * 1.5f);
1172 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1180 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1181 Port *port = ds->io()->input (0);
1182 port->request_monitor_input (!port->monitoring_input());
1187 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1195 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1196 ds->set_record_enabled (!ds->record_enabled(), this);
1201 ARDOUR_UI::queue_transport_change ()
1203 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1207 ARDOUR_UI::map_transport_state ()
1209 float sp = session->transport_speed();
1212 transport_rolling ();
1213 } else if (sp < 0.0f) {
1214 transport_rewinding ();
1215 } else if (sp > 0.0f) {
1216 transport_forwarding ();
1218 transport_stopped ();
1223 ARDOUR_UI::send_all_midi_feedback ()
1226 session->send_all_midi_feedback();
1231 ARDOUR_UI::allow_local_only ()
1237 ARDOUR_UI::allow_mmc_only ()
1243 ARDOUR_UI::allow_mmc_and_local ()
1249 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1251 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1252 (int) adj.get_value()].c_str());
1256 ARDOUR_UI::engine_stopped ()
1258 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1259 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1260 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1265 ARDOUR_UI::engine_running ()
1267 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1268 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1269 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1273 ARDOUR_UI::engine_halted ()
1275 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1277 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1278 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1280 update_sample_rate (0);
1282 ArdourMessage msg (editor, X_("halted"),
1284 JACK has either been shutdown or it\n\
1285 disconnected Ardour because Ardour\n\
1286 was not fast enough. You can save the\n\
1287 session and/or try to reconnect to JACK ."));
1291 ARDOUR_UI::do_engine_start ()
1297 catch (AudioEngine::PortRegistrationFailure& err) {
1299 error << _("Unable to create all required ports")
1307 error << _("Unable to start the session running")
1317 ARDOUR_UI::start_engine ()
1319 if (do_engine_start () == 0) {
1320 if (session && _session_is_new) {
1321 /* we need to retain initial visual
1322 settings for a new session
1324 session->save_state ("");
1327 /* there is too much going on, in too many threads, for us to
1328 end up with a clean session. So wait 1 second after loading,
1329 and fix it up. its ugly, but until i come across a better
1330 solution, its what we have.
1333 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1340 ARDOUR_UI::update_clocks ()
1342 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1346 ARDOUR_UI::start_clocking ()
1348 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1352 ARDOUR_UI::stop_clocking ()
1354 clock_signal_connection.disconnect ();
1358 ARDOUR_UI::toggle_clocking ()
1361 if (clock_button.get_active()) {
1370 ARDOUR_UI::_blink (void *arg)
1373 ((ARDOUR_UI *) arg)->blink ();
1380 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1384 ARDOUR_UI::start_blinking ()
1386 /* Start the blink signal. Everybody with a blinking widget
1387 uses Blink to drive the widget's state.
1390 if (blink_timeout_tag < 0) {
1392 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1397 ARDOUR_UI::stop_blinking ()
1399 if (blink_timeout_tag >= 0) {
1400 gtk_timeout_remove (blink_timeout_tag);
1401 blink_timeout_tag = -1;
1407 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1409 using namespace Gtk;
1410 using namespace Menu_Helpers;
1412 if (dstream.hidden()) {
1416 MenuList& items = diskstream_menu->items();
1417 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1421 ARDOUR_UI::diskstream_selected (gint32 id)
1423 selected_dstream = id;
1428 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1430 using namespace Gtk;
1431 using namespace Menu_Helpers;
1437 diskstream_menu = new Menu();
1438 diskstream_menu->set_name ("ArdourContextMenu");
1439 using namespace Gtk;
1440 using namespace Menu_Helpers;
1442 MenuList& items = diskstream_menu->items();
1443 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1445 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1448 diskstream_menu->popup (ev->button, ev->time);
1450 diskstream_menu->popup (0, 0);
1453 selected_dstream = -1;
1457 delete diskstream_menu;
1459 return selected_dstream;
1463 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1469 if (io.n_inputs() == 0) {
1474 /* XXX we're not handling multiple ports yet. */
1476 const char **connections = io.input(0)->get_connections();
1478 if (connections == 0 || connections[0] == '\0') {
1481 buf = connections[0];
1488 if (io.n_outputs() == 0) {
1493 /* XXX we're not handling multiple ports yet. */
1495 const char **connections = io.output(0)->get_connections();
1497 if (connections == 0 || connections[0] == '\0') {
1500 buf = connections[0];
1508 ARDOUR_UI::snapshot_session ()
1510 ArdourPrompter prompter (true);
1517 now = now.substr (0, now.length() - 1);
1519 prompter.set_name ("Prompter");
1520 prompter.set_prompt (_("Name for snapshot"));
1521 prompter.set_initial_text (now);
1523 switch (prompter.run()) {
1524 case RESPONSE_ACCEPT:
1525 prompter.get_result (snapname);
1526 if (snapname.length()){
1527 save_state (snapname);
1537 ARDOUR_UI::save_state (const string & name)
1539 (void) save_state_canfail (name);
1543 ARDOUR_UI::save_state_canfail (string name)
1548 if (name.length() == 0) {
1549 name = session->snap_name();
1552 if ((ret = session->save_state (name)) != 0) {
1556 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1561 ARDOUR_UI::restore_state (string name)
1564 if (name.length() == 0) {
1565 name = session->name();
1567 session->restore_state (name);
1572 ARDOUR_UI::primary_clock_value_changed ()
1575 session->request_locate (primary_clock.current_time ());
1580 ARDOUR_UI::secondary_clock_value_changed ()
1583 session->request_locate (secondary_clock.current_time ());
1588 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1590 if (session && dstream && dstream->record_enabled()) {
1592 Session::RecordState rs;
1594 rs = session->record_status ();
1597 case Session::Disabled:
1598 case Session::Enabled:
1599 if (w->get_state() != STATE_SELECTED) {
1600 w->set_state (STATE_SELECTED);
1604 case Session::Recording:
1605 if (w->get_state() != STATE_ACTIVE) {
1606 w->set_state (STATE_ACTIVE);
1612 if (w->get_state() != STATE_NORMAL) {
1613 w->set_state (STATE_NORMAL);
1619 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1625 switch (session->record_status()) {
1626 case Session::Enabled:
1628 rec_button.set_state (1);
1630 rec_button.set_state (0);
1634 case Session::Recording:
1635 rec_button.set_state (2);
1639 rec_button.set_state (0);
1645 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1653 ARDOUR_UI::start_keyboard_prefix ()
1655 keyboard->start_prefix();
1659 ARDOUR_UI::save_template ()
1662 ArdourPrompter prompter (true);
1665 prompter.set_name (X_("Prompter"));
1666 prompter.set_prompt (_("Name for mix template:"));
1667 prompter.set_initial_text(session->name() + _("-template"));
1669 switch (prompter.run()) {
1670 case RESPONSE_ACCEPT:
1671 prompter.get_result (name);
1673 if (name.length()) {
1674 session->save_template (name);
1684 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1686 m_new_session_dialog->show_all();
1687 m_new_session_dialog->set_transient_for(*editor);
1688 m_new_session_dialog->set_name(predetermined_path);
1690 int response = Gtk::RESPONSE_CANCEL;
1693 response = m_new_session_dialog->run ();
1695 if(response == Gtk::RESPONSE_OK) {
1697 _session_is_new = true;
1699 std::string session_name = m_new_session_dialog->session_name();
1700 std::string session_path = m_new_session_dialog->session_folder();
1703 XXX This is needed because session constructor wants a
1704 non-existant path. hopefully this will be fixed at some point.
1706 session_path = Glib::build_filename(session_path, session_name);
1708 std::string template_name = m_new_session_dialog->session_template_name();
1710 if (m_new_session_dialog->use_session_template()) {
1712 load_session (session_path, session_name, &template_name);
1718 Session::AutoConnectOption iconnect;
1719 Session::AutoConnectOption oconnect;
1721 if (m_new_session_dialog->create_control_bus()) {
1722 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1727 if (m_new_session_dialog->create_master_bus()) {
1728 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1733 if (m_new_session_dialog->connect_inputs()) {
1734 iconnect = Session::AutoConnectPhysical;
1736 iconnect = Session::AutoConnectOption (0);
1739 /// @todo some minor tweaks.
1741 if (m_new_session_dialog->connect_outs_to_master()) {
1742 oconnect = Session::AutoConnectMaster;
1743 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1744 oconnect = Session::AutoConnectPhysical;
1746 oconnect = Session::AutoConnectOption (0);
1749 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1750 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1752 build_session (session_path,
1760 engine->frame_rate() * 60 * 5);
1764 } while(response == Gtk::RESPONSE_HELP);
1765 m_new_session_dialog->hide_all();
1769 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1771 Session *new_session;
1773 session_loaded = false;
1774 x = unload_session ();
1782 /* if it already exists, we must have write access */
1784 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1785 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
1786 You do not have write access to this session.\n\
1787 This prevents the session from being loaded."));
1792 new_session = new Session (*engine, path, snap_name, mix_template);
1797 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1801 connect_to_session (new_session);
1803 //if (engine->running()) {
1804 //mixer->show_window();
1806 session_loaded = true;
1811 ARDOUR_UI::make_session_clean ()
1814 session->set_clean ();
1821 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1822 uint32_t control_channels,
1823 uint32_t master_channels,
1824 Session::AutoConnectOption input_connect,
1825 Session::AutoConnectOption output_connect,
1828 jack_nframes_t initial_length)
1830 Session *new_session;
1833 session_loaded = false;
1834 x = unload_session ();
1841 _session_is_new = true;
1844 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1845 control_channels, master_channels, nphysin, nphysout, initial_length);
1850 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1854 connect_to_session (new_session);
1856 //if (engine->running()) {
1857 //mixer->show_window();
1859 session_loaded = true;
1867 editor->show_window ();
1871 if (session && mixer) {
1872 // mixer->show_window ();
1881 ARDOUR_UI::show_splash ()
1884 about = new About();
1890 ARDOUR_UI::hide_splash ()
1898 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1902 removed = rep.paths.size();
1905 ArdourMessage msg (editor, X_("cleanupresults"),
1907 No audio files were ready for cleanup\n\n\
1908 If this seems suprising, check for any existing\n\
1909 snapshots. These may still include regions that\n\
1910 require some unused files to continue to exist."));
1914 ArdourDialog results (_("ardour: cleanup"), true);
1916 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1917 CleanupResultsModelColumns() {
1921 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1922 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1926 Glib::RefPtr<Gtk::ListStore> results_model;
1927 CleanupResultsModelColumns results_columns;
1928 Gtk::TreeView results_display;
1930 results_model = ListStore::create (results_columns);
1931 results_display.set_model (results_model);
1932 results_display.append_column (list_title, results_columns.visible_name);
1933 results_display.set_headers_visible (true);
1935 Gtk::ScrolledWindow list_scroller;
1938 if (rep.space < 1048576.0f) {
1940 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1942 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1946 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1948 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1952 results.get_vbox()->pack_start (txt, false, false);
1954 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1955 TreeModel::Row row = *(results_model->append());
1956 row[results_columns.visible_name] = *i;
1957 row[results_columns.fullpath] = *i;
1960 list_scroller.add (results_display);
1961 list_scroller.set_size_request (-1, 250);
1962 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1964 results.get_vbox()->pack_start (list_scroller, true, true);
1965 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1966 results.set_position (Gtk::WIN_POS_MOUSE);
1972 ARDOUR_UI::cleanup ()
1975 /* shouldn't happen: menu item is insensitive */
1979 ArdourDialog checker (_("ardour cleanup"));
1980 Gtk::Label label (_("\
1981 Cleanup is a destructive operation.\n\
1982 ALL undo/redo information will be lost if you cleanup.\n\
1983 Unused audio files will be moved to a \"dead sounds\" location."));
1985 checker.get_vbox()->pack_start (label, false, false);
1986 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
1987 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1989 checker.set_name (_("CleanupDialog"));
1990 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1991 checker.set_position (Gtk::WIN_POS_MOUSE);
1993 switch (checker.run()) {
1994 case RESPONSE_ACCEPT:
2000 Session::cleanup_report rep;
2002 editor->prepare_for_cleanup ();
2004 if (session->cleanup_sources (rep)) {
2008 display_cleanup_results (rep,
2011 The following %1 %2 were not in use.\n\
2012 The next time you flush the wastebasket\n\
2013 it will release an additional %3 %4bytes\n\
2019 ARDOUR_UI::flush_trash ()
2022 /* shouldn't happen: menu item is insensitive */
2026 Session::cleanup_report rep;
2028 if (session->cleanup_trash_sources (rep)) {
2032 display_cleanup_results (rep,
2034 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2038 ARDOUR_UI::add_route ()
2046 if (add_route_dialog == 0) {
2047 add_route_dialog = new AddRouteDialog;
2048 editor->ensure_float (*add_route_dialog);
2051 if (add_route_dialog->is_visible()) {
2052 /* we're already doing this */
2056 ResponseType r = (ResponseType) add_route_dialog->run ();
2058 add_route_dialog->hide();
2061 case RESPONSE_ACCEPT:
2068 if ((count = add_route_dialog->count()) <= 0) {
2072 uint32_t input_chan = add_route_dialog->channels ();
2073 uint32_t output_chan;
2074 string name_template = add_route_dialog->name_template ();
2075 bool track = add_route_dialog->track ();
2077 Session::AutoConnectOption oac = session->get_output_auto_connect();
2079 if (oac & Session::AutoConnectMaster) {
2080 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2082 output_chan = input_chan;
2085 /* XXX do something with name template */
2089 session_add_audio_track (input_chan, output_chan);
2091 session_add_audio_bus (input_chan, output_chan);
2095 while (Main::events_pending()) {
2102 ARDOUR_UI::mixer_settings () const
2107 node = session->instant_xml(X_("Mixer"), session->path());
2109 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2113 node = new XMLNode (X_("Mixer"));
2120 ARDOUR_UI::editor_settings () const
2125 node = session->instant_xml(X_("Editor"), session->path());
2127 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2131 node = new XMLNode (X_("Editor"));
2137 ARDOUR_UI::keyboard_settings () const
2141 node = Config->extra_xml(X_("Keyboard"));
2144 node = new XMLNode (X_("Keyboard"));
2150 ARDOUR_UI::halt_on_xrun_message ()
2152 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2154 ArdourMessage msg (editor, X_("haltonxrun"),
2155 _("Recording was stopped because your system could not keep up."));
2159 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2161 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2163 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2167 delete deletion_list;
2171 ARDOUR_UI::disk_overrun_handler ()
2173 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2175 if (!have_disk_overrun_displayed) {
2176 have_disk_overrun_displayed = true;
2177 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
2178 The disk system on your computer\n\
2179 was not able to keep up with Ardour.\n\
2181 Specifically, it failed to write data to disk\n\
2182 quickly enough to keep up with recording.\n"));
2183 have_disk_overrun_displayed = false;
2188 ARDOUR_UI::disk_underrun_handler ()
2190 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2192 if (!have_disk_underrun_displayed) {
2193 have_disk_underrun_displayed = true;
2194 ArdourMessage msg (editor, X_("diskrate2 dialog"),
2195 (_("The disk system on your computer\n\
2196 was not able to keep up with Ardour.\n\
2198 Specifically, it failed to read data from disk\n\
2199 quickly enough to keep up with playback.\n")));
2200 have_disk_underrun_displayed = false;
2205 ARDOUR_UI::disk_underrun_message_gone ()
2207 have_disk_underrun_displayed = false;
2211 ARDOUR_UI::disk_overrun_message_gone ()
2213 have_disk_underrun_displayed = false;
2217 ARDOUR_UI::pending_state_dialog ()
2219 ArdourDialog dialog ("pending state dialog");
2221 This session appears to have been in\n\
2222 middle of recording when ardour or\n\
2223 the computer was shutdown.\n\
2225 Ardour can recover any captured audio for\n\
2226 you, or it can ignore it. Please decide\n\
2227 what you would like to do.\n"));
2229 dialog.get_vbox()->pack_start (message);
2230 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2231 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2233 dialog.set_position (WIN_POS_CENTER);
2236 switch (dialog.run ()) {
2237 case RESPONSE_ACCEPT:
2248 ARDOUR_UI::disconnect_from_jack ()
2251 if( engine->disconnect_from_jack ()) {
2252 ArdourMessage msg (editor, X_("nojack dialog"),
2253 _("Could not disconnect from JACK"));
2256 update_sample_rate (0);
2261 ARDOUR_UI::reconnect_to_jack ()
2264 if (engine->reconnect_to_jack ()) {
2265 ArdourMessage msg (editor, X_("nojack dialog"),
2266 _("Could not reconnect to JACK"));
2269 update_sample_rate (0);
2274 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2276 engine->request_buffer_size (nframes);
2277 update_sample_rate (0);
2281 ARDOUR_UI::cmdline_new_session (string path)
2283 if (path[0] != '/') {
2284 char buf[PATH_MAX+1];
2287 getcwd (buf, sizeof (buf));
2294 new_session (false, path);
2296 _will_create_new_session_automatically = false; /* done it */
2297 return FALSE; /* don't call it again */