2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #include <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
73 #include "gui_thread.h"
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
90 static const gchar *h_meter_strip_xpm[] = {
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
286 static const gchar * v_meter_strip_xpm[] = {
769 static const char* channel_setup_names[] = {
780 vector<string> channel_combo_strings;
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
784 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
786 primary_clock (X_("TransportClockDisplay"), true, false, true),
787 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788 preroll_clock (X_("PreRollClock"), true, true),
789 postroll_clock (X_("PostRollClock"), true, true),
793 adjuster_table (3, 3),
797 preroll_button (_("pre\nroll")),
798 postroll_button (_("post\nroll")),
802 big_clock ("BigClockDisplay", true),
806 shuttle_units_button (_("% ")),
807 shuttle_style_button (_("spring")),
809 punch_in_button (_("punch\nin")),
810 punch_out_button (_("punch\nout")),
811 auto_return_button (_("auto\nreturn")),
812 auto_play_button (_("auto\nplay")),
813 auto_input_button (_("auto\ninput")),
814 click_button (_("click")),
815 follow_button (_("follow\nPH")),
816 auditioning_alert_button (_("AUDITIONING")),
817 solo_alert_button (_("SOLO")),
821 using namespace Gtk::Menu_Helpers;
825 /* actually, its already loaded, but ... */
827 cerr << "Loading UI configuration file " << rcfile << endl;
831 if (theArdourUI == 0) {
835 // allow run-time rebinding of accels
837 Settings::get_default()->property_gtk_can_change_accels() = true;
839 ActionManager::init ();
841 m_new_session_dialog = 0;
842 m_new_session_dialog_ref = NewSessionDialogFactory::create();
843 m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
847 _session_is_new = false;
848 big_clock_window = 0;
849 session_selector_window = 0;
850 last_key_press_time = 0;
851 connection_editor = 0;
852 add_route_dialog = 0;
856 open_session_selector = 0;
857 have_configure_timeout = false;
858 have_disk_overrun_displayed = false;
859 have_disk_underrun_displayed = false;
860 _will_create_new_session_automatically = false;
861 session_loaded = false;
864 last_configure_time.tv_sec = 0;
865 last_configure_time.tv_usec = 0;
867 shuttle_grabbed = false;
870 set_shuttle_units (Percentage);
871 set_shuttle_behaviour (Sprung);
873 shuttle_style_menu = 0;
874 shuttle_unit_menu = 0;
876 gettimeofday (&last_peak_grab, 0);
877 gettimeofday (&last_shuttle_request, 0);
879 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
884 /* handle pending state with a dialog */
886 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
888 channel_combo_strings = internationalize (channel_setup_names);
890 /* have to wait for AudioEngine and Configuration before proceeding */
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
896 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
898 string msg = string_compose (_("\
899 You cannot record-enable\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
905 ArdourMessage message (editor, X_("cannotrecord"), msg);
909 ARDOUR_UI::set_engine (AudioEngine& e)
913 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
920 keyboard = new Keyboard;
921 install_keybindings ();
923 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
926 if (setup_windows ()) {
927 throw failed_constructor ();
930 if (GTK_ARDOUR::show_key_actions) {
932 // show_all_actions ();
936 /* start with timecode, metering enabled
939 blink_timeout_tag = -1;
941 /* this being a GUI and all, we want peakfiles */
943 FileSource::set_build_peakfiles (true);
944 FileSource::set_build_missing_peakfiles (true);
946 if (Source::start_peak_thread ()) {
947 throw failed_constructor();
950 /* start the time-of-day-clock */
952 update_wall_clock ();
953 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
955 update_disk_space ();
957 update_sample_rate (engine->frame_rate());
959 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
960 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
963 ARDOUR_UI::~ARDOUR_UI ()
965 save_ardour_state ();
979 if (add_route_dialog) {
980 delete add_route_dialog;
983 Source::stop_peak_thread ();
987 ARDOUR_UI::configure_timeout ()
992 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
993 /* no configure events yet */
997 gettimeofday (&now, 0);
998 timersub (&now, &last_configure_time, &diff);
1000 /* force a gap of 0.5 seconds since the last configure event
1003 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1006 have_configure_timeout = false;
1007 save_ardour_state ();
1013 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1015 if (have_configure_timeout) {
1016 gettimeofday (&last_configure_time, 0);
1018 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1019 have_configure_timeout = true;
1026 ARDOUR_UI::save_ardour_state ()
1028 if (!keyboard || !mixer || !editor) {
1032 /* XXX this is all a bit dubious. add_extra_xml() uses
1033 a different lifetime model from add_instant_xml().
1036 XMLNode* node = new XMLNode (keyboard->get_state());
1037 Config->add_extra_xml (*node);
1038 Config->save_state();
1040 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1041 XMLNode& mnode (mixer->get_state());
1044 session->add_instant_xml(enode, session->path());
1045 session->add_instant_xml(mnode, session->path());
1047 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1048 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1053 ARDOUR_UI::startup ()
1055 /* Once the UI is up and running, start the audio engine. Doing
1056 this before the UI is up and running can cause problems
1057 when not running with SCHED_FIFO, because the amount of
1058 CPU and disk work needed to get the UI started can interfere
1059 with the scheduling of the audio thread.
1062 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1068 if (session && session->dirty()) {
1069 switch (ask_about_saving_session(_("quit"))) {
1074 /* use the default name */
1075 if (save_state_canfail ("")) {
1076 /* failed - don't quit */
1077 ArdourMessage (editor, X_("badsave dialog"),
1079 Ardour was unable to save your session.\n\n\
1080 If you still wish to quit, please use the\n\n\
1081 \"Just quit\" option."));
1094 ARDOUR_UI::ask_about_saving_session (string what)
1096 ArdourDialog window (_("ardour: save session?"));
1097 Gtk::Label prompt_label;
1100 msg = string_compose(_("Save and %1"), what);
1101 window.add_button (msg, RESPONSE_ACCEPT);
1102 msg = string_compose(_("Just %1"), what);
1103 window.add_button (msg, RESPONSE_REJECT);
1104 msg = string_compose(_("Don't %1"), what);
1105 window.add_button (msg, RESPONSE_REJECT);
1107 Gtk::Button noquit_button (msg);
1108 noquit_button.set_name ("EditorGTKButton");
1113 if (session->snap_name() == session->name()) {
1114 type = _("session");
1116 type = _("snapshot");
1118 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?"),
1119 type, session->snap_name());
1121 prompt_label.set_text (prompt);
1122 prompt_label.set_alignment (0.5, 0.5);
1123 prompt_label.set_name (X_("PrompterLabel"));
1125 window.get_vbox()->pack_start (prompt_label);
1127 window.set_name (_("Prompter"));
1128 window.set_position (Gtk::WIN_POS_MOUSE);
1129 window.set_modal (true);
1132 save_the_session = 0;
1134 editor->ensure_float (window);
1136 ResponseType r = (ResponseType) window.run();
1141 case RESPONSE_ACCEPT:
1151 ARDOUR_UI::every_second ()
1154 update_buffer_load ();
1155 update_disk_space ();
1156 // update_disk_rate ();
1161 ARDOUR_UI::every_point_one_seconds ()
1164 struct timeval diff;
1166 /* do not attempt to grab peak power more than once per cycle.
1169 gettimeofday (&now, 0);
1170 timersub (&now, &last_peak_grab, &diff);
1172 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1173 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1174 last_peak_grab = now;
1177 update_speed_display ();
1178 RapidScreenUpdate(); /* EMIT_SIGNAL */
1183 ARDOUR_UI::every_point_zero_one_seconds ()
1185 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1190 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1194 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1196 if (!engine->connected()) {
1198 snprintf (buf, sizeof (buf), _("disconnected"));
1202 jack_nframes_t rate = engine->frame_rate();
1204 if (fmod (rate, 1000.0) != 0.0) {
1205 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1206 (float) rate/1000.0f,
1207 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1209 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1211 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1215 sample_rate_label.set_text (buf);
1219 ARDOUR_UI::update_cpu_load ()
1222 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1223 cpu_load_label.set_text (buf);
1227 ARDOUR_UI::update_disk_rate ()
1232 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1233 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1234 disk_rate_label.set_text (buf);
1236 disk_rate_label.set_text ("");
1241 ARDOUR_UI::update_buffer_load ()
1246 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1247 session->playback_load(), session->capture_load());
1248 buffer_load_label.set_text (buf);
1250 buffer_load_label.set_text ("");
1255 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1257 if (ds.record_enabled()) {
1258 rec_enabled_diskstreams++;
1263 ARDOUR_UI::update_disk_space()
1269 jack_nframes_t frames = session->available_capture_duration();
1272 if (frames == max_frames) {
1273 strcpy (buf, _("space: 24hrs+"));
1278 jack_nframes_t fr = session->frame_rate();
1280 if (session->actively_recording()){
1282 rec_enabled_diskstreams = 0;
1283 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1285 if (rec_enabled_diskstreams) {
1286 frames /= rec_enabled_diskstreams;
1291 /* hmmm. shall we divide by the route count? or the diskstream count?
1292 or what? for now, do nothing ...
1297 hrs = frames / (fr * 3600);
1298 frames -= hrs * fr * 3600;
1299 mins = frames / (fr * 60);
1300 frames -= mins * fr * 60;
1303 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1306 disk_space_label.set_text (buf);
1310 ARDOUR_UI::update_wall_clock ()
1317 tm_now = localtime (&now);
1319 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1320 wall_clock_label.set_text (buf);
1326 ARDOUR_UI::toggle_recording_plugins ()
1328 /* XXX use toggle_some_session_state */
1334 session->set_recording_plugins (!session->get_recording_plugins());
1338 ARDOUR_UI::toggle_auto_play ()
1341 toggle_some_session_state (auto_play_button,
1342 &Session::get_auto_play,
1343 &Session::set_auto_play);
1347 ARDOUR_UI::toggle_auto_return ()
1350 toggle_some_session_state (auto_return_button,
1351 &Session::get_auto_return,
1352 &Session::set_auto_return);
1356 ARDOUR_UI::toggle_click ()
1358 toggle_some_session_state (click_button,
1359 &Session::get_clicking,
1360 &Session::set_clicking);
1364 ARDOUR_UI::follow_changed ()
1372 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1373 follow_button.set_active (x);
1378 ARDOUR_UI::toggle_follow ()
1386 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1387 editor->set_follow_playhead (x);
1392 ARDOUR_UI::toggle_session_auto_loop ()
1395 if (session->get_auto_loop()) {
1396 if (session->transport_rolling()) {
1400 session->request_auto_loop (false);
1404 session->request_auto_loop (true);
1410 ARDOUR_UI::toggle_session_punch_in ()
1413 session->set_punch_in (!session->get_punch_in());
1418 ARDOUR_UI::toggle_punch_out ()
1420 toggle_some_session_state (punch_out_button,
1421 &Session::get_punch_out,
1422 &Session::set_punch_out);
1426 ARDOUR_UI::toggle_punch_in ()
1428 toggle_some_session_state (punch_in_button,
1429 &Session::get_punch_in,
1430 &Session::set_punch_in);
1434 ARDOUR_UI::map_button_state ()
1437 map_some_session_state (auto_return_button,
1438 &Session::get_auto_return);
1439 map_some_session_state (auto_play_button,
1440 &Session::get_auto_play);
1441 map_some_session_state (auto_input_button,
1442 &Session::get_auto_input);
1443 map_some_session_state (punch_in_button,
1444 &Session::get_punch_in);
1445 map_some_session_state (punch_out_button,
1446 &Session::get_punch_out);
1447 map_some_session_state (click_button,
1448 &Session::get_clicking);
1452 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1454 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1458 ARDOUR_UI::map_control_change (Session::ControlType t)
1461 case Session::AutoPlay:
1462 map_some_session_state (auto_play_button, &Session::get_auto_play);
1465 case Session::AutoLoop:
1468 case Session::AutoReturn:
1469 map_some_session_state (auto_return_button, &Session::get_auto_return);
1472 case Session::AutoInput:
1473 map_some_session_state (auto_input_button, &Session::get_auto_input);
1476 case Session::PunchOut:
1477 map_some_session_state (punch_in_button, &Session::get_punch_out);
1480 case Session::PunchIn:
1481 map_some_session_state (punch_in_button, &Session::get_punch_in);
1484 case Session::Clicking:
1485 map_some_session_state (click_button, &Session::get_clicking);
1488 case Session::SlaveType:
1489 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1492 case Session::SendMTC:
1493 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1496 case Session::SendMMC:
1497 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1500 case Session::MMCControl:
1501 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1504 case Session::MidiFeedback:
1505 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1507 case Session::MidiControl:
1508 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1514 case Session::RecordingPlugins:
1517 case Session::CrossFadesActive:
1520 case Session::EditingMode:
1523 case Session::PlayRange:
1526 case Session::AlignChoice:
1527 /* don't care, this is handled by the options editor */
1529 case Session::SeamlessLoop:
1530 /* don't care, this is handled by the options editor */
1537 ARDOUR_UI::control_methods_adjusted ()
1542 which_method = (int) online_control_button->adjustment.get_value();
1543 switch (which_method) {
1545 allow_mmc_and_local ();
1551 allow_local_only ();
1554 fatal << _("programming error: impossible control method") << endmsg;
1560 ARDOUR_UI::mmc_device_id_adjusted ()
1565 int dev_id = (int) mmc_id_button->adjustment.get_value();
1566 mmc->set_device_id (dev_id);
1572 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1573 bool (Session::*get)() const)
1582 if (button.get_active() != (x = (session->*get)())) {
1583 button.set_active (x);
1588 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1589 bool (Session::*get)() const,
1590 void (Session::*set)(bool))
1600 button_state = button.get_active ();
1601 session_state = (session->*get)();
1603 if (button_state != session_state) {
1604 (session->*set) (button_state);
1607 /* check that it worked, and reverse
1608 the button state if it didn't
1611 if ((session->*get)() != button_state) {
1612 button->set_active (!button_state);
1620 ARDOUR_UI::session_menu (GdkEventButton *ev)
1622 session_popup_menu->popup (0, 0);
1627 ARDOUR_UI::redisplay_recent_sessions ()
1629 vector<string *> *sessions;
1630 vector<string *>::iterator i;
1631 RecentSessionsSorter cmp;
1633 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1634 recent_session_model->clear ();
1637 ARDOUR::read_recent_sessions (rs);
1640 recent_session_display.set_model (recent_session_model);
1644 /* sort them alphabetically */
1645 sort (rs.begin(), rs.end(), cmp);
1646 sessions = new vector<string*>;
1648 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1649 sessions->push_back (new string ((*i).second));
1652 for (i = sessions->begin(); i != sessions->end(); ++i) {
1654 vector<string*>* states;
1655 vector<const gchar*> item;
1656 string fullpath = *(*i);
1658 /* remove any trailing / */
1660 if (fullpath[fullpath.length()-1] == '/') {
1661 fullpath = fullpath.substr (0, fullpath.length()-1);
1664 /* now get available states for this session */
1666 if ((states = Session::possible_states (fullpath)) == 0) {
1667 /* no state file? */
1671 TreeModel::Row row = *(recent_session_model->append());
1673 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1674 row[recent_session_columns.fullpath] = fullpath;
1676 if (states->size() > 1) {
1678 /* add the children */
1680 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1682 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1684 child_row[recent_session_columns.visible_name] = **i2;
1685 child_row[recent_session_columns.fullpath] = fullpath;
1694 recent_session_display.set_model (recent_session_model);
1699 ARDOUR_UI::build_session_selector ()
1701 session_selector_window = new ArdourDialog ("session selector");
1703 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1705 session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1706 session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1708 recent_session_model = TreeStore::create (recent_session_columns);
1709 recent_session_display.set_model (recent_session_model);
1710 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1711 recent_session_display.set_headers_visible (false);
1713 scroller->add (recent_session_display);
1714 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1716 session_selector_window->set_name ("SessionSelectorWindow");
1717 session_selector_window->set_size_request (200, 400);
1718 session_selector_window->get_vbox()->pack_start (*scroller);
1722 ARDOUR_UI::open_recent_session ()
1724 /* popup selector window */
1726 if (session_selector_window == 0) {
1727 build_session_selector ();
1730 redisplay_recent_sessions ();
1732 ResponseType r = (ResponseType) session_selector_window->run ();
1734 session_selector_window->hide();
1737 case RESPONSE_ACCEPT:
1743 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1745 if (i == recent_session_model->children().end()) {
1749 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1750 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1752 _session_is_new = false;
1754 load_session (path, state);
1758 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1760 struct stat statbuf;
1762 if (stat (info.filename.c_str(), &statbuf) != 0) {
1766 if (!S_ISDIR(statbuf.st_mode)) {
1770 string session_file = info.filename;
1771 session_file += '/';
1772 session_file += PBD::basename (info.filename);
1773 session_file += ".ardour";
1775 if (stat (session_file.c_str(), &statbuf) != 0) {
1779 return S_ISREG (statbuf.st_mode);
1783 ARDOUR_UI::open_session ()
1785 /* popup selector window */
1787 if (open_session_selector == 0) {
1788 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1789 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1790 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1792 FileFilter filter_ardour;
1793 filter_ardour.set_name (_("Ardour sessions"));
1794 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1796 open_session_selector->add_filter (filter_ardour);
1799 switch (open_session_selector->run ()) {
1806 string session_path = open_session_selector->get_filename();
1810 if (session_path.length() > 0) {
1811 if (Session::find_session (session_path, path, name, isnew) == 0) {
1812 _session_is_new = isnew;
1813 load_session (path, name);
1820 ARDOUR_UI::session_add_midi_track ()
1822 cerr << _("Patience is a virtue.\n");
1826 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1831 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1837 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1838 error << _("could not create new audio track") << endmsg;
1841 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1842 error << _("could not create new audio bus") << endmsg;
1847 if (need_control_room_outs) {
1853 route->set_stereo_control_outs (control_lr_channels);
1854 route->control_outs()->set_stereo_pan (pans, this);
1856 #endif /* CONTROLOUTS */
1860 ArdourMessage msg (editor, X_("noport dialog"),
1861 _("There are insufficient JACK ports available\n\
1862 to create a new track or bus.\n\
1863 You should save Ardour, exit and\n\
1864 restart JACK with more ports."));
1869 ARDOUR_UI::diskstream_added (DiskStream* ds)
1874 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1876 jack_nframes_t _preroll;
1879 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1881 if (new_position > _preroll) {
1882 new_position -= _preroll;
1887 session->request_locate (new_position);
1892 ARDOUR_UI::transport_goto_start ()
1895 session->request_locate (0);
1898 /* force displayed area in editor to start no matter
1899 what "follow playhead" setting is.
1903 editor->reposition_x_origin (0);
1909 ARDOUR_UI::transport_goto_end ()
1912 jack_nframes_t frame = session->current_end_frame();
1913 session->request_locate (frame);
1915 /* force displayed area in editor to start no matter
1916 what "follow playhead" setting is.
1920 editor->reposition_x_origin (frame);
1926 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1931 if (session->transport_stopped()) {
1932 session->request_locate (session->last_transport_start());
1934 if (session->get_auto_loop()) {
1935 session->request_auto_loop (false);
1938 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1939 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1947 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1954 ARDOUR_UI::transport_stop ()
1960 if (session->is_auditioning()) {
1961 session->cancel_audition ();
1965 if (session->get_auto_loop()) {
1966 session->request_auto_loop (false);
1969 session->request_stop ();
1973 ARDOUR_UI::transport_stop_and_forget_capture ()
1976 session->request_stop (true);
1981 ARDOUR_UI::remove_last_capture()
1984 editor->remove_last_capture();
1989 ARDOUR_UI::transport_record ()
1992 switch (session->record_status()) {
1993 case Session::Disabled:
1994 if (session->ntracks() == 0) {
1995 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1996 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1999 session->maybe_enable_record ();
2001 case Session::Recording:
2002 case Session::Enabled:
2003 session->disable_record ();
2009 ARDOUR_UI::transport_roll ()
2017 rolling = session->transport_rolling ();
2019 if (session->get_auto_loop()) {
2020 session->request_auto_loop (false);
2021 auto_loop_button.set_active (false);
2022 roll_button.set_active (true);
2023 } else if (session->get_play_range ()) {
2024 session->request_play_range (false);
2025 play_selection_button.set_active (false);
2026 } else if (rolling) {
2027 session->request_locate (session->last_transport_start(), true);
2030 session->request_transport_speed (1.0f);
2034 ARDOUR_UI::transport_loop()
2037 if (session->get_auto_loop()) {
2038 if (session->transport_rolling()) {
2039 Location * looploc = session->locations()->auto_loop_location();
2041 session->request_locate (looploc->start(), true);
2046 session->request_auto_loop (true);
2052 ARDOUR_UI::transport_play_selection ()
2058 if (!session->get_play_range()) {
2059 session->request_stop ();
2062 editor->play_selection ();
2066 ARDOUR_UI::transport_rewind (int option)
2068 float current_transport_speed;
2071 current_transport_speed = session->transport_speed();
2073 if (current_transport_speed >= 0.0f) {
2076 session->request_transport_speed (-1.0f);
2079 session->request_transport_speed (-4.0f);
2082 session->request_transport_speed (-0.5f);
2087 session->request_transport_speed (current_transport_speed * 1.5f);
2093 ARDOUR_UI::transport_forward (int option)
2095 float current_transport_speed;
2098 current_transport_speed = session->transport_speed();
2100 if (current_transport_speed <= 0.0f) {
2103 session->request_transport_speed (1.0f);
2106 session->request_transport_speed (4.0f);
2109 session->request_transport_speed (0.5f);
2114 session->request_transport_speed (current_transport_speed * 1.5f);
2120 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2128 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2129 Port *port = ds->io()->input (0);
2130 port->request_monitor_input (!port->monitoring_input());
2135 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2143 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2144 ds->set_record_enabled (!ds->record_enabled(), this);
2149 ARDOUR_UI::queue_transport_change ()
2151 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2155 ARDOUR_UI::map_transport_state ()
2157 float sp = session->transport_speed();
2160 transport_rolling ();
2161 } else if (sp < 0.0f) {
2162 transport_rewinding ();
2163 } else if (sp > 0.0f) {
2164 transport_forwarding ();
2166 transport_stopped ();
2171 ARDOUR_UI::send_all_midi_feedback ()
2174 session->send_all_midi_feedback();
2179 ARDOUR_UI::allow_local_only ()
2185 ARDOUR_UI::allow_mmc_only ()
2191 ARDOUR_UI::allow_mmc_and_local ()
2197 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2199 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2200 (int) adj.get_value()].c_str());
2204 ARDOUR_UI::engine_stopped ()
2206 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2207 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2208 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2213 ARDOUR_UI::engine_running ()
2215 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2216 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2217 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2221 ARDOUR_UI::engine_halted ()
2223 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2225 ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2226 ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2228 update_sample_rate (0);
2230 ArdourMessage msg (editor, X_("halted"),
2232 JACK has either been shutdown or it\n\
2233 disconnected Ardour because Ardour\n\
2234 was not fast enough. You can save the\n\
2235 session and/or try to reconnect to JACK ."));
2239 ARDOUR_UI::do_engine_start ()
2245 catch (AudioEngine::PortRegistrationFailure& err) {
2247 error << _("Unable to create all required ports")
2255 error << _("Unable to start the session running")
2265 ARDOUR_UI::start_engine ()
2267 if (do_engine_start () == 0) {
2268 if (session && _session_is_new) {
2269 /* we need to retain initial visual
2270 settings for a new session
2272 session->save_state ("");
2275 /* there is too much going on, in too many threads, for us to
2276 end up with a clean session. So wait 1 second after loading,
2277 and fix it up. its ugly, but until i come across a better
2278 solution, its what we have.
2281 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2288 ARDOUR_UI::update_clocks ()
2290 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2294 ARDOUR_UI::start_clocking ()
2296 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2300 ARDOUR_UI::stop_clocking ()
2302 clock_signal_connection.disconnect ();
2306 ARDOUR_UI::toggle_clocking ()
2309 if (clock_button.get_active()) {
2318 ARDOUR_UI::_blink (void *arg)
2321 ((ARDOUR_UI *) arg)->blink ();
2328 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2332 ARDOUR_UI::start_blinking ()
2334 /* Start the blink signal. Everybody with a blinking widget
2335 uses Blink to drive the widget's state.
2338 if (blink_timeout_tag < 0) {
2340 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2345 ARDOUR_UI::stop_blinking ()
2347 if (blink_timeout_tag >= 0) {
2348 gtk_timeout_remove (blink_timeout_tag);
2349 blink_timeout_tag = -1;
2355 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2357 using namespace Gtk;
2358 using namespace Menu_Helpers;
2360 if (dstream.hidden()) {
2364 MenuList& items = diskstream_menu->items();
2365 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2369 ARDOUR_UI::diskstream_selected (gint32 id)
2371 selected_dstream = id;
2376 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2378 using namespace Gtk;
2379 using namespace Menu_Helpers;
2385 diskstream_menu = new Menu();
2386 diskstream_menu->set_name ("ArdourContextMenu");
2387 using namespace Gtk;
2388 using namespace Menu_Helpers;
2390 MenuList& items = diskstream_menu->items();
2391 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2393 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2396 diskstream_menu->popup (ev->button, ev->time);
2398 diskstream_menu->popup (0, 0);
2401 selected_dstream = -1;
2405 delete diskstream_menu;
2407 return selected_dstream;
2411 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2417 if (io.n_inputs() == 0) {
2422 /* XXX we're not handling multiple ports yet. */
2424 const char **connections = io.input(0)->get_connections();
2426 if (connections == 0 || connections[0] == '\0') {
2429 buf = connections[0];
2436 if (io.n_outputs() == 0) {
2441 /* XXX we're not handling multiple ports yet. */
2443 const char **connections = io.output(0)->get_connections();
2445 if (connections == 0 || connections[0] == '\0') {
2448 buf = connections[0];
2456 ARDOUR_UI::snapshot_session ()
2458 ArdourPrompter prompter (true);
2465 now = now.substr (0, now.length() - 1);
2467 prompter.set_name ("Prompter");
2468 prompter.set_prompt (_("Name for snapshot"));
2469 prompter.set_initial_text (now);
2471 switch (prompter.run()) {
2472 case RESPONSE_ACCEPT:
2473 prompter.get_result (snapname);
2474 if (snapname.length()){
2475 save_state (snapname);
2485 ARDOUR_UI::save_state (string name)
2487 (void) save_state_canfail (name);
2491 ARDOUR_UI::save_state_canfail (string name)
2496 if (name.length() == 0) {
2497 name = session->snap_name();
2500 if ((ret = session->save_state (name)) != 0) {
2504 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2509 ARDOUR_UI::restore_state (string name)
2512 if (name.length() == 0) {
2513 name = session->name();
2515 session->restore_state (name);
2520 ARDOUR_UI::primary_clock_value_changed ()
2523 session->request_locate (primary_clock.current_time ());
2528 ARDOUR_UI::secondary_clock_value_changed ()
2531 session->request_locate (secondary_clock.current_time ());
2536 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2538 if (session && dstream && dstream->record_enabled()) {
2540 Session::RecordState rs;
2542 rs = session->record_status ();
2545 case Session::Disabled:
2546 case Session::Enabled:
2547 if (w->get_state() != STATE_SELECTED) {
2548 w->set_state (STATE_SELECTED);
2552 case Session::Recording:
2553 if (w->get_state() != STATE_ACTIVE) {
2554 w->set_state (STATE_ACTIVE);
2560 if (w->get_state() != STATE_NORMAL) {
2561 w->set_state (STATE_NORMAL);
2567 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2573 switch (session->record_status()) {
2574 case Session::Enabled:
2576 rec_button.set_state (STATE_ACTIVE);
2578 rec_button.set_state (STATE_NORMAL);
2582 case Session::Recording:
2583 rec_button.set_state (STATE_ACTIVE);
2587 rec_button.set_active (false);
2588 rec_button.set_state (STATE_NORMAL);
2594 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2602 ARDOUR_UI::start_keyboard_prefix ()
2604 keyboard->start_prefix();
2608 ARDOUR_UI::save_template ()
2611 ArdourPrompter prompter (true);
2614 prompter.set_name (X_("Prompter"));
2615 prompter.set_prompt (_("Name for mix template:"));
2616 prompter.set_initial_text(session->name() + _("-template"));
2618 switch (prompter.run()) {
2619 case RESPONSE_ACCEPT:
2620 prompter.get_result (name);
2622 if (name.length()) {
2623 session->save_template (name);
2633 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2635 m_new_session_dialog->show_all();
2636 m_new_session_dialog->set_transient_for(*editor);
2637 m_new_session_dialog->set_name(predetermined_path);
2639 int response = Gtk::RESPONSE_CANCEL;
2642 response = m_new_session_dialog->run ();
2644 if(response == Gtk::RESPONSE_OK) {
2646 _session_is_new = true;
2648 std::string session_name = m_new_session_dialog->session_name();
2649 std::string session_path = m_new_session_dialog->session_folder();
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 (string path, string 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 (string path, string 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, string 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 */