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 (_("% ")),
808 punch_in_button (_("punch\nin")),
809 punch_out_button (_("punch\nout")),
810 auto_return_button (_("auto\nreturn")),
811 auto_play_button (_("auto\nplay")),
812 auto_input_button (_("auto\ninput")),
813 click_button (_("click")),
814 follow_button (_("follow\nPH")),
815 auditioning_alert_button (_("AUDITIONING")),
816 solo_alert_button (_("SOLO")),
820 using namespace Gtk::Menu_Helpers;
824 /* actually, its already loaded, but ... */
826 cerr << "Loading UI configuration file " << rcfile << endl;
830 if (theArdourUI == 0) {
834 // allow run-time rebinding of accels
836 Settings::get_default()->property_gtk_can_change_accels() = true;
838 ActionManager::init ();
840 m_new_session_dialog = 0;
841 m_new_session_dialog_ref = NewSessionDialogFactory::create();
842 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
846 _session_is_new = false;
847 big_clock_window = 0;
848 session_selector_window = 0;
849 last_key_press_time = 0;
850 connection_editor = 0;
851 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 (stringcr_t 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 (stringcr_t 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 (1);
2572 rec_button.set_state (0);
2576 case Session::Recording:
2577 rec_button.set_state (2);
2581 rec_button.set_state (0);
2587 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2595 ARDOUR_UI::start_keyboard_prefix ()
2597 keyboard->start_prefix();
2601 ARDOUR_UI::save_template ()
2604 ArdourPrompter prompter (true);
2607 prompter.set_name (X_("Prompter"));
2608 prompter.set_prompt (_("Name for mix template:"));
2609 prompter.set_initial_text(session->name() + _("-template"));
2611 switch (prompter.run()) {
2612 case RESPONSE_ACCEPT:
2613 prompter.get_result (name);
2615 if (name.length()) {
2616 session->save_template (name);
2626 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2628 m_new_session_dialog->show_all();
2629 m_new_session_dialog->set_transient_for(*editor);
2630 m_new_session_dialog->set_name(predetermined_path);
2632 int response = Gtk::RESPONSE_CANCEL;
2635 response = m_new_session_dialog->run ();
2637 if(response == Gtk::RESPONSE_OK) {
2639 _session_is_new = true;
2641 std::string session_name = m_new_session_dialog->session_name();
2642 std::string session_path = m_new_session_dialog->session_folder();
2645 XXX This is needed because session constructor wants a
2646 non-existant path. hopefully this will be fixed at some point.
2648 session_path = Glib::build_filename(session_path, session_name);
2650 std::string template_name = m_new_session_dialog->session_template_name();
2652 if (m_new_session_dialog->use_session_template()) {
2654 load_session (session_path, session_name, &template_name);
2660 Session::AutoConnectOption iconnect;
2661 Session::AutoConnectOption oconnect;
2663 if (m_new_session_dialog->create_control_bus()) {
2664 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2669 if (m_new_session_dialog->create_master_bus()) {
2670 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2675 if (m_new_session_dialog->connect_inputs()) {
2676 iconnect = Session::AutoConnectPhysical;
2678 iconnect = Session::AutoConnectOption (0);
2681 /// @todo some minor tweaks.
2683 if (m_new_session_dialog->connect_outs_to_master()) {
2684 oconnect = Session::AutoConnectMaster;
2685 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2686 oconnect = Session::AutoConnectPhysical;
2688 oconnect = Session::AutoConnectOption (0);
2691 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2692 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2694 build_session (session_path,
2702 engine->frame_rate() * 60 * 5);
2706 } while(response == Gtk::RESPONSE_HELP);
2707 m_new_session_dialog->hide_all();
2711 ARDOUR_UI::load_session (stringcr_t path, stringcr_t snap_name, string* mix_template)
2713 Session *new_session;
2715 session_loaded = false;
2716 x = unload_session ();
2724 /* if it already exists, we must have write access */
2726 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2727 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2728 You do not have write access to this session.\n\
2729 This prevents the session from being loaded."));
2734 new_session = new Session (*engine, path, snap_name, mix_template);
2739 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2743 connect_to_session (new_session);
2745 //if (engine->running()) {
2746 //mixer->show_window();
2748 session_loaded = true;
2753 ARDOUR_UI::make_session_clean ()
2756 session->set_clean ();
2763 ARDOUR_UI::build_session (stringcr_t path, stringcr_t snap_name,
2764 uint32_t control_channels,
2765 uint32_t master_channels,
2766 Session::AutoConnectOption input_connect,
2767 Session::AutoConnectOption output_connect,
2770 jack_nframes_t initial_length)
2772 Session *new_session;
2775 session_loaded = false;
2776 x = unload_session ();
2783 _session_is_new = true;
2786 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2787 control_channels, master_channels, nphysin, nphysout, initial_length);
2792 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2796 connect_to_session (new_session);
2798 //if (engine->running()) {
2799 //mixer->show_window();
2801 session_loaded = true;
2809 editor->show_window ();
2813 if (session && mixer) {
2814 // mixer->show_window ();
2823 ARDOUR_UI::show_splash ()
2826 about = new About();
2832 ARDOUR_UI::hide_splash ()
2840 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, stringcr_t msg)
2844 removed = rep.paths.size();
2847 ArdourMessage msg (editor, X_("cleanupresults"),
2849 No audio files were ready for cleanup\n\n\
2850 If this seems suprising, check for any existing\n\
2851 snapshots. These may still include regions that\n\
2852 require some unused files to continue to exist."));
2856 ArdourDialog results (_("ardour: cleanup"), true);
2858 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2859 CleanupResultsModelColumns() {
2863 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2864 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2868 Glib::RefPtr<Gtk::ListStore> results_model;
2869 CleanupResultsModelColumns results_columns;
2870 Gtk::TreeView results_display;
2872 results_model = ListStore::create (results_columns);
2873 results_display.set_model (results_model);
2874 results_display.append_column (list_title, results_columns.visible_name);
2875 results_display.set_headers_visible (true);
2877 Gtk::ScrolledWindow list_scroller;
2880 if (rep.space < 1048576.0f) {
2882 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2884 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2888 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2890 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2894 results.get_vbox()->pack_start (txt, false, false);
2896 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2897 TreeModel::Row row = *(results_model->append());
2898 row[results_columns.visible_name] = *i;
2899 row[results_columns.fullpath] = *i;
2902 list_scroller.add (results_display);
2903 list_scroller.set_size_request (-1, 250);
2904 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2906 results.get_vbox()->pack_start (list_scroller, true, true);
2907 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2908 results.set_position (Gtk::WIN_POS_MOUSE);
2914 ARDOUR_UI::cleanup ()
2917 /* shouldn't happen: menu item is insensitive */
2921 ArdourDialog checker (_("ardour cleanup"));
2922 Gtk::Label label (_("\
2923 Cleanup is a destructive operation.\n\
2924 ALL undo/redo information will be lost if you cleanup.\n\
2925 Unused audio files will be moved to a \"dead sounds\" location."));
2927 checker.get_vbox()->pack_start (label, false, false);
2928 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2929 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2931 checker.set_name (_("CleanupDialog"));
2932 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2933 checker.set_position (Gtk::WIN_POS_MOUSE);
2935 switch (checker.run()) {
2936 case RESPONSE_ACCEPT:
2942 Session::cleanup_report rep;
2944 editor->prepare_for_cleanup ();
2946 if (session->cleanup_sources (rep)) {
2950 display_cleanup_results (rep,
2953 The following %1 %2 were not in use.\n\
2954 The next time you flush the wastebasket\n\
2955 it will release an additional %3 %4bytes\n\
2961 ARDOUR_UI::flush_trash ()
2964 /* shouldn't happen: menu item is insensitive */
2968 Session::cleanup_report rep;
2970 if (session->cleanup_trash_sources (rep)) {
2974 display_cleanup_results (rep,
2976 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2980 ARDOUR_UI::add_route ()
2988 if (add_route_dialog == 0) {
2989 add_route_dialog = new AddRouteDialog;
2990 editor->ensure_float (*add_route_dialog);
2993 if (add_route_dialog->is_visible()) {
2994 /* we're already doing this */
2998 ResponseType r = (ResponseType) add_route_dialog->run ();
3000 add_route_dialog->hide();
3003 case RESPONSE_ACCEPT:
3010 if ((count = add_route_dialog->count()) <= 0) {
3014 uint32_t input_chan = add_route_dialog->channels ();
3015 uint32_t output_chan;
3016 string name_template = add_route_dialog->name_template ();
3017 bool track = add_route_dialog->track ();
3019 Session::AutoConnectOption oac = session->get_output_auto_connect();
3021 if (oac & Session::AutoConnectMaster) {
3022 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3024 output_chan = input_chan;
3027 /* XXX do something with name template */
3031 session_add_audio_track (input_chan, output_chan);
3033 session_add_audio_bus (input_chan, output_chan);
3037 while (Main::events_pending()) {
3044 ARDOUR_UI::mixer_settings () const
3049 node = session->instant_xml(X_("Mixer"), session->path());
3051 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3055 node = new XMLNode (X_("Mixer"));
3062 ARDOUR_UI::editor_settings () const
3067 node = session->instant_xml(X_("Editor"), session->path());
3069 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3073 node = new XMLNode (X_("Editor"));
3079 ARDOUR_UI::keyboard_settings () const
3083 node = Config->extra_xml(X_("Keyboard"));
3086 node = new XMLNode (X_("Keyboard"));
3092 ARDOUR_UI::halt_on_xrun_message ()
3094 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3096 ArdourMessage msg (editor, X_("haltonxrun"),
3097 _("Recording was stopped because your system could not keep up."));
3101 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3103 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3105 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3109 delete deletion_list;
3113 ARDOUR_UI::disk_overrun_handler ()
3115 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3117 if (!have_disk_overrun_displayed) {
3118 have_disk_overrun_displayed = true;
3119 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3120 The disk system on your computer\n\
3121 was not able to keep up with Ardour.\n\
3123 Specifically, it failed to write data to disk\n\
3124 quickly enough to keep up with recording.\n"));
3125 have_disk_overrun_displayed = false;
3130 ARDOUR_UI::disk_underrun_handler ()
3132 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3134 if (!have_disk_underrun_displayed) {
3135 have_disk_underrun_displayed = true;
3136 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3137 (_("The disk system on your computer\n\
3138 was not able to keep up with Ardour.\n\
3140 Specifically, it failed to read data from disk\n\
3141 quickly enough to keep up with playback.\n")));
3142 have_disk_underrun_displayed = false;
3147 ARDOUR_UI::disk_underrun_message_gone ()
3149 have_disk_underrun_displayed = false;
3153 ARDOUR_UI::disk_overrun_message_gone ()
3155 have_disk_underrun_displayed = false;
3159 ARDOUR_UI::pending_state_dialog ()
3161 ArdourDialog dialog ("pending state dialog");
3163 This session appears to have been in\n\
3164 middle of recording when ardour or\n\
3165 the computer was shutdown.\n\
3167 Ardour can recover any captured audio for\n\
3168 you, or it can ignore it. Please decide\n\
3169 what you would like to do.\n"));
3171 dialog.get_vbox()->pack_start (message);
3172 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3173 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3175 dialog.set_position (WIN_POS_CENTER);
3178 switch (dialog.run ()) {
3179 case RESPONSE_ACCEPT:
3190 ARDOUR_UI::disconnect_from_jack ()
3193 if( engine->disconnect_from_jack ()) {
3194 ArdourMessage msg (editor, X_("nojack dialog"),
3195 _("Could not disconnect from JACK"));
3198 update_sample_rate (0);
3203 ARDOUR_UI::reconnect_to_jack ()
3206 if (engine->reconnect_to_jack ()) {
3207 ArdourMessage msg (editor, X_("nojack dialog"),
3208 _("Could not reconnect to JACK"));
3211 update_sample_rate (0);
3216 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3218 engine->request_buffer_size (nframes);
3219 update_sample_rate (0);
3223 ARDOUR_UI::cmdline_new_session (string path)
3225 if (path[0] != '/') {
3226 char buf[PATH_MAX+1];
3229 getcwd (buf, sizeof (buf));
3236 new_session (false, path);
3238 _will_create_new_session_automatically = false; /* done it */
3239 return FALSE; /* don't call it again */