20 #include <gdkmm/pixbuf.h>
31 #include <gtkmm/menu.h>
32 #include <gtkmm/menuitem.h>
58 #define PX_SCALE(px) std::max((float)px, rintf((float)px * ARDOUR_UI::ui_scale))
64 , channel_table_viewport (*channel_table_scroller.get_hadjustment()
65 , *channel_table_scroller.get_vadjustment ())
68 , solo_boost_control (0)
69 , solo_cut_control (0)
72 , solo_boost_display (0)
73 , solo_cut_display (0)
74 , _output_selector (0)
75 , solo_in_place_button (
_(
"SiP"),
ArdourButton::led_default_elements)
78 , exclusive_solo_button (
ArdourButton::led_default_elements)
79 , solo_mute_override_button (
ArdourButton::led_default_elements)
80 , _inhibit_solo_model_update (false)
83 using namespace Menu_Helpers;
85 Glib::RefPtr<Action> act;
117 UI::instance()->set_tip (
rude_solo_button,
_(
"When active, something is soloed.\nClick to de-solo everything"));
120 UI::instance()->set_tip (
rude_iso_button,
_(
"When active, something is solo-isolated.\nClick to de-isolate everything"));
123 UI::instance()->set_tip (
rude_audition_button,
_(
"When active, auditioning is active.\nClick to stop the audition"));
126 afl_button.set_name (
"monitor section solo model");
127 pfl_button.set_name (
"monitor section solo model");
172 HBox* solo_packer = manage (
new HBox);
173 solo_packer->set_spacing (6);
174 solo_packer->show ();
176 spin_label = manage (
new Label (
_(
"Solo Boost")));
177 spin_packer = manage (
new VBox);
178 spin_packer->show ();
179 spin_packer->set_spacing (3);
180 spin_packer->pack_start (*spin_label,
false,
false);
184 solo_packer->pack_start (*spin_packer,
true,
false);
202 spin_label = manage (
new Label (
_(
"SiP Cut")));
203 spin_packer = manage (
new VBox);
204 spin_packer->show ();
205 spin_packer->set_spacing (3);
206 spin_packer->pack_start (*spin_label,
false,
false);
210 solo_packer->pack_start (*spin_packer,
true,
false);
228 HBox* dim_packer = manage (
new HBox);
231 spin_label = manage (
new Label (
_(
"Dim")));
232 spin_packer = manage (
new VBox);
233 spin_packer->show ();
234 spin_packer->set_spacing (3);
235 spin_packer->pack_start (*spin_label,
false,
false);
236 spin_packer->pack_start (*
dim_control,
false,
false);
237 spin_packer->pack_start (*
dim_display,
false,
false);
239 dim_packer->pack_start (*spin_packer,
true,
false);
259 HBox* solo_opt_box = manage (
new HBox);
260 solo_opt_box->set_spacing (12);
261 solo_opt_box->set_homogeneous (
true);
264 solo_opt_box->show ();
268 Gtk::HBox* rude_box = manage (
new HBox);
276 upper_packer.pack_start (*solo_packer,
false,
false, 12);
303 HBox* bbox = manage (
new HBox);
305 bbox->set_spacing (12);
329 Label* output_label = manage (
new Label (
_(
"Output")));
330 output_label->set_name (
X_(
"MonitorSectionLabel"));
336 VBox* out_packer = manage (
new VBox);
337 out_packer->set_spacing (6);
338 out_packer->pack_start (*output_label,
false,
false);
341 spin_label = manage (
new Label (
_(
"Monitor")));
342 spin_packer = manage (
new VBox);
343 spin_packer->show ();
344 spin_packer->set_spacing (3);
345 spin_packer->pack_start (*spin_label,
false,
false);
348 spin_packer->pack_start (*out_packer,
false,
false, 24);
364 Label* l1 = manage (
new Label (
X_(
" ")));
365 l1->set_name (
X_(
"MonitorSectionLabel"));
368 l1 = manage (
new Label (
_(
"Mute")));
369 l1->set_name (
X_(
"MonitorSectionLabel"));
372 l1 = manage (
new Label (
_(
"Dim")));
373 l1->set_name (
X_(
"MonitorSectionLabel"));
376 l1 = manage (
new Label (
_(
"Solo")));
377 l1->set_name (
X_(
"MonitorSectionLabel"));
380 l1 = manage (
new Label (
_(
"Inv")));
381 l1->set_name (
X_(
"MonitorSectionLabel"));
394 vpacker.pack_start (*dim_packer,
false,
false);
432 AudioEngine::instance()->PortConnectedOrDisconnected.connect (
539 cut.set_name (
X_(
"monitor section cut"));
540 dim.set_name (
X_(
"monitor section dim"));
541 solo.set_name (
X_(
"monitor section solo"));
542 invert.set_name (
X_(
"monitor section invert"));
544 cut.unset_flags (Gtk::CAN_FOCUS);
545 dim.unset_flags (Gtk::CAN_FOCUS);
546 solo.unset_flags (Gtk::CAN_FOCUS);
547 invert.unset_flags (Gtk::CAN_FOCUS);
557 Glib::RefPtr<Action> act;
565 const uint32_t row_offset = 0;
567 for (uint32_t i = 0; i < nchans; ++i) {
580 snprintf (buf,
sizeof (buf),
"%d", i+1);
584 Label* label = manage (
new Label (l));
585 channel_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, EXPAND|FILL);
591 channel_table.attach (cbs->
cut, 1, 2, i+row_offset, i+row_offset+1, EXPAND|FILL);
592 channel_table.attach (cbs->
dim, 2, 3, i+row_offset, i+row_offset+1, EXPAND|FILL);
593 channel_table.attach (cbs->
solo, 3, 4, i+row_offset, i+row_offset+1, EXPAND|FILL);
596 snprintf (buf,
sizeof (buf),
"monitor-cut-%u", i+1);
602 snprintf (buf,
sizeof (buf),
"monitor-dim-%u", i+1);
608 snprintf (buf,
sizeof (buf),
"monitor-solo-%u", i+1);
614 snprintf (buf,
sizeof (buf),
"monitor-invert-%u", i+1);
633 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
634 Config->set_exclusive_solo (tact->get_active());
648 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
649 Config->set_solo_mute_override (tact->get_active());
662 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
677 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
691 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
704 snprintf (buf,
sizeof (buf),
"monitor-cut-%u", chn);
710 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
723 snprintf (buf,
sizeof (buf),
"monitor-dim-%u", chn);
729 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
743 snprintf (buf,
sizeof (buf),
"monitor-solo-%u", chn);
749 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
763 snprintf (buf,
sizeof (buf),
"monitor-invert-%u", chn);
769 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
779 Glib::RefPtr<Action> act;
796 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
797 tact->set_active (
Config->get_exclusive_solo());
802 tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
803 tact->set_active (
Config->get_solo_mute_override());
808 for (uint32_t chn = 1; chn <= 16; ++chn) {
833 Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (
X_(
"Solo"));
834 RadioAction::Group solo_group;
857 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
859 if (!ract->get_active ()) {
867 Config->set_solo_control_is_listen_control (!ract->get_active());
883 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
885 if (ract->get_active()) {
886 Config->set_solo_control_is_listen_control (
true);
903 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
905 if (ract->get_active()) {
906 Config->set_solo_control_is_listen_control (
true);
920 const char* action_name = 0;
921 Glib::RefPtr<Action> act;
923 if (
Config->get_solo_control_is_listen_control()) {
924 switch (
Config->get_listen_position()) {
926 action_name =
X_(
"solo-use-afl");
929 action_name =
X_(
"solo-use-pfl");
933 action_name =
X_(
"solo-use-in-place");
939 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
945 if (ract->get_active()) {
946 ract->set_active (
false);
948 ract->set_active (
true);
961 Glib::RefPtr<Action> act;
967 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
975 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
983 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
993 for (uint32_t n = 0; n < nchans; ++n) {
995 char action_name[32];
997 snprintf (action_name,
sizeof (action_name),
"monitor-cut-%u", n);
1000 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
1006 snprintf (action_name,
sizeof (action_name),
"monitor-dim-%u", n);
1009 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
1015 snprintf (action_name,
sizeof (action_name),
"monitor-solo-%u", n);
1018 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
1024 snprintf (action_name,
sizeof (action_name),
"monitor-invert-%u", n);
1027 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
1114 #define SYNCHRONIZE_TOGGLE_ACTION(action, value) \
1116 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(action); \
1117 if (tact && tact->get_active() != value) { \
1118 tact->set_active(value); \
1125 if (name ==
"solo-control-is-listen-control") {
1127 }
else if (name ==
"listen-position") {
1129 }
else if (name ==
"solo-mute-override") {
1132 Config->get_solo_mute_override ())
1133 }
else if (name ==
"exclusive-solo") {
1136 Config->get_exclusive_solo ())
1195 return "monitor-section";
1201 using namespace Menu_Helpers;
1220 std::string n = b->
name ();
1232 if (std::find (current.begin(), current.end(), c) == current.end()) {
1233 _route->
output()->connect_ports_to_bundle (c,
true,
this);
1235 _route->
output()->disconnect_ports_from_bundle (c,
this);
1242 switch (ev->button) {
1253 return a->
name().compare (b->
name()) < 0;
1260 using namespace Menu_Helpers;
1262 MessageDialog msg (
_(
"No session - no I/O changes are possible"));
1268 switch (ev->button) {
1281 citems.push_back (SeparatorElem());
1282 uint32_t
const n_with_separator = citems.size ();
1290 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
1291 if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
1296 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
1297 if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
1305 for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
1309 if (citems.size() == n_with_separator) {
1314 citems.push_back (SeparatorElem());
1343 vector<string> port_connections;
1345 uint32_t total_connection_count = 0;
1346 uint32_t io_connection_count = 0;
1347 uint32_t ardour_connection_count = 0;
1348 uint32_t system_connection_count = 0;
1349 uint32_t other_connection_count = 0;
1351 ostringstream label;
1353 bool have_label =
false;
1354 bool each_io_has_one_connection =
true;
1356 string connection_name;
1357 string ardour_track_name;
1358 string other_connection_type;
1359 string system_ports;
1362 ostringstream tooltip;
1363 char * tooltip_cstr;
1369 for (io_index = 0; io_index < io_count; ++io_index) {
1374 if (port->
type() != DataType::AUDIO) {
1378 port_connections.clear ();
1380 io_connection_count = 0;
1382 if (!port_connections.empty()) {
1383 for (vector<string>::iterator i = port_connections.begin(); i != port_connections.end(); ++i) {
1385 string& connection_name (*i);
1387 if (connection_name.find(
"system:") == 0) {
1388 pn = AudioEngine::instance()->get_pretty_name_by_name (connection_name);
1391 if (io_connection_count == 0) {
1392 tooltip << endl << Glib::Markup::escape_text(port->
name().substr(port->
name().find(
"/") + 1))
1394 << Glib::Markup::escape_text( pn.empty() ? connection_name : pn );
1397 << Glib::Markup::escape_text( pn.empty() ? connection_name : pn );
1400 if (connection_name.find(
"ardour:") == 0) {
1401 if (ardour_track_name.empty()) {
1403 string::size_type slash = connection_name.find(
"/");
1404 if (slash != string::npos) {
1405 ardour_track_name = connection_name.substr(0, slash + 1);
1409 if (connection_name.find(ardour_track_name) == 0) {
1410 ++ardour_connection_count;
1412 }
else if (!pn.empty()) {
1413 if (system_ports.empty()) {
1416 system_ports +=
"/" + pn;
1418 if (connection_name.find(
"system:") == 0) {
1419 ++system_connection_count;
1421 }
else if (connection_name.find(
"system:") == 0) {
1423 system_port = connection_name.substr(16);
1424 if (system_ports.empty()) {
1425 system_ports += system_port;
1427 system_ports +=
"/" + system_port;
1430 ++system_connection_count;
1432 if (other_connection_type.empty()) {
1434 other_connection_type = connection_name.substr(0, connection_name.find(
":") + 1);
1437 if (connection_name.find(other_connection_type) == 0) {
1438 ++other_connection_count;
1442 ++total_connection_count;
1443 ++io_connection_count;
1447 if (io_connection_count != 1) {
1448 each_io_has_one_connection =
false;
1452 if (total_connection_count == 0) {
1453 tooltip << endl <<
_(
"Disconnected");
1456 tooltip_cstr =
new char[tooltip.str().size() + 1];
1457 strcpy(tooltip_cstr, tooltip.str().c_str());
1461 if (each_io_has_one_connection) {
1462 if (total_connection_count == ardour_connection_count) {
1465 string::size_type slash = ardour_track_name.find(
"/");
1466 if (slash != string::npos) {
1467 label << ardour_track_name.substr(7, slash - 7);
1470 }
else if (total_connection_count == system_connection_count) {
1472 label << system_ports;
1474 }
else if (total_connection_count == other_connection_count) {
1477 label << other_connection_type.substr(0, other_connection_type.size() - 1);
1483 if (total_connection_count == 0) {
1488 label <<
"*" << total_connection_count <<
"*";
virtual DataType type() const =0
Gtk::HBox channel_table_packer
boost::shared_ptr< PBD::Controllable > dim_control() const
void toggle_exclusive_solo()
boost::shared_ptr< PBD::Controllable > solo_cut_control() const
bool inverted(uint32_t chn) const
#define SYNCHRONIZE_TOGGLE_ACTION(action, value)
ArdourButton exclusive_solo_button
void set_listen(boost::shared_ptr< RouteList >, bool, SessionEvent::RTeventCallback after=rt_cleanup, bool group_override=false)
bool solo_isolated() const
ArdourButton rude_solo_button
void set_solo(boost::shared_ptr< RouteList >, bool, SessionEvent::RTeventCallback after=rt_cleanup, bool group_override=false)
void update_output_display()
boost::shared_ptr< ARDOUR::Route > _route
void dim_channel(uint32_t)
void set_cut(uint32_t, bool cut)
void toggle_mute_overrides_solo()
void cut_channel(uint32_t)
static ARDOUR_UI * instance()
ArdourKnob * solo_cut_control
bool forward_key_press(GdkEventKey *ev)
ArdourButton solo_mute_override_button
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > get_action(const char *group, const char *name)
Gtk::Viewport channel_table_viewport
boost::shared_ptr< AutomationControl > gain_control() const
bool is_auditioning() const
bool cut(uint32_t chn) const
boost::shared_ptr< MonitorProcessor > monitor_control() const
ArdourButton cut_all_button
boost::shared_ptr< PBD::Controllable > dim_level_control() const
Gtk::Table channel_table_header
LIBPBD_API int replace_all(std::string &str, const std::string &target, const std::string &replacement)
static Element default_elements
boost::shared_ptr< PBD::Controllable > solo_boost_control() const
void add_controllable_preset(const char *, float)
Gtkmm2ext::TearOff * _tearoff
boost::shared_ptr< PBD::Controllable > cut_control() const
ArdourKnob * gain_control
ChannelButtons _channel_buttons
bool soloed(uint32_t chn) const
bool cancel_isolate(GdkEventButton *)
void edit_output_configuration()
MonitorSelectorWindow * _output_selector
LIBARDOUR_API RCConfiguration * Config
ArdourKnob * solo_boost_control
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > register_radio_action(Glib::RefPtr< Gtk::ActionGroup > group, Gtk::RadioAction::Group &, const char *name, const char *label, sigc::slot< void > sl, guint key, Gdk::ModifierType mods)
std::vector< boost::shared_ptr< Bundle > > BundleList
ArdourButton dim_all_button
std::string state_id() const
Glib::RefPtr< Gtk::SizeGroup > channel_size_group
boost::shared_ptr< PBD::Controllable > mono_control() const
void set_controllable(boost::shared_ptr< PBD::Controllable > c)
void set_controllable(boost::shared_ptr< PBD::Controllable > c)
void output_button_resized(Gtk::Allocation &)
bool ports_are_inputs() const
bool dimmed(uint32_t chn) const
bool cancel_solo(GdkEventButton *)
boost::shared_ptr< BundleList > bundles()
ChanCount n_outputs() const
ChanCount nchannels() const
boost::shared_ptr< ARDOUR::MonitorProcessor > _monitor
bool deletion_in_progress() const
void set_solo(uint32_t, bool)
ArdourDisplay * gain_display
gint output_release(GdkEventButton *)
boost::shared_ptr< RouteList > get_routes() const
std::list< boost::shared_ptr< ARDOUR::Bundle > > output_menu_bundles
void set_dim(uint32_t, bool dim)
Gtk::Tooltips & tooltips()
ArdourButton rude_iso_button
void solo_channel(uint32_t)
Gtk::Window & tearoff_window()
gint output_press(GdkEventButton *)
static Glib::RefPtr< Gtk::ActionGroup > monitor_actions
PBD::Signal1< void, std::string > ParameterChanged
void parameter_changed(std::string)
sigc::connection blink_connect(const sigc::slot< void, bool > &slot)
void set_tip(Gtk::Widget &w, const gchar *tip)
ArdourDisplay * dim_display
ArdourDisplay * solo_boost_display
bool cancel_audition(GdkEventButton *)
ArdourButton rude_audition_button
PBD::ScopedConnectionList control_connections
LIBARDOUR_API PBD::PropertyDescriptor< bool > solo
void port_connected_or_disconnected(boost::weak_ptr< ARDOUR::Port >, boost::weak_ptr< ARDOUR::Port >)
void assign_controllables()
int get_connections(std::vector< std::string > &) const
ArdourButton * output_button
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > register_toggle_action(Glib::RefPtr< Gtk::ActionGroup > group, const char *name, const char *label, sigc::slot< void > sl, guint key, Gdk::ModifierType mods)
void maybe_add_bundle_to_output_menu(boost::shared_ptr< ARDOUR::Bundle >, ARDOUR::BundleList const &)
void set_polarity(uint32_t, bool invert)
ArdourButton solo_in_place_button
boost::shared_ptr< IO > input() const
void set_session(ARDOUR::Session *)
virtual void set_session(ARDOUR::Session *)
boost::shared_ptr< IO > output() const
ArdourDisplay * solo_cut_display
void invert_channel(uint32_t)
Gtk::ScrolledWindow channel_table_scroller
MonitorSection(ARDOUR::Session *)
void audition_blink(bool)
PBD::ScopedConnection config_connection
PBD::ScopedConnection _output_changed_connection
void set_solo_isolated(boost::shared_ptr< RouteList >, bool, SessionEvent::RTeventCallback after=rt_cleanup, bool group_override=false)
LIBGTKMM2EXT_API void add_action_group(Glib::RefPtr< Gtk::ActionGroup >)
std::list< boost::shared_ptr< Route > > RouteList
boost::shared_ptr< Route > monitor_out() const
bool _inhibit_solo_model_update
ARDOUR::Session * _session
bool has_same_ports(boost::shared_ptr< Bundle >) const
std::string string_compose(const std::string &fmt, const T1 &o1)
void bundle_output_chosen(boost::shared_ptr< ARDOUR::Bundle >)
virtual ChanCount output_streams() const