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.
32 #include <pbd/error.h>
33 #include <pbd/compose.h>
34 #include <pbd/basename.h>
35 #include <pbd/pathscanner.h>
36 #include <pbd/failed_constructor.h>
37 #include <gtkmm2ext/gtk_ui.h>
38 #include <gtkmm2ext/pix.h>
39 #include <gtkmm2ext/utils.h>
40 #include <gtkmm2ext/click_box.h>
41 #include <gtkmm2ext/fastmeter.h>
42 #include <gtkmm2ext/stop_signal.h>
43 #include <gtkmm2ext/popup.h>
45 #include <midi++/port.h>
46 #include <midi++/mmc.h>
48 #include <ardour/ardour.h>
49 #include <ardour/port.h>
50 #include <ardour/audioengine.h>
51 #include <ardour/playlist.h>
52 #include <ardour/utils.h>
53 #include <ardour/diskstream.h>
54 #include <ardour/filesource.h>
55 #include <ardour/recent_sessions.h>
56 #include <ardour/session_diskstream.h>
57 #include <ardour/port.h>
58 #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;
83 SoundFileSelector* ARDOUR_UI::sfdb_window = 0;
85 sigc::signal<void,bool> ARDOUR_UI::Blink;
86 sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
87 sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
88 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
91 static const gchar *h_meter_strip_xpm[] = {
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.`. +++",
284 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 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.`. +++"};
287 static const gchar * v_meter_strip_xpm[] = {
770 static const char* channel_setup_names[] = {
781 vector<string> channel_combo_strings;
783 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
785 : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
787 primary_clock (X_("TransportClockDisplay"), true, false, true),
788 secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
789 preroll_clock (X_("PreRollClock"), true, true),
790 postroll_clock (X_("PostRollClock"), true, true),
794 adjuster_table (3, 3),
798 preroll_button (_("pre\nroll")),
799 postroll_button (_("post\nroll")),
803 big_clock ("BigClockDisplay", true),
807 shuttle_units_button (_("% ")),
808 shuttle_style_button (_("spring")),
810 punch_in_button (_("punch\nin")),
811 punch_out_button (_("punch\nout")),
812 auto_return_button (_("auto\nreturn")),
813 auto_play_button (_("auto\nplay")),
814 auto_input_button (_("auto\ninput")),
815 click_button (_("click")),
816 follow_button (_("follow\nPH")),
817 auditioning_alert_button (_("AUDITIONING")),
818 solo_alert_button (_("SOLO")),
822 using namespace Gtk::Menu_Helpers;
826 /* actually, its already loaded, but ... */
828 cerr << "Loading UI configuration file " << rcfile << endl;
832 if (theArdourUI == 0) {
839 _session_is_new = false;
840 big_clock_window = 0;
841 session_selector_window = 0;
842 last_key_press_time = 0;
843 connection_editor = 0;
844 add_route_dialog = 0;
850 new_session_window = 0;
851 open_session_selector = 0;
852 have_configure_timeout = false;
853 have_disk_overrun_displayed = false;
854 have_disk_underrun_displayed = false;
855 _will_create_new_session_automatically = false;
856 session_loaded = false;
858 last_configure_time.tv_sec = 0;
859 last_configure_time.tv_usec = 0;
861 ui_manager = UIManager::create ();
863 shuttle_grabbed = false;
866 set_shuttle_units (Percentage);
867 set_shuttle_behaviour (Sprung);
869 Glib::RefPtr<ActionGroup> shuttle_actions = ActionGroup::create ("ShuttleActions");
871 shuttle_actions->add (Action::create (X_("SetShuttleUnitsPercentage"), _("Percentage")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Percentage));
872 shuttle_actions->add (Action::create (X_("SetShuttleUnitsSemitones"), _("Semitones")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_units), Semitones));
873 shuttle_actions->add (Action::create (X_("SetShuttleActionSprung"), _("Sprung")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Sprung));
874 shuttle_actions->add (Action::create (X_("SetShuttleActionWheel"), _("Wheel")), bind (mem_fun(*this, &ARDOUR_UI::set_shuttle_behaviour), Wheel));
876 ui_manager->insert_action_group (shuttle_actions);
878 shuttle_style_menu = dynamic_cast<Menu*> (ui_manager->get_widget ("ShuttleStylePopup"));
879 shuttle_unit_menu = dynamic_cast<Menu*> (ui_manager->get_widget ("ShuttleUnitPopup"));
881 gettimeofday (&last_peak_grab, 0);
882 gettimeofday (&last_shuttle_request, 0);
884 ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
885 ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
886 ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
887 ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
889 /* handle pending state with a dialog */
891 ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
893 channel_combo_strings = internationalize (channel_setup_names);
895 /* have to wait for AudioEngine and Configuration before proceeding */
899 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
901 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
903 string msg = string_compose (_("\
904 You cannot record-enable\n\
906 because it has no input connections.\n\
907 You would be wasting space recording silence."),
910 ArdourMessage message (editor, X_("cannotrecord"), msg);
914 ARDOUR_UI::set_engine (AudioEngine& e)
918 engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
919 engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
920 engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
921 engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
925 keyboard = new Keyboard;
926 install_keybindings ();
928 FastMeter::set_vertical_xpm (v_meter_strip_xpm);
929 FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
931 if (setup_windows ()) {
932 throw failed_constructor ();
935 if (GTK_ARDOUR::show_key_actions) {
936 KeyboardTarget::show_all_actions ();
940 /* start with timecode, metering enabled
943 blink_timeout_tag = -1;
945 /* this being a GUI and all, we want peakfiles */
947 FileSource::set_build_peakfiles (true);
948 FileSource::set_build_missing_peakfiles (true);
950 if (Source::start_peak_thread ()) {
951 throw failed_constructor();
954 /* start the time-of-day-clock */
956 update_wall_clock ();
957 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
959 update_disk_space ();
961 update_sample_rate (engine->frame_rate());
963 starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
964 stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
967 ARDOUR_UI::~ARDOUR_UI ()
969 save_ardour_state ();
983 if (add_route_dialog) {
984 delete add_route_dialog;
987 Source::stop_peak_thread ();
991 ARDOUR_UI::configure_timeout ()
996 if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
997 /* no configure events yet */
1001 gettimeofday (&now, 0);
1002 timersub (&now, &last_configure_time, &diff);
1004 /* force a gap of 0.5 seconds since the last configure event
1007 if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1010 have_configure_timeout = false;
1011 save_ardour_state ();
1017 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1019 if (have_configure_timeout) {
1020 gettimeofday (&last_configure_time, 0);
1022 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1023 have_configure_timeout = true;
1030 ARDOUR_UI::save_ardour_state ()
1032 if (!keyboard || !mixer || !editor) {
1036 /* XXX this is all a bit dubious. add_extra_xml() uses
1037 a different lifetime model from add_instant_xml().
1040 XMLNode* node = new XMLNode (keyboard->get_state());
1041 Config->add_extra_xml (*node);
1042 Config->save_state();
1044 XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1045 XMLNode& mnode (mixer->get_state());
1048 session->add_instant_xml(enode, session->path());
1049 session->add_instant_xml(mnode, session->path());
1051 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1052 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1057 ARDOUR_UI::startup ()
1059 /* Once the UI is up and running, start the audio engine. Doing
1060 this before the UI is up and running can cause problems
1061 when not running with SCHED_FIFO, because the amount of
1062 CPU and disk work needed to get the UI started can interfere
1063 with the scheduling of the audio thread.
1066 Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1072 if (session && session->dirty()) {
1073 switch (ask_about_saving_session(_("quit"))) {
1078 /* use the default name */
1079 if (save_state_canfail ("")) {
1080 /* failed - don't quit */
1081 ArdourMessage (editor, X_("badsave dialog"),
1083 Ardour was unable to save your session.\n\n\
1084 If you still wish to quit, please use the\n\n\
1085 \"Just quit\" option."));
1098 ARDOUR_UI::ask_about_saving_session (string what)
1100 ArdourDialog window ("saving dialog");
1102 Gtk::Label prompt_label;
1103 Gtk::HBox button_packer;
1107 msg = string_compose(_("Save and %1"), what);
1109 Gtk::Button save_button (msg);
1110 save_button.set_name ("EditorGTKButton");
1112 msg = string_compose(_("Just %1"), what);
1114 Gtk::Button nosave_button (msg);
1115 nosave_button.set_name ("EditorGTKButton");
1117 msg = string_compose(_("Don't %1"), what);
1119 Gtk::Button noquit_button (msg);
1120 noquit_button.set_name ("EditorGTKButton");
1125 if (session->snap_name() == session->name()) {
1126 type = _("session");
1128 type = _("snapshot");
1130 prompt = string_compose(_("The %1\n\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1131 type, session->snap_name());
1133 prompt_label.set_text (prompt);
1134 prompt_label.set_alignment (0.5, 0.5);
1135 prompt_label.set_name (X_("PrompterLabel"));
1137 save_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), 1));
1138 nosave_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), 0));
1139 noquit_button.signal_clicked().connect (bind(mem_fun(window,&ArdourDialog::stop), -1));
1141 button_packer.set_spacing (10);
1142 button_packer.pack_start (save_button);
1143 button_packer.pack_start (nosave_button);
1144 button_packer.pack_start (noquit_button);
1146 packer.set_spacing (10);
1147 packer.set_border_width (10);
1148 packer.pack_start (prompt_label);
1149 packer.pack_start (button_packer);
1151 window.set_name (_("Prompter"));
1152 window.set_title (_("ardour: save session?"));
1153 window.set_position (Gtk::WIN_POS_MOUSE);
1154 window.set_modal (true);
1155 window.add (packer);
1157 window.set_keyboard_input (true);
1159 save_the_session = 0;
1161 editor->ensure_float (window);
1165 return window.run_status();
1169 ARDOUR_UI::every_second ()
1172 update_buffer_load ();
1173 update_disk_space ();
1174 // update_disk_rate ();
1179 ARDOUR_UI::every_point_one_seconds ()
1182 struct timeval diff;
1184 /* do not attempt to grab peak power more than once per cycle.
1187 gettimeofday (&now, 0);
1188 timersub (&now, &last_peak_grab, &diff);
1190 if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1191 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1192 last_peak_grab = now;
1195 update_speed_display ();
1196 RapidScreenUpdate(); /* EMIT_SIGNAL */
1201 ARDOUR_UI::every_point_zero_one_seconds ()
1203 SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1208 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1212 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1214 if (!engine->connected()) {
1216 snprintf (buf, sizeof (buf), _("disconnected"));
1220 jack_nframes_t rate = engine->frame_rate();
1222 if (fmod (rate, 1000.0) != 0.0) {
1223 snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
1224 (float) rate/1000.0f,
1225 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1227 snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
1229 (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1233 sample_rate_label.set_text (buf);
1237 ARDOUR_UI::update_cpu_load ()
1240 snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1241 cpu_load_label.set_text (buf);
1245 ARDOUR_UI::update_disk_rate ()
1250 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
1251 session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1252 disk_rate_label.set_text (buf);
1254 disk_rate_label.set_text ("");
1259 ARDOUR_UI::update_buffer_load ()
1264 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1265 session->playback_load(), session->capture_load());
1266 buffer_load_label.set_text (buf);
1268 buffer_load_label.set_text ("");
1273 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1275 if (ds.record_enabled()) {
1276 rec_enabled_diskstreams++;
1281 ARDOUR_UI::update_disk_space()
1287 jack_nframes_t frames = session->available_capture_duration();
1290 if (frames == max_frames) {
1291 strcpy (buf, _("space: 24hrs+"));
1296 jack_nframes_t fr = session->frame_rate();
1298 if (session->actively_recording()){
1300 rec_enabled_diskstreams = 0;
1301 session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1303 if (rec_enabled_diskstreams) {
1304 frames /= rec_enabled_diskstreams;
1309 /* hmmm. shall we divide by the route count? or the diskstream count?
1310 or what? for now, do nothing ...
1315 hrs = frames / (fr * 3600);
1316 frames -= hrs * fr * 3600;
1317 mins = frames / (fr * 60);
1318 frames -= mins * fr * 60;
1321 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1324 disk_space_label.set_text (buf);
1328 ARDOUR_UI::update_wall_clock ()
1335 tm_now = localtime (&now);
1337 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1338 wall_clock_label.set_text (buf);
1344 ARDOUR_UI::toggle_recording_plugins ()
1346 /* XXX use toggle_some_session_state */
1352 session->set_recording_plugins (!session->get_recording_plugins());
1356 ARDOUR_UI::toggle_auto_play ()
1359 toggle_some_session_state (auto_play_button,
1360 &Session::get_auto_play,
1361 &Session::set_auto_play);
1365 ARDOUR_UI::toggle_auto_return ()
1368 toggle_some_session_state (auto_return_button,
1369 &Session::get_auto_return,
1370 &Session::set_auto_return);
1374 ARDOUR_UI::toggle_click ()
1376 toggle_some_session_state (click_button,
1377 &Session::get_clicking,
1378 &Session::set_clicking);
1382 ARDOUR_UI::follow_changed ()
1390 if (follow_button.get_active() != (x = editor->follow_playhead())) {
1391 follow_button.set_active (x);
1396 ARDOUR_UI::toggle_follow ()
1404 if (editor->follow_playhead() != (x = follow_button.get_active())) {
1405 editor->set_follow_playhead (x);
1410 ARDOUR_UI::toggle_session_auto_loop ()
1413 if (session->get_auto_loop()) {
1414 if (session->transport_rolling()) {
1418 session->request_auto_loop (false);
1422 session->request_auto_loop (true);
1428 ARDOUR_UI::toggle_session_punch_in ()
1431 session->set_punch_in (!session->get_punch_in());
1436 ARDOUR_UI::toggle_punch_out ()
1438 toggle_some_session_state (punch_out_button,
1439 &Session::get_punch_out,
1440 &Session::set_punch_out);
1444 ARDOUR_UI::toggle_punch_in ()
1446 toggle_some_session_state (punch_in_button,
1447 &Session::get_punch_in,
1448 &Session::set_punch_in);
1452 ARDOUR_UI::map_button_state ()
1455 map_some_session_state (auto_return_button,
1456 &Session::get_auto_return);
1457 map_some_session_state (auto_play_button,
1458 &Session::get_auto_play);
1459 map_some_session_state (auto_input_button,
1460 &Session::get_auto_input);
1461 map_some_session_state (punch_in_button,
1462 &Session::get_punch_in);
1463 map_some_session_state (punch_out_button,
1464 &Session::get_punch_out);
1465 map_some_session_state (click_button,
1466 &Session::get_clicking);
1470 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1472 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1476 ARDOUR_UI::map_control_change (Session::ControlType t)
1479 case Session::AutoPlay:
1480 map_some_session_state (auto_play_button, &Session::get_auto_play);
1483 case Session::AutoLoop:
1486 case Session::AutoReturn:
1487 map_some_session_state (auto_return_button, &Session::get_auto_return);
1490 case Session::AutoInput:
1491 map_some_session_state (auto_input_button, &Session::get_auto_input);
1494 case Session::PunchOut:
1495 map_some_session_state (punch_in_button, &Session::get_punch_out);
1498 case Session::PunchIn:
1499 map_some_session_state (punch_in_button, &Session::get_punch_in);
1502 case Session::Clicking:
1503 map_some_session_state (click_button, &Session::get_clicking);
1506 case Session::SlaveType:
1507 // map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1510 case Session::SendMTC:
1511 // map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1514 case Session::SendMMC:
1515 // map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1518 case Session::MMCControl:
1519 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1522 case Session::MidiFeedback:
1523 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1525 case Session::MidiControl:
1526 // map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1532 case Session::RecordingPlugins:
1535 case Session::CrossFadesActive:
1538 case Session::EditingMode:
1541 case Session::PlayRange:
1544 case Session::AlignChoice:
1545 /* don't care, this is handled by the options editor */
1547 case Session::SeamlessLoop:
1548 /* don't care, this is handled by the options editor */
1555 ARDOUR_UI::control_methods_adjusted ()
1560 which_method = (int) online_control_button->adjustment.get_value();
1561 switch (which_method) {
1563 allow_mmc_and_local ();
1569 allow_local_only ();
1572 fatal << _("programming error: impossible control method") << endmsg;
1578 ARDOUR_UI::mmc_device_id_adjusted ()
1583 int dev_id = (int) mmc_id_button->adjustment.get_value();
1584 mmc->set_device_id (dev_id);
1590 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1591 bool (Session::*get)() const)
1600 if (button.get_active() != (x = (session->*get)())) {
1601 button.set_active (x);
1606 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1607 bool (Session::*get)() const,
1608 void (Session::*set)(bool))
1618 button_state = button.get_active ();
1619 session_state = (session->*get)();
1621 if (button_state != session_state) {
1622 (session->*set) (button_state);
1625 /* check that it worked, and reverse
1626 the button state if it didn't
1629 if ((session->*get)() != button_state) {
1630 button->set_active (!button_state);
1638 ARDOUR_UI::session_menu (GdkEventButton *ev)
1640 session_popup_menu->popup (0, 0);
1645 ARDOUR_UI::redisplay_recent_sessions ()
1647 vector<string *> *sessions;
1648 vector<string *>::iterator i;
1649 RecentSessionsSorter cmp;
1651 recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1652 recent_session_model->clear ();
1655 ARDOUR::read_recent_sessions (rs);
1658 recent_session_display.set_model (recent_session_model);
1662 /* sort them alphabetically */
1663 sort (rs.begin(), rs.end(), cmp);
1664 sessions = new vector<string*>;
1666 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1667 sessions->push_back (new string ((*i).second));
1670 for (i = sessions->begin(); i != sessions->end(); ++i) {
1672 vector<string*>* states;
1673 vector<const gchar*> item;
1674 string fullpath = *(*i);
1676 /* remove any trailing / */
1678 if (fullpath[fullpath.length()-1] == '/') {
1679 fullpath = fullpath.substr (0, fullpath.length()-1);
1682 /* now get available states for this session */
1684 if ((states = Session::possible_states (fullpath)) == 0) {
1685 /* no state file? */
1689 TreeModel::Row row = *(recent_session_model->append());
1691 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1692 row[recent_session_columns.fullpath] = fullpath;
1694 if (states->size() > 1) {
1696 /* add the children */
1698 for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1700 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1702 child_row[recent_session_columns.visible_name] = **i2;
1703 child_row[recent_session_columns.fullpath] = fullpath;
1712 recent_session_display.set_model (recent_session_model);
1717 ARDOUR_UI::build_session_selector ()
1719 session_selector_window = new ArdourDialog ("session selector");
1721 Gtk::VBox *vpacker = manage (new Gtk::VBox);
1722 Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1723 Gtk::HBox *button_packer = manage (new Gtk::HBox);
1724 Gtk::Button *cancel_button = manage (new Gtk::Button (_("cancel")));
1725 Gtk::Button *rescan_button = manage (new Gtk::Button (_("rescan")));
1727 button_packer->pack_start (*rescan_button);
1728 button_packer->pack_start (*cancel_button);
1730 vpacker->pack_start (*scroller);
1731 vpacker->pack_start (*button_packer, false, false);
1733 recent_session_model = TreeStore::create (recent_session_columns);
1734 recent_session_display.set_model (recent_session_model);
1735 recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1736 recent_session_display.set_headers_visible (false);
1738 scroller->add (recent_session_display);
1739 scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1741 session_selector_window->add (*vpacker);
1742 session_selector_window->set_name ("SessionSelectorWindow");
1743 session_selector_window->set_size_request (200, 400);
1747 ARDOUR_UI::open_recent_session ()
1749 /* popup selector window */
1751 if (session_selector_window == 0) {
1752 build_session_selector ();
1755 redisplay_recent_sessions ();
1757 session_selector_window->run ();
1760 switch (session_selector_window->run_status()) {
1768 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1770 if (i == recent_session_model->children().end()) {
1774 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1775 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1777 session_selector_window->response (RESPONSE_ACCEPT);
1778 _session_is_new = false;
1780 load_session (path, state);
1785 ARDOUR_UI::fs_cancel_clicked (Gtk::FileSelection* fs)
1788 fs->get_selection_entry()->set_text("");
1789 allow_focus (false);
1793 ARDOUR_UI::fs_delete_event (GdkEventAny* ev, Gtk::FileSelection* fs)
1795 fs_cancel_clicked (fs);
1800 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info)
1802 struct stat statbuf;
1804 if (stat (info.filename.c_str(), &statbuf) != 0) {
1808 if (!S_ISDIR(statbuf.st_mode)) {
1812 string session_file = info.filename;
1813 session_file += '/';
1814 session_file += PBD::basename (info.filename);
1815 session_file += ".ardour";
1817 if (stat (session_file.c_str(), &statbuf) != 0) {
1821 return S_ISREG (statbuf.st_mode);
1825 ARDOUR_UI::open_session ()
1827 /* popup selector window */
1829 if (open_session_selector == 0) {
1830 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1831 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1832 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1834 FileFilter filter_ardour;
1835 filter_ardour.set_name (_("Ardour sessions"));
1836 filter_ardour.add_custom (FILE_FILTER_FILENAME, mem_fun (*this, &ARDOUR_UI::filter_ardour_session_dirs));
1838 open_session_selector->add_filter (filter_ardour);
1841 switch (open_session_selector->run ()) {
1848 string session_path = open_session_selector->get_filename();
1852 if (session_path.length() > 0) {
1853 if (Session::find_session (session_path, path, name, isnew) == 0) {
1854 _session_is_new = isnew;
1855 load_session (path, name);
1862 ARDOUR_UI::session_add_midi_track ()
1864 cerr << _("Patience is a virtue.\n");
1868 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1873 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1879 if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1880 error << _("could not create new audio track") << endmsg;
1883 if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1884 error << _("could not create new audio bus") << endmsg;
1889 if (need_control_room_outs) {
1895 route->set_stereo_control_outs (control_lr_channels);
1896 route->control_outs()->set_stereo_pan (pans, this);
1898 #endif /* CONTROLOUTS */
1902 ArdourMessage msg (editor, X_("noport dialog"),
1903 _("There are insufficient JACK ports available\n\
1904 to create a new track or bus.\n\
1905 You should save Ardour, exit and\n\
1906 restart JACK with more ports."));
1911 ARDOUR_UI::diskstream_added (DiskStream* ds)
1913 // meter_bridge_dialog_check->set_sensitive (true);
1917 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1919 jack_nframes_t _preroll;
1922 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1924 if (new_position > _preroll) {
1925 new_position -= _preroll;
1930 session->request_locate (new_position);
1935 ARDOUR_UI::transport_goto_start ()
1938 session->request_locate (0);
1941 /* force displayed area in editor to start no matter
1942 what "follow playhead" setting is.
1946 editor->reposition_x_origin (0);
1952 ARDOUR_UI::transport_goto_end ()
1955 jack_nframes_t frame = session->current_end_frame();
1956 session->request_locate (frame);
1958 /* force displayed area in editor to start no matter
1959 what "follow playhead" setting is.
1963 editor->reposition_x_origin (frame);
1969 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1974 if (session->transport_stopped()) {
1975 session->request_locate (session->last_transport_start());
1977 if (session->get_auto_loop()) {
1978 session->request_auto_loop (false);
1981 Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1982 session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1990 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1997 ARDOUR_UI::transport_stop ()
2003 if (session->is_auditioning()) {
2004 session->cancel_audition ();
2008 if (session->get_auto_loop()) {
2009 session->request_auto_loop (false);
2012 session->request_stop ();
2016 ARDOUR_UI::transport_stop_and_forget_capture ()
2019 session->request_stop (true);
2024 ARDOUR_UI::remove_last_capture()
2027 editor->remove_last_capture();
2032 ARDOUR_UI::transport_record ()
2035 switch (session->record_status()) {
2036 case Session::Disabled:
2037 if (session->ntracks() == 0) {
2038 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
2039 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2042 session->maybe_enable_record ();
2044 case Session::Recording:
2045 case Session::Enabled:
2046 session->disable_record ();
2052 ARDOUR_UI::transport_roll ()
2060 rolling = session->transport_rolling ();
2062 if (session->get_auto_loop()) {
2063 session->request_auto_loop (false);
2064 auto_loop_button.set_active (false);
2065 roll_button.set_active (true);
2066 } else if (session->get_play_range ()) {
2067 session->request_play_range (false);
2068 play_selection_button.set_active (false);
2069 } else if (rolling) {
2070 session->request_locate (session->last_transport_start(), true);
2073 session->request_transport_speed (1.0f);
2077 ARDOUR_UI::transport_loop()
2080 if (session->get_auto_loop()) {
2081 if (session->transport_rolling()) {
2082 Location * looploc = session->locations()->auto_loop_location();
2084 session->request_locate (looploc->start(), true);
2089 session->request_auto_loop (true);
2095 ARDOUR_UI::transport_play_selection ()
2101 if (!session->get_play_range()) {
2102 session->request_stop ();
2105 editor->play_selection ();
2109 ARDOUR_UI::transport_rewind (int option)
2111 float current_transport_speed;
2114 current_transport_speed = session->transport_speed();
2116 if (current_transport_speed >= 0.0f) {
2119 session->request_transport_speed (-1.0f);
2122 session->request_transport_speed (-4.0f);
2125 session->request_transport_speed (-0.5f);
2130 session->request_transport_speed (current_transport_speed * 1.5f);
2136 ARDOUR_UI::transport_forward (int option)
2138 float current_transport_speed;
2141 current_transport_speed = session->transport_speed();
2143 if (current_transport_speed <= 0.0f) {
2146 session->request_transport_speed (1.0f);
2149 session->request_transport_speed (4.0f);
2152 session->request_transport_speed (0.5f);
2157 session->request_transport_speed (current_transport_speed * 1.5f);
2163 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2171 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2172 Port *port = ds->io()->input (0);
2173 port->request_monitor_input (!port->monitoring_input());
2178 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2186 if ((ds = session->diskstream_by_id (dstream)) != 0) {
2187 ds->set_record_enabled (!ds->record_enabled(), this);
2192 ARDOUR_UI::queue_transport_change ()
2194 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2198 ARDOUR_UI::map_transport_state ()
2200 float sp = session->transport_speed();
2203 transport_rolling ();
2204 } else if (sp < 0.0f) {
2205 transport_rewinding ();
2206 } else if (sp > 0.0f) {
2207 transport_forwarding ();
2209 transport_stopped ();
2214 ARDOUR_UI::send_all_midi_feedback ()
2217 session->send_all_midi_feedback();
2222 ARDOUR_UI::allow_local_only ()
2228 ARDOUR_UI::allow_mmc_only ()
2234 ARDOUR_UI::allow_mmc_and_local ()
2240 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2242 snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2243 (int) adj.get_value()].c_str());
2247 ARDOUR_UI::engine_stopped ()
2249 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2251 jack_disconnect_item->set_sensitive (false);
2252 jack_reconnect_item->set_sensitive (true);
2253 jack_bufsize_menu->set_sensitive (false);
2258 ARDOUR_UI::engine_running ()
2260 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2262 jack_disconnect_item->set_sensitive (true);
2263 jack_reconnect_item->set_sensitive (false);
2264 jack_bufsize_menu->set_sensitive (true);
2268 ARDOUR_UI::engine_halted ()
2270 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2272 jack_disconnect_item->set_sensitive (false);
2273 jack_reconnect_item->set_sensitive (true);
2274 jack_bufsize_menu->set_sensitive (false);
2276 update_sample_rate (0);
2278 ArdourMessage msg (editor, X_("halted"),
2280 JACK has either been shutdown or it\n\
2281 disconnected Ardour because Ardour\n\
2282 was not fast enough. You can save the\n\
2283 session and/or try to reconnect to JACK ."));
2287 ARDOUR_UI::do_engine_start ()
2293 catch (AudioEngine::PortRegistrationFailure& err) {
2295 error << _("Unable to create all required ports")
2303 error << _("Unable to start the session running")
2313 ARDOUR_UI::start_engine ()
2315 if (do_engine_start () == 0) {
2316 if (session && _session_is_new) {
2317 /* we need to retain initial visual
2318 settings for a new session
2320 session->save_state ("");
2323 /* there is too much going on, in too many threads, for us to
2324 end up with a clean session. So wait 1 second after loading,
2325 and fix it up. its ugly, but until i come across a better
2326 solution, its what we have.
2329 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2336 ARDOUR_UI::update_clocks ()
2338 Clock (session->audible_frame()); /* EMIT_SIGNAL */
2342 ARDOUR_UI::start_clocking ()
2344 clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2348 ARDOUR_UI::stop_clocking ()
2350 clock_signal_connection.disconnect ();
2354 ARDOUR_UI::toggle_clocking ()
2357 if (clock_button.get_active()) {
2366 ARDOUR_UI::_blink (void *arg)
2369 ((ARDOUR_UI *) arg)->blink ();
2376 Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2380 ARDOUR_UI::start_blinking ()
2382 /* Start the blink signal. Everybody with a blinking widget
2383 uses Blink to drive the widget's state.
2386 if (blink_timeout_tag < 0) {
2388 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2393 ARDOUR_UI::stop_blinking ()
2395 if (blink_timeout_tag >= 0) {
2396 gtk_timeout_remove (blink_timeout_tag);
2397 blink_timeout_tag = -1;
2403 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2405 using namespace Gtk;
2406 using namespace Menu_Helpers;
2408 if (dstream.hidden()) {
2412 MenuList& items = diskstream_menu->items();
2413 items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2417 ARDOUR_UI::diskstream_selected (gint32 id)
2419 selected_dstream = id;
2424 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2426 using namespace Gtk;
2427 using namespace Menu_Helpers;
2433 diskstream_menu = new Menu();
2434 diskstream_menu->set_name ("ArdourContextMenu");
2435 using namespace Gtk;
2436 using namespace Menu_Helpers;
2438 MenuList& items = diskstream_menu->items();
2439 items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2441 session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2444 diskstream_menu->popup (ev->button, ev->time);
2446 diskstream_menu->popup (0, 0);
2449 selected_dstream = -1;
2453 delete diskstream_menu;
2455 return selected_dstream;
2459 ARDOUR_UI::name_io_setup (AudioEngine& engine,
2465 if (io.n_inputs() == 0) {
2470 /* XXX we're not handling multiple ports yet. */
2472 const char **connections = io.input(0)->get_connections();
2474 if (connections == 0 || connections[0] == '\0') {
2477 buf = connections[0];
2484 if (io.n_outputs() == 0) {
2489 /* XXX we're not handling multiple ports yet. */
2491 const char **connections = io.output(0)->get_connections();
2493 if (connections == 0 || connections[0] == '\0') {
2496 buf = connections[0];
2504 ARDOUR_UI::snapshot_session ()
2506 ArdourPrompter prompter (true);
2513 now = now.substr (0, now.length() - 1);
2515 prompter.set_name ("Prompter");
2516 prompter.set_prompt (_("Name for snapshot"));
2517 prompter.set_initial_text (now);
2519 switch (prompter.run()) {
2520 case RESPONSE_ACCEPT:
2521 prompter.get_result (snapname);
2522 if (snapname.length()){
2523 save_state (snapname);
2533 ARDOUR_UI::save_state (string name)
2535 (void) save_state_canfail (name);
2539 ARDOUR_UI::save_state_canfail (string name)
2544 if (name.length() == 0) {
2545 name = session->snap_name();
2548 if ((ret = session->save_state (name)) != 0) {
2552 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2557 ARDOUR_UI::restore_state (string name)
2560 if (name.length() == 0) {
2561 name = session->name();
2563 session->restore_state (name);
2568 ARDOUR_UI::allow_focus (bool yn)
2571 keyboard->allow_focus (yn);
2576 ARDOUR_UI::primary_clock_value_changed ()
2579 session->request_locate (primary_clock.current_time ());
2584 ARDOUR_UI::secondary_clock_value_changed ()
2587 session->request_locate (secondary_clock.current_time ());
2592 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2594 if (session && dstream && dstream->record_enabled()) {
2596 Session::RecordState rs;
2598 rs = session->record_status ();
2601 case Session::Disabled:
2602 case Session::Enabled:
2603 if (w->get_state() != STATE_SELECTED) {
2604 w->set_state (STATE_SELECTED);
2608 case Session::Recording:
2609 if (w->get_state() != STATE_ACTIVE) {
2610 w->set_state (STATE_ACTIVE);
2616 if (w->get_state() != STATE_NORMAL) {
2617 w->set_state (STATE_NORMAL);
2623 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2629 switch (session->record_status()) {
2630 case Session::Enabled:
2632 rec_button.set_state (STATE_ACTIVE);
2634 rec_button.set_state (STATE_NORMAL);
2638 case Session::Recording:
2639 rec_button.set_state (STATE_ACTIVE);
2643 rec_button.set_active (false);
2644 rec_button.set_state (STATE_NORMAL);
2650 ARDOUR_UI::generic_focus_in_event (GdkEventFocus *ev)
2652 ARDOUR_UI::instance()->allow_focus (true);
2657 ARDOUR_UI::generic_focus_out_event (GdkEventFocus *ev)
2659 ARDOUR_UI::instance()->allow_focus (false);
2664 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2672 ARDOUR_UI::start_keyboard_prefix ()
2674 keyboard->start_prefix();
2678 ARDOUR_UI::save_template ()
2681 ArdourPrompter prompter (true);
2684 prompter.set_name (X_("Prompter"));
2685 prompter.set_prompt (_("Name for mix template:"));
2686 prompter.set_initial_text(session->name() + _("-template"));
2688 switch (prompter.run()) {
2689 case RESPONSE_ACCEPT:
2690 prompter.get_result (name);
2692 if (name.length()) {
2693 session->save_template (name);
2703 ARDOUR_UI::new_session (bool startup, string predetermined_path)
2705 if (new_session_window == 0){
2706 new_session_window = new NewSessionDialog (*engine, startup, predetermined_path);
2707 editor->ensure_float (*new_session_window);
2710 new_session_window->run ();
2715 /* write favorites either way */
2716 Session::FavoriteDirs favs;
2717 new_session_window->file_selector.get_favorites (favs);
2718 Session::write_favorite_dirs (favs);
2720 if (new_session_window->run_status()) {
2725 string session_path = new_session_window->file_selector.get_filename ();
2726 string session_name = PBD::basename (session_path);
2728 // Check that it doesn't already exist.
2729 access(session_path.c_str(), R_OK);
2730 if (errno != ENOENT){
2731 error << string_compose(_("Session %1 already exists at %2"), session_name, session_path) << endmsg;
2735 _session_is_new = true;
2737 if (session_path[session_path.length()-1] != '/') {
2739 string template_name = new_session_window->get_template_name ();
2741 if (template_name.length()) {
2743 load_session (session_path, session_name, &template_name);
2749 Session::AutoConnectOption iconnect;
2750 Session::AutoConnectOption oconnect;
2752 if (new_session_window->use_control_button.get_active()) {
2753 cchns = (uint32_t) channel_combo_get_channel_count (new_session_window->control_out_channel_combo);
2757 if (new_session_window->use_master_button.get_active()) {
2758 mchns = (uint32_t) channel_combo_get_channel_count (new_session_window->master_out_channel_combo);
2763 if (new_session_window->connect_to_physical_inputs_button.get_active()) {
2764 iconnect = Session::AutoConnectPhysical;
2766 iconnect = Session::AutoConnectOption (0);
2769 if (new_session_window->connect_to_master_button.get_active ()) {
2770 oconnect = Session::AutoConnectMaster;
2771 } else if (new_session_window->connect_to_physical_outputs_button.get_active ()) {
2772 oconnect = Session::AutoConnectPhysical;
2774 oconnect = Session::AutoConnectOption (0);
2777 uint32_t nphysin = (uint32_t) new_session_window->in_count_adjustment.get_value();
2778 uint32_t nphysout = (uint32_t) new_session_window->out_count_adjustment.get_value();
2780 build_session (session_path, session_name, cchns, mchns, iconnect, oconnect, nphysin, nphysout,
2781 engine->frame_rate() * 60 * 5);
2787 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2789 Session *new_session;
2791 session_loaded = false;
2792 x = unload_session ();
2800 /* if it already exists, we must have write access */
2802 if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2803 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2804 You do not have write access to this session.\n\
2805 This prevents the session from being loaded."));
2810 new_session = new Session (*engine, path, snap_name, mix_template);
2815 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2819 connect_to_session (new_session);
2821 //if (engine->running()) {
2822 //mixer->show_window();
2824 session_loaded = true;
2829 ARDOUR_UI::make_session_clean ()
2832 session->set_clean ();
2839 ARDOUR_UI::build_session (string path, string snap_name,
2840 uint32_t control_channels,
2841 uint32_t master_channels,
2842 Session::AutoConnectOption input_connect,
2843 Session::AutoConnectOption output_connect,
2846 jack_nframes_t initial_length)
2848 Session *new_session;
2851 session_loaded = false;
2852 x = unload_session ();
2859 _session_is_new = true;
2862 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2863 control_channels, master_channels, nphysin, nphysout, initial_length);
2868 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2872 connect_to_session (new_session);
2874 //if (engine->running()) {
2875 //mixer->show_window();
2877 session_loaded = true;
2882 ARDOUR_UI::hide_dialog (ArdourDialog *dialog)
2891 editor->show_window ();
2895 if (session && mixer) {
2896 mixer->show_window ();
2905 ARDOUR_UI::show_splash ()
2908 about = new About();
2914 ARDOUR_UI::hide_splash ()
2922 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2926 removed = rep.paths.size();
2929 ArdourMessage msg (editor, X_("cleanupresults"),
2931 No audio files were ready for cleanup\n\n\
2932 If this seems suprising, check for any existing\n\
2933 snapshots. These may still include regions that\n\
2934 require some unused files to continue to exist."));
2938 ArdourDialog results ("cleanup results");
2940 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2941 CleanupResultsModelColumns() {
2945 Gtk::TreeModelColumn<Glib::ustring> visible_name;
2946 Gtk::TreeModelColumn<Glib::ustring> fullpath;
2950 Glib::RefPtr<Gtk::ListStore> results_model;
2951 CleanupResultsModelColumns results_columns;
2952 Gtk::TreeView results_display;
2954 results_model = ListStore::create (results_columns);
2955 results_display.set_model (results_model);
2956 results_display.append_column (list_title, results_columns.visible_name);
2957 results_display.set_headers_visible (true);
2959 Gtk::ScrolledWindow list_scroller;
2961 Gtk::Button ok_button (_("OK"));
2964 vpacker.set_border_width (10);
2965 vpacker.set_spacing (10);
2967 if (rep.space < 1048576.0f) {
2969 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2971 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2975 txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2977 txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2981 vpacker.pack_start (txt, false, false);
2983 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2984 TreeModel::Row row = *(results_model->append());
2985 row[results_columns.visible_name] = *i;
2986 row[results_columns.fullpath] = *i;
2989 list_scroller.add (results_display);
2990 list_scroller.set_size_request (-1, 250);
2991 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2993 vpacker.pack_start (list_scroller, true, true);
2994 vpacker.pack_start (ok_button, false, false);
2996 results.add (vpacker);
2998 results.set_position (Gtk::WIN_POS_MOUSE);
2999 results.set_title (_("ardour: cleanup"));
3000 results.set_modal (true);
3006 ARDOUR_UI::cleanup ()
3009 /* shouldn't happen: menu item is insensitive */
3013 ArdourDialog checker (X_("cleanup confirm dialog"));
3014 Gtk::Label label (_("\
3015 Cleanup is a destructive operation.\n\
3016 ALL undo/redo information will be lost if you cleanup.\n\
3017 Unused audio files will be moved to a \"dead sounds\" location."));
3019 Gtk::Button ok_button (_("Proceed with cleanup"));
3020 Gtk::Button cancel_button (_("Cancel"));
3024 bbox.set_border_width (6);
3025 bbox.set_spacing (12);
3026 bbox.pack_start (ok_button, true, false);
3027 bbox.pack_start (cancel_button, true, false);
3029 vbox.set_border_width (6);
3030 vbox.set_spacing (12);
3031 vbox.pack_start (label, false, false);
3032 vbox.pack_start (bbox, false, false);
3035 checker.set_name (_("CleanupDialog"));
3036 checker.set_title (_("ardour cleanup"));
3037 checker.set_wmclass (_("ardour_cleanup"), "Ardour");
3038 checker.set_position (Gtk::WIN_POS_MOUSE);
3040 ok_button.signal_clicked().connect (bind (mem_fun (checker, &ArdourDialog::stop), 1));
3041 cancel_button.signal_clicked().connect (bind (mem_fun (checker, &ArdourDialog::stop), 0));
3045 switch (checker.run_status()) {
3052 Session::cleanup_report rep;
3054 editor->prepare_for_cleanup ();
3056 if (session->cleanup_sources (rep)) {
3060 display_cleanup_results (rep,
3063 The following %1 %2 were not in use.\n\
3064 The next time you flush the wastebasket\n\
3065 it will release an additional %3 %4bytes\n\
3071 ARDOUR_UI::flush_trash ()
3074 /* shouldn't happen: menu item is insensitive */
3078 Session::cleanup_report rep;
3080 if (session->cleanup_trash_sources (rep)) {
3084 display_cleanup_results (rep,
3086 _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
3090 ARDOUR_UI::add_route ()
3098 if (add_route_dialog == 0) {
3099 add_route_dialog = new AddRouteDialog;
3100 editor->ensure_float (*add_route_dialog);
3103 if (add_route_dialog->is_visible()) {
3104 /* we're already doing this */
3108 add_route_dialog->run ();
3110 if (add_route_dialog->run_status()) {
3114 if ((count = add_route_dialog->count()) <= 0) {
3118 uint32_t input_chan = add_route_dialog->channels ();
3119 uint32_t output_chan;
3120 string name_template = add_route_dialog->name_template ();
3121 bool track = add_route_dialog->track ();
3123 Session::AutoConnectOption oac = session->get_output_auto_connect();
3125 if (oac & Session::AutoConnectMaster) {
3126 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3128 output_chan = input_chan;
3131 /* XXX do something with name template */
3135 session_add_audio_track (input_chan, output_chan);
3137 session_add_audio_bus (input_chan, output_chan);
3141 while (Main::events_pending()) {
3148 ARDOUR_UI::mixer_settings () const
3153 node = session->instant_xml(X_("Mixer"), session->path());
3155 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3159 node = new XMLNode (X_("Mixer"));
3166 ARDOUR_UI::editor_settings () const
3171 node = session->instant_xml(X_("Editor"), session->path());
3173 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3177 node = new XMLNode (X_("Editor"));
3183 ARDOUR_UI::keyboard_settings () const
3187 node = Config->extra_xml(X_("Keyboard"));
3190 node = new XMLNode (X_("Keyboard"));
3196 ARDOUR_UI::halt_on_xrun_message ()
3198 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3200 ArdourMessage msg (editor, X_("haltonxrun"),
3201 _("Recording was stopped because your system could not keep up."));
3205 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3207 ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3209 for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3213 delete deletion_list;
3217 ARDOUR_UI::disk_overrun_handler ()
3219 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3221 if (!have_disk_overrun_displayed) {
3222 have_disk_overrun_displayed = true;
3223 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3224 The disk system on your computer\n\
3225 was not able to keep up with Ardour.\n\
3227 Specifically, it failed to write data to disk\n\
3228 quickly enough to keep up with recording.\n"));
3229 have_disk_overrun_displayed = false;
3234 ARDOUR_UI::disk_underrun_handler ()
3236 ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3238 if (!have_disk_underrun_displayed) {
3239 have_disk_underrun_displayed = true;
3240 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3241 (_("The disk system on your computer\n\
3242 was not able to keep up with Ardour.\n\
3244 Specifically, it failed to read data from disk\n\
3245 quickly enough to keep up with playback.\n")));
3246 have_disk_underrun_displayed = false;
3251 ARDOUR_UI::disk_underrun_message_gone ()
3253 have_disk_underrun_displayed = false;
3257 ARDOUR_UI::disk_overrun_message_gone ()
3259 have_disk_underrun_displayed = false;
3263 ARDOUR_UI::pending_state_dialog ()
3265 ArdourDialog dialog ("pending state dialog");
3266 Button use_button (_("Recover from crash"));
3267 Button cancel_button (_("Ignore crash data"));
3269 This session appears to have been in\n\
3270 middle of recording when ardour or\n\
3271 the computer was shutdown.\n\
3273 Ardour can recover any captured audio for\n\
3274 you, or it can ignore it. Please decide\n\
3275 what you would like to do.\n"));
3279 vpacker.set_border_width (12);
3280 vpacker.set_spacing (7);
3281 vpacker.pack_start (message);
3282 vpacker.pack_start (hpacker);
3284 hpacker.set_spacing (7);
3285 hpacker.pack_start (use_button);
3286 hpacker.pack_start (cancel_button);
3288 use_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
3289 cancel_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
3291 dialog.add (vpacker);
3292 dialog.set_position (WIN_POS_CENTER);
3297 if (dialog.run_status () != 0) {
3306 ARDOUR_UI::disconnect_from_jack ()
3309 if( engine->disconnect_from_jack ()) {
3310 ArdourMessage msg (editor, X_("nojack dialog"),
3311 _("Could not disconnect from JACK"));
3314 update_sample_rate (0);
3319 ARDOUR_UI::reconnect_to_jack ()
3322 if (engine->reconnect_to_jack ()) {
3323 ArdourMessage msg (editor, X_("nojack dialog"),
3324 _("Could not reconnect to JACK"));
3327 update_sample_rate (0);
3332 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3334 engine->request_buffer_size (nframes);
3335 update_sample_rate (0);
3339 ARDOUR_UI::cmdline_new_session (string path)
3341 if (path[0] != '/') {
3342 char buf[PATH_MAX+1];
3345 getcwd (buf, sizeof (buf));
3352 new_session (false, path);
3354 _will_create_new_session_automatically = false; /* done it */
3355 return FALSE; /* don't call it again */