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"
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
90 static const gchar *h_meter_strip_xpm[] = {
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
286 static const gchar * v_meter_strip_xpm[] = {
769 static const char* channel_setup_names[] = {
780 vector<string> channel_combo_strings;
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
784 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
786 primary_clock (X_("TransportClockDisplay"), true, false, true),
787 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788 preroll_clock (X_("PreRollClock"), true, true),
789 postroll_clock (X_("PostRollClock"), true, true),
793 adjuster_table (3, 3),
797 preroll_button (_("pre\nroll")),
798 postroll_button (_("post\nroll")),
802 big_clock ("BigClockDisplay", true),
806 shuttle_units_button (_("% ")),
807 shuttle_style_button (_("spring")),
809 punch_in_button (_("punch\nin")),
810 punch_out_button (_("punch\nout")),
811 auto_return_button (_("auto\nreturn")),
812 auto_play_button (_("auto\nplay")),
813 auto_input_button (_("auto\ninput")),
814 click_button (_("click")),
815 follow_button (_("follow\nPH")),
816 auditioning_alert_button (_("AUDITIONING")),
817 solo_alert_button (_("SOLO")),
821 using namespace Gtk::Menu_Helpers;
825 /* actually, its already loaded, but ... */
827 cerr << "Loading UI configuration file " << rcfile << endl;
831 if (theArdourUI == 0) {
835 // allow run-time rebinding of accels
837 Settings::get_default()->property_gtk_can_change_accels() = true;
839 ActionManager::init ();
841 m_new_session_dialog = 0;
842 m_new_session_dialog_ref = NewSessionDialogFactory::create();
843 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
847 _session_is_new = false;
848 big_clock_window = 0;
849 session_selector_window = 0;
850 last_key_press_time = 0;
851 connection_editor = 0;
852 add_route_dialog = 0;
857 open_session_selector = 0;
858 have_configure_timeout = false;
859 have_disk_overrun_displayed = false;
860 have_disk_underrun_displayed = false;
861 _will_create_new_session_automatically = false;
862 session_loaded = false;
865 last_configure_time.tv_sec = 0;
866 last_configure_time.tv_usec = 0;
868 shuttle_grabbed = false;
871 set_shuttle_units (Percentage);
872 set_shuttle_behaviour (Sprung);
874 shuttle_style_menu = 0;
875 shuttle_unit_menu = 0;
877 gettimeofday (&last_peak_grab, 0);
878 gettimeofday (&last_shuttle_request, 0);
880 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
881 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
882 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
883 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
885 /* handle pending state with a dialog */
887 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
889 channel_combo_strings = internationalize (channel_setup_names);
891 /* have to wait for AudioEngine and Configuration before proceeding */
895 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
897 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
899 string msg = string_compose (_("\
900 You cannot record-enable\n\
902 because it has no input connections.\n\
903 You would be wasting space recording silence."),
906 ArdourMessage message (editor, X_("cannotrecord"), msg);
910 ARDOUR_UI::set_engine (AudioEngine& e)
914 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
915 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
916 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
917 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
921 keyboard = new Keyboard;
922 install_keybindings ();
924 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
925 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
927 if (setup_windows ()) {
928 throw failed_constructor ();
931 if (GTK_ARDOUR::show_key_actions) {
932 vector<string> names;
933 vector<string> paths;
935 vector<AccelKey> bindings;
937 ActionManager::get_all_actions (names, paths, keys, bindings);
939 vector<string>::iterator n;
940 vector<string>::iterator k;
941 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
942 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
948 /* start with timecode, metering enabled
951 blink_timeout_tag = -1;
953 /* this being a GUI and all, we want peakfiles */
955 FileSource::set_build_peakfiles (true);
956 FileSource::set_build_missing_peakfiles (true);
958 if (Source::start_peak_thread ()) {
959 throw failed_constructor();
962 /* start the time-of-day-clock */
964 update_wall_clock ();
965 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
967 update_disk_space ();
969 update_sample_rate (engine->frame_rate());
971 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
972 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
975 ARDOUR_UI::~ARDOUR_UI ()
977 save_ardour_state ();
991 if (add_route_dialog) {
992 delete add_route_dialog;
995 Source::stop_peak_thread ();
999 ARDOUR_UI::configure_timeout ()
1002 struct timeval diff;
1004 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1005 /* no configure events yet */
1009 gettimeofday (&now, 0);
1010 timersub (&now, &last_configure_time, &diff);
1012 /* force a gap of 0.5 seconds since the last configure event
1015 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1018 have_configure_timeout = false;
1019 save_ardour_state ();
1025 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1027 if (have_configure_timeout) {
1028 gettimeofday (&last_configure_time, 0);
1030 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1031 have_configure_timeout = true;
1038 ARDOUR_UI::save_ardour_state ()
1040 if (!keyboard || !mixer || !editor) {
1044 /* XXX this is all a bit dubious. add_extra_xml() uses
1045 a different lifetime model from add_instant_xml().
1048 XMLNode* node = new XMLNode (keyboard->get_state());
1049 Config->add_extra_xml (*node);
1050 Config->save_state();
1052 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1053 XMLNode& mnode (mixer->get_state());
1056 session->add_instant_xml(enode, session->path());
1057 session->add_instant_xml(mnode, session->path());
1059 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1060 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1065 ARDOUR_UI::startup ()
1067 /* Once the UI is up and running, start the audio engine. Doing
1068 this before the UI is up and running can cause problems
1069 when not running with SCHED_FIFO, because the amount of
1070 CPU and disk work needed to get the UI started can interfere
1071 with the scheduling of the audio thread.
1074 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1080 if (session && session->dirty()) {
1081 switch (ask_about_saving_session(_("quit"))) {
1086 /* use the default name */
1087 if (save_state_canfail ("")) {
1088 /* failed - don't quit */
1089 ArdourMessage (editor, X_("badsave dialog"),
1091 Ardour was unable to save your session.\n\n\
1092 If you still wish to quit, please use the\n\n\
1093 \"Just quit\" option."));
1106 ARDOUR_UI::ask_about_saving_session (string what)
1108 ArdourDialog window (_("ardour: save session?"));
1109 Gtk::Label prompt_label;
1112 msg = string_compose(_("Save and %1"), what);
1113 window.add_button (msg, RESPONSE_ACCEPT);
1114 msg = string_compose(_("Just %1"), what);
1115 window.add_button (msg, RESPONSE_APPLY);
1116 msg = string_compose(_("Don't %1"), what);
1117 window.add_button (msg, RESPONSE_REJECT);
1119 Gtk::Button noquit_button (msg);
1120 noquit_button.set_name ("EditorGTKButton");
1125 if (session->snap_name() == session->name()) {
1126 type = _("session");
1128 type = _("snapshot");
1130 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?"),
1131 type, session->snap_name());
1133 prompt_label.set_text (prompt);
1134 prompt_label.set_alignment (0.5, 0.5);
1135 prompt_label.set_name (X_("PrompterLabel"));
1137 window.get_vbox()->pack_start (prompt_label);
1139 window.set_name (_("Prompter"));
1140 window.set_position (Gtk::WIN_POS_MOUSE);
1141 window.set_modal (true);
1144 save_the_session = 0;
1146 editor->ensure_float (window);
1148 ResponseType r = (ResponseType) window.run();
1153 case RESPONSE_ACCEPT: // save and get out of here
1155 case RESPONSE_APPLY: // get out of here
1165 ARDOUR_UI::every_second ()
1168 update_buffer_load ();
1169 update_disk_space ();
1170 // update_disk_rate ();
1175 ARDOUR_UI::every_point_one_seconds ()
1178 struct timeval diff;
1180 /* do not attempt to grab peak power more than once per cycle.
1183 gettimeofday (&now, 0);
1184 timersub (&now, &last_peak_grab, &diff);
1186 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1187 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1188 last_peak_grab = now;
1191 update_speed_display ();
1192 RapidScreenUpdate(); /* EMIT_SIGNAL */
1197 ARDOUR_UI::every_point_zero_one_seconds ()
1199 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1204 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1208 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1210 if (!engine->connected()) {
1212 snprintf (buf, sizeof (buf), _("disconnected"));
1216 jack_nframes_t rate = engine->frame_rate();
1218 if (fmod (rate, 1000.0) != 0.0) {
1219 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1220 (float) rate/1000.0f,
1221 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1223 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1225 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1229 sample_rate_label.set_text (buf);
1233 ARDOUR_UI::update_cpu_load ()
1236 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1237 cpu_load_label.set_text (buf);
1241 ARDOUR_UI::update_disk_rate ()
1246 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1247 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1248 disk_rate_label.set_text (buf);
1250 disk_rate_label.set_text ("");
1255 ARDOUR_UI::update_buffer_load ()
1260 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1261 session->playback_load(), session->capture_load());
1262 buffer_load_label.set_text (buf);
1264 buffer_load_label.set_text ("");
1269 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1271 if (ds.record_enabled()) {
1272 rec_enabled_diskstreams++;
1277 ARDOUR_UI::update_disk_space()
1283 jack_nframes_t frames = session->available_capture_duration();
1286 if (frames == max_frames) {
1287 strcpy (buf, _("space: 24hrs+"));
1292 jack_nframes_t fr = session->frame_rate();
1294 if (session->actively_recording()){
1296 rec_enabled_diskstreams = 0;
1297 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1299 if (rec_enabled_diskstreams) {
1300 frames /= rec_enabled_diskstreams;
1305 /* hmmm. shall we divide by the route count? or the diskstream count?
1306 or what? for now, do nothing ...
1311 hrs = frames / (fr * 3600);
1312 frames -= hrs * fr * 3600;
1313 mins = frames / (fr * 60);
1314 frames -= mins * fr * 60;
1317 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1320 disk_space_label.set_text (buf);
1324 ARDOUR_UI::update_wall_clock ()
1331 tm_now = localtime (&now);
1333 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1334 wall_clock_label.set_text (buf);
1340 ARDOUR_UI::toggle_recording_plugins ()
1342 /* XXX use toggle_some_session_state */
1348 session->set_recording_plugins (!session->get_recording_plugins());
1352 ARDOUR_UI::toggle_auto_play ()
1355 toggle_some_session_state (auto_play_button,
1356 &Session::get_auto_play,
1357 &Session::set_auto_play);
1361 ARDOUR_UI::toggle_auto_return ()
1364 toggle_some_session_state (auto_return_button,
1365 &Session::get_auto_return,
1366 &Session::set_auto_return);
1370 ARDOUR_UI::toggle_click ()
1372 toggle_some_session_state (click_button,
1373 &Session::get_clicking,
1374 &Session::set_clicking);
1378 ARDOUR_UI::follow_changed ()
1386 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1387 follow_button.set_active (x);
1392 ARDOUR_UI::toggle_follow ()
1400 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1401 editor->set_follow_playhead (x);
1406 ARDOUR_UI::toggle_session_auto_loop ()
1409 if (session->get_auto_loop()) {
1410 if (session->transport_rolling()) {
1414 session->request_auto_loop (false);
1418 session->request_auto_loop (true);
1424 ARDOUR_UI::toggle_session_punch_in ()
1427 session->set_punch_in (!session->get_punch_in());
1432 ARDOUR_UI::toggle_punch_out ()
1434 toggle_some_session_state (punch_out_button,
1435 &Session::get_punch_out,
1436 &Session::set_punch_out);
1440 ARDOUR_UI::toggle_punch_in ()
1442 toggle_some_session_state (punch_in_button,
1443 &Session::get_punch_in,
1444 &Session::set_punch_in);
1448 ARDOUR_UI::map_button_state ()
1451 map_some_session_state (auto_return_button,
1452 &Session::get_auto_return);
1453 map_some_session_state (auto_play_button,
1454 &Session::get_auto_play);
1455 map_some_session_state (auto_input_button,
1456 &Session::get_auto_input);
1457 map_some_session_state (punch_in_button,
1458 &Session::get_punch_in);
1459 map_some_session_state (punch_out_button,
1460 &Session::get_punch_out);
1461 map_some_session_state (click_button,
1462 &Session::get_clicking);
1466 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1468 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1472 ARDOUR_UI::map_control_change (Session::ControlType t)
1475 case Session::AutoPlay:
1476 map_some_session_state (auto_play_button, &Session::get_auto_play);
1479 case Session::AutoLoop:
1482 case Session::AutoReturn:
1483 map_some_session_state (auto_return_button, &Session::get_auto_return);
1486 case Session::AutoInput:
1487 map_some_session_state (auto_input_button, &Session::get_auto_input);
1490 case Session::PunchOut:
1491 map_some_session_state (punch_in_button, &Session::get_punch_out);
1494 case Session::PunchIn:
1495 map_some_session_state (punch_in_button, &Session::get_punch_in);
1498 case Session::Clicking:
1499 map_some_session_state (click_button, &Session::get_clicking);
1502 case Session::SlaveType:
1503 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1506 case Session::SendMTC:
1507 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1510 case Session::SendMMC:
1511 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1514 case Session::MMCControl:
1515 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1518 case Session::MidiFeedback:
1519 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1521 case Session::MidiControl:
1522 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1528 case Session::RecordingPlugins:
1531 case Session::CrossFadesActive:
1534 case Session::EditingMode:
1537 case Session::PlayRange:
1540 case Session::AlignChoice:
1541 /* don't care, this is handled by the options editor */
1543 case Session::SeamlessLoop:
1544 /* don't care, this is handled by the options editor */
1551 ARDOUR_UI::control_methods_adjusted ()
1556 which_method = (int) online_control_button->adjustment.get_value();
1557 switch (which_method) {
1559 allow_mmc_and_local ();
1565 allow_local_only ();
1568 fatal << _("programming error: impossible control method") << endmsg;
1574 ARDOUR_UI::mmc_device_id_adjusted ()
1579 int dev_id = (int) mmc_id_button->adjustment.get_value();
1580 mmc->set_device_id (dev_id);
1586 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1587 bool (Session::*get)() const)
1596 if (button.get_active() != (x = (session->*get)())) {
1597 button.set_active (x);
1602 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1603 bool (Session::*get)() const,
1604 void (Session::*set)(bool))
1614 button_state = button.get_active ();
1615 session_state = (session->*get)();
1617 if (button_state != session_state) {
1618 (session->*set) (button_state);
1621 /* check that it worked, and reverse
1622 the button state if it didn't
1625 if ((session->*get)() != button_state) {
1626 button->set_active (!button_state);
1634 ARDOUR_UI::session_menu (GdkEventButton *ev)
1636 session_popup_menu->popup (0, 0);
1641 ARDOUR_UI::redisplay_recent_sessions ()
1643 vector<string *> *sessions;
1644 vector<string *>::iterator i;
1645 RecentSessionsSorter cmp;
1647 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1648 recent_session_model->clear ();
1651 ARDOUR::read_recent_sessions (rs);
1654 recent_session_display.set_model (recent_session_model);
1658 /* sort them alphabetically */
1659 sort (rs.begin(), rs.end(), cmp);
1660 sessions = new vector<string*>;
1662 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1663 sessions->push_back (new string ((*i).second));
1666 for (i = sessions->begin(); i != sessions->end(); ++i) {
1668 vector<string*>* states;
1669 vector<const gchar*> item;
1670 string fullpath = *(*i);
1672 /* remove any trailing / */
1674 if (fullpath[fullpath.length()-1] == '/') {
1675 fullpath = fullpath.substr (0, fullpath.length()-1);
1678 /* now get available states for this session */
1680 if ((states = Session::possible_states (fullpath)) == 0) {
1681 /* no state file? */
1685 TreeModel::Row row = *(recent_session_model->append());
1687 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1688 row[recent_session_columns.fullpath] = fullpath;
1690 if (states->size() > 1) {
1692 /* add the children */
1694 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1696 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1698 child_row[recent_session_columns.visible_name] = **i2;
1699 child_row[recent_session_columns.fullpath] = fullpath;
1708 recent_session_display.set_model (recent_session_model);
1713 ARDOUR_UI::build_session_selector ()
1715 session_selector_window = new ArdourDialog ("session selector");
1717 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1719 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1720 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1722 recent_session_model = TreeStore::create (recent_session_columns);
1723 recent_session_display.set_model (recent_session_model);
1724 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1725 recent_session_display.set_headers_visible (false);
1727 scroller->add (recent_session_display);
1728 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1730 session_selector_window->set_name ("SessionSelectorWindow");
1731 session_selector_window->set_size_request (200, 400);
1732 session_selector_window->get_vbox()->pack_start (*scroller);
1733 session_selector_window->show_all_children();
1737 ARDOUR_UI::open_recent_session ()
1739 /* popup selector window */
1741 if (session_selector_window == 0) {
1742 build_session_selector ();
1745 redisplay_recent_sessions ();
1747 ResponseType r = (ResponseType) session_selector_window->run ();
1749 session_selector_window->hide();
1752 case RESPONSE_ACCEPT:
1758 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1760 if (i == recent_session_model->children().end()) {
1764 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1765 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1767 _session_is_new = false;
1769 load_session (path, state);
1773 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1775 struct stat statbuf;
1777 if (stat (info.filename.c_str(), &statbuf) != 0) {
1781 if (!S_ISDIR(statbuf.st_mode)) {
1785 string session_file = info.filename;
1786 session_file += '/';
1787 session_file += PBD::basename (info.filename);
1788 session_file += ".ardour";
1790 if (stat (session_file.c_str(), &statbuf) != 0) {
1794 return S_ISREG (statbuf.st_mode);
1798 ARDOUR_UI::open_session ()
1800 /* popup selector window */
1802 if (open_session_selector == 0) {
1804 /* ardour sessions are folders */
1806 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1807 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1808 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1810 FileFilter session_filter;
1811 session_filter.add_pattern ("*.ardour");
1812 session_filter.set_name (_("Ardour sessions"));
1813 open_session_selector->add_filter (session_filter);
1814 open_session_selector->set_filter (session_filter);
1817 int response = open_session_selector->run();
1818 open_session_selector->hide ();
1821 case RESPONSE_ACCEPT:
1824 open_session_selector->hide();
1828 open_session_selector->hide();
1829 string session_path = open_session_selector->get_filename();
1833 if (session_path.length() > 0) {
1834 if (Session::find_session (session_path, path, name, isnew) == 0) {
1835 _session_is_new = isnew;
1836 load_session (path, name);
1843 ARDOUR_UI::session_add_midi_track ()
1845 cerr << _("Patience is a virtue.\n");
1849 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1854 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1860 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1861 error << _("could not create new audio track") << endmsg;
1864 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1865 error << _("could not create new audio bus") << endmsg;
1870 if (need_control_room_outs) {
1876 route->set_stereo_control_outs (control_lr_channels);
1877 route->control_outs()->set_stereo_pan (pans, this);
1879 #endif /* CONTROLOUTS */
1883 ArdourMessage msg (editor, X_("noport dialog"),
1884 _("There are insufficient JACK ports available\n\
1885 to create a new track or bus.\n\
1886 You should save Ardour, exit and\n\
1887 restart JACK with more ports."));
1892 ARDOUR_UI::diskstream_added (DiskStream* ds)
1897 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1899 jack_nframes_t _preroll;
1902 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1904 if (new_position > _preroll) {
1905 new_position -= _preroll;
1910 session->request_locate (new_position);
1915 ARDOUR_UI::transport_goto_start ()
1918 session->request_locate (0);
1921 /* force displayed area in editor to start no matter
1922 what "follow playhead" setting is.
1926 editor->reposition_x_origin (0);
1932 ARDOUR_UI::transport_goto_end ()
1935 jack_nframes_t frame = session->current_end_frame();
1936 session->request_locate (frame);
1938 /* force displayed area in editor to start no matter
1939 what "follow playhead" setting is.
1943 editor->reposition_x_origin (frame);
1949 ARDOUR_UI::transport_stop ()
1955 if (session->is_auditioning()) {
1956 session->cancel_audition ();
1960 if (session->get_auto_loop()) {
1961 session->request_auto_loop (false);
1964 session->request_stop ();
1968 ARDOUR_UI::transport_stop_and_forget_capture ()
1971 session->request_stop (true);
1976 ARDOUR_UI::remove_last_capture()
1979 editor->remove_last_capture();
1984 ARDOUR_UI::transport_record ()
1987 switch (session->record_status()) {
1988 case Session::Disabled:
1989 if (session->ntracks() == 0) {
1990 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1991 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1994 session->maybe_enable_record ();
1996 case Session::Recording:
1997 case Session::Enabled:
1998 session->disable_record ();
2004 ARDOUR_UI::transport_roll ()
2012 rolling = session->transport_rolling ();
2014 if (session->get_auto_loop()) {
2015 session->request_auto_loop (false);
2016 auto_loop_button.set_active (false);
2017 roll_button.set_active (true);
2018 } else if (session->get_play_range ()) {
2019 session->request_play_range (false);
2020 play_selection_button.set_active (false);
2021 } else if (rolling) {
2022 session->request_locate (session->last_transport_start(), true);
2025 session->request_transport_speed (1.0f);
2029 ARDOUR_UI::transport_loop()
2032 if (session->get_auto_loop()) {
2033 if (session->transport_rolling()) {
2034 Location * looploc = session->locations()->auto_loop_location();
2036 session->request_locate (looploc->start(), true);
2041 session->request_auto_loop (true);
2047 ARDOUR_UI::transport_play_selection ()
2053 if (!session->get_play_range()) {
2054 session->request_stop ();
2057 editor->play_selection ();
2061 ARDOUR_UI::transport_rewind (int option)
2063 float current_transport_speed;
2066 current_transport_speed = session->transport_speed();
2068 if (current_transport_speed >= 0.0f) {
2071 session->request_transport_speed (-1.0f);
2074 session->request_transport_speed (-4.0f);
2077 session->request_transport_speed (-0.5f);
2082 session->request_transport_speed (current_transport_speed * 1.5f);
2088 ARDOUR_UI::transport_forward (int option)
2090 float current_transport_speed;
2093 current_transport_speed = session->transport_speed();
2095 if (current_transport_speed <= 0.0f) {
2098 session->request_transport_speed (1.0f);
2101 session->request_transport_speed (4.0f);
2104 session->request_transport_speed (0.5f);
2109 session->request_transport_speed (current_transport_speed * 1.5f);
2115 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2123 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2124 Port *port = ds->io()->input (0);
2125 port->request_monitor_input (!port->monitoring_input());
2130 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2138 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2139 ds->set_record_enabled (!ds->record_enabled(), this);
2144 ARDOUR_UI::queue_transport_change ()
2146 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2150 ARDOUR_UI::map_transport_state ()
2152 float sp = session->transport_speed();
2155 transport_rolling ();
2156 } else if (sp < 0.0f) {
2157 transport_rewinding ();
2158 } else if (sp > 0.0f) {
2159 transport_forwarding ();
2161 transport_stopped ();
2166 ARDOUR_UI::send_all_midi_feedback ()
2169 session->send_all_midi_feedback();
2174 ARDOUR_UI::allow_local_only ()
2180 ARDOUR_UI::allow_mmc_only ()
2186 ARDOUR_UI::allow_mmc_and_local ()
2192 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2194 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2195 (int) adj.get_value()].c_str());
2199 ARDOUR_UI::engine_stopped ()
2201 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2202 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2203 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2208 ARDOUR_UI::engine_running ()
2210 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2211 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2212 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2216 ARDOUR_UI::engine_halted ()
2218 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2220 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2221 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2223 update_sample_rate (0);
2225 ArdourMessage msg (editor, X_("halted"),
2227 JACK has either been shutdown or it\n\
2228 disconnected Ardour because Ardour\n\
2229 was not fast enough. You can save the\n\
2230 session and/or try to reconnect to JACK ."));
2234 ARDOUR_UI::do_engine_start ()
2240 catch (AudioEngine::PortRegistrationFailure& err) {
2242 error << _("Unable to create all required ports")
2250 error << _("Unable to start the session running")
2260 ARDOUR_UI::start_engine ()
2262 if (do_engine_start () == 0) {
2263 if (session && _session_is_new) {
2264 /* we need to retain initial visual
2265 settings for a new session
2267 session->save_state ("");
2270 /* there is too much going on, in too many threads, for us to
2271 end up with a clean session. So wait 1 second after loading,
2272 and fix it up. its ugly, but until i come across a better
2273 solution, its what we have.
2276 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2283 ARDOUR_UI::update_clocks ()
2285 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2289 ARDOUR_UI::start_clocking ()
2291 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2295 ARDOUR_UI::stop_clocking ()
2297 clock_signal_connection.disconnect ();
2301 ARDOUR_UI::toggle_clocking ()
2304 if (clock_button.get_active()) {
2313 ARDOUR_UI::_blink (void *arg)
2316 ((ARDOUR_UI *) arg)->blink ();
2323 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2327 ARDOUR_UI::start_blinking ()
2329 /* Start the blink signal. Everybody with a blinking widget
2330 uses Blink to drive the widget's state.
2333 if (blink_timeout_tag < 0) {
2335 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2340 ARDOUR_UI::stop_blinking ()
2342 if (blink_timeout_tag >= 0) {
2343 gtk_timeout_remove (blink_timeout_tag);
2344 blink_timeout_tag = -1;
2350 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2352 using namespace Gtk;
2353 using namespace Menu_Helpers;
2355 if (dstream.hidden()) {
2359 MenuList& items = diskstream_menu->items();
2360 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2364 ARDOUR_UI::diskstream_selected (gint32 id)
2366 selected_dstream = id;
2371 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2373 using namespace Gtk;
2374 using namespace Menu_Helpers;
2380 diskstream_menu = new Menu();
2381 diskstream_menu->set_name ("ArdourContextMenu");
2382 using namespace Gtk;
2383 using namespace Menu_Helpers;
2385 MenuList& items = diskstream_menu->items();
2386 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2388 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2391 diskstream_menu->popup (ev->button, ev->time);
2393 diskstream_menu->popup (0, 0);
2396 selected_dstream = -1;
2400 delete diskstream_menu;
2402 return selected_dstream;
2406 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2412 if (io.n_inputs() == 0) {
2417 /* XXX we're not handling multiple ports yet. */
2419 const char **connections = io.input(0)->get_connections();
2421 if (connections == 0 || connections[0] == '\0') {
2424 buf = connections[0];
2431 if (io.n_outputs() == 0) {
2436 /* XXX we're not handling multiple ports yet. */
2438 const char **connections = io.output(0)->get_connections();
2440 if (connections == 0 || connections[0] == '\0') {
2443 buf = connections[0];
2451 ARDOUR_UI::snapshot_session ()
2453 ArdourPrompter prompter (true);
2460 now = now.substr (0, now.length() - 1);
2462 prompter.set_name ("Prompter");
2463 prompter.set_prompt (_("Name for snapshot"));
2464 prompter.set_initial_text (now);
2466 switch (prompter.run()) {
2467 case RESPONSE_ACCEPT:
2468 prompter.get_result (snapname);
2469 if (snapname.length()){
2470 save_state (snapname);
2480 ARDOUR_UI::save_state (string name)
2482 (void) save_state_canfail (name);
2486 ARDOUR_UI::save_state_canfail (string name)
2491 if (name.length() == 0) {
2492 name = session->snap_name();
2495 if ((ret = session->save_state (name)) != 0) {
2499 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2504 ARDOUR_UI::restore_state (string name)
2507 if (name.length() == 0) {
2508 name = session->name();
2510 session->restore_state (name);
2515 ARDOUR_UI::primary_clock_value_changed ()
2518 session->request_locate (primary_clock.current_time ());
2523 ARDOUR_UI::secondary_clock_value_changed ()
2526 session->request_locate (secondary_clock.current_time ());
2531 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2533 if (session && dstream && dstream->record_enabled()) {
2535 Session::RecordState rs;
2537 rs = session->record_status ();
2540 case Session::Disabled:
2541 case Session::Enabled:
2542 if (w->get_state() != STATE_SELECTED) {
2543 w->set_state (STATE_SELECTED);
2547 case Session::Recording:
2548 if (w->get_state() != STATE_ACTIVE) {
2549 w->set_state (STATE_ACTIVE);
2555 if (w->get_state() != STATE_NORMAL) {
2556 w->set_state (STATE_NORMAL);
2562 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2568 switch (session->record_status()) {
2569 case Session::Enabled:
2571 rec_button.set_state (STATE_ACTIVE);
2573 rec_button.set_state (STATE_NORMAL);
2577 case Session::Recording:
2578 rec_button.set_state (STATE_ACTIVE);
2582 rec_button.set_active (false);
2583 rec_button.set_state (STATE_NORMAL);
2589 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2597 ARDOUR_UI::start_keyboard_prefix ()
2599 keyboard->start_prefix();
2603 ARDOUR_UI::save_template ()
2606 ArdourPrompter prompter (true);
2609 prompter.set_name (X_("Prompter"));
2610 prompter.set_prompt (_("Name for mix template:"));
2611 prompter.set_initial_text(session->name() + _("-template"));
2613 switch (prompter.run()) {
2614 case RESPONSE_ACCEPT:
2615 prompter.get_result (name);
2617 if (name.length()) {
2618 session->save_template (name);
2628 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2630 m_new_session_dialog->show_all();
2631 m_new_session_dialog->set_transient_for(*editor);
2632 m_new_session_dialog->set_name(predetermined_path);
2634 int response = Gtk::RESPONSE_CANCEL;
2637 response = m_new_session_dialog->run ();
2639 if(response == Gtk::RESPONSE_OK) {
2641 _session_is_new = true;
2643 std::string session_name = m_new_session_dialog->session_name();
2644 std::string session_path = m_new_session_dialog->session_folder();
2647 XXX This is needed because session constructor wants a
2648 non-existant path. hopefully this will be fixed at some point.
2650 session_path = Glib::build_filename(session_path, session_name);
2652 std::string template_name = m_new_session_dialog->session_template_name();
2654 if (m_new_session_dialog->use_session_template()) {
2656 load_session (session_path, session_name, &template_name);
2662 Session::AutoConnectOption iconnect;
2663 Session::AutoConnectOption oconnect;
2665 if (m_new_session_dialog->create_control_bus()) {
2666 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2671 if (m_new_session_dialog->create_master_bus()) {
2672 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2677 if (m_new_session_dialog->connect_inputs()) {
2678 iconnect = Session::AutoConnectPhysical;
2680 iconnect = Session::AutoConnectOption (0);
2683 /// @todo some minor tweaks.
2685 if (m_new_session_dialog->connect_outs_to_master()) {
2686 oconnect = Session::AutoConnectMaster;
2687 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2688 oconnect = Session::AutoConnectPhysical;
2690 oconnect = Session::AutoConnectOption (0);
2693 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2694 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2696 build_session (session_path,
2704 engine->frame_rate() * 60 * 5);
2708 } while(response == Gtk::RESPONSE_HELP);
2709 m_new_session_dialog->hide_all();
2713 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2715 Session *new_session;
2717 session_loaded = false;
2718 x = unload_session ();
2726 /* if it already exists, we must have write access */
2728 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2729 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2730 You do not have write access to this session.\n\
2731 This prevents the session from being loaded."));
2736 new_session = new Session (*engine, path, snap_name, mix_template);
2741 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2745 connect_to_session (new_session);
2747 //if (engine->running()) {
2748 //mixer->show_window();
2750 session_loaded = true;
2755 ARDOUR_UI::make_session_clean ()
2758 session->set_clean ();
2765 ARDOUR_UI::build_session (string path, string snap_name,
2766 uint32_t control_channels,
2767 uint32_t master_channels,
2768 Session::AutoConnectOption input_connect,
2769 Session::AutoConnectOption output_connect,
2772 jack_nframes_t initial_length)
2774 Session *new_session;
2777 session_loaded = false;
2778 x = unload_session ();
2785 _session_is_new = true;
2788 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2789 control_channels, master_channels, nphysin, nphysout, initial_length);
2794 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2798 connect_to_session (new_session);
2800 //if (engine->running()) {
2801 //mixer->show_window();
2803 session_loaded = true;
2811 editor->show_window ();
2815 if (session && mixer) {
2816 // mixer->show_window ();
2825 ARDOUR_UI::show_splash ()
2828 about = new About();
2834 ARDOUR_UI::hide_splash ()
2842 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2846 removed = rep.paths.size();
2849 ArdourMessage msg (editor, X_("cleanupresults"),
2851 No audio files were ready for cleanup\n\n\
2852 If this seems suprising, check for any existing\n\
2853 snapshots. These may still include regions that\n\
2854 require some unused files to continue to exist."));
2858 ArdourDialog results (_("ardour: cleanup"), true);
2860 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2861 CleanupResultsModelColumns() {
2865 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2866 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2870 Glib::RefPtr<Gtk::ListStore> results_model;
2871 CleanupResultsModelColumns results_columns;
2872 Gtk::TreeView results_display;
2874 results_model = ListStore::create (results_columns);
2875 results_display.set_model (results_model);
2876 results_display.append_column (list_title, results_columns.visible_name);
2877 results_display.set_headers_visible (true);
2879 Gtk::ScrolledWindow list_scroller;
2882 if (rep.space < 1048576.0f) {
2884 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2886 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2890 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2892 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2896 results.get_vbox()->pack_start (txt, false, false);
2898 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2899 TreeModel::Row row = *(results_model->append());
2900 row[results_columns.visible_name] = *i;
2901 row[results_columns.fullpath] = *i;
2904 list_scroller.add (results_display);
2905 list_scroller.set_size_request (-1, 250);
2906 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2908 results.get_vbox()->pack_start (list_scroller, true, true);
2909 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2910 results.set_position (Gtk::WIN_POS_MOUSE);
2916 ARDOUR_UI::cleanup ()
2919 /* shouldn't happen: menu item is insensitive */
2923 ArdourDialog checker (_("ardour cleanup"));
2924 Gtk::Label label (_("\
2925 Cleanup is a destructive operation.\n\
2926 ALL undo/redo information will be lost if you cleanup.\n\
2927 Unused audio files will be moved to a \"dead sounds\" location."));
2929 checker.get_vbox()->pack_start (label, false, false);
2930 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2931 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2933 checker.set_name (_("CleanupDialog"));
2934 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2935 checker.set_position (Gtk::WIN_POS_MOUSE);
2937 switch (checker.run()) {
2938 case RESPONSE_ACCEPT:
2944 Session::cleanup_report rep;
2946 editor->prepare_for_cleanup ();
2948 if (session->cleanup_sources (rep)) {
2952 display_cleanup_results (rep,
2955 The following %1 %2 were not in use.\n\
2956 The next time you flush the wastebasket\n\
2957 it will release an additional %3 %4bytes\n\
2963 ARDOUR_UI::flush_trash ()
2966 /* shouldn't happen: menu item is insensitive */
2970 Session::cleanup_report rep;
2972 if (session->cleanup_trash_sources (rep)) {
2976 display_cleanup_results (rep,
2978 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2982 ARDOUR_UI::add_route ()
2990 if (add_route_dialog == 0) {
2991 add_route_dialog = new AddRouteDialog;
2992 editor->ensure_float (*add_route_dialog);
2995 if (add_route_dialog->is_visible()) {
2996 /* we're already doing this */
3000 ResponseType r = (ResponseType) add_route_dialog->run ();
3002 add_route_dialog->hide();
3005 case RESPONSE_ACCEPT:
3012 if ((count = add_route_dialog->count()) <= 0) {
3016 uint32_t input_chan = add_route_dialog->channels ();
3017 uint32_t output_chan;
3018 string name_template = add_route_dialog->name_template ();
3019 bool track = add_route_dialog->track ();
3021 Session::AutoConnectOption oac = session->get_output_auto_connect();
3023 if (oac & Session::AutoConnectMaster) {
3024 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3026 output_chan = input_chan;
3029 /* XXX do something with name template */
3033 session_add_audio_track (input_chan, output_chan);
3035 session_add_audio_bus (input_chan, output_chan);
3039 while (Main::events_pending()) {
3046 ARDOUR_UI::mixer_settings () const
3051 node = session->instant_xml(X_("Mixer"), session->path());
3053 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3057 node = new XMLNode (X_("Mixer"));
3064 ARDOUR_UI::editor_settings () const
3069 node = session->instant_xml(X_("Editor"), session->path());
3071 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3075 node = new XMLNode (X_("Editor"));
3081 ARDOUR_UI::keyboard_settings () const
3085 node = Config->extra_xml(X_("Keyboard"));
3088 node = new XMLNode (X_("Keyboard"));
3094 ARDOUR_UI::halt_on_xrun_message ()
3096 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3098 ArdourMessage msg (editor, X_("haltonxrun"),
3099 _("Recording was stopped because your system could not keep up."));
3103 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3105 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3107 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3111 delete deletion_list;
3115 ARDOUR_UI::disk_overrun_handler ()
3117 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3119 if (!have_disk_overrun_displayed) {
3120 have_disk_overrun_displayed = true;
3121 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3122 The disk system on your computer\n\
3123 was not able to keep up with Ardour.\n\
3125 Specifically, it failed to write data to disk\n\
3126 quickly enough to keep up with recording.\n"));
3127 have_disk_overrun_displayed = false;
3132 ARDOUR_UI::disk_underrun_handler ()
3134 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3136 if (!have_disk_underrun_displayed) {
3137 have_disk_underrun_displayed = true;
3138 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3139 (_("The disk system on your computer\n\
3140 was not able to keep up with Ardour.\n\
3142 Specifically, it failed to read data from disk\n\
3143 quickly enough to keep up with playback.\n")));
3144 have_disk_underrun_displayed = false;
3149 ARDOUR_UI::disk_underrun_message_gone ()
3151 have_disk_underrun_displayed = false;
3155 ARDOUR_UI::disk_overrun_message_gone ()
3157 have_disk_underrun_displayed = false;
3161 ARDOUR_UI::pending_state_dialog ()
3163 ArdourDialog dialog ("pending state dialog");
3165 This session appears to have been in\n\
3166 middle of recording when ardour or\n\
3167 the computer was shutdown.\n\
3169 Ardour can recover any captured audio for\n\
3170 you, or it can ignore it. Please decide\n\
3171 what you would like to do.\n"));
3173 dialog.get_vbox()->pack_start (message);
3174 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3175 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3177 dialog.set_position (WIN_POS_CENTER);
3180 switch (dialog.run ()) {
3181 case RESPONSE_ACCEPT:
3192 ARDOUR_UI::disconnect_from_jack ()
3195 if( engine->disconnect_from_jack ()) {
3196 ArdourMessage msg (editor, X_("nojack dialog"),
3197 _("Could not disconnect from JACK"));
3200 update_sample_rate (0);
3205 ARDOUR_UI::reconnect_to_jack ()
3208 if (engine->reconnect_to_jack ()) {
3209 ArdourMessage msg (editor, X_("nojack dialog"),
3210 _("Could not reconnect to JACK"));
3213 update_sample_rate (0);
3218 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3220 engine->request_buffer_size (nframes);
3221 update_sample_rate (0);
3225 ARDOUR_UI::cmdline_new_session (string path)
3227 if (path[0] != '/') {
3228 char buf[PATH_MAX+1];
3231 getcwd (buf, sizeof (buf));
3238 new_session (false, path);
3240 _will_create_new_session_automatically = false; /* done it */
3241 return FALSE; /* don't call it again */