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 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
92 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
94 primary_clock (X_("TransportClockDisplay"), true, false, true),
95 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
96 preroll_clock (X_("PreRollClock"), true, true),
97 postroll_clock (X_("PostRollClock"), true, true),
101 adjuster_table (3, 3),
105 preroll_button (_("pre\nroll")),
106 postroll_button (_("post\nroll")),
110 big_clock ("BigClockDisplay", true),
114 time_master_button (_("time\nmaster")),
116 shuttle_units_button (_("% ")),
118 punch_in_button (_("punch\nin")),
119 punch_out_button (_("punch\nout")),
120 auto_return_button (_("auto\nreturn")),
121 auto_play_button (_("auto\nplay")),
122 auto_input_button (_("auto\ninput")),
123 click_button (_("click")),
124 auditioning_alert_button (_("AUDITIONING")),
125 solo_alert_button (_("SOLO")),
129 using namespace Gtk::Menu_Helpers;
133 /* actually, its already loaded, but ... */
135 cerr << "Loading UI configuration file " << rcfile << endl;
139 if (theArdourUI == 0) {
143 ActionManager::init ();
145 m_new_session_dialog = 0;
146 m_new_session_dialog_ref = NewSessionDialogFactory::create();
147 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
151 _session_is_new = false;
152 big_clock_window = 0;
153 session_selector_window = 0;
154 last_key_press_time = 0;
155 connection_editor = 0;
156 add_route_dialog = 0;
161 open_session_selector = 0;
162 have_configure_timeout = false;
163 have_disk_overrun_displayed = false;
164 have_disk_underrun_displayed = false;
165 _will_create_new_session_automatically = false;
166 session_loaded = false;
167 last_speed_displayed = -1.0f;
169 last_configure_time.tv_sec = 0;
170 last_configure_time.tv_usec = 0;
172 shuttle_grabbed = false;
175 set_shuttle_units (Percentage);
176 set_shuttle_behaviour (Sprung);
178 shuttle_style_menu = 0;
179 shuttle_unit_menu = 0;
181 gettimeofday (&last_peak_grab, 0);
182 gettimeofday (&last_shuttle_request, 0);
184 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
185 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
186 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
187 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
189 /* handle pending state with a dialog */
191 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
193 /* have to wait for AudioEngine and Configuration before proceeding */
197 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
199 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
201 string msg = string_compose (_("\
202 You cannot record-enable\n\
204 because it has no input connections.\n\
205 You would be wasting space recording silence."),
208 ArdourMessage message (editor, X_("cannotrecord"), msg);
212 ARDOUR_UI::set_engine (AudioEngine& e)
216 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
217 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
218 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
219 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
223 keyboard = new Keyboard;
224 install_keybindings ();
226 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
227 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
229 if (setup_windows ()) {
230 throw failed_constructor ();
233 if (GTK_ARDOUR::show_key_actions) {
234 vector<string> names;
235 vector<string> paths;
237 vector<AccelKey> bindings;
239 ActionManager::get_all_actions (names, paths, keys, bindings);
241 vector<string>::iterator n;
242 vector<string>::iterator k;
243 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
244 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
250 /* start with timecode, metering enabled
253 blink_timeout_tag = -1;
255 /* this being a GUI and all, we want peakfiles */
257 FileSource::set_build_peakfiles (true);
258 FileSource::set_build_missing_peakfiles (true);
260 if (Source::start_peak_thread ()) {
261 throw failed_constructor();
264 /* start the time-of-day-clock */
266 update_wall_clock ();
267 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
269 update_disk_space ();
271 update_sample_rate (engine->frame_rate());
273 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
274 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
277 ARDOUR_UI::~ARDOUR_UI ()
279 save_ardour_state ();
293 if (add_route_dialog) {
294 delete add_route_dialog;
297 Source::stop_peak_thread ();
301 ARDOUR_UI::configure_timeout ()
306 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
307 /* no configure events yet */
311 gettimeofday (&now, 0);
312 timersub (&now, &last_configure_time, &diff);
314 /* force a gap of 0.5 seconds since the last configure event
317 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
320 have_configure_timeout = false;
321 save_ardour_state ();
327 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
329 if (have_configure_timeout) {
330 gettimeofday (&last_configure_time, 0);
332 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
333 have_configure_timeout = true;
340 ARDOUR_UI::save_ardour_state ()
342 if (!keyboard || !mixer || !editor) {
346 /* XXX this is all a bit dubious. add_extra_xml() uses
347 a different lifetime model from add_instant_xml().
350 XMLNode* node = new XMLNode (keyboard->get_state());
351 Config->add_extra_xml (*node);
352 Config->save_state();
354 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
355 XMLNode& mnode (mixer->get_state());
358 session->add_instant_xml(enode, session->path());
359 session->add_instant_xml(mnode, session->path());
361 Config->add_instant_xml(enode, Config->get_user_ardour_path());
362 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
367 ARDOUR_UI::startup ()
369 /* Once the UI is up and running, start the audio engine. Doing
370 this before the UI is up and running can cause problems
371 when not running with SCHED_FIFO, because the amount of
372 CPU and disk work needed to get the UI started can interfere
373 with the scheduling of the audio thread.
376 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
382 if (session && session->dirty()) {
383 switch (ask_about_saving_session(_("quit"))) {
388 /* use the default name */
389 if (save_state_canfail ("")) {
390 /* failed - don't quit */
391 ArdourMessage (editor, X_("badsave dialog"),
393 Ardour was unable to save your session.\n\n\
394 If you still wish to quit, please use the\n\n\
395 \"Just quit\" option."));
408 ARDOUR_UI::ask_about_saving_session (const string & what)
410 ArdourDialog window (_("ardour: save session?"));
411 Gtk::Label prompt_label;
414 msg = string_compose(_("Save and %1"), what);
415 window.add_button (msg, RESPONSE_ACCEPT);
416 msg = string_compose(_("Just %1"), what);
417 window.add_button (msg, RESPONSE_APPLY);
418 msg = string_compose(_("Don't %1"), what);
419 window.add_button (msg, RESPONSE_REJECT);
421 Gtk::Button noquit_button (msg);
422 noquit_button.set_name ("EditorGTKButton");
427 if (session->snap_name() == session->name()) {
430 type = _("snapshot");
432 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?"),
433 type, session->snap_name());
435 prompt_label.set_text (prompt);
436 prompt_label.set_alignment (0.5, 0.5);
437 prompt_label.set_name (X_("PrompterLabel"));
439 window.get_vbox()->pack_start (prompt_label);
441 window.set_name (_("Prompter"));
442 window.set_position (Gtk::WIN_POS_MOUSE);
443 window.set_modal (true);
446 save_the_session = 0;
448 editor->ensure_float (window);
450 ResponseType r = (ResponseType) window.run();
455 case RESPONSE_ACCEPT: // save and get out of here
457 case RESPONSE_APPLY: // get out of here
467 ARDOUR_UI::every_second ()
470 update_buffer_load ();
471 update_disk_space ();
472 // update_disk_rate ();
477 ARDOUR_UI::every_point_one_seconds ()
482 /* do not attempt to grab peak power more than once per cycle.
485 gettimeofday (&now, 0);
486 timersub (&now, &last_peak_grab, &diff);
488 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
489 IO::GrabPeakPower(); /* EMIT_SIGNAL */
490 last_peak_grab = now;
493 update_speed_display ();
494 RapidScreenUpdate(); /* EMIT_SIGNAL */
499 ARDOUR_UI::every_point_zero_one_seconds ()
501 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
506 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
510 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
512 if (!engine->connected()) {
514 snprintf (buf, sizeof (buf), _("disconnected"));
518 jack_nframes_t rate = engine->frame_rate();
520 if (fmod (rate, 1000.0) != 0.0) {
521 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
522 (float) rate/1000.0f,
523 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
525 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
527 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
531 sample_rate_label.set_text (buf);
535 ARDOUR_UI::update_cpu_load ()
538 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
539 cpu_load_label.set_text (buf);
543 ARDOUR_UI::update_disk_rate ()
548 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
549 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
550 disk_rate_label.set_text (buf);
552 disk_rate_label.set_text ("");
557 ARDOUR_UI::update_buffer_load ()
562 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
563 session->playback_load(), session->capture_load());
564 buffer_load_label.set_text (buf);
566 buffer_load_label.set_text ("");
571 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
573 if (ds.record_enabled()) {
574 rec_enabled_diskstreams++;
579 ARDOUR_UI::update_disk_space()
585 jack_nframes_t frames = session->available_capture_duration();
588 if (frames == max_frames) {
589 strcpy (buf, _("space: 24hrs+"));
594 jack_nframes_t fr = session->frame_rate();
596 if (session->actively_recording()){
598 rec_enabled_diskstreams = 0;
599 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
601 if (rec_enabled_diskstreams) {
602 frames /= rec_enabled_diskstreams;
607 /* hmmm. shall we divide by the route count? or the diskstream count?
608 or what? for now, do nothing ...
613 hrs = frames / (fr * 3600);
614 frames -= hrs * fr * 3600;
615 mins = frames / (fr * 60);
616 frames -= mins * fr * 60;
619 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
622 disk_space_label.set_text (buf);
626 ARDOUR_UI::update_wall_clock ()
633 tm_now = localtime (&now);
635 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
636 wall_clock_label.set_text (buf);
641 ARDOUR_UI::control_methods_adjusted ()
646 which_method = (int) online_control_button->adjustment.get_value();
647 switch (which_method) {
649 allow_mmc_and_local ();
658 fatal << _("programming error: impossible control method") << endmsg;
664 ARDOUR_UI::mmc_device_id_adjusted ()
669 int dev_id = (int) mmc_id_button->adjustment.get_value();
670 mmc->set_device_id (dev_id);
676 ARDOUR_UI::session_menu (GdkEventButton *ev)
678 session_popup_menu->popup (0, 0);
683 ARDOUR_UI::redisplay_recent_sessions ()
685 vector<string *> *sessions;
686 vector<string *>::iterator i;
687 RecentSessionsSorter cmp;
689 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
690 recent_session_model->clear ();
693 ARDOUR::read_recent_sessions (rs);
696 recent_session_display.set_model (recent_session_model);
700 /* sort them alphabetically */
701 sort (rs.begin(), rs.end(), cmp);
702 sessions = new vector<string*>;
704 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
705 sessions->push_back (new string ((*i).second));
708 for (i = sessions->begin(); i != sessions->end(); ++i) {
710 vector<string*>* states;
711 vector<const gchar*> item;
712 string fullpath = *(*i);
714 /* remove any trailing / */
716 if (fullpath[fullpath.length()-1] == '/') {
717 fullpath = fullpath.substr (0, fullpath.length()-1);
720 /* now get available states for this session */
722 if ((states = Session::possible_states (fullpath)) == 0) {
727 TreeModel::Row row = *(recent_session_model->append());
729 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
730 row[recent_session_columns.fullpath] = fullpath;
732 if (states->size() > 1) {
734 /* add the children */
736 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
738 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
740 child_row[recent_session_columns.visible_name] = **i2;
741 child_row[recent_session_columns.fullpath] = fullpath;
750 recent_session_display.set_model (recent_session_model);
755 ARDOUR_UI::build_session_selector ()
757 session_selector_window = new ArdourDialog ("session selector");
759 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
761 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
762 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
764 recent_session_model = TreeStore::create (recent_session_columns);
765 recent_session_display.set_model (recent_session_model);
766 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
767 recent_session_display.set_headers_visible (false);
769 scroller->add (recent_session_display);
770 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
772 session_selector_window->set_name ("SessionSelectorWindow");
773 session_selector_window->set_size_request (200, 400);
774 session_selector_window->get_vbox()->pack_start (*scroller);
775 session_selector_window->show_all_children();
779 ARDOUR_UI::open_recent_session ()
781 /* popup selector window */
783 if (session_selector_window == 0) {
784 build_session_selector ();
787 redisplay_recent_sessions ();
789 ResponseType r = (ResponseType) session_selector_window->run ();
791 session_selector_window->hide();
794 case RESPONSE_ACCEPT:
800 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
802 if (i == recent_session_model->children().end()) {
806 Glib::ustring path = (*i)[recent_session_columns.fullpath];
807 Glib::ustring state = (*i)[recent_session_columns.visible_name];
809 _session_is_new = false;
811 load_session (path, state);
815 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
819 if (stat (info.filename.c_str(), &statbuf) != 0) {
823 if (!S_ISDIR(statbuf.st_mode)) {
827 string session_file = info.filename;
829 session_file += PBD::basename (info.filename);
830 session_file += ".ardour";
832 if (stat (session_file.c_str(), &statbuf) != 0) {
836 return S_ISREG (statbuf.st_mode);
840 ARDOUR_UI::open_session ()
842 /* popup selector window */
844 if (open_session_selector == 0) {
846 /* ardour sessions are folders */
848 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
849 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
850 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
852 FileFilter session_filter;
853 session_filter.add_pattern ("*.ardour");
854 session_filter.set_name (_("Ardour sessions"));
855 open_session_selector->add_filter (session_filter);
856 open_session_selector->set_filter (session_filter);
859 int response = open_session_selector->run();
860 open_session_selector->hide ();
863 case RESPONSE_ACCEPT:
866 open_session_selector->hide();
870 open_session_selector->hide();
871 string session_path = open_session_selector->get_filename();
875 if (session_path.length() > 0) {
876 if (Session::find_session (session_path, path, name, isnew) == 0) {
877 _session_is_new = isnew;
878 load_session (path, name);
885 ARDOUR_UI::session_add_midi_track ()
887 cerr << _("Patience is a virtue.\n");
891 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
896 warning << _("You cannot add a track without a session already loaded.") << endmsg;
902 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
903 error << _("could not create new audio track") << endmsg;
906 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
907 error << _("could not create new audio bus") << endmsg;
912 if (need_control_room_outs) {
918 route->set_stereo_control_outs (control_lr_channels);
919 route->control_outs()->set_stereo_pan (pans, this);
921 #endif /* CONTROLOUTS */
925 ArdourMessage msg (editor, X_("noport dialog"),
926 _("There are insufficient JACK ports available\n\
927 to create a new track or bus.\n\
928 You should save Ardour, exit and\n\
929 restart JACK with more ports."));
934 ARDOUR_UI::diskstream_added (DiskStream* ds)
939 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
941 jack_nframes_t _preroll;
944 _preroll = session->convert_to_frames_at (new_position, session->preroll);
946 if (new_position > _preroll) {
947 new_position -= _preroll;
952 session->request_locate (new_position);
957 ARDOUR_UI::transport_goto_start ()
960 session->request_locate (0);
963 /* force displayed area in editor to start no matter
964 what "follow playhead" setting is.
968 editor->reposition_x_origin (0);
974 ARDOUR_UI::transport_goto_end ()
977 jack_nframes_t frame = session->current_end_frame();
978 session->request_locate (frame);
980 /* force displayed area in editor to start no matter
981 what "follow playhead" setting is.
985 editor->reposition_x_origin (frame);
991 ARDOUR_UI::transport_stop ()
997 if (session->is_auditioning()) {
998 session->cancel_audition ();
1002 if (session->get_auto_loop()) {
1003 session->request_auto_loop (false);
1006 session->request_stop ();
1010 ARDOUR_UI::transport_stop_and_forget_capture ()
1013 session->request_stop (true);
1018 ARDOUR_UI::remove_last_capture()
1021 editor->remove_last_capture();
1026 ARDOUR_UI::transport_record ()
1029 switch (session->record_status()) {
1030 case Session::Disabled:
1031 if (session->ntracks() == 0) {
1032 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1033 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1036 session->maybe_enable_record ();
1038 case Session::Recording:
1039 case Session::Enabled:
1040 session->disable_record (true);
1046 ARDOUR_UI::transport_roll ()
1054 rolling = session->transport_rolling ();
1056 if (session->get_auto_loop()) {
1057 session->request_auto_loop (false);
1058 auto_loop_button.set_active (false);
1059 roll_button.set_active (true);
1060 } else if (session->get_play_range ()) {
1061 session->request_play_range (false);
1062 play_selection_button.set_active (false);
1063 } else if (rolling) {
1064 session->request_locate (session->last_transport_start(), true);
1067 session->request_transport_speed (1.0f);
1071 ARDOUR_UI::transport_loop()
1074 if (session->get_auto_loop()) {
1075 if (session->transport_rolling()) {
1076 Location * looploc = session->locations()->auto_loop_location();
1078 session->request_locate (looploc->start(), true);
1083 session->request_auto_loop (true);
1089 ARDOUR_UI::transport_play_selection ()
1095 if (!session->get_play_range()) {
1096 session->request_stop ();
1099 editor->play_selection ();
1103 ARDOUR_UI::transport_rewind (int option)
1105 float current_transport_speed;
1108 current_transport_speed = session->transport_speed();
1110 if (current_transport_speed >= 0.0f) {
1113 session->request_transport_speed (-1.0f);
1116 session->request_transport_speed (-4.0f);
1119 session->request_transport_speed (-0.5f);
1124 session->request_transport_speed (current_transport_speed * 1.5f);
1130 ARDOUR_UI::transport_forward (int option)
1132 float current_transport_speed;
1135 current_transport_speed = session->transport_speed();
1137 if (current_transport_speed <= 0.0f) {
1140 session->request_transport_speed (1.0f);
1143 session->request_transport_speed (4.0f);
1146 session->request_transport_speed (0.5f);
1151 session->request_transport_speed (current_transport_speed * 1.5f);
1157 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1165 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1166 Port *port = ds->io()->input (0);
1167 port->request_monitor_input (!port->monitoring_input());
1172 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1180 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1181 ds->set_record_enabled (!ds->record_enabled(), this);
1186 ARDOUR_UI::queue_transport_change ()
1188 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1192 ARDOUR_UI::map_transport_state ()
1194 float sp = session->transport_speed();
1197 transport_rolling ();
1198 } else if (sp < 0.0f) {
1199 transport_rewinding ();
1200 } else if (sp > 0.0f) {
1201 transport_forwarding ();
1203 transport_stopped ();
1208 ARDOUR_UI::send_all_midi_feedback ()
1211 session->send_all_midi_feedback();
1216 ARDOUR_UI::allow_local_only ()
1222 ARDOUR_UI::allow_mmc_only ()
1228 ARDOUR_UI::allow_mmc_and_local ()
1234 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1236 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1237 (int) adj.get_value()].c_str());
1241 ARDOUR_UI::engine_stopped ()
1243 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1244 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1245 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1250 ARDOUR_UI::engine_running ()
1252 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1253 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1254 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1258 ARDOUR_UI::engine_halted ()
1260 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1262 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1263 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1265 update_sample_rate (0);
1267 ArdourMessage msg (editor, X_("halted"),
1269 JACK has either been shutdown or it\n\
1270 disconnected Ardour because Ardour\n\
1271 was not fast enough. You can save the\n\
1272 session and/or try to reconnect to JACK ."));
1276 ARDOUR_UI::do_engine_start ()
1282 catch (AudioEngine::PortRegistrationFailure& err) {
1284 error << _("Unable to create all required ports")
1292 error << _("Unable to start the session running")
1302 ARDOUR_UI::start_engine ()
1304 if (do_engine_start () == 0) {
1305 if (session && _session_is_new) {
1306 /* we need to retain initial visual
1307 settings for a new session
1309 session->save_state ("");
1312 /* there is too much going on, in too many threads, for us to
1313 end up with a clean session. So wait 1 second after loading,
1314 and fix it up. its ugly, but until i come across a better
1315 solution, its what we have.
1318 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1325 ARDOUR_UI::update_clocks ()
1327 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1331 ARDOUR_UI::start_clocking ()
1333 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1337 ARDOUR_UI::stop_clocking ()
1339 clock_signal_connection.disconnect ();
1343 ARDOUR_UI::toggle_clocking ()
1346 if (clock_button.get_active()) {
1355 ARDOUR_UI::_blink (void *arg)
1358 ((ARDOUR_UI *) arg)->blink ();
1365 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1369 ARDOUR_UI::start_blinking ()
1371 /* Start the blink signal. Everybody with a blinking widget
1372 uses Blink to drive the widget's state.
1375 if (blink_timeout_tag < 0) {
1377 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1382 ARDOUR_UI::stop_blinking ()
1384 if (blink_timeout_tag >= 0) {
1385 gtk_timeout_remove (blink_timeout_tag);
1386 blink_timeout_tag = -1;
1392 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1394 using namespace Gtk;
1395 using namespace Menu_Helpers;
1397 if (dstream.hidden()) {
1401 MenuList& items = diskstream_menu->items();
1402 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1406 ARDOUR_UI::diskstream_selected (gint32 id)
1408 selected_dstream = id;
1413 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1415 using namespace Gtk;
1416 using namespace Menu_Helpers;
1422 diskstream_menu = new Menu();
1423 diskstream_menu->set_name ("ArdourContextMenu");
1424 using namespace Gtk;
1425 using namespace Menu_Helpers;
1427 MenuList& items = diskstream_menu->items();
1428 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1430 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1433 diskstream_menu->popup (ev->button, ev->time);
1435 diskstream_menu->popup (0, 0);
1438 selected_dstream = -1;
1442 delete diskstream_menu;
1444 return selected_dstream;
1448 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1454 if (io.n_inputs() == 0) {
1459 /* XXX we're not handling multiple ports yet. */
1461 const char **connections = io.input(0)->get_connections();
1463 if (connections == 0 || connections[0] == '\0') {
1466 buf = connections[0];
1473 if (io.n_outputs() == 0) {
1478 /* XXX we're not handling multiple ports yet. */
1480 const char **connections = io.output(0)->get_connections();
1482 if (connections == 0 || connections[0] == '\0') {
1485 buf = connections[0];
1493 ARDOUR_UI::snapshot_session ()
1495 ArdourPrompter prompter (true);
1502 now = now.substr (0, now.length() - 1);
1504 prompter.set_name ("Prompter");
1505 prompter.set_prompt (_("Name for snapshot"));
1506 prompter.set_initial_text (now);
1508 switch (prompter.run()) {
1509 case RESPONSE_ACCEPT:
1510 prompter.get_result (snapname);
1511 if (snapname.length()){
1512 save_state (snapname);
1522 ARDOUR_UI::save_state (const string & name)
1524 (void) save_state_canfail (name);
1528 ARDOUR_UI::save_state_canfail (string name)
1533 if (name.length() == 0) {
1534 name = session->snap_name();
1537 if ((ret = session->save_state (name)) != 0) {
1541 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1546 ARDOUR_UI::restore_state (string name)
1549 if (name.length() == 0) {
1550 name = session->name();
1552 session->restore_state (name);
1557 ARDOUR_UI::primary_clock_value_changed ()
1560 session->request_locate (primary_clock.current_time ());
1565 ARDOUR_UI::secondary_clock_value_changed ()
1568 session->request_locate (secondary_clock.current_time ());
1573 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1575 if (session && dstream && dstream->record_enabled()) {
1577 Session::RecordState rs;
1579 rs = session->record_status ();
1582 case Session::Disabled:
1583 case Session::Enabled:
1584 if (w->get_state() != STATE_SELECTED) {
1585 w->set_state (STATE_SELECTED);
1589 case Session::Recording:
1590 if (w->get_state() != STATE_ACTIVE) {
1591 w->set_state (STATE_ACTIVE);
1597 if (w->get_state() != STATE_NORMAL) {
1598 w->set_state (STATE_NORMAL);
1604 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1610 switch (session->record_status()) {
1611 case Session::Enabled:
1613 rec_button.set_state (1);
1615 rec_button.set_state (0);
1619 case Session::Recording:
1620 rec_button.set_state (2);
1624 rec_button.set_state (0);
1630 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1638 ARDOUR_UI::start_keyboard_prefix ()
1640 keyboard->start_prefix();
1644 ARDOUR_UI::save_template ()
1647 ArdourPrompter prompter (true);
1650 prompter.set_name (X_("Prompter"));
1651 prompter.set_prompt (_("Name for mix template:"));
1652 prompter.set_initial_text(session->name() + _("-template"));
1654 switch (prompter.run()) {
1655 case RESPONSE_ACCEPT:
1656 prompter.get_result (name);
1658 if (name.length()) {
1659 session->save_template (name);
1669 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1671 m_new_session_dialog->show_all();
1672 m_new_session_dialog->set_transient_for(*editor);
1673 m_new_session_dialog->set_name(predetermined_path);
1675 int response = Gtk::RESPONSE_CANCEL;
1678 response = m_new_session_dialog->run ();
1680 if(response == Gtk::RESPONSE_OK) {
1682 _session_is_new = true;
1684 std::string session_name = m_new_session_dialog->session_name();
1685 std::string session_path = m_new_session_dialog->session_folder();
1688 XXX This is needed because session constructor wants a
1689 non-existant path. hopefully this will be fixed at some point.
1691 session_path = Glib::build_filename(session_path, session_name);
1693 std::string template_name = m_new_session_dialog->session_template_name();
1695 if (m_new_session_dialog->use_session_template()) {
1697 load_session (session_path, session_name, &template_name);
1703 Session::AutoConnectOption iconnect;
1704 Session::AutoConnectOption oconnect;
1706 if (m_new_session_dialog->create_control_bus()) {
1707 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1712 if (m_new_session_dialog->create_master_bus()) {
1713 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1718 if (m_new_session_dialog->connect_inputs()) {
1719 iconnect = Session::AutoConnectPhysical;
1721 iconnect = Session::AutoConnectOption (0);
1724 /// @todo some minor tweaks.
1726 if (m_new_session_dialog->connect_outs_to_master()) {
1727 oconnect = Session::AutoConnectMaster;
1728 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1729 oconnect = Session::AutoConnectPhysical;
1731 oconnect = Session::AutoConnectOption (0);
1734 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1735 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1737 build_session (session_path,
1745 engine->frame_rate() * 60 * 5);
1749 } while(response == Gtk::RESPONSE_HELP);
1750 m_new_session_dialog->hide_all();
1754 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1756 Session *new_session;
1758 session_loaded = false;
1759 x = unload_session ();
1767 /* if it already exists, we must have write access */
1769 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1770 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
1771 You do not have write access to this session.\n\
1772 This prevents the session from being loaded."));
1777 new_session = new Session (*engine, path, snap_name, mix_template);
1782 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1786 connect_to_session (new_session);
1788 //if (engine->running()) {
1789 //mixer->show_window();
1791 session_loaded = true;
1796 ARDOUR_UI::make_session_clean ()
1799 session->set_clean ();
1806 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1807 uint32_t control_channels,
1808 uint32_t master_channels,
1809 Session::AutoConnectOption input_connect,
1810 Session::AutoConnectOption output_connect,
1813 jack_nframes_t initial_length)
1815 Session *new_session;
1818 session_loaded = false;
1819 x = unload_session ();
1826 _session_is_new = true;
1829 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1830 control_channels, master_channels, nphysin, nphysout, initial_length);
1835 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1839 connect_to_session (new_session);
1841 //if (engine->running()) {
1842 //mixer->show_window();
1844 session_loaded = true;
1852 editor->show_window ();
1856 if (session && mixer) {
1857 // mixer->show_window ();
1866 ARDOUR_UI::show_splash ()
1869 about = new About();
1875 ARDOUR_UI::hide_splash ()
1883 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1887 removed = rep.paths.size();
1890 ArdourMessage msg (editor, X_("cleanupresults"),
1892 No audio files were ready for cleanup\n\n\
1893 If this seems suprising, check for any existing\n\
1894 snapshots. These may still include regions that\n\
1895 require some unused files to continue to exist."));
1899 ArdourDialog results (_("ardour: cleanup"), true);
1901 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1902 CleanupResultsModelColumns() {
1906 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1907 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1911 Glib::RefPtr<Gtk::ListStore> results_model;
1912 CleanupResultsModelColumns results_columns;
1913 Gtk::TreeView results_display;
1915 results_model = ListStore::create (results_columns);
1916 results_display.set_model (results_model);
1917 results_display.append_column (list_title, results_columns.visible_name);
1918 results_display.set_headers_visible (true);
1920 Gtk::ScrolledWindow list_scroller;
1923 if (rep.space < 1048576.0f) {
1925 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1927 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1931 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1933 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1937 results.get_vbox()->pack_start (txt, false, false);
1939 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1940 TreeModel::Row row = *(results_model->append());
1941 row[results_columns.visible_name] = *i;
1942 row[results_columns.fullpath] = *i;
1945 list_scroller.add (results_display);
1946 list_scroller.set_size_request (-1, 250);
1947 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1949 results.get_vbox()->pack_start (list_scroller, true, true);
1950 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1951 results.set_position (Gtk::WIN_POS_MOUSE);
1957 ARDOUR_UI::cleanup ()
1960 /* shouldn't happen: menu item is insensitive */
1964 ArdourDialog checker (_("ardour cleanup"));
1965 Gtk::Label label (_("\
1966 Cleanup is a destructive operation.\n\
1967 ALL undo/redo information will be lost if you cleanup.\n\
1968 Unused audio files will be moved to a \"dead sounds\" location."));
1970 checker.get_vbox()->pack_start (label, false, false);
1971 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
1972 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1974 checker.set_name (_("CleanupDialog"));
1975 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1976 checker.set_position (Gtk::WIN_POS_MOUSE);
1978 switch (checker.run()) {
1979 case RESPONSE_ACCEPT:
1985 Session::cleanup_report rep;
1987 editor->prepare_for_cleanup ();
1989 if (session->cleanup_sources (rep)) {
1993 display_cleanup_results (rep,
1996 The following %1 %2 were not in use.\n\
1997 The next time you flush the wastebasket\n\
1998 it will release an additional %3 %4bytes\n\
2004 ARDOUR_UI::flush_trash ()
2007 /* shouldn't happen: menu item is insensitive */
2011 Session::cleanup_report rep;
2013 if (session->cleanup_trash_sources (rep)) {
2017 display_cleanup_results (rep,
2019 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2023 ARDOUR_UI::add_route ()
2031 if (add_route_dialog == 0) {
2032 add_route_dialog = new AddRouteDialog;
2033 editor->ensure_float (*add_route_dialog);
2036 if (add_route_dialog->is_visible()) {
2037 /* we're already doing this */
2041 ResponseType r = (ResponseType) add_route_dialog->run ();
2043 add_route_dialog->hide();
2046 case RESPONSE_ACCEPT:
2053 if ((count = add_route_dialog->count()) <= 0) {
2057 uint32_t input_chan = add_route_dialog->channels ();
2058 uint32_t output_chan;
2059 string name_template = add_route_dialog->name_template ();
2060 bool track = add_route_dialog->track ();
2062 Session::AutoConnectOption oac = session->get_output_auto_connect();
2064 if (oac & Session::AutoConnectMaster) {
2065 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2067 output_chan = input_chan;
2070 /* XXX do something with name template */
2074 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2076 session_add_audio_bus (input_chan, output_chan);
2080 while (Main::events_pending()) {
2087 ARDOUR_UI::mixer_settings () const
2092 node = session->instant_xml(X_("Mixer"), session->path());
2094 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2098 node = new XMLNode (X_("Mixer"));
2105 ARDOUR_UI::editor_settings () const
2110 node = session->instant_xml(X_("Editor"), session->path());
2112 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2116 node = new XMLNode (X_("Editor"));
2122 ARDOUR_UI::keyboard_settings () const
2126 node = Config->extra_xml(X_("Keyboard"));
2129 node = new XMLNode (X_("Keyboard"));
2135 ARDOUR_UI::halt_on_xrun_message ()
2137 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2139 ArdourMessage msg (editor, X_("haltonxrun"),
2140 _("Recording was stopped because your system could not keep up."));
2144 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2146 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2148 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2152 delete deletion_list;
2156 ARDOUR_UI::disk_overrun_handler ()
2158 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2160 if (!have_disk_overrun_displayed) {
2161 have_disk_overrun_displayed = true;
2162 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
2163 The disk system on your computer\n\
2164 was not able to keep up with Ardour.\n\
2166 Specifically, it failed to write data to disk\n\
2167 quickly enough to keep up with recording.\n"));
2168 have_disk_overrun_displayed = false;
2173 ARDOUR_UI::disk_underrun_handler ()
2175 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2177 if (!have_disk_underrun_displayed) {
2178 have_disk_underrun_displayed = true;
2179 ArdourMessage msg (editor, X_("diskrate2 dialog"),
2180 (_("The disk system on your computer\n\
2181 was not able to keep up with Ardour.\n\
2183 Specifically, it failed to read data from disk\n\
2184 quickly enough to keep up with playback.\n")));
2185 have_disk_underrun_displayed = false;
2190 ARDOUR_UI::disk_underrun_message_gone ()
2192 have_disk_underrun_displayed = false;
2196 ARDOUR_UI::disk_overrun_message_gone ()
2198 have_disk_underrun_displayed = false;
2202 ARDOUR_UI::pending_state_dialog ()
2204 ArdourDialog dialog ("pending state dialog");
2206 This session appears to have been in\n\
2207 middle of recording when ardour or\n\
2208 the computer was shutdown.\n\
2210 Ardour can recover any captured audio for\n\
2211 you, or it can ignore it. Please decide\n\
2212 what you would like to do.\n"));
2214 dialog.get_vbox()->pack_start (message);
2215 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2216 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2218 dialog.set_position (WIN_POS_CENTER);
2221 switch (dialog.run ()) {
2222 case RESPONSE_ACCEPT:
2233 ARDOUR_UI::disconnect_from_jack ()
2236 if( engine->disconnect_from_jack ()) {
2237 ArdourMessage msg (editor, X_("nojack dialog"),
2238 _("Could not disconnect from JACK"));
2241 update_sample_rate (0);
2246 ARDOUR_UI::reconnect_to_jack ()
2249 if (engine->reconnect_to_jack ()) {
2250 ArdourMessage msg (editor, X_("nojack dialog"),
2251 _("Could not reconnect to JACK"));
2254 update_sample_rate (0);
2259 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2261 engine->request_buffer_size (nframes);
2262 update_sample_rate (0);
2266 ARDOUR_UI::cmdline_new_session (string path)
2268 if (path[0] != '/') {
2269 char buf[PATH_MAX+1];
2272 getcwd (buf, sizeof (buf));
2279 new_session (false, path);
2281 _will_create_new_session_automatically = false; /* done it */
2282 return FALSE; /* don't call it again */