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;
856 open_session_selector = 0;
857 have_configure_timeout = false;
858 have_disk_overrun_displayed = false;
859 have_disk_underrun_displayed = false;
860 _will_create_new_session_automatically = false;
861 session_loaded = false;
864 last_configure_time.tv_sec = 0;
865 last_configure_time.tv_usec = 0;
867 shuttle_grabbed = false;
870 set_shuttle_units (Percentage);
871 set_shuttle_behaviour (Sprung);
873 shuttle_style_menu = 0;
874 shuttle_unit_menu = 0;
876 gettimeofday (&last_peak_grab, 0);
877 gettimeofday (&last_shuttle_request, 0);
879 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
884 /* handle pending state with a dialog */
886 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
888 channel_combo_strings = internationalize (channel_setup_names);
890 /* have to wait for AudioEngine and Configuration before proceeding */
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
896 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
898 string msg = string_compose (_("\
899 You cannot record-enable\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
905 ArdourMessage message (editor, X_("cannotrecord"), msg);
909 ARDOUR_UI::set_engine (AudioEngine& e)
913 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
920 keyboard = new Keyboard;
921 install_keybindings ();
923 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
926 if (setup_windows ()) {
927 throw failed_constructor ();
930 if (GTK_ARDOUR::show_key_actions) {
931 vector<string> names;
932 vector<string> paths;
934 vector<AccelKey> bindings;
936 ActionManager::get_all_actions (names, paths, keys, bindings);
938 vector<string>::iterator n;
939 vector<string>::iterator k;
940 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
941 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
947 /* start with timecode, metering enabled
950 blink_timeout_tag = -1;
952 /* this being a GUI and all, we want peakfiles */
954 FileSource::set_build_peakfiles (true);
955 FileSource::set_build_missing_peakfiles (true);
957 if (Source::start_peak_thread ()) {
958 throw failed_constructor();
961 /* start the time-of-day-clock */
963 update_wall_clock ();
964 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
966 update_disk_space ();
968 update_sample_rate (engine->frame_rate());
970 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
971 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
974 ARDOUR_UI::~ARDOUR_UI ()
976 save_ardour_state ();
990 if (add_route_dialog) {
991 delete add_route_dialog;
994 Source::stop_peak_thread ();
998 ARDOUR_UI::configure_timeout ()
1001 struct timeval diff;
1003 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1004 /* no configure events yet */
1008 gettimeofday (&now, 0);
1009 timersub (&now, &last_configure_time, &diff);
1011 /* force a gap of 0.5 seconds since the last configure event
1014 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1017 have_configure_timeout = false;
1018 save_ardour_state ();
1024 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1026 if (have_configure_timeout) {
1027 gettimeofday (&last_configure_time, 0);
1029 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1030 have_configure_timeout = true;
1037 ARDOUR_UI::save_ardour_state ()
1039 if (!keyboard || !mixer || !editor) {
1043 /* XXX this is all a bit dubious. add_extra_xml() uses
1044 a different lifetime model from add_instant_xml().
1047 XMLNode* node = new XMLNode (keyboard->get_state());
1048 Config->add_extra_xml (*node);
1049 Config->save_state();
1051 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1052 XMLNode& mnode (mixer->get_state());
1055 session->add_instant_xml(enode, session->path());
1056 session->add_instant_xml(mnode, session->path());
1058 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1059 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1064 ARDOUR_UI::startup ()
1066 /* Once the UI is up and running, start the audio engine. Doing
1067 this before the UI is up and running can cause problems
1068 when not running with SCHED_FIFO, because the amount of
1069 CPU and disk work needed to get the UI started can interfere
1070 with the scheduling of the audio thread.
1073 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1079 if (session && session->dirty()) {
1080 switch (ask_about_saving_session(_("quit"))) {
1085 /* use the default name */
1086 if (save_state_canfail ("")) {
1087 /* failed - don't quit */
1088 ArdourMessage (editor, X_("badsave dialog"),
1090 Ardour was unable to save your session.\n\n\
1091 If you still wish to quit, please use the\n\n\
1092 \"Just quit\" option."));
1105 ARDOUR_UI::ask_about_saving_session (string what)
1107 ArdourDialog window (_("ardour: save session?"));
1108 Gtk::Label prompt_label;
1111 msg = string_compose(_("Save and %1"), what);
1112 window.add_button (msg, RESPONSE_ACCEPT);
1113 msg = string_compose(_("Just %1"), what);
1114 window.add_button (msg, RESPONSE_APPLY);
1115 msg = string_compose(_("Don't %1"), what);
1116 window.add_button (msg, RESPONSE_REJECT);
1118 Gtk::Button noquit_button (msg);
1119 noquit_button.set_name ("EditorGTKButton");
1124 if (session->snap_name() == session->name()) {
1125 type = _("session");
1127 type = _("snapshot");
1129 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?"),
1130 type, session->snap_name());
1132 prompt_label.set_text (prompt);
1133 prompt_label.set_alignment (0.5, 0.5);
1134 prompt_label.set_name (X_("PrompterLabel"));
1136 window.get_vbox()->pack_start (prompt_label);
1138 window.set_name (_("Prompter"));
1139 window.set_position (Gtk::WIN_POS_MOUSE);
1140 window.set_modal (true);
1143 save_the_session = 0;
1145 editor->ensure_float (window);
1147 ResponseType r = (ResponseType) window.run();
1152 case RESPONSE_ACCEPT: // save and get out of here
1154 case RESPONSE_APPLY: // get out of here
1164 ARDOUR_UI::every_second ()
1167 update_buffer_load ();
1168 update_disk_space ();
1169 // update_disk_rate ();
1174 ARDOUR_UI::every_point_one_seconds ()
1177 struct timeval diff;
1179 /* do not attempt to grab peak power more than once per cycle.
1182 gettimeofday (&now, 0);
1183 timersub (&now, &last_peak_grab, &diff);
1185 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1186 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1187 last_peak_grab = now;
1190 update_speed_display ();
1191 RapidScreenUpdate(); /* EMIT_SIGNAL */
1196 ARDOUR_UI::every_point_zero_one_seconds ()
1198 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1203 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1207 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1209 if (!engine->connected()) {
1211 snprintf (buf, sizeof (buf), _("disconnected"));
1215 jack_nframes_t rate = engine->frame_rate();
1217 if (fmod (rate, 1000.0) != 0.0) {
1218 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1219 (float) rate/1000.0f,
1220 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1222 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1224 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1228 sample_rate_label.set_text (buf);
1232 ARDOUR_UI::update_cpu_load ()
1235 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1236 cpu_load_label.set_text (buf);
1240 ARDOUR_UI::update_disk_rate ()
1245 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1246 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1247 disk_rate_label.set_text (buf);
1249 disk_rate_label.set_text ("");
1254 ARDOUR_UI::update_buffer_load ()
1259 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1260 session->playback_load(), session->capture_load());
1261 buffer_load_label.set_text (buf);
1263 buffer_load_label.set_text ("");
1268 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1270 if (ds.record_enabled()) {
1271 rec_enabled_diskstreams++;
1276 ARDOUR_UI::update_disk_space()
1282 jack_nframes_t frames = session->available_capture_duration();
1285 if (frames == max_frames) {
1286 strcpy (buf, _("space: 24hrs+"));
1291 jack_nframes_t fr = session->frame_rate();
1293 if (session->actively_recording()){
1295 rec_enabled_diskstreams = 0;
1296 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1298 if (rec_enabled_diskstreams) {
1299 frames /= rec_enabled_diskstreams;
1304 /* hmmm. shall we divide by the route count? or the diskstream count?
1305 or what? for now, do nothing ...
1310 hrs = frames / (fr * 3600);
1311 frames -= hrs * fr * 3600;
1312 mins = frames / (fr * 60);
1313 frames -= mins * fr * 60;
1316 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1319 disk_space_label.set_text (buf);
1323 ARDOUR_UI::update_wall_clock ()
1330 tm_now = localtime (&now);
1332 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1333 wall_clock_label.set_text (buf);
1339 ARDOUR_UI::toggle_recording_plugins ()
1341 /* XXX use toggle_some_session_state */
1347 session->set_recording_plugins (!session->get_recording_plugins());
1351 ARDOUR_UI::toggle_auto_play ()
1354 toggle_some_session_state (auto_play_button,
1355 &Session::get_auto_play,
1356 &Session::set_auto_play);
1360 ARDOUR_UI::toggle_auto_return ()
1363 toggle_some_session_state (auto_return_button,
1364 &Session::get_auto_return,
1365 &Session::set_auto_return);
1369 ARDOUR_UI::toggle_click ()
1371 toggle_some_session_state (click_button,
1372 &Session::get_clicking,
1373 &Session::set_clicking);
1377 ARDOUR_UI::follow_changed ()
1385 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1386 follow_button.set_active (x);
1391 ARDOUR_UI::toggle_follow ()
1399 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1400 editor->set_follow_playhead (x);
1405 ARDOUR_UI::toggle_session_auto_loop ()
1408 if (session->get_auto_loop()) {
1409 if (session->transport_rolling()) {
1413 session->request_auto_loop (false);
1417 session->request_auto_loop (true);
1423 ARDOUR_UI::toggle_session_punch_in ()
1426 session->set_punch_in (!session->get_punch_in());
1431 ARDOUR_UI::toggle_punch_out ()
1433 toggle_some_session_state (punch_out_button,
1434 &Session::get_punch_out,
1435 &Session::set_punch_out);
1439 ARDOUR_UI::toggle_punch_in ()
1441 toggle_some_session_state (punch_in_button,
1442 &Session::get_punch_in,
1443 &Session::set_punch_in);
1447 ARDOUR_UI::map_button_state ()
1450 map_some_session_state (auto_return_button,
1451 &Session::get_auto_return);
1452 map_some_session_state (auto_play_button,
1453 &Session::get_auto_play);
1454 map_some_session_state (auto_input_button,
1455 &Session::get_auto_input);
1456 map_some_session_state (punch_in_button,
1457 &Session::get_punch_in);
1458 map_some_session_state (punch_out_button,
1459 &Session::get_punch_out);
1460 map_some_session_state (click_button,
1461 &Session::get_clicking);
1465 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1467 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1471 ARDOUR_UI::map_control_change (Session::ControlType t)
1474 case Session::AutoPlay:
1475 map_some_session_state (auto_play_button, &Session::get_auto_play);
1478 case Session::AutoLoop:
1481 case Session::AutoReturn:
1482 map_some_session_state (auto_return_button, &Session::get_auto_return);
1485 case Session::AutoInput:
1486 map_some_session_state (auto_input_button, &Session::get_auto_input);
1489 case Session::PunchOut:
1490 map_some_session_state (punch_in_button, &Session::get_punch_out);
1493 case Session::PunchIn:
1494 map_some_session_state (punch_in_button, &Session::get_punch_in);
1497 case Session::Clicking:
1498 map_some_session_state (click_button, &Session::get_clicking);
1501 case Session::SlaveType:
1502 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1505 case Session::SendMTC:
1506 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1509 case Session::SendMMC:
1510 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1513 case Session::MMCControl:
1514 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1517 case Session::MidiFeedback:
1518 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1520 case Session::MidiControl:
1521 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1527 case Session::RecordingPlugins:
1530 case Session::CrossFadesActive:
1533 case Session::EditingMode:
1536 case Session::PlayRange:
1539 case Session::AlignChoice:
1540 /* don't care, this is handled by the options editor */
1542 case Session::SeamlessLoop:
1543 /* don't care, this is handled by the options editor */
1550 ARDOUR_UI::control_methods_adjusted ()
1555 which_method = (int) online_control_button->adjustment.get_value();
1556 switch (which_method) {
1558 allow_mmc_and_local ();
1564 allow_local_only ();
1567 fatal << _("programming error: impossible control method") << endmsg;
1573 ARDOUR_UI::mmc_device_id_adjusted ()
1578 int dev_id = (int) mmc_id_button->adjustment.get_value();
1579 mmc->set_device_id (dev_id);
1585 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1586 bool (Session::*get)() const)
1595 if (button.get_active() != (x = (session->*get)())) {
1596 button.set_active (x);
1601 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1602 bool (Session::*get)() const,
1603 void (Session::*set)(bool))
1613 button_state = button.get_active ();
1614 session_state = (session->*get)();
1616 if (button_state != session_state) {
1617 (session->*set) (button_state);
1620 /* check that it worked, and reverse
1621 the button state if it didn't
1624 if ((session->*get)() != button_state) {
1625 button->set_active (!button_state);
1633 ARDOUR_UI::session_menu (GdkEventButton *ev)
1635 session_popup_menu->popup (0, 0);
1640 ARDOUR_UI::redisplay_recent_sessions ()
1642 vector<string *> *sessions;
1643 vector<string *>::iterator i;
1644 RecentSessionsSorter cmp;
1646 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1647 recent_session_model->clear ();
1650 ARDOUR::read_recent_sessions (rs);
1653 recent_session_display.set_model (recent_session_model);
1657 /* sort them alphabetically */
1658 sort (rs.begin(), rs.end(), cmp);
1659 sessions = new vector<string*>;
1661 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1662 sessions->push_back (new string ((*i).second));
1665 for (i = sessions->begin(); i != sessions->end(); ++i) {
1667 vector<string*>* states;
1668 vector<const gchar*> item;
1669 string fullpath = *(*i);
1671 /* remove any trailing / */
1673 if (fullpath[fullpath.length()-1] == '/') {
1674 fullpath = fullpath.substr (0, fullpath.length()-1);
1677 /* now get available states for this session */
1679 if ((states = Session::possible_states (fullpath)) == 0) {
1680 /* no state file? */
1684 TreeModel::Row row = *(recent_session_model->append());
1686 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1687 row[recent_session_columns.fullpath] = fullpath;
1689 if (states->size() > 1) {
1691 /* add the children */
1693 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1695 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1697 child_row[recent_session_columns.visible_name] = **i2;
1698 child_row[recent_session_columns.fullpath] = fullpath;
1707 recent_session_display.set_model (recent_session_model);
1712 ARDOUR_UI::build_session_selector ()
1714 session_selector_window = new ArdourDialog ("session selector");
1716 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1718 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1719 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1721 recent_session_model = TreeStore::create (recent_session_columns);
1722 recent_session_display.set_model (recent_session_model);
1723 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1724 recent_session_display.set_headers_visible (false);
1726 scroller->add (recent_session_display);
1727 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1729 session_selector_window->set_name ("SessionSelectorWindow");
1730 session_selector_window->set_size_request (200, 400);
1731 session_selector_window->get_vbox()->pack_start (*scroller);
1732 session_selector_window->show_all_children();
1736 ARDOUR_UI::open_recent_session ()
1738 /* popup selector window */
1740 if (session_selector_window == 0) {
1741 build_session_selector ();
1744 redisplay_recent_sessions ();
1746 ResponseType r = (ResponseType) session_selector_window->run ();
1748 session_selector_window->hide();
1751 case RESPONSE_ACCEPT:
1757 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1759 if (i == recent_session_model->children().end()) {
1763 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1764 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1766 _session_is_new = false;
1768 load_session (path, state);
1772 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1774 struct stat statbuf;
1776 if (stat (info.filename.c_str(), &statbuf) != 0) {
1780 if (!S_ISDIR(statbuf.st_mode)) {
1784 string session_file = info.filename;
1785 session_file += '/';
1786 session_file += PBD::basename (info.filename);
1787 session_file += ".ardour";
1789 if (stat (session_file.c_str(), &statbuf) != 0) {
1793 return S_ISREG (statbuf.st_mode);
1797 ARDOUR_UI::open_session ()
1799 /* popup selector window */
1801 if (open_session_selector == 0) {
1803 /* ardour sessions are folders */
1805 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1806 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1807 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1809 FileFilter session_filter;
1810 session_filter.add_pattern ("*.ardour");
1811 session_filter.set_name (_("Ardour sessions"));
1812 open_session_selector->add_filter (session_filter);
1813 open_session_selector->set_filter (session_filter);
1816 int response = open_session_selector->run();
1817 open_session_selector->hide ();
1820 case RESPONSE_ACCEPT:
1823 open_session_selector->hide();
1827 open_session_selector->hide();
1828 string session_path = open_session_selector->get_filename();
1832 if (session_path.length() > 0) {
1833 if (Session::find_session (session_path, path, name, isnew) == 0) {
1834 _session_is_new = isnew;
1835 load_session (path, name);
1842 ARDOUR_UI::session_add_midi_track ()
1844 cerr << _("Patience is a virtue.\n");
1848 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1853 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1859 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1860 error << _("could not create new audio track") << endmsg;
1863 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1864 error << _("could not create new audio bus") << endmsg;
1869 if (need_control_room_outs) {
1875 route->set_stereo_control_outs (control_lr_channels);
1876 route->control_outs()->set_stereo_pan (pans, this);
1878 #endif /* CONTROLOUTS */
1882 ArdourMessage msg (editor, X_("noport dialog"),
1883 _("There are insufficient JACK ports available\n\
1884 to create a new track or bus.\n\
1885 You should save Ardour, exit and\n\
1886 restart JACK with more ports."));
1891 ARDOUR_UI::diskstream_added (DiskStream* ds)
1896 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1898 jack_nframes_t _preroll;
1901 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1903 if (new_position > _preroll) {
1904 new_position -= _preroll;
1909 session->request_locate (new_position);
1914 ARDOUR_UI::transport_goto_start ()
1917 session->request_locate (0);
1920 /* force displayed area in editor to start no matter
1921 what "follow playhead" setting is.
1925 editor->reposition_x_origin (0);
1931 ARDOUR_UI::transport_goto_end ()
1934 jack_nframes_t frame = session->current_end_frame();
1935 session->request_locate (frame);
1937 /* force displayed area in editor to start no matter
1938 what "follow playhead" setting is.
1942 editor->reposition_x_origin (frame);
1948 ARDOUR_UI::transport_stop ()
1954 if (session->is_auditioning()) {
1955 session->cancel_audition ();
1959 if (session->get_auto_loop()) {
1960 session->request_auto_loop (false);
1963 session->request_stop ();
1967 ARDOUR_UI::transport_stop_and_forget_capture ()
1970 session->request_stop (true);
1975 ARDOUR_UI::remove_last_capture()
1978 editor->remove_last_capture();
1983 ARDOUR_UI::transport_record ()
1986 switch (session->record_status()) {
1987 case Session::Disabled:
1988 if (session->ntracks() == 0) {
1989 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1990 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1993 session->maybe_enable_record ();
1995 case Session::Recording:
1996 case Session::Enabled:
1997 session->disable_record ();
2003 ARDOUR_UI::transport_roll ()
2011 rolling = session->transport_rolling ();
2013 if (session->get_auto_loop()) {
2014 session->request_auto_loop (false);
2015 auto_loop_button.set_active (false);
2016 roll_button.set_active (true);
2017 } else if (session->get_play_range ()) {
2018 session->request_play_range (false);
2019 play_selection_button.set_active (false);
2020 } else if (rolling) {
2021 session->request_locate (session->last_transport_start(), true);
2024 session->request_transport_speed (1.0f);
2028 ARDOUR_UI::transport_loop()
2031 if (session->get_auto_loop()) {
2032 if (session->transport_rolling()) {
2033 Location * looploc = session->locations()->auto_loop_location();
2035 session->request_locate (looploc->start(), true);
2040 session->request_auto_loop (true);
2046 ARDOUR_UI::transport_play_selection ()
2052 if (!session->get_play_range()) {
2053 session->request_stop ();
2056 editor->play_selection ();
2060 ARDOUR_UI::transport_rewind (int option)
2062 float current_transport_speed;
2065 current_transport_speed = session->transport_speed();
2067 if (current_transport_speed >= 0.0f) {
2070 session->request_transport_speed (-1.0f);
2073 session->request_transport_speed (-4.0f);
2076 session->request_transport_speed (-0.5f);
2081 session->request_transport_speed (current_transport_speed * 1.5f);
2087 ARDOUR_UI::transport_forward (int option)
2089 float current_transport_speed;
2092 current_transport_speed = session->transport_speed();
2094 if (current_transport_speed <= 0.0f) {
2097 session->request_transport_speed (1.0f);
2100 session->request_transport_speed (4.0f);
2103 session->request_transport_speed (0.5f);
2108 session->request_transport_speed (current_transport_speed * 1.5f);
2114 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2122 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2123 Port *port = ds->io()->input (0);
2124 port->request_monitor_input (!port->monitoring_input());
2129 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2137 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2138 ds->set_record_enabled (!ds->record_enabled(), this);
2143 ARDOUR_UI::queue_transport_change ()
2145 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2149 ARDOUR_UI::map_transport_state ()
2151 float sp = session->transport_speed();
2154 transport_rolling ();
2155 } else if (sp < 0.0f) {
2156 transport_rewinding ();
2157 } else if (sp > 0.0f) {
2158 transport_forwarding ();
2160 transport_stopped ();
2165 ARDOUR_UI::send_all_midi_feedback ()
2168 session->send_all_midi_feedback();
2173 ARDOUR_UI::allow_local_only ()
2179 ARDOUR_UI::allow_mmc_only ()
2185 ARDOUR_UI::allow_mmc_and_local ()
2191 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2193 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2194 (int) adj.get_value()].c_str());
2198 ARDOUR_UI::engine_stopped ()
2200 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2201 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2202 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2207 ARDOUR_UI::engine_running ()
2209 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2210 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2211 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2215 ARDOUR_UI::engine_halted ()
2217 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2219 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2220 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2222 update_sample_rate (0);
2224 ArdourMessage msg (editor, X_("halted"),
2226 JACK has either been shutdown or it\n\
2227 disconnected Ardour because Ardour\n\
2228 was not fast enough. You can save the\n\
2229 session and/or try to reconnect to JACK ."));
2233 ARDOUR_UI::do_engine_start ()
2239 catch (AudioEngine::PortRegistrationFailure& err) {
2241 error << _("Unable to create all required ports")
2249 error << _("Unable to start the session running")
2259 ARDOUR_UI::start_engine ()
2261 if (do_engine_start () == 0) {
2262 if (session && _session_is_new) {
2263 /* we need to retain initial visual
2264 settings for a new session
2266 session->save_state ("");
2269 /* there is too much going on, in too many threads, for us to
2270 end up with a clean session. So wait 1 second after loading,
2271 and fix it up. its ugly, but until i come across a better
2272 solution, its what we have.
2275 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2282 ARDOUR_UI::update_clocks ()
2284 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2288 ARDOUR_UI::start_clocking ()
2290 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2294 ARDOUR_UI::stop_clocking ()
2296 clock_signal_connection.disconnect ();
2300 ARDOUR_UI::toggle_clocking ()
2303 if (clock_button.get_active()) {
2312 ARDOUR_UI::_blink (void *arg)
2315 ((ARDOUR_UI *) arg)->blink ();
2322 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2326 ARDOUR_UI::start_blinking ()
2328 /* Start the blink signal. Everybody with a blinking widget
2329 uses Blink to drive the widget's state.
2332 if (blink_timeout_tag < 0) {
2334 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2339 ARDOUR_UI::stop_blinking ()
2341 if (blink_timeout_tag >= 0) {
2342 gtk_timeout_remove (blink_timeout_tag);
2343 blink_timeout_tag = -1;
2349 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2351 using namespace Gtk;
2352 using namespace Menu_Helpers;
2354 if (dstream.hidden()) {
2358 MenuList& items = diskstream_menu->items();
2359 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2363 ARDOUR_UI::diskstream_selected (gint32 id)
2365 selected_dstream = id;
2370 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2372 using namespace Gtk;
2373 using namespace Menu_Helpers;
2379 diskstream_menu = new Menu();
2380 diskstream_menu->set_name ("ArdourContextMenu");
2381 using namespace Gtk;
2382 using namespace Menu_Helpers;
2384 MenuList& items = diskstream_menu->items();
2385 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2387 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2390 diskstream_menu->popup (ev->button, ev->time);
2392 diskstream_menu->popup (0, 0);
2395 selected_dstream = -1;
2399 delete diskstream_menu;
2401 return selected_dstream;
2405 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2411 if (io.n_inputs() == 0) {
2416 /* XXX we're not handling multiple ports yet. */
2418 const char **connections = io.input(0)->get_connections();
2420 if (connections == 0 || connections[0] == '\0') {
2423 buf = connections[0];
2430 if (io.n_outputs() == 0) {
2435 /* XXX we're not handling multiple ports yet. */
2437 const char **connections = io.output(0)->get_connections();
2439 if (connections == 0 || connections[0] == '\0') {
2442 buf = connections[0];
2450 ARDOUR_UI::snapshot_session ()
2452 ArdourPrompter prompter (true);
2459 now = now.substr (0, now.length() - 1);
2461 prompter.set_name ("Prompter");
2462 prompter.set_prompt (_("Name for snapshot"));
2463 prompter.set_initial_text (now);
2465 switch (prompter.run()) {
2466 case RESPONSE_ACCEPT:
2467 prompter.get_result (snapname);
2468 if (snapname.length()){
2469 save_state (snapname);
2479 ARDOUR_UI::save_state (string name)
2481 (void) save_state_canfail (name);
2485 ARDOUR_UI::save_state_canfail (string name)
2490 if (name.length() == 0) {
2491 name = session->snap_name();
2494 if ((ret = session->save_state (name)) != 0) {
2498 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2503 ARDOUR_UI::restore_state (string name)
2506 if (name.length() == 0) {
2507 name = session->name();
2509 session->restore_state (name);
2514 ARDOUR_UI::primary_clock_value_changed ()
2517 session->request_locate (primary_clock.current_time ());
2522 ARDOUR_UI::secondary_clock_value_changed ()
2525 session->request_locate (secondary_clock.current_time ());
2530 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2532 if (session && dstream && dstream->record_enabled()) {
2534 Session::RecordState rs;
2536 rs = session->record_status ();
2539 case Session::Disabled:
2540 case Session::Enabled:
2541 if (w->get_state() != STATE_SELECTED) {
2542 w->set_state (STATE_SELECTED);
2546 case Session::Recording:
2547 if (w->get_state() != STATE_ACTIVE) {
2548 w->set_state (STATE_ACTIVE);
2554 if (w->get_state() != STATE_NORMAL) {
2555 w->set_state (STATE_NORMAL);
2561 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2567 switch (session->record_status()) {
2568 case Session::Enabled:
2570 rec_button.set_state (STATE_ACTIVE);
2572 rec_button.set_state (STATE_NORMAL);
2576 case Session::Recording:
2577 rec_button.set_state (STATE_ACTIVE);
2581 rec_button.set_active (false);
2582 rec_button.set_state (STATE_NORMAL);
2588 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2596 ARDOUR_UI::start_keyboard_prefix ()
2598 keyboard->start_prefix();
2602 ARDOUR_UI::save_template ()
2605 ArdourPrompter prompter (true);
2608 prompter.set_name (X_("Prompter"));
2609 prompter.set_prompt (_("Name for mix template:"));
2610 prompter.set_initial_text(session->name() + _("-template"));
2612 switch (prompter.run()) {
2613 case RESPONSE_ACCEPT:
2614 prompter.get_result (name);
2616 if (name.length()) {
2617 session->save_template (name);
2627 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2629 m_new_session_dialog->show_all();
2630 m_new_session_dialog->set_transient_for(*editor);
2631 m_new_session_dialog->set_name(predetermined_path);
2633 int response = Gtk::RESPONSE_CANCEL;
2636 response = m_new_session_dialog->run ();
2638 if(response == Gtk::RESPONSE_OK) {
2640 _session_is_new = true;
2642 std::string session_name = m_new_session_dialog->session_name();
2643 std::string session_path = m_new_session_dialog->session_folder();
2646 XXX This is needed because session constructor wants a
2647 non-existant path. hopefully this will be fixed at some point.
2649 session_path = Glib::build_filename(session_path, session_name);
2651 std::string template_name = m_new_session_dialog->session_template_name();
2653 if (m_new_session_dialog->use_session_template()) {
2655 load_session (session_path, session_name, &template_name);
2661 Session::AutoConnectOption iconnect;
2662 Session::AutoConnectOption oconnect;
2664 if (m_new_session_dialog->create_control_bus()) {
2665 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2670 if (m_new_session_dialog->create_master_bus()) {
2671 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2676 if (m_new_session_dialog->connect_inputs()) {
2677 iconnect = Session::AutoConnectPhysical;
2679 iconnect = Session::AutoConnectOption (0);
2682 /// @todo some minor tweaks.
2684 if (m_new_session_dialog->connect_outs_to_master()) {
2685 oconnect = Session::AutoConnectMaster;
2686 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2687 oconnect = Session::AutoConnectPhysical;
2689 oconnect = Session::AutoConnectOption (0);
2692 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2693 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2695 build_session (session_path,
2703 engine->frame_rate() * 60 * 5);
2707 } while(response == Gtk::RESPONSE_HELP);
2708 m_new_session_dialog->hide_all();
2712 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2714 Session *new_session;
2716 session_loaded = false;
2717 x = unload_session ();
2725 /* if it already exists, we must have write access */
2727 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2728 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2729 You do not have write access to this session.\n\
2730 This prevents the session from being loaded."));
2735 new_session = new Session (*engine, path, snap_name, mix_template);
2740 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2744 connect_to_session (new_session);
2746 //if (engine->running()) {
2747 //mixer->show_window();
2749 session_loaded = true;
2754 ARDOUR_UI::make_session_clean ()
2757 session->set_clean ();
2764 ARDOUR_UI::build_session (string path, string snap_name,
2765 uint32_t control_channels,
2766 uint32_t master_channels,
2767 Session::AutoConnectOption input_connect,
2768 Session::AutoConnectOption output_connect,
2771 jack_nframes_t initial_length)
2773 Session *new_session;
2776 session_loaded = false;
2777 x = unload_session ();
2784 _session_is_new = true;
2787 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2788 control_channels, master_channels, nphysin, nphysout, initial_length);
2793 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2797 connect_to_session (new_session);
2799 //if (engine->running()) {
2800 //mixer->show_window();
2802 session_loaded = true;
2810 editor->show_window ();
2814 if (session && mixer) {
2815 // mixer->show_window ();
2824 ARDOUR_UI::show_splash ()
2827 about = new About();
2833 ARDOUR_UI::hide_splash ()
2841 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2845 removed = rep.paths.size();
2848 ArdourMessage msg (editor, X_("cleanupresults"),
2850 No audio files were ready for cleanup\n\n\
2851 If this seems suprising, check for any existing\n\
2852 snapshots. These may still include regions that\n\
2853 require some unused files to continue to exist."));
2857 ArdourDialog results (_("ardour: cleanup"), true);
2859 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2860 CleanupResultsModelColumns() {
2864 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2865 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2869 Glib::RefPtr<Gtk::ListStore> results_model;
2870 CleanupResultsModelColumns results_columns;
2871 Gtk::TreeView results_display;
2873 results_model = ListStore::create (results_columns);
2874 results_display.set_model (results_model);
2875 results_display.append_column (list_title, results_columns.visible_name);
2876 results_display.set_headers_visible (true);
2878 Gtk::ScrolledWindow list_scroller;
2881 if (rep.space < 1048576.0f) {
2883 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2885 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2889 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2891 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2895 results.get_vbox()->pack_start (txt, false, false);
2897 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2898 TreeModel::Row row = *(results_model->append());
2899 row[results_columns.visible_name] = *i;
2900 row[results_columns.fullpath] = *i;
2903 list_scroller.add (results_display);
2904 list_scroller.set_size_request (-1, 250);
2905 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2907 results.get_vbox()->pack_start (list_scroller, true, true);
2908 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2909 results.set_position (Gtk::WIN_POS_MOUSE);
2915 ARDOUR_UI::cleanup ()
2918 /* shouldn't happen: menu item is insensitive */
2922 ArdourDialog checker (_("ardour cleanup"));
2923 Gtk::Label label (_("\
2924 Cleanup is a destructive operation.\n\
2925 ALL undo/redo information will be lost if you cleanup.\n\
2926 Unused audio files will be moved to a \"dead sounds\" location."));
2928 checker.get_vbox()->pack_start (label, false, false);
2929 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2930 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2932 checker.set_name (_("CleanupDialog"));
2933 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2934 checker.set_position (Gtk::WIN_POS_MOUSE);
2936 switch (checker.run()) {
2937 case RESPONSE_ACCEPT:
2943 Session::cleanup_report rep;
2945 editor->prepare_for_cleanup ();
2947 if (session->cleanup_sources (rep)) {
2951 display_cleanup_results (rep,
2954 The following %1 %2 were not in use.\n\
2955 The next time you flush the wastebasket\n\
2956 it will release an additional %3 %4bytes\n\
2962 ARDOUR_UI::flush_trash ()
2965 /* shouldn't happen: menu item is insensitive */
2969 Session::cleanup_report rep;
2971 if (session->cleanup_trash_sources (rep)) {
2975 display_cleanup_results (rep,
2977 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2981 ARDOUR_UI::add_route ()
2989 if (add_route_dialog == 0) {
2990 add_route_dialog = new AddRouteDialog;
2991 editor->ensure_float (*add_route_dialog);
2994 if (add_route_dialog->is_visible()) {
2995 /* we're already doing this */
2999 ResponseType r = (ResponseType) add_route_dialog->run ();
3001 add_route_dialog->hide();
3004 case RESPONSE_ACCEPT:
3011 if ((count = add_route_dialog->count()) <= 0) {
3015 uint32_t input_chan = add_route_dialog->channels ();
3016 uint32_t output_chan;
3017 string name_template = add_route_dialog->name_template ();
3018 bool track = add_route_dialog->track ();
3020 Session::AutoConnectOption oac = session->get_output_auto_connect();
3022 if (oac & Session::AutoConnectMaster) {
3023 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3025 output_chan = input_chan;
3028 /* XXX do something with name template */
3032 session_add_audio_track (input_chan, output_chan);
3034 session_add_audio_bus (input_chan, output_chan);
3038 while (Main::events_pending()) {
3045 ARDOUR_UI::mixer_settings () const
3050 node = session->instant_xml(X_("Mixer"), session->path());
3052 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3056 node = new XMLNode (X_("Mixer"));
3063 ARDOUR_UI::editor_settings () const
3068 node = session->instant_xml(X_("Editor"), session->path());
3070 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3074 node = new XMLNode (X_("Editor"));
3080 ARDOUR_UI::keyboard_settings () const
3084 node = Config->extra_xml(X_("Keyboard"));
3087 node = new XMLNode (X_("Keyboard"));
3093 ARDOUR_UI::halt_on_xrun_message ()
3095 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3097 ArdourMessage msg (editor, X_("haltonxrun"),
3098 _("Recording was stopped because your system could not keep up."));
3102 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3104 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3106 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3110 delete deletion_list;
3114 ARDOUR_UI::disk_overrun_handler ()
3116 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3118 if (!have_disk_overrun_displayed) {
3119 have_disk_overrun_displayed = true;
3120 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3121 The disk system on your computer\n\
3122 was not able to keep up with Ardour.\n\
3124 Specifically, it failed to write data to disk\n\
3125 quickly enough to keep up with recording.\n"));
3126 have_disk_overrun_displayed = false;
3131 ARDOUR_UI::disk_underrun_handler ()
3133 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3135 if (!have_disk_underrun_displayed) {
3136 have_disk_underrun_displayed = true;
3137 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3138 (_("The disk system on your computer\n\
3139 was not able to keep up with Ardour.\n\
3141 Specifically, it failed to read data from disk\n\
3142 quickly enough to keep up with playback.\n")));
3143 have_disk_underrun_displayed = false;
3148 ARDOUR_UI::disk_underrun_message_gone ()
3150 have_disk_underrun_displayed = false;
3154 ARDOUR_UI::disk_overrun_message_gone ()
3156 have_disk_underrun_displayed = false;
3160 ARDOUR_UI::pending_state_dialog ()
3162 ArdourDialog dialog ("pending state dialog");
3164 This session appears to have been in\n\
3165 middle of recording when ardour or\n\
3166 the computer was shutdown.\n\
3168 Ardour can recover any captured audio for\n\
3169 you, or it can ignore it. Please decide\n\
3170 what you would like to do.\n"));
3172 dialog.get_vbox()->pack_start (message);
3173 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3174 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3176 dialog.set_position (WIN_POS_CENTER);
3179 switch (dialog.run ()) {
3180 case RESPONSE_ACCEPT:
3191 ARDOUR_UI::disconnect_from_jack ()
3194 if( engine->disconnect_from_jack ()) {
3195 ArdourMessage msg (editor, X_("nojack dialog"),
3196 _("Could not disconnect from JACK"));
3199 update_sample_rate (0);
3204 ARDOUR_UI::reconnect_to_jack ()
3207 if (engine->reconnect_to_jack ()) {
3208 ArdourMessage msg (editor, X_("nojack dialog"),
3209 _("Could not reconnect to JACK"));
3212 update_sample_rate (0);
3217 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3219 engine->request_buffer_size (nframes);
3220 update_sample_rate (0);
3224 ARDOUR_UI::cmdline_new_session (string path)
3226 if (path[0] != '/') {
3227 char buf[PATH_MAX+1];
3230 getcwd (buf, sizeof (buf));
3237 new_session (false, path);
3239 _will_create_new_session_automatically = false; /* done it */
3240 return FALSE; /* don't call it again */