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 ActionManager::init ();
836 m_new_session_dialog = 0;
837 m_new_session_dialog_ref = NewSessionDialogFactory::create();
838 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
842 _session_is_new = false;
843 big_clock_window = 0;
844 session_selector_window = 0;
845 last_key_press_time = 0;
846 connection_editor = 0;
847 add_route_dialog = 0;
852 open_session_selector = 0;
853 have_configure_timeout = false;
854 have_disk_overrun_displayed = false;
855 have_disk_underrun_displayed = false;
856 _will_create_new_session_automatically = false;
857 session_loaded = false;
860 last_configure_time.tv_sec = 0;
861 last_configure_time.tv_usec = 0;
863 shuttle_grabbed = false;
866 set_shuttle_units (Percentage);
867 set_shuttle_behaviour (Sprung);
869 shuttle_style_menu = 0;
870 shuttle_unit_menu = 0;
872 gettimeofday (&last_peak_grab, 0);
873 gettimeofday (&last_shuttle_request, 0);
875 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
876 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
877 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
878 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
880 /* handle pending state with a dialog */
882 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
884 channel_combo_strings = internationalize (channel_setup_names);
886 /* have to wait for AudioEngine and Configuration before proceeding */
890 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
892 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
894 string msg = string_compose (_("\
895 You cannot record-enable\n\
897 because it has no input connections.\n\
898 You would be wasting space recording silence."),
901 ArdourMessage message (editor, X_("cannotrecord"), msg);
905 ARDOUR_UI::set_engine (AudioEngine& e)
909 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
910 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
911 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
912 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
916 keyboard = new Keyboard;
917 install_keybindings ();
919 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
920 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
922 if (setup_windows ()) {
923 throw failed_constructor ();
926 if (GTK_ARDOUR::show_key_actions) {
927 vector<string> names;
928 vector<string> paths;
930 vector<AccelKey> bindings;
932 ActionManager::get_all_actions (names, paths, keys, bindings);
934 vector<string>::iterator n;
935 vector<string>::iterator k;
936 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
937 cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
943 /* start with timecode, metering enabled
946 blink_timeout_tag = -1;
948 /* this being a GUI and all, we want peakfiles */
950 FileSource::set_build_peakfiles (true);
951 FileSource::set_build_missing_peakfiles (true);
953 if (Source::start_peak_thread ()) {
954 throw failed_constructor();
957 /* start the time-of-day-clock */
959 update_wall_clock ();
960 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
962 update_disk_space ();
964 update_sample_rate (engine->frame_rate());
966 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
967 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
970 ARDOUR_UI::~ARDOUR_UI ()
972 save_ardour_state ();
986 if (add_route_dialog) {
987 delete add_route_dialog;
990 Source::stop_peak_thread ();
994 ARDOUR_UI::configure_timeout ()
999 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1000 /* no configure events yet */
1004 gettimeofday (&now, 0);
1005 timersub (&now, &last_configure_time, &diff);
1007 /* force a gap of 0.5 seconds since the last configure event
1010 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1013 have_configure_timeout = false;
1014 save_ardour_state ();
1020 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1022 if (have_configure_timeout) {
1023 gettimeofday (&last_configure_time, 0);
1025 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1026 have_configure_timeout = true;
1033 ARDOUR_UI::save_ardour_state ()
1035 if (!keyboard || !mixer || !editor) {
1039 /* XXX this is all a bit dubious. add_extra_xml() uses
1040 a different lifetime model from add_instant_xml().
1043 XMLNode* node = new XMLNode (keyboard->get_state());
1044 Config->add_extra_xml (*node);
1045 Config->save_state();
1047 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1048 XMLNode& mnode (mixer->get_state());
1051 session->add_instant_xml(enode, session->path());
1052 session->add_instant_xml(mnode, session->path());
1054 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1055 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1060 ARDOUR_UI::startup ()
1062 /* Once the UI is up and running, start the audio engine. Doing
1063 this before the UI is up and running can cause problems
1064 when not running with SCHED_FIFO, because the amount of
1065 CPU and disk work needed to get the UI started can interfere
1066 with the scheduling of the audio thread.
1069 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1075 if (session && session->dirty()) {
1076 switch (ask_about_saving_session(_("quit"))) {
1081 /* use the default name */
1082 if (save_state_canfail ("")) {
1083 /* failed - don't quit */
1084 ArdourMessage (editor, X_("badsave dialog"),
1086 Ardour was unable to save your session.\n\n\
1087 If you still wish to quit, please use the\n\n\
1088 \"Just quit\" option."));
1101 ARDOUR_UI::ask_about_saving_session (const string & what)
1103 ArdourDialog window (_("ardour: save session?"));
1104 Gtk::Label prompt_label;
1107 msg = string_compose(_("Save and %1"), what);
1108 window.add_button (msg, RESPONSE_ACCEPT);
1109 msg = string_compose(_("Just %1"), what);
1110 window.add_button (msg, RESPONSE_APPLY);
1111 msg = string_compose(_("Don't %1"), what);
1112 window.add_button (msg, RESPONSE_REJECT);
1114 Gtk::Button noquit_button (msg);
1115 noquit_button.set_name ("EditorGTKButton");
1120 if (session->snap_name() == session->name()) {
1121 type = _("session");
1123 type = _("snapshot");
1125 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?"),
1126 type, session->snap_name());
1128 prompt_label.set_text (prompt);
1129 prompt_label.set_alignment (0.5, 0.5);
1130 prompt_label.set_name (X_("PrompterLabel"));
1132 window.get_vbox()->pack_start (prompt_label);
1134 window.set_name (_("Prompter"));
1135 window.set_position (Gtk::WIN_POS_MOUSE);
1136 window.set_modal (true);
1139 save_the_session = 0;
1141 editor->ensure_float (window);
1143 ResponseType r = (ResponseType) window.run();
1148 case RESPONSE_ACCEPT: // save and get out of here
1150 case RESPONSE_APPLY: // get out of here
1160 ARDOUR_UI::every_second ()
1163 update_buffer_load ();
1164 update_disk_space ();
1165 // update_disk_rate ();
1170 ARDOUR_UI::every_point_one_seconds ()
1173 struct timeval diff;
1175 /* do not attempt to grab peak power more than once per cycle.
1178 gettimeofday (&now, 0);
1179 timersub (&now, &last_peak_grab, &diff);
1181 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1182 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1183 last_peak_grab = now;
1186 update_speed_display ();
1187 RapidScreenUpdate(); /* EMIT_SIGNAL */
1192 ARDOUR_UI::every_point_zero_one_seconds ()
1194 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1199 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1203 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1205 if (!engine->connected()) {
1207 snprintf (buf, sizeof (buf), _("disconnected"));
1211 jack_nframes_t rate = engine->frame_rate();
1213 if (fmod (rate, 1000.0) != 0.0) {
1214 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1215 (float) rate/1000.0f,
1216 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1218 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1220 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1224 sample_rate_label.set_text (buf);
1228 ARDOUR_UI::update_cpu_load ()
1231 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1232 cpu_load_label.set_text (buf);
1236 ARDOUR_UI::update_disk_rate ()
1241 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1242 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1243 disk_rate_label.set_text (buf);
1245 disk_rate_label.set_text ("");
1250 ARDOUR_UI::update_buffer_load ()
1255 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1256 session->playback_load(), session->capture_load());
1257 buffer_load_label.set_text (buf);
1259 buffer_load_label.set_text ("");
1264 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1266 if (ds.record_enabled()) {
1267 rec_enabled_diskstreams++;
1272 ARDOUR_UI::update_disk_space()
1278 jack_nframes_t frames = session->available_capture_duration();
1281 if (frames == max_frames) {
1282 strcpy (buf, _("space: 24hrs+"));
1287 jack_nframes_t fr = session->frame_rate();
1289 if (session->actively_recording()){
1291 rec_enabled_diskstreams = 0;
1292 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1294 if (rec_enabled_diskstreams) {
1295 frames /= rec_enabled_diskstreams;
1300 /* hmmm. shall we divide by the route count? or the diskstream count?
1301 or what? for now, do nothing ...
1306 hrs = frames / (fr * 3600);
1307 frames -= hrs * fr * 3600;
1308 mins = frames / (fr * 60);
1309 frames -= mins * fr * 60;
1312 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1315 disk_space_label.set_text (buf);
1319 ARDOUR_UI::update_wall_clock ()
1326 tm_now = localtime (&now);
1328 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1329 wall_clock_label.set_text (buf);
1335 ARDOUR_UI::toggle_recording_plugins ()
1337 /* XXX use toggle_some_session_state */
1343 session->set_recording_plugins (!session->get_recording_plugins());
1347 ARDOUR_UI::toggle_auto_play ()
1350 toggle_some_session_state (auto_play_button,
1351 &Session::get_auto_play,
1352 &Session::set_auto_play);
1356 ARDOUR_UI::toggle_auto_return ()
1359 toggle_some_session_state (auto_return_button,
1360 &Session::get_auto_return,
1361 &Session::set_auto_return);
1365 ARDOUR_UI::toggle_click ()
1367 toggle_some_session_state (click_button,
1368 &Session::get_clicking,
1369 &Session::set_clicking);
1373 ARDOUR_UI::follow_changed ()
1381 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1382 follow_button.set_active (x);
1387 ARDOUR_UI::toggle_follow ()
1395 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1396 editor->set_follow_playhead (x);
1401 ARDOUR_UI::toggle_session_auto_loop ()
1404 if (session->get_auto_loop()) {
1405 if (session->transport_rolling()) {
1409 session->request_auto_loop (false);
1413 session->request_auto_loop (true);
1419 ARDOUR_UI::toggle_session_punch_in ()
1422 session->set_punch_in (!session->get_punch_in());
1427 ARDOUR_UI::toggle_punch_out ()
1429 toggle_some_session_state (punch_out_button,
1430 &Session::get_punch_out,
1431 &Session::set_punch_out);
1435 ARDOUR_UI::toggle_punch_in ()
1437 toggle_some_session_state (punch_in_button,
1438 &Session::get_punch_in,
1439 &Session::set_punch_in);
1443 ARDOUR_UI::map_button_state ()
1446 map_some_session_state (auto_return_button,
1447 &Session::get_auto_return);
1448 map_some_session_state (auto_play_button,
1449 &Session::get_auto_play);
1450 map_some_session_state (auto_input_button,
1451 &Session::get_auto_input);
1452 map_some_session_state (punch_in_button,
1453 &Session::get_punch_in);
1454 map_some_session_state (punch_out_button,
1455 &Session::get_punch_out);
1456 map_some_session_state (click_button,
1457 &Session::get_clicking);
1461 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1463 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1467 ARDOUR_UI::map_control_change (Session::ControlType t)
1470 case Session::AutoPlay:
1471 map_some_session_state (auto_play_button, &Session::get_auto_play);
1474 case Session::AutoLoop:
1477 case Session::AutoReturn:
1478 map_some_session_state (auto_return_button, &Session::get_auto_return);
1481 case Session::AutoInput:
1482 map_some_session_state (auto_input_button, &Session::get_auto_input);
1485 case Session::PunchOut:
1486 map_some_session_state (punch_in_button, &Session::get_punch_out);
1489 case Session::PunchIn:
1490 map_some_session_state (punch_in_button, &Session::get_punch_in);
1493 case Session::Clicking:
1494 map_some_session_state (click_button, &Session::get_clicking);
1497 case Session::SlaveType:
1498 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1501 case Session::SendMTC:
1502 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1505 case Session::SendMMC:
1506 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1509 case Session::MMCControl:
1510 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1513 case Session::MidiFeedback:
1514 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1516 case Session::MidiControl:
1517 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1523 case Session::RecordingPlugins:
1526 case Session::CrossFadesActive:
1529 case Session::EditingMode:
1532 case Session::PlayRange:
1535 case Session::AlignChoice:
1536 /* don't care, this is handled by the options editor */
1538 case Session::SeamlessLoop:
1539 /* don't care, this is handled by the options editor */
1546 ARDOUR_UI::control_methods_adjusted ()
1551 which_method = (int) online_control_button->adjustment.get_value();
1552 switch (which_method) {
1554 allow_mmc_and_local ();
1560 allow_local_only ();
1563 fatal << _("programming error: impossible control method") << endmsg;
1569 ARDOUR_UI::mmc_device_id_adjusted ()
1574 int dev_id = (int) mmc_id_button->adjustment.get_value();
1575 mmc->set_device_id (dev_id);
1581 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1582 bool (Session::*get)() const)
1591 if (button.get_active() != (x = (session->*get)())) {
1592 button.set_active (x);
1597 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1598 bool (Session::*get)() const,
1599 void (Session::*set)(bool))
1609 button_state = button.get_active ();
1610 session_state = (session->*get)();
1612 if (button_state != session_state) {
1613 (session->*set) (button_state);
1616 /* check that it worked, and reverse
1617 the button state if it didn't
1620 if ((session->*get)() != button_state) {
1621 button->set_active (!button_state);
1629 ARDOUR_UI::session_menu (GdkEventButton *ev)
1631 session_popup_menu->popup (0, 0);
1636 ARDOUR_UI::redisplay_recent_sessions ()
1638 vector<string *> *sessions;
1639 vector<string *>::iterator i;
1640 RecentSessionsSorter cmp;
1642 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1643 recent_session_model->clear ();
1646 ARDOUR::read_recent_sessions (rs);
1649 recent_session_display.set_model (recent_session_model);
1653 /* sort them alphabetically */
1654 sort (rs.begin(), rs.end(), cmp);
1655 sessions = new vector<string*>;
1657 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1658 sessions->push_back (new string ((*i).second));
1661 for (i = sessions->begin(); i != sessions->end(); ++i) {
1663 vector<string*>* states;
1664 vector<const gchar*> item;
1665 string fullpath = *(*i);
1667 /* remove any trailing / */
1669 if (fullpath[fullpath.length()-1] == '/') {
1670 fullpath = fullpath.substr (0, fullpath.length()-1);
1673 /* now get available states for this session */
1675 if ((states = Session::possible_states (fullpath)) == 0) {
1676 /* no state file? */
1680 TreeModel::Row row = *(recent_session_model->append());
1682 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1683 row[recent_session_columns.fullpath] = fullpath;
1685 if (states->size() > 1) {
1687 /* add the children */
1689 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1691 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1693 child_row[recent_session_columns.visible_name] = **i2;
1694 child_row[recent_session_columns.fullpath] = fullpath;
1703 recent_session_display.set_model (recent_session_model);
1708 ARDOUR_UI::build_session_selector ()
1710 session_selector_window = new ArdourDialog ("session selector");
1712 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1714 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1715 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1717 recent_session_model = TreeStore::create (recent_session_columns);
1718 recent_session_display.set_model (recent_session_model);
1719 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1720 recent_session_display.set_headers_visible (false);
1722 scroller->add (recent_session_display);
1723 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1725 session_selector_window->set_name ("SessionSelectorWindow");
1726 session_selector_window->set_size_request (200, 400);
1727 session_selector_window->get_vbox()->pack_start (*scroller);
1728 session_selector_window->show_all_children();
1732 ARDOUR_UI::open_recent_session ()
1734 /* popup selector window */
1736 if (session_selector_window == 0) {
1737 build_session_selector ();
1740 redisplay_recent_sessions ();
1742 ResponseType r = (ResponseType) session_selector_window->run ();
1744 session_selector_window->hide();
1747 case RESPONSE_ACCEPT:
1753 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1755 if (i == recent_session_model->children().end()) {
1759 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1760 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1762 _session_is_new = false;
1764 load_session (path, state);
1768 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1770 struct stat statbuf;
1772 if (stat (info.filename.c_str(), &statbuf) != 0) {
1776 if (!S_ISDIR(statbuf.st_mode)) {
1780 string session_file = info.filename;
1781 session_file += '/';
1782 session_file += PBD::basename (info.filename);
1783 session_file += ".ardour";
1785 if (stat (session_file.c_str(), &statbuf) != 0) {
1789 return S_ISREG (statbuf.st_mode);
1793 ARDOUR_UI::open_session ()
1795 /* popup selector window */
1797 if (open_session_selector == 0) {
1799 /* ardour sessions are folders */
1801 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1802 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1803 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1805 FileFilter session_filter;
1806 session_filter.add_pattern ("*.ardour");
1807 session_filter.set_name (_("Ardour sessions"));
1808 open_session_selector->add_filter (session_filter);
1809 open_session_selector->set_filter (session_filter);
1812 int response = open_session_selector->run();
1813 open_session_selector->hide ();
1816 case RESPONSE_ACCEPT:
1819 open_session_selector->hide();
1823 open_session_selector->hide();
1824 string session_path = open_session_selector->get_filename();
1828 if (session_path.length() > 0) {
1829 if (Session::find_session (session_path, path, name, isnew) == 0) {
1830 _session_is_new = isnew;
1831 load_session (path, name);
1838 ARDOUR_UI::session_add_midi_track ()
1840 cerr << _("Patience is a virtue.\n");
1844 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1849 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1855 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1856 error << _("could not create new audio track") << endmsg;
1859 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1860 error << _("could not create new audio bus") << endmsg;
1865 if (need_control_room_outs) {
1871 route->set_stereo_control_outs (control_lr_channels);
1872 route->control_outs()->set_stereo_pan (pans, this);
1874 #endif /* CONTROLOUTS */
1878 ArdourMessage msg (editor, X_("noport dialog"),
1879 _("There are insufficient JACK ports available\n\
1880 to create a new track or bus.\n\
1881 You should save Ardour, exit and\n\
1882 restart JACK with more ports."));
1887 ARDOUR_UI::diskstream_added (DiskStream* ds)
1892 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1894 jack_nframes_t _preroll;
1897 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1899 if (new_position > _preroll) {
1900 new_position -= _preroll;
1905 session->request_locate (new_position);
1910 ARDOUR_UI::transport_goto_start ()
1913 session->request_locate (0);
1916 /* force displayed area in editor to start no matter
1917 what "follow playhead" setting is.
1921 editor->reposition_x_origin (0);
1927 ARDOUR_UI::transport_goto_end ()
1930 jack_nframes_t frame = session->current_end_frame();
1931 session->request_locate (frame);
1933 /* force displayed area in editor to start no matter
1934 what "follow playhead" setting is.
1938 editor->reposition_x_origin (frame);
1944 ARDOUR_UI::transport_stop ()
1950 if (session->is_auditioning()) {
1951 session->cancel_audition ();
1955 if (session->get_auto_loop()) {
1956 session->request_auto_loop (false);
1959 session->request_stop ();
1963 ARDOUR_UI::transport_stop_and_forget_capture ()
1966 session->request_stop (true);
1971 ARDOUR_UI::remove_last_capture()
1974 editor->remove_last_capture();
1979 ARDOUR_UI::transport_record ()
1982 switch (session->record_status()) {
1983 case Session::Disabled:
1984 if (session->ntracks() == 0) {
1985 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1986 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1989 session->maybe_enable_record ();
1991 case Session::Recording:
1992 case Session::Enabled:
1993 session->disable_record ();
1999 ARDOUR_UI::transport_roll ()
2007 rolling = session->transport_rolling ();
2009 if (session->get_auto_loop()) {
2010 session->request_auto_loop (false);
2011 auto_loop_button.set_active (false);
2012 roll_button.set_active (true);
2013 } else if (session->get_play_range ()) {
2014 session->request_play_range (false);
2015 play_selection_button.set_active (false);
2016 } else if (rolling) {
2017 session->request_locate (session->last_transport_start(), true);
2020 session->request_transport_speed (1.0f);
2024 ARDOUR_UI::transport_loop()
2027 if (session->get_auto_loop()) {
2028 if (session->transport_rolling()) {
2029 Location * looploc = session->locations()->auto_loop_location();
2031 session->request_locate (looploc->start(), true);
2036 session->request_auto_loop (true);
2042 ARDOUR_UI::transport_play_selection ()
2048 if (!session->get_play_range()) {
2049 session->request_stop ();
2052 editor->play_selection ();
2056 ARDOUR_UI::transport_rewind (int option)
2058 float current_transport_speed;
2061 current_transport_speed = session->transport_speed();
2063 if (current_transport_speed >= 0.0f) {
2066 session->request_transport_speed (-1.0f);
2069 session->request_transport_speed (-4.0f);
2072 session->request_transport_speed (-0.5f);
2077 session->request_transport_speed (current_transport_speed * 1.5f);
2083 ARDOUR_UI::transport_forward (int option)
2085 float current_transport_speed;
2088 current_transport_speed = session->transport_speed();
2090 if (current_transport_speed <= 0.0f) {
2093 session->request_transport_speed (1.0f);
2096 session->request_transport_speed (4.0f);
2099 session->request_transport_speed (0.5f);
2104 session->request_transport_speed (current_transport_speed * 1.5f);
2110 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2118 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2119 Port *port = ds->io()->input (0);
2120 port->request_monitor_input (!port->monitoring_input());
2125 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2133 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2134 ds->set_record_enabled (!ds->record_enabled(), this);
2139 ARDOUR_UI::queue_transport_change ()
2141 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2145 ARDOUR_UI::map_transport_state ()
2147 float sp = session->transport_speed();
2150 transport_rolling ();
2151 } else if (sp < 0.0f) {
2152 transport_rewinding ();
2153 } else if (sp > 0.0f) {
2154 transport_forwarding ();
2156 transport_stopped ();
2161 ARDOUR_UI::send_all_midi_feedback ()
2164 session->send_all_midi_feedback();
2169 ARDOUR_UI::allow_local_only ()
2175 ARDOUR_UI::allow_mmc_only ()
2181 ARDOUR_UI::allow_mmc_and_local ()
2187 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2189 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2190 (int) adj.get_value()].c_str());
2194 ARDOUR_UI::engine_stopped ()
2196 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2197 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2198 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2203 ARDOUR_UI::engine_running ()
2205 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2206 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2207 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2211 ARDOUR_UI::engine_halted ()
2213 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2215 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2216 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2218 update_sample_rate (0);
2220 ArdourMessage msg (editor, X_("halted"),
2222 JACK has either been shutdown or it\n\
2223 disconnected Ardour because Ardour\n\
2224 was not fast enough. You can save the\n\
2225 session and/or try to reconnect to JACK ."));
2229 ARDOUR_UI::do_engine_start ()
2235 catch (AudioEngine::PortRegistrationFailure& err) {
2237 error << _("Unable to create all required ports")
2245 error << _("Unable to start the session running")
2255 ARDOUR_UI::start_engine ()
2257 if (do_engine_start () == 0) {
2258 if (session && _session_is_new) {
2259 /* we need to retain initial visual
2260 settings for a new session
2262 session->save_state ("");
2265 /* there is too much going on, in too many threads, for us to
2266 end up with a clean session. So wait 1 second after loading,
2267 and fix it up. its ugly, but until i come across a better
2268 solution, its what we have.
2271 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2278 ARDOUR_UI::update_clocks ()
2280 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2284 ARDOUR_UI::start_clocking ()
2286 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2290 ARDOUR_UI::stop_clocking ()
2292 clock_signal_connection.disconnect ();
2296 ARDOUR_UI::toggle_clocking ()
2299 if (clock_button.get_active()) {
2308 ARDOUR_UI::_blink (void *arg)
2311 ((ARDOUR_UI *) arg)->blink ();
2318 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2322 ARDOUR_UI::start_blinking ()
2324 /* Start the blink signal. Everybody with a blinking widget
2325 uses Blink to drive the widget's state.
2328 if (blink_timeout_tag < 0) {
2330 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2335 ARDOUR_UI::stop_blinking ()
2337 if (blink_timeout_tag >= 0) {
2338 gtk_timeout_remove (blink_timeout_tag);
2339 blink_timeout_tag = -1;
2345 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2347 using namespace Gtk;
2348 using namespace Menu_Helpers;
2350 if (dstream.hidden()) {
2354 MenuList& items = diskstream_menu->items();
2355 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2359 ARDOUR_UI::diskstream_selected (gint32 id)
2361 selected_dstream = id;
2366 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2368 using namespace Gtk;
2369 using namespace Menu_Helpers;
2375 diskstream_menu = new Menu();
2376 diskstream_menu->set_name ("ArdourContextMenu");
2377 using namespace Gtk;
2378 using namespace Menu_Helpers;
2380 MenuList& items = diskstream_menu->items();
2381 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2383 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2386 diskstream_menu->popup (ev->button, ev->time);
2388 diskstream_menu->popup (0, 0);
2391 selected_dstream = -1;
2395 delete diskstream_menu;
2397 return selected_dstream;
2401 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2407 if (io.n_inputs() == 0) {
2412 /* XXX we're not handling multiple ports yet. */
2414 const char **connections = io.input(0)->get_connections();
2416 if (connections == 0 || connections[0] == '\0') {
2419 buf = connections[0];
2426 if (io.n_outputs() == 0) {
2431 /* XXX we're not handling multiple ports yet. */
2433 const char **connections = io.output(0)->get_connections();
2435 if (connections == 0 || connections[0] == '\0') {
2438 buf = connections[0];
2446 ARDOUR_UI::snapshot_session ()
2448 ArdourPrompter prompter (true);
2455 now = now.substr (0, now.length() - 1);
2457 prompter.set_name ("Prompter");
2458 prompter.set_prompt (_("Name for snapshot"));
2459 prompter.set_initial_text (now);
2461 switch (prompter.run()) {
2462 case RESPONSE_ACCEPT:
2463 prompter.get_result (snapname);
2464 if (snapname.length()){
2465 save_state (snapname);
2475 ARDOUR_UI::save_state (const string & name)
2477 (void) save_state_canfail (name);
2481 ARDOUR_UI::save_state_canfail (string name)
2486 if (name.length() == 0) {
2487 name = session->snap_name();
2490 if ((ret = session->save_state (name)) != 0) {
2494 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2499 ARDOUR_UI::restore_state (string name)
2502 if (name.length() == 0) {
2503 name = session->name();
2505 session->restore_state (name);
2510 ARDOUR_UI::primary_clock_value_changed ()
2513 session->request_locate (primary_clock.current_time ());
2518 ARDOUR_UI::secondary_clock_value_changed ()
2521 session->request_locate (secondary_clock.current_time ());
2526 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2528 if (session && dstream && dstream->record_enabled()) {
2530 Session::RecordState rs;
2532 rs = session->record_status ();
2535 case Session::Disabled:
2536 case Session::Enabled:
2537 if (w->get_state() != STATE_SELECTED) {
2538 w->set_state (STATE_SELECTED);
2542 case Session::Recording:
2543 if (w->get_state() != STATE_ACTIVE) {
2544 w->set_state (STATE_ACTIVE);
2550 if (w->get_state() != STATE_NORMAL) {
2551 w->set_state (STATE_NORMAL);
2557 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2563 switch (session->record_status()) {
2564 case Session::Enabled:
2566 rec_button.set_state (1);
2568 rec_button.set_state (0);
2572 case Session::Recording:
2573 rec_button.set_state (2);
2577 rec_button.set_state (0);
2583 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2591 ARDOUR_UI::start_keyboard_prefix ()
2593 keyboard->start_prefix();
2597 ARDOUR_UI::save_template ()
2600 ArdourPrompter prompter (true);
2603 prompter.set_name (X_("Prompter"));
2604 prompter.set_prompt (_("Name for mix template:"));
2605 prompter.set_initial_text(session->name() + _("-template"));
2607 switch (prompter.run()) {
2608 case RESPONSE_ACCEPT:
2609 prompter.get_result (name);
2611 if (name.length()) {
2612 session->save_template (name);
2622 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2624 m_new_session_dialog->show_all();
2625 m_new_session_dialog->set_transient_for(*editor);
2626 m_new_session_dialog->set_name(predetermined_path);
2628 int response = Gtk::RESPONSE_CANCEL;
2631 response = m_new_session_dialog->run ();
2633 if(response == Gtk::RESPONSE_OK) {
2635 _session_is_new = true;
2637 std::string session_name = m_new_session_dialog->session_name();
2638 std::string session_path = m_new_session_dialog->session_folder();
2641 XXX This is needed because session constructor wants a
2642 non-existant path. hopefully this will be fixed at some point.
2644 session_path = Glib::build_filename(session_path, session_name);
2646 std::string template_name = m_new_session_dialog->session_template_name();
2648 if (m_new_session_dialog->use_session_template()) {
2650 load_session (session_path, session_name, &template_name);
2656 Session::AutoConnectOption iconnect;
2657 Session::AutoConnectOption oconnect;
2659 if (m_new_session_dialog->create_control_bus()) {
2660 cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2665 if (m_new_session_dialog->create_master_bus()) {
2666 mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2671 if (m_new_session_dialog->connect_inputs()) {
2672 iconnect = Session::AutoConnectPhysical;
2674 iconnect = Session::AutoConnectOption (0);
2677 /// @todo some minor tweaks.
2679 if (m_new_session_dialog->connect_outs_to_master()) {
2680 oconnect = Session::AutoConnectMaster;
2681 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2682 oconnect = Session::AutoConnectPhysical;
2684 oconnect = Session::AutoConnectOption (0);
2687 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2688 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2690 build_session (session_path,
2698 engine->frame_rate() * 60 * 5);
2702 } while(response == Gtk::RESPONSE_HELP);
2703 m_new_session_dialog->hide_all();
2707 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2709 Session *new_session;
2711 session_loaded = false;
2712 x = unload_session ();
2720 /* if it already exists, we must have write access */
2722 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2723 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2724 You do not have write access to this session.\n\
2725 This prevents the session from being loaded."));
2730 new_session = new Session (*engine, path, snap_name, mix_template);
2735 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2739 connect_to_session (new_session);
2741 //if (engine->running()) {
2742 //mixer->show_window();
2744 session_loaded = true;
2749 ARDOUR_UI::make_session_clean ()
2752 session->set_clean ();
2759 ARDOUR_UI::build_session (const string & path, const string & snap_name,
2760 uint32_t control_channels,
2761 uint32_t master_channels,
2762 Session::AutoConnectOption input_connect,
2763 Session::AutoConnectOption output_connect,
2766 jack_nframes_t initial_length)
2768 Session *new_session;
2771 session_loaded = false;
2772 x = unload_session ();
2779 _session_is_new = true;
2782 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2783 control_channels, master_channels, nphysin, nphysout, initial_length);
2788 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2792 connect_to_session (new_session);
2794 //if (engine->running()) {
2795 //mixer->show_window();
2797 session_loaded = true;
2805 editor->show_window ();
2809 if (session && mixer) {
2810 // mixer->show_window ();
2819 ARDOUR_UI::show_splash ()
2822 about = new About();
2828 ARDOUR_UI::hide_splash ()
2836 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2840 removed = rep.paths.size();
2843 ArdourMessage msg (editor, X_("cleanupresults"),
2845 No audio files were ready for cleanup\n\n\
2846 If this seems suprising, check for any existing\n\
2847 snapshots. These may still include regions that\n\
2848 require some unused files to continue to exist."));
2852 ArdourDialog results (_("ardour: cleanup"), true);
2854 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2855 CleanupResultsModelColumns() {
2859 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2860 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2864 Glib::RefPtr<Gtk::ListStore> results_model;
2865 CleanupResultsModelColumns results_columns;
2866 Gtk::TreeView results_display;
2868 results_model = ListStore::create (results_columns);
2869 results_display.set_model (results_model);
2870 results_display.append_column (list_title, results_columns.visible_name);
2871 results_display.set_headers_visible (true);
2873 Gtk::ScrolledWindow list_scroller;
2876 if (rep.space < 1048576.0f) {
2878 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2880 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2884 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2886 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2890 results.get_vbox()->pack_start (txt, false, false);
2892 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2893 TreeModel::Row row = *(results_model->append());
2894 row[results_columns.visible_name] = *i;
2895 row[results_columns.fullpath] = *i;
2898 list_scroller.add (results_display);
2899 list_scroller.set_size_request (-1, 250);
2900 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2902 results.get_vbox()->pack_start (list_scroller, true, true);
2903 results.add_button (Stock::OK, RESPONSE_ACCEPT);
2904 results.set_position (Gtk::WIN_POS_MOUSE);
2910 ARDOUR_UI::cleanup ()
2913 /* shouldn't happen: menu item is insensitive */
2917 ArdourDialog checker (_("ardour cleanup"));
2918 Gtk::Label label (_("\
2919 Cleanup is a destructive operation.\n\
2920 ALL undo/redo information will be lost if you cleanup.\n\
2921 Unused audio files will be moved to a \"dead sounds\" location."));
2923 checker.get_vbox()->pack_start (label, false, false);
2924 checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2925 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2927 checker.set_name (_("CleanupDialog"));
2928 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2929 checker.set_position (Gtk::WIN_POS_MOUSE);
2931 switch (checker.run()) {
2932 case RESPONSE_ACCEPT:
2938 Session::cleanup_report rep;
2940 editor->prepare_for_cleanup ();
2942 if (session->cleanup_sources (rep)) {
2946 display_cleanup_results (rep,
2949 The following %1 %2 were not in use.\n\
2950 The next time you flush the wastebasket\n\
2951 it will release an additional %3 %4bytes\n\
2957 ARDOUR_UI::flush_trash ()
2960 /* shouldn't happen: menu item is insensitive */
2964 Session::cleanup_report rep;
2966 if (session->cleanup_trash_sources (rep)) {
2970 display_cleanup_results (rep,
2972 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2976 ARDOUR_UI::add_route ()
2984 if (add_route_dialog == 0) {
2985 add_route_dialog = new AddRouteDialog;
2986 editor->ensure_float (*add_route_dialog);
2989 if (add_route_dialog->is_visible()) {
2990 /* we're already doing this */
2994 ResponseType r = (ResponseType) add_route_dialog->run ();
2996 add_route_dialog->hide();
2999 case RESPONSE_ACCEPT:
3006 if ((count = add_route_dialog->count()) <= 0) {
3010 uint32_t input_chan = add_route_dialog->channels ();
3011 uint32_t output_chan;
3012 string name_template = add_route_dialog->name_template ();
3013 bool track = add_route_dialog->track ();
3015 Session::AutoConnectOption oac = session->get_output_auto_connect();
3017 if (oac & Session::AutoConnectMaster) {
3018 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3020 output_chan = input_chan;
3023 /* XXX do something with name template */
3027 session_add_audio_track (input_chan, output_chan);
3029 session_add_audio_bus (input_chan, output_chan);
3033 while (Main::events_pending()) {
3040 ARDOUR_UI::mixer_settings () const
3045 node = session->instant_xml(X_("Mixer"), session->path());
3047 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3051 node = new XMLNode (X_("Mixer"));
3058 ARDOUR_UI::editor_settings () const
3063 node = session->instant_xml(X_("Editor"), session->path());
3065 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3069 node = new XMLNode (X_("Editor"));
3075 ARDOUR_UI::keyboard_settings () const
3079 node = Config->extra_xml(X_("Keyboard"));
3082 node = new XMLNode (X_("Keyboard"));
3088 ARDOUR_UI::halt_on_xrun_message ()
3090 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3092 ArdourMessage msg (editor, X_("haltonxrun"),
3093 _("Recording was stopped because your system could not keep up."));
3097 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3099 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3101 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3105 delete deletion_list;
3109 ARDOUR_UI::disk_overrun_handler ()
3111 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3113 if (!have_disk_overrun_displayed) {
3114 have_disk_overrun_displayed = true;
3115 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3116 The disk system on your computer\n\
3117 was not able to keep up with Ardour.\n\
3119 Specifically, it failed to write data to disk\n\
3120 quickly enough to keep up with recording.\n"));
3121 have_disk_overrun_displayed = false;
3126 ARDOUR_UI::disk_underrun_handler ()
3128 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3130 if (!have_disk_underrun_displayed) {
3131 have_disk_underrun_displayed = true;
3132 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3133 (_("The disk system on your computer\n\
3134 was not able to keep up with Ardour.\n\
3136 Specifically, it failed to read data from disk\n\
3137 quickly enough to keep up with playback.\n")));
3138 have_disk_underrun_displayed = false;
3143 ARDOUR_UI::disk_underrun_message_gone ()
3145 have_disk_underrun_displayed = false;
3149 ARDOUR_UI::disk_overrun_message_gone ()
3151 have_disk_underrun_displayed = false;
3155 ARDOUR_UI::pending_state_dialog ()
3157 ArdourDialog dialog ("pending state dialog");
3159 This session appears to have been in\n\
3160 middle of recording when ardour or\n\
3161 the computer was shutdown.\n\
3163 Ardour can recover any captured audio for\n\
3164 you, or it can ignore it. Please decide\n\
3165 what you would like to do.\n"));
3167 dialog.get_vbox()->pack_start (message);
3168 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3169 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3171 dialog.set_position (WIN_POS_CENTER);
3174 switch (dialog.run ()) {
3175 case RESPONSE_ACCEPT:
3186 ARDOUR_UI::disconnect_from_jack ()
3189 if( engine->disconnect_from_jack ()) {
3190 ArdourMessage msg (editor, X_("nojack dialog"),
3191 _("Could not disconnect from JACK"));
3194 update_sample_rate (0);
3199 ARDOUR_UI::reconnect_to_jack ()
3202 if (engine->reconnect_to_jack ()) {
3203 ArdourMessage msg (editor, X_("nojack dialog"),
3204 _("Could not reconnect to JACK"));
3207 update_sample_rate (0);
3212 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3214 engine->request_buffer_size (nframes);
3215 update_sample_rate (0);
3219 ARDOUR_UI::cmdline_new_session (string path)
3221 if (path[0] != '/') {
3222 char buf[PATH_MAX+1];
3225 getcwd (buf, sizeof (buf));
3232 new_session (false, path);
3234 _will_create_new_session_automatically = false; /* done it */
3235 return FALSE; /* don't call it again */