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 <gtkmm/messagedialog.h>
33 #include <pbd/error.h>
34 #include <pbd/compose.h>
35 #include <pbd/basename.h>
36 #include <pbd/pathscanner.h>
37 #include <pbd/failed_constructor.h>
38 #include <gtkmm2ext/gtk_ui.h>
39 #include <gtkmm2ext/pix.h>
40 #include <gtkmm2ext/utils.h>
41 #include <gtkmm2ext/click_box.h>
42 #include <gtkmm2ext/fastmeter.h>
43 #include <gtkmm2ext/stop_signal.h>
44 #include <gtkmm2ext/popup.h>
46 #include <midi++/port.h>
47 #include <midi++/mmc.h>
49 #include <ardour/ardour.h>
50 #include <ardour/port.h>
51 #include <ardour/audioengine.h>
52 #include <ardour/playlist.h>
53 #include <ardour/utils.h>
54 #include <ardour/diskstream.h>
55 #include <ardour/filesource.h>
56 #include <ardour/recent_sessions.h>
57 #include <ardour/session_diskstream.h>
58 #include <ardour/port.h>
59 #include <ardour/audio_track.h>
62 #include "ardour_ui.h"
63 #include "public_editor.h"
64 #include "audio_clock.h"
69 #include "keyboard_target.h"
70 #include "add_route_dialog.h"
71 #include "new_session_dialog.h"
74 #include "gui_thread.h"
75 #include "meter_xpms.h"
76 #include "color_manager.h"
80 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
85 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
87 sigc::signal<void,bool> ARDOUR_UI::Blink;
88 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
89 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
90 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
92 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
94 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
96 primary_clock (X_("TransportClockDisplay"), true, false, true),
97 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
98 preroll_clock (X_("PreRollClock"), true, true),
99 postroll_clock (X_("PostRollClock"), true, true),
103 adjuster_table (3, 3),
107 preroll_button (_("pre\nroll")),
108 postroll_button (_("post\nroll")),
112 big_clock ("BigClockDisplay", true),
116 time_master_button (_("time\nmaster")),
118 shuttle_units_button (_("% ")),
120 punch_in_button (_("punch\nin")),
121 punch_out_button (_("punch\nout")),
122 auto_return_button (_("auto\nreturn")),
123 auto_play_button (_("auto\nplay")),
124 auto_input_button (_("auto\ninput")),
125 click_button (_("click")),
126 auditioning_alert_button (_("AUDITIONING")),
127 solo_alert_button (_("SOLO")),
131 using namespace Gtk::Menu_Helpers;
135 /* actually, its already loaded, but ... */
137 cerr << "Loading UI configuration file " << rcfile << endl;
141 if (theArdourUI == 0) {
145 ActionManager::init ();
149 color_manager = new ColorManager();
151 std::string color_file = Glib::getenv(X_("ARDOUR_COLORS"));
152 if(!Glib::file_test(color_file, Glib::FILE_TEST_EXISTS)) {
153 color_file = ARDOUR::find_config_file("ardour.colors");
156 cerr << "Loading UI color configuration file " << color_file << endl;
158 color_manager->load (color_file);
160 m_new_session_dialog = 0;
161 m_new_session_dialog_ref = NewSessionDialogFactory::create();
162 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
166 _session_is_new = false;
167 big_clock_window = 0;
168 session_selector_window = 0;
169 last_key_press_time = 0;
170 connection_editor = 0;
171 add_route_dialog = 0;
176 open_session_selector = 0;
177 have_configure_timeout = false;
178 have_disk_overrun_displayed = false;
179 have_disk_underrun_displayed = false;
180 _will_create_new_session_automatically = false;
181 session_loaded = false;
182 last_speed_displayed = -1.0f;
184 last_configure_time.tv_sec = 0;
185 last_configure_time.tv_usec = 0;
187 shuttle_grabbed = false;
190 set_shuttle_units (Percentage);
191 set_shuttle_behaviour (Sprung);
193 shuttle_style_menu = 0;
194 shuttle_unit_menu = 0;
196 gettimeofday (&last_peak_grab, 0);
197 gettimeofday (&last_shuttle_request, 0);
199 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
200 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
201 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
202 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
204 /* handle pending state with a dialog */
206 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
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 MessageDialog message (*editor, msg);
228 ARDOUR_UI::set_engine (AudioEngine& e)
232 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
233 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
234 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
235 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
239 keyboard = new Keyboard;
240 install_keybindings ();
242 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
243 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
245 if (setup_windows ()) {
246 throw failed_constructor ();
249 if (GTK_ARDOUR::show_key_actions) {
250 vector<string> names;
251 vector<string> paths;
253 vector<AccelKey> bindings;
255 ActionManager::get_all_actions (names, paths, keys, bindings);
257 vector<string>::iterator n;
258 vector<string>::iterator k;
259 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
260 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
266 /* start with timecode, metering enabled
269 blink_timeout_tag = -1;
271 /* this being a GUI and all, we want peakfiles */
273 FileSource::set_build_peakfiles (true);
274 FileSource::set_build_missing_peakfiles (true);
276 if (Source::start_peak_thread ()) {
277 throw failed_constructor();
280 /* start the time-of-day-clock */
282 update_wall_clock ();
283 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
285 update_disk_space ();
287 update_sample_rate (engine->frame_rate());
289 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
290 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
293 ARDOUR_UI::~ARDOUR_UI ()
295 save_ardour_state ();
309 if (add_route_dialog) {
310 delete add_route_dialog;
313 Source::stop_peak_thread ();
317 ARDOUR_UI::configure_timeout ()
322 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
323 /* no configure events yet */
327 gettimeofday (&now, 0);
328 timersub (&now, &last_configure_time, &diff);
330 /* force a gap of 0.5 seconds since the last configure event
333 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
336 have_configure_timeout = false;
337 save_ardour_state ();
343 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
345 if (have_configure_timeout) {
346 gettimeofday (&last_configure_time, 0);
348 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
349 have_configure_timeout = true;
356 ARDOUR_UI::save_ardour_state ()
358 if (!keyboard || !mixer || !editor) {
362 /* XXX this is all a bit dubious. add_extra_xml() uses
363 a different lifetime model from add_instant_xml().
366 XMLNode* node = new XMLNode (keyboard->get_state());
367 Config->add_extra_xml (*node);
368 Config->save_state();
370 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
371 XMLNode& mnode (mixer->get_state());
374 session->add_instant_xml(enode, session->path());
375 session->add_instant_xml(mnode, session->path());
377 Config->add_instant_xml(enode, Config->get_user_ardour_path());
378 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
383 ARDOUR_UI::startup ()
385 /* Once the UI is up and running, start the audio engine. Doing
386 this before the UI is up and running can cause problems
387 when not running with SCHED_FIFO, because the amount of
388 CPU and disk work needed to get the UI started can interfere
389 with the scheduling of the audio thread.
392 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
398 if (session && session->dirty()) {
399 switch (ask_about_saving_session(_("quit"))) {
404 /* use the default name */
405 if (save_state_canfail ("")) {
406 /* failed - don't quit */
407 MessageDialog msg (*editor,
409 Ardour was unable to save your session.\n\n\
410 If you still wish to quit, please use the\n\n\
411 \"Just quit\" option."));
425 ARDOUR_UI::ask_about_saving_session (const string & what)
427 ArdourDialog window (_("ardour: save session?"));
428 Gtk::Label prompt_label;
431 msg = string_compose(_("Save and %1"), what);
432 window.add_button (msg, RESPONSE_ACCEPT);
433 msg = string_compose(_("Just %1"), what);
434 window.add_button (msg, RESPONSE_APPLY);
435 msg = string_compose(_("Don't %1"), what);
436 window.add_button (msg, RESPONSE_REJECT);
438 Gtk::Button noquit_button (msg);
439 noquit_button.set_name ("EditorGTKButton");
444 if (session->snap_name() == session->name()) {
447 type = _("snapshot");
449 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?"),
450 type, session->snap_name());
452 prompt_label.set_text (prompt);
453 prompt_label.set_alignment (0.5, 0.5);
454 prompt_label.set_name (X_("PrompterLabel"));
456 window.get_vbox()->pack_start (prompt_label);
458 window.set_name (_("Prompter"));
459 window.set_position (Gtk::WIN_POS_MOUSE);
460 window.set_modal (true);
463 save_the_session = 0;
465 editor->ensure_float (window);
467 ResponseType r = (ResponseType) window.run();
472 case RESPONSE_ACCEPT: // save and get out of here
474 case RESPONSE_APPLY: // get out of here
484 ARDOUR_UI::every_second ()
487 update_buffer_load ();
488 update_disk_space ();
489 // update_disk_rate ();
494 ARDOUR_UI::every_point_one_seconds ()
499 /* do not attempt to grab peak power more than once per cycle.
502 gettimeofday (&now, 0);
503 timersub (&now, &last_peak_grab, &diff);
505 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
506 IO::GrabPeakPower(); /* EMIT_SIGNAL */
507 last_peak_grab = now;
510 update_speed_display ();
511 RapidScreenUpdate(); /* EMIT_SIGNAL */
516 ARDOUR_UI::every_point_zero_one_seconds ()
518 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
523 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
527 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
529 if (!engine->connected()) {
531 snprintf (buf, sizeof (buf), _("disconnected"));
535 jack_nframes_t rate = engine->frame_rate();
537 if (fmod (rate, 1000.0) != 0.0) {
538 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
539 (float) rate/1000.0f,
540 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
542 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
544 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
548 sample_rate_label.set_text (buf);
552 ARDOUR_UI::update_cpu_load ()
555 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
556 cpu_load_label.set_text (buf);
560 ARDOUR_UI::update_disk_rate ()
565 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
566 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
567 disk_rate_label.set_text (buf);
569 disk_rate_label.set_text ("");
574 ARDOUR_UI::update_buffer_load ()
579 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
580 session->playback_load(), session->capture_load());
581 buffer_load_label.set_text (buf);
583 buffer_load_label.set_text ("");
588 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
590 if (ds.record_enabled()) {
591 rec_enabled_diskstreams++;
596 ARDOUR_UI::update_disk_space()
602 jack_nframes_t frames = session->available_capture_duration();
605 if (frames == max_frames) {
606 strcpy (buf, _("space: 24hrs+"));
611 jack_nframes_t fr = session->frame_rate();
613 if (session->actively_recording()){
615 rec_enabled_diskstreams = 0;
616 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
618 if (rec_enabled_diskstreams) {
619 frames /= rec_enabled_diskstreams;
624 /* hmmm. shall we divide by the route count? or the diskstream count?
625 or what? for now, do nothing ...
630 hrs = frames / (fr * 3600);
631 frames -= hrs * fr * 3600;
632 mins = frames / (fr * 60);
633 frames -= mins * fr * 60;
636 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
639 disk_space_label.set_text (buf);
643 ARDOUR_UI::update_wall_clock ()
650 tm_now = localtime (&now);
652 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
653 wall_clock_label.set_text (buf);
658 ARDOUR_UI::control_methods_adjusted ()
663 which_method = (int) online_control_button->adjustment.get_value();
664 switch (which_method) {
666 allow_mmc_and_local ();
675 fatal << _("programming error: impossible control method") << endmsg;
681 ARDOUR_UI::mmc_device_id_adjusted ()
686 int dev_id = (int) mmc_id_button->adjustment.get_value();
687 mmc->set_device_id (dev_id);
693 ARDOUR_UI::session_menu (GdkEventButton *ev)
695 session_popup_menu->popup (0, 0);
700 ARDOUR_UI::redisplay_recent_sessions ()
702 vector<string *> *sessions;
703 vector<string *>::iterator i;
704 RecentSessionsSorter cmp;
706 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
707 recent_session_model->clear ();
710 ARDOUR::read_recent_sessions (rs);
713 recent_session_display.set_model (recent_session_model);
717 /* sort them alphabetically */
718 sort (rs.begin(), rs.end(), cmp);
719 sessions = new vector<string*>;
721 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
722 sessions->push_back (new string ((*i).second));
725 for (i = sessions->begin(); i != sessions->end(); ++i) {
727 vector<string*>* states;
728 vector<const gchar*> item;
729 string fullpath = *(*i);
731 /* remove any trailing / */
733 if (fullpath[fullpath.length()-1] == '/') {
734 fullpath = fullpath.substr (0, fullpath.length()-1);
737 /* now get available states for this session */
739 if ((states = Session::possible_states (fullpath)) == 0) {
744 TreeModel::Row row = *(recent_session_model->append());
746 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
747 row[recent_session_columns.fullpath] = fullpath;
749 if (states->size() > 1) {
751 /* add the children */
753 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
755 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
757 child_row[recent_session_columns.visible_name] = **i2;
758 child_row[recent_session_columns.fullpath] = fullpath;
767 recent_session_display.set_model (recent_session_model);
772 ARDOUR_UI::build_session_selector ()
774 session_selector_window = new ArdourDialog ("session selector");
776 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
778 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
779 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
781 recent_session_model = TreeStore::create (recent_session_columns);
782 recent_session_display.set_model (recent_session_model);
783 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
784 recent_session_display.set_headers_visible (false);
786 scroller->add (recent_session_display);
787 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
789 session_selector_window->set_name ("SessionSelectorWindow");
790 session_selector_window->set_size_request (200, 400);
791 session_selector_window->get_vbox()->pack_start (*scroller);
792 session_selector_window->show_all_children();
796 ARDOUR_UI::open_recent_session ()
798 /* popup selector window */
800 if (session_selector_window == 0) {
801 build_session_selector ();
804 redisplay_recent_sessions ();
806 ResponseType r = (ResponseType) session_selector_window->run ();
808 session_selector_window->hide();
811 case RESPONSE_ACCEPT:
817 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
819 if (i == recent_session_model->children().end()) {
823 Glib::ustring path = (*i)[recent_session_columns.fullpath];
824 Glib::ustring state = (*i)[recent_session_columns.visible_name];
826 _session_is_new = false;
828 load_session (path, state);
832 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
836 if (stat (info.filename.c_str(), &statbuf) != 0) {
840 if (!S_ISDIR(statbuf.st_mode)) {
844 string session_file = info.filename;
846 session_file += PBD::basename (info.filename);
847 session_file += ".ardour";
849 if (stat (session_file.c_str(), &statbuf) != 0) {
853 return S_ISREG (statbuf.st_mode);
857 ARDOUR_UI::open_session ()
859 /* popup selector window */
861 if (open_session_selector == 0) {
863 /* ardour sessions are folders */
865 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
866 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
867 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
869 FileFilter session_filter;
870 session_filter.add_pattern ("*.ardour");
871 session_filter.set_name (_("Ardour sessions"));
872 open_session_selector->add_filter (session_filter);
873 open_session_selector->set_filter (session_filter);
876 int response = open_session_selector->run();
877 open_session_selector->hide ();
880 case RESPONSE_ACCEPT:
883 open_session_selector->hide();
887 open_session_selector->hide();
888 string session_path = open_session_selector->get_filename();
892 if (session_path.length() > 0) {
893 if (Session::find_session (session_path, path, name, isnew) == 0) {
894 _session_is_new = isnew;
895 load_session (path, name);
902 ARDOUR_UI::session_add_midi_track ()
904 cerr << _("Patience is a virtue.\n");
908 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
913 warning << _("You cannot add a track without a session already loaded.") << endmsg;
919 if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
920 error << _("could not create new audio track") << endmsg;
923 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
924 error << _("could not create new audio bus") << endmsg;
929 if (need_control_room_outs) {
935 route->set_stereo_control_outs (control_lr_channels);
936 route->control_outs()->set_stereo_pan (pans, this);
938 #endif /* CONTROLOUTS */
942 MessageDialog msg (*editor,
943 _("There are insufficient JACK ports available\n\
944 to create a new track or bus.\n\
945 You should save Ardour, exit and\n\
946 restart JACK with more ports."));
952 ARDOUR_UI::diskstream_added (DiskStream* ds)
957 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
959 jack_nframes_t _preroll;
962 _preroll = session->convert_to_frames_at (new_position, session->preroll);
964 if (new_position > _preroll) {
965 new_position -= _preroll;
970 session->request_locate (new_position);
975 ARDOUR_UI::transport_goto_start ()
978 session->request_locate (0);
981 /* force displayed area in editor to start no matter
982 what "follow playhead" setting is.
986 editor->reposition_x_origin (0);
992 ARDOUR_UI::transport_goto_end ()
995 jack_nframes_t frame = session->current_end_frame();
996 session->request_locate (frame);
998 /* force displayed area in editor to start no matter
999 what "follow playhead" setting is.
1003 editor->reposition_x_origin (frame);
1009 ARDOUR_UI::transport_stop ()
1015 if (session->is_auditioning()) {
1016 session->cancel_audition ();
1020 if (session->get_auto_loop()) {
1021 session->request_auto_loop (false);
1024 session->request_stop ();
1028 ARDOUR_UI::transport_stop_and_forget_capture ()
1031 session->request_stop (true);
1036 ARDOUR_UI::remove_last_capture()
1039 editor->remove_last_capture();
1044 ARDOUR_UI::transport_record ()
1047 switch (session->record_status()) {
1048 case Session::Disabled:
1049 if (session->ntracks() == 0) {
1050 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1051 MessageDialog msg (*editor, txt);
1055 session->maybe_enable_record ();
1057 case Session::Recording:
1058 case Session::Enabled:
1059 session->disable_record (true);
1065 ARDOUR_UI::transport_roll ()
1073 rolling = session->transport_rolling ();
1075 if (session->get_auto_loop()) {
1076 session->request_auto_loop (false);
1077 auto_loop_button.set_active (false);
1078 roll_button.set_active (true);
1079 } else if (session->get_play_range ()) {
1080 session->request_play_range (false);
1081 play_selection_button.set_active (false);
1082 } else if (rolling) {
1083 session->request_locate (session->last_transport_start(), true);
1086 session->request_transport_speed (1.0f);
1090 ARDOUR_UI::transport_loop()
1093 if (session->get_auto_loop()) {
1094 if (session->transport_rolling()) {
1095 Location * looploc = session->locations()->auto_loop_location();
1097 session->request_locate (looploc->start(), true);
1102 session->request_auto_loop (true);
1108 ARDOUR_UI::transport_play_selection ()
1114 if (!session->get_play_range()) {
1115 session->request_stop ();
1118 editor->play_selection ();
1122 ARDOUR_UI::transport_rewind (int option)
1124 float current_transport_speed;
1127 current_transport_speed = session->transport_speed();
1129 if (current_transport_speed >= 0.0f) {
1132 session->request_transport_speed (-1.0f);
1135 session->request_transport_speed (-4.0f);
1138 session->request_transport_speed (-0.5f);
1143 session->request_transport_speed (current_transport_speed * 1.5f);
1149 ARDOUR_UI::transport_forward (int option)
1151 float current_transport_speed;
1154 current_transport_speed = session->transport_speed();
1156 if (current_transport_speed <= 0.0f) {
1159 session->request_transport_speed (1.0f);
1162 session->request_transport_speed (4.0f);
1165 session->request_transport_speed (0.5f);
1170 session->request_transport_speed (current_transport_speed * 1.5f);
1176 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
1184 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1185 Port *port = ds->io()->input (0);
1186 port->request_monitor_input (!port->monitoring_input());
1191 ARDOUR_UI::toggle_record_enable (guint32 dstream)
1199 if ((ds = session->diskstream_by_id (dstream)) != 0) {
1200 ds->set_record_enabled (!ds->record_enabled(), this);
1205 ARDOUR_UI::queue_transport_change ()
1207 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1211 ARDOUR_UI::map_transport_state ()
1213 float sp = session->transport_speed();
1216 transport_rolling ();
1217 } else if (sp < 0.0f) {
1218 transport_rewinding ();
1219 } else if (sp > 0.0f) {
1220 transport_forwarding ();
1222 transport_stopped ();
1227 ARDOUR_UI::send_all_midi_feedback ()
1230 session->send_all_midi_feedback();
1235 ARDOUR_UI::allow_local_only ()
1241 ARDOUR_UI::allow_mmc_only ()
1247 ARDOUR_UI::allow_mmc_and_local ()
1253 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1255 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1256 (int) adj.get_value()].c_str());
1260 ARDOUR_UI::engine_stopped ()
1262 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1263 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1264 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1269 ARDOUR_UI::engine_running ()
1271 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1272 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1273 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1277 ARDOUR_UI::engine_halted ()
1279 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1281 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1282 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1284 update_sample_rate (0);
1286 MessageDialog msg (*editor,
1288 JACK has either been shutdown or it\n\
1289 disconnected Ardour because Ardour\n\
1290 was not fast enough. You can save the\n\
1291 session and/or try to reconnect to JACK ."));
1296 ARDOUR_UI::do_engine_start ()
1302 catch (AudioEngine::PortRegistrationFailure& err) {
1304 error << _("Unable to create all required ports")
1312 error << _("Unable to start the session running")
1322 ARDOUR_UI::start_engine ()
1324 if (do_engine_start () == 0) {
1325 if (session && _session_is_new) {
1326 /* we need to retain initial visual
1327 settings for a new session
1329 session->save_state ("");
1332 /* there is too much going on, in too many threads, for us to
1333 end up with a clean session. So wait 1 second after loading,
1334 and fix it up. its ugly, but until i come across a better
1335 solution, its what we have.
1338 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1345 ARDOUR_UI::update_clocks ()
1347 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1351 ARDOUR_UI::start_clocking ()
1353 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1357 ARDOUR_UI::stop_clocking ()
1359 clock_signal_connection.disconnect ();
1363 ARDOUR_UI::toggle_clocking ()
1366 if (clock_button.get_active()) {
1375 ARDOUR_UI::_blink (void *arg)
1378 ((ARDOUR_UI *) arg)->blink ();
1385 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1389 ARDOUR_UI::start_blinking ()
1391 /* Start the blink signal. Everybody with a blinking widget
1392 uses Blink to drive the widget's state.
1395 if (blink_timeout_tag < 0) {
1397 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1402 ARDOUR_UI::stop_blinking ()
1404 if (blink_timeout_tag >= 0) {
1405 gtk_timeout_remove (blink_timeout_tag);
1406 blink_timeout_tag = -1;
1412 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1414 using namespace Gtk;
1415 using namespace Menu_Helpers;
1417 if (dstream.hidden()) {
1421 MenuList& items = diskstream_menu->items();
1422 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1426 ARDOUR_UI::diskstream_selected (gint32 id)
1428 selected_dstream = id;
1433 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1435 using namespace Gtk;
1436 using namespace Menu_Helpers;
1442 diskstream_menu = new Menu();
1443 diskstream_menu->set_name ("ArdourContextMenu");
1444 using namespace Gtk;
1445 using namespace Menu_Helpers;
1447 MenuList& items = diskstream_menu->items();
1448 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1450 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1453 diskstream_menu->popup (ev->button, ev->time);
1455 diskstream_menu->popup (0, 0);
1458 selected_dstream = -1;
1462 delete diskstream_menu;
1464 return selected_dstream;
1468 ARDOUR_UI::name_io_setup (AudioEngine& engine,
1474 if (io.n_inputs() == 0) {
1479 /* XXX we're not handling multiple ports yet. */
1481 const char **connections = io.input(0)->get_connections();
1483 if (connections == 0 || connections[0] == '\0') {
1486 buf = connections[0];
1493 if (io.n_outputs() == 0) {
1498 /* XXX we're not handling multiple ports yet. */
1500 const char **connections = io.output(0)->get_connections();
1502 if (connections == 0 || connections[0] == '\0') {
1505 buf = connections[0];
1513 ARDOUR_UI::snapshot_session ()
1515 ArdourPrompter prompter (true);
1522 now = now.substr (0, now.length() - 1);
1524 prompter.set_name ("Prompter");
1525 prompter.set_prompt (_("Name for snapshot"));
1526 prompter.set_initial_text (now);
1528 switch (prompter.run()) {
1529 case RESPONSE_ACCEPT:
1530 prompter.get_result (snapname);
1531 if (snapname.length()){
1532 save_state (snapname);
1542 ARDOUR_UI::save_state (const string & name)
1544 (void) save_state_canfail (name);
1548 ARDOUR_UI::save_state_canfail (string name)
1553 if (name.length() == 0) {
1554 name = session->snap_name();
1557 if ((ret = session->save_state (name)) != 0) {
1561 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1566 ARDOUR_UI::restore_state (string name)
1569 if (name.length() == 0) {
1570 name = session->name();
1572 session->restore_state (name);
1577 ARDOUR_UI::primary_clock_value_changed ()
1580 session->request_locate (primary_clock.current_time ());
1585 ARDOUR_UI::secondary_clock_value_changed ()
1588 session->request_locate (secondary_clock.current_time ());
1593 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1595 if (session && dstream && dstream->record_enabled()) {
1597 Session::RecordState rs;
1599 rs = session->record_status ();
1602 case Session::Disabled:
1603 case Session::Enabled:
1604 if (w->get_state() != STATE_SELECTED) {
1605 w->set_state (STATE_SELECTED);
1609 case Session::Recording:
1610 if (w->get_state() != STATE_ACTIVE) {
1611 w->set_state (STATE_ACTIVE);
1617 if (w->get_state() != STATE_NORMAL) {
1618 w->set_state (STATE_NORMAL);
1624 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1630 switch (session->record_status()) {
1631 case Session::Enabled:
1633 rec_button.set_state (1);
1635 rec_button.set_state (0);
1639 case Session::Recording:
1640 rec_button.set_state (2);
1644 rec_button.set_state (0);
1650 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1658 ARDOUR_UI::start_keyboard_prefix ()
1660 keyboard->start_prefix();
1664 ARDOUR_UI::save_template ()
1667 ArdourPrompter prompter (true);
1670 prompter.set_name (X_("Prompter"));
1671 prompter.set_prompt (_("Name for mix template:"));
1672 prompter.set_initial_text(session->name() + _("-template"));
1674 switch (prompter.run()) {
1675 case RESPONSE_ACCEPT:
1676 prompter.get_result (name);
1678 if (name.length()) {
1679 session->save_template (name);
1689 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1691 m_new_session_dialog->show_all();
1692 m_new_session_dialog->set_transient_for(*editor);
1693 m_new_session_dialog->set_name(predetermined_path);
1695 int response = Gtk::RESPONSE_CANCEL;
1698 response = m_new_session_dialog->run ();
1700 if(response == Gtk::RESPONSE_OK) {
1702 _session_is_new = true;
1704 std::string session_name = m_new_session_dialog->session_name();
1705 std::string session_path = m_new_session_dialog->session_folder();
1708 XXX This is needed because session constructor wants a
1709 non-existant path. hopefully this will be fixed at some point.
1711 session_path = Glib::build_filename(session_path, session_name);
1713 std::string template_name = m_new_session_dialog->session_template_name();
1715 if (m_new_session_dialog->use_session_template()) {
1717 load_session (session_path, session_name, &template_name);
1723 Session::AutoConnectOption iconnect;
1724 Session::AutoConnectOption oconnect;
1726 if (m_new_session_dialog->create_control_bus()) {
1727 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1732 if (m_new_session_dialog->create_master_bus()) {
1733 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1738 if (m_new_session_dialog->connect_inputs()) {
1739 iconnect = Session::AutoConnectPhysical;
1741 iconnect = Session::AutoConnectOption (0);
1744 /// @todo some minor tweaks.
1746 if (m_new_session_dialog->connect_outs_to_master()) {
1747 oconnect = Session::AutoConnectMaster;
1748 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1749 oconnect = Session::AutoConnectPhysical;
1751 oconnect = Session::AutoConnectOption (0);
1754 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1755 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1757 build_session (session_path,
1765 engine->frame_rate() * 60 * 5);
1769 } while(response == Gtk::RESPONSE_HELP);
1770 m_new_session_dialog->hide_all();
1774 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1776 Session *new_session;
1778 session_loaded = false;
1779 x = unload_session ();
1787 /* if it already exists, we must have write access */
1789 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1790 MessageDialog msg (*editor, _("\
1791 You do not have write access to this session.\n\
1792 This prevents the session from being loaded."));
1798 new_session = new Session (*engine, path, snap_name, mix_template);
1803 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1807 connect_to_session (new_session);
1809 //if (engine->running()) {
1810 //mixer->show_window();
1812 session_loaded = true;
1817 ARDOUR_UI::make_session_clean ()
1820 session->set_clean ();
1827 ARDOUR_UI::build_session (const string & path, const string & snap_name,
1828 uint32_t control_channels,
1829 uint32_t master_channels,
1830 Session::AutoConnectOption input_connect,
1831 Session::AutoConnectOption output_connect,
1834 jack_nframes_t initial_length)
1836 Session *new_session;
1839 session_loaded = false;
1840 x = unload_session ();
1847 _session_is_new = true;
1850 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1851 control_channels, master_channels, nphysin, nphysout, initial_length);
1856 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1860 connect_to_session (new_session);
1862 //if (engine->running()) {
1863 //mixer->show_window();
1865 session_loaded = true;
1873 editor->show_window ();
1877 if (session && mixer) {
1878 // mixer->show_window ();
1887 ARDOUR_UI::show_splash ()
1890 about = new About();
1896 ARDOUR_UI::hide_splash ()
1904 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1908 removed = rep.paths.size();
1911 MessageDialog msg (*editor, X_("cleanupresults"),
1913 No audio files were ready for cleanup\n\n\
1914 If this seems suprising, check for any existing\n\
1915 snapshots. These may still include regions that\n\
1916 require some unused files to continue to exist."));
1921 ArdourDialog results (_("ardour: cleanup"), true);
1923 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1924 CleanupResultsModelColumns() {
1928 Gtk::TreeModelColumn<Glib::ustring> visible_name;
1929 Gtk::TreeModelColumn<Glib::ustring> fullpath;
1933 Glib::RefPtr<Gtk::ListStore> results_model;
1934 CleanupResultsModelColumns results_columns;
1935 Gtk::TreeView results_display;
1937 results_model = ListStore::create (results_columns);
1938 results_display.set_model (results_model);
1939 results_display.append_column (list_title, results_columns.visible_name);
1940 results_display.set_headers_visible (true);
1942 Gtk::ScrolledWindow list_scroller;
1945 if (rep.space < 1048576.0f) {
1947 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1949 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1953 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1955 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1959 results.get_vbox()->pack_start (txt, false, false);
1961 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1962 TreeModel::Row row = *(results_model->append());
1963 row[results_columns.visible_name] = *i;
1964 row[results_columns.fullpath] = *i;
1967 list_scroller.add (results_display);
1968 list_scroller.set_size_request (-1, 250);
1969 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1971 results.get_vbox()->pack_start (list_scroller, true, true);
1972 results.add_button (Stock::OK, RESPONSE_ACCEPT);
1973 results.set_position (Gtk::WIN_POS_MOUSE);
1979 ARDOUR_UI::cleanup ()
1982 /* shouldn't happen: menu item is insensitive */
1986 ArdourDialog checker (_("ardour cleanup"));
1987 Gtk::Label label (_("\
1988 Cleanup is a destructive operation.\n\
1989 ALL undo/redo information will be lost if you cleanup.\n\
1990 Unused audio files will be moved to a \"dead sounds\" location."));
1992 checker.get_vbox()->pack_start (label, false, false);
1993 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
1994 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1996 checker.set_name (_("CleanupDialog"));
1997 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
1998 checker.set_position (Gtk::WIN_POS_MOUSE);
2000 switch (checker.run()) {
2001 case RESPONSE_ACCEPT:
2007 Session::cleanup_report rep;
2009 editor->prepare_for_cleanup ();
2011 if (session->cleanup_sources (rep)) {
2015 display_cleanup_results (rep,
2018 The following %1 %2 were not in use.\n\
2019 The next time you flush the wastebasket\n\
2020 it will release an additional %3 %4bytes\n\
2026 ARDOUR_UI::flush_trash ()
2029 /* shouldn't happen: menu item is insensitive */
2033 Session::cleanup_report rep;
2035 if (session->cleanup_trash_sources (rep)) {
2039 display_cleanup_results (rep,
2041 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2045 ARDOUR_UI::add_route ()
2053 if (add_route_dialog == 0) {
2054 add_route_dialog = new AddRouteDialog;
2055 editor->ensure_float (*add_route_dialog);
2058 if (add_route_dialog->is_visible()) {
2059 /* we're already doing this */
2063 ResponseType r = (ResponseType) add_route_dialog->run ();
2065 add_route_dialog->hide();
2068 case RESPONSE_ACCEPT:
2075 if ((count = add_route_dialog->count()) <= 0) {
2079 uint32_t input_chan = add_route_dialog->channels ();
2080 uint32_t output_chan;
2081 string name_template = add_route_dialog->name_template ();
2082 bool track = add_route_dialog->track ();
2084 Session::AutoConnectOption oac = session->get_output_auto_connect();
2086 if (oac & Session::AutoConnectMaster) {
2087 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2089 output_chan = input_chan;
2092 /* XXX do something with name template */
2096 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2098 session_add_audio_bus (input_chan, output_chan);
2102 while (Main::events_pending()) {
2109 ARDOUR_UI::mixer_settings () const
2114 node = session->instant_xml(X_("Mixer"), session->path());
2116 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
2120 node = new XMLNode (X_("Mixer"));
2127 ARDOUR_UI::editor_settings () const
2132 node = session->instant_xml(X_("Editor"), session->path());
2134 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
2138 node = new XMLNode (X_("Editor"));
2144 ARDOUR_UI::keyboard_settings () const
2148 node = Config->extra_xml(X_("Keyboard"));
2151 node = new XMLNode (X_("Keyboard"));
2157 ARDOUR_UI::halt_on_xrun_message ()
2159 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2161 MessageDialog msg (*editor,
2162 _("Recording was stopped because your system could not keep up."));
2167 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2169 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2171 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2175 delete deletion_list;
2179 ARDOUR_UI::disk_overrun_handler ()
2181 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2183 if (!have_disk_overrun_displayed) {
2184 have_disk_overrun_displayed = true;
2185 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2186 The disk system on your computer\n\
2187 was not able to keep up with Ardour.\n\
2189 Specifically, it failed to write data to disk\n\
2190 quickly enough to keep up with recording.\n"));
2192 have_disk_overrun_displayed = false;
2197 ARDOUR_UI::disk_underrun_handler ()
2199 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2201 if (!have_disk_underrun_displayed) {
2202 have_disk_underrun_displayed = true;
2203 MessageDialog msg (*editor,
2204 (_("The disk system on your computer\n\
2205 was not able to keep up with Ardour.\n\
2207 Specifically, it failed to read data from disk\n\
2208 quickly enough to keep up with playback.\n")));
2210 have_disk_underrun_displayed = false;
2215 ARDOUR_UI::disk_underrun_message_gone ()
2217 have_disk_underrun_displayed = false;
2221 ARDOUR_UI::disk_overrun_message_gone ()
2223 have_disk_underrun_displayed = false;
2227 ARDOUR_UI::pending_state_dialog ()
2229 ArdourDialog dialog ("pending state dialog");
2231 This session appears to have been in\n\
2232 middle of recording when ardour or\n\
2233 the computer was shutdown.\n\
2235 Ardour can recover any captured audio for\n\
2236 you, or it can ignore it. Please decide\n\
2237 what you would like to do.\n"));
2239 dialog.get_vbox()->pack_start (message);
2240 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2241 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2243 dialog.set_position (WIN_POS_CENTER);
2246 switch (dialog.run ()) {
2247 case RESPONSE_ACCEPT:
2258 ARDOUR_UI::disconnect_from_jack ()
2261 if( engine->disconnect_from_jack ()) {
2262 MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2266 update_sample_rate (0);
2271 ARDOUR_UI::reconnect_to_jack ()
2274 if (engine->reconnect_to_jack ()) {
2275 MessageDialog msg (*editor, _("Could not reconnect to JACK"));
2279 update_sample_rate (0);
2284 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2286 engine->request_buffer_size (nframes);
2287 update_sample_rate (0);
2291 ARDOUR_UI::cmdline_new_session (string path)
2293 if (path[0] != '/') {
2294 char buf[PATH_MAX+1];
2297 getcwd (buf, sizeof (buf));
2304 new_session (false, path);
2306 _will_create_new_session_automatically = false; /* done it */
2307 return FALSE; /* don't call it again */