#include <sigc++/bind.h>
-#include "pbd/convert.h"
-#include "canvas/utils.h"
-
#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
#include <gtkmm/messagedialog.h>
-#include <gtkmm2ext/gtk_ui.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/choice.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/doi.h>
-#include <gtkmm2ext/rgb_macros.h>
+#include "gtkmm2ext/colors.h"
+#include "gtkmm2ext/gtk_ui.h"
+#include "gtkmm2ext/menu_elems.h"
+#include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/doi.h"
+#include "gtkmm2ext/rgb_macros.h"
+
+#include "widgets/choice.h"
+#include "widgets/prompter.h"
+#include "widgets/tooltips.h"
#include "ardour/amp.h"
#include "ardour/audio_track.h"
#include "ardour/send.h"
#include "ardour/session.h"
#include "ardour/types.h"
+#include "ardour/value_as_string.h"
#include "LuaBridge/LuaBridge.h"
#include "plugin_ui.h"
#include "port_insert_ui.h"
#include "processor_box.h"
+#include "processor_selection.h"
#include "public_editor.h"
#include "return_ui.h"
-#include "route_processor_selection.h"
#include "script_selector.h"
#include "send_ui.h"
#include "timers.h"
-#include "tooltips.h"
#include "new_plugin_preset_dialog.h"
#include "pbd/i18n.h"
using namespace Gtk;
using namespace Glib;
using namespace Gtkmm2ext;
+using namespace ArdourWidgets;
ProcessorBox* ProcessorBox::_current_processor_box = 0;
RefPtr<Action> ProcessorBox::paste_action;
boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_processor);
if (pi && pi->plugin() && pi->plugin()->has_inline_display()) {
if (pi->plugin()->get_info()->type != ARDOUR::Lua) {
- _plugin_display = new PluginDisplay (*this, pi->plugin(),
+ _plugin_display = new PluginInlineDisplay (*this, pi->plugin(),
std::max (60.f, rintf(112.f * UIConfiguration::instance().get_ui_scale())));
} else {
assert (boost::dynamic_pointer_cast<LuaProc>(pi->plugin()));
}
}
+ boost::shared_ptr<InternalSend> aux;
+ if ((aux = boost::dynamic_pointer_cast<InternalSend> (_processor))) {
+ if (aux->allow_feedback ()) {
+ _button.set_name ("processor auxfeedback");
+ return;
+ }
+ }
+
switch (_position) {
case PreFader:
if (_plugin_display) { _plugin_display->set_name ("processor prefader"); }
if (pi) {
std::string postfix = "";
uint32_t replicated;
+
+ if (pi->plugin()->has_inline_display()) {
+ postfix += string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
+ }
+
if ((replicated = pi->get_count()) > 1) {
- postfix = string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
+ postfix += string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
}
+
if (pi->plugin()->has_editor()) {
- ARDOUR_UI_UTILS::set_tooltip (_button,
- string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::primary_modifier_name (), postfix));
+ set_tooltip (_button,
+ string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::secondary_modifier_name (), postfix));
} else {
- ARDOUR_UI_UTILS::set_tooltip (_button,
+ set_tooltip (_button,
string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
}
return;
if ((send = boost::dynamic_pointer_cast<Send> (_processor)) != 0 &&
!boost::dynamic_pointer_cast<InternalSend>(_processor)) {
if (send->remove_on_disconnect ()) {
- ARDOUR_UI_UTILS::set_tooltip (_button, string_compose ("<b>> %1</b>\nThis (sidechain) send will be removed when disconnected.", _processor->name()));
+ set_tooltip (_button, string_compose ("<b>> %1</b>\nThis (sidechain) send will be removed when disconnected.", _processor->name()));
} else {
- ARDOUR_UI_UTILS::set_tooltip (_button, string_compose ("<b>> %1</b>", _processor->name()));
+ set_tooltip (_button, string_compose ("<b>> %1</b>", _processor->name()));
}
return;
}
}
- ARDOUR_UI_UTILS::set_tooltip (_button, string_compose ("<b>%1</b>", name (Wide)));
+ set_tooltip (_button, string_compose ("<b>%1</b>", name (Wide)));
}
string
if (_plugin_display) {
XMLNode* c = new XMLNode (X_("Object"));
- c->add_property (X_("id"), X_("InlineDisplay"));
- c->add_property (X_("visible"), _plugin_display->is_visible ());
+ c->set_property (X_("id"), X_("InlineDisplay"));
+ c->set_property (X_("visible"), _plugin_display->is_visible ());
node->add_child_nocopy (*c);
}
}
if (_plugin_display) {
XMLNode* n = GUIObjectState::get_node (node, X_("InlineDisplay"));
- XMLProperty const * p = n ? n->property (X_("visible")) : NULL;
- if (p) {
- if (string_is_affirmative (p->value ())) {
- _plugin_display->show();
+ if (!n) return;
+
+ bool visible;
+ if (n->get_property (X_("visible"), visible)) {
+ if (visible) {
+ _plugin_display->show ();
} else {
- _plugin_display->hide();
+ _plugin_display->hide ();
}
}
}
}
for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
- items.push_back (CheckMenuElem ((*i)->name ()));
+ items.push_back (CheckMenuElemNoMnemonic ((*i)->name ()));
Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
c->set_active ((*i)->visible ());
c->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ProcessorEntry::toggle_control_visibility), *i));
Menu* menu = manage (new Menu);
MenuList& items = menu->items ();
- boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
- if (send) {
+ if (!ARDOUR::Profile->get_mixbus()) {
+ boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
+ if (send) {
+ items.push_back (CheckMenuElem (_("Link panner controls")));
+ Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
+ c->set_active (send->panner_shell()->is_linked_to_route());
+ c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
+ }
+ }
- items.push_back (CheckMenuElem (_("Link panner controls")));
+ boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
+ if (aux) {
+ items.push_back (CheckMenuElem (_("Allow Feedback Loop")));
Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
- c->set_active (send->panner_shell()->is_linked_to_route());
- c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
-
+ c->set_active (aux->allow_feedback());
+ c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_allow_feedback));
}
return menu;
}
}
}
+void
+ProcessorEntry::toggle_allow_feedback ()
+{
+ boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
+ if (aux) {
+ aux->set_allow_feedback (!aux->allow_feedback ());
+ }
+}
+
ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string const & n)
: _control (c)
, _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
_button.signal_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked));
_button.signal_led_clicked.connect (sigc::mem_fun (*this, &Control::button_clicked_event));
- // dup. currently timers are used :(
- //c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
+ c->Changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_changed, this), gui_context ());
+ if (c->alist ()) {
+ c->alist()->automation_state_changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_automation_state_changed, this), gui_context());
+ control_automation_state_changed ();
+ }
} else {
_slider.show ();
const ARDOUR::ParameterDescriptor& desc = c->desc();
- double const lo = c->internal_to_interface(desc.lower);
- double const up = c->internal_to_interface(desc.upper);
- double const normal = c->internal_to_interface(desc.normal);
- double smallstep = desc.smallstep;
- double largestep = desc.largestep;
-
- if (smallstep == 0.0) {
- smallstep = up / 1000.;
- } else {
- smallstep = c->internal_to_interface(desc.lower + smallstep);
- }
-
- if (largestep == 0.0) {
- largestep = up / 40.;
- } else {
- largestep = c->internal_to_interface(desc.lower + largestep);
- }
+ double const lo = c->internal_to_interface (desc.lower);
+ double const up = c->internal_to_interface (desc.upper);
+ double const normal = c->internal_to_interface (desc.normal);
+ double const smallstep = c->internal_to_interface (desc.lower + desc.smallstep);
+ double const largestep = c->internal_to_interface (desc.lower + desc.largestep);
_adjustment.set_lower (lo);
_adjustment.set_upper (up);
_adjustment.set_page_increment (largestep);
_slider.set_default_value (normal);
+ _slider.StartGesture.connect(sigc::mem_fun(*this, &Control::start_touch));
+ _slider.StopGesture.connect(sigc::mem_fun(*this, &Control::end_touch));
+
_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Control::slider_adjusted));
- // dup. currently timers are used :(
- //c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
+ c->Changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_changed, this), gui_context ());
+ if (c->alist ()) {
+ c->alist()->automation_state_changed.connect (_connections, invalidator (*this), boost::bind (&Control::control_automation_state_changed, this), gui_context());
+ control_automation_state_changed ();
+ }
}
- // yuck, do we really need to do this?
- // according to c404374 this is only needed for send automation
- timer_connection = Timers::rapid_connect (sigc::mem_fun (*this, &Control::control_changed));
-
control_changed ();
set_tooltip ();
ProcessorEntry::Control::~Control ()
{
- timer_connection.disconnect ();
}
void
if (!c) {
return;
}
- char tmp[256];
- if (c->toggled ()) {
- snprintf (tmp, sizeof(tmp), "%s: %s", _name.c_str(), c->get_value() > 0.5 ? _("on") : _("off"));
- } else {
- snprintf (tmp, sizeof(tmp), "%s: %.2f", _name.c_str(), c->internal_to_user (c->get_value ()));
- }
-
- string sm = Gtkmm2ext::markup_escape_text (tmp);
+ std::string tt = _name + ": " + ARDOUR::value_as_string (c->desc(), c->get_value ());
+ string sm = Gtkmm2ext::markup_escape_text (tt);
_slider_persistant_tooltip.set_tip (sm);
- ARDOUR_UI_UTILS::set_tooltip (_button, sm);
+ ArdourWidgets::set_tooltip (_button, sm);
}
void
set_tooltip ();
}
+void
+ProcessorEntry::Control::start_touch ()
+{
+ boost::shared_ptr<AutomationControl> c = _control.lock ();
+ if (!c) {
+ return;
+ }
+ c->start_touch (c->session().transport_frame());
+}
+
+void
+ProcessorEntry::Control::end_touch ()
+{
+ boost::shared_ptr<AutomationControl> c = _control.lock ();
+ if (!c) {
+ return;
+ }
+ c->stop_touch (c->session().transport_frame());
+}
+
void
ProcessorEntry::Control::button_clicked ()
{
button_clicked ();
}
+void
+ProcessorEntry::Control::control_automation_state_changed ()
+{
+ boost::shared_ptr<AutomationControl> c = _control.lock ();
+ if (!c) {
+ return;
+ }
+ bool x = c->alist()->automation_state() & Play;
+ if (c->toggled ()) {
+ _button.set_sensitive (!x);
+ } else {
+ _slider.set_sensitive (!x);
+ }
+}
+
void
ProcessorEntry::Control::control_changed ()
{
_ignore_ui_adjustment = true;
if (c->toggled ()) {
-
_button.set_active (c->get_value() > 0.5);
-
} else {
- // as long as rapid timers are used, only update the tooltip
- // if the value has changed.
+ // Note: the _slider watches the controllable by itself
const double nval = c->internal_to_interface (c->get_value ());
if (_adjustment.get_value() != nval) {
_adjustment.set_value (nval);
ProcessorEntry::Control::add_state (XMLNode* node) const
{
XMLNode* c = new XMLNode (X_("Object"));
- c->add_property (X_("id"), state_id ());
- c->add_property (X_("visible"), _visible);
+ c->set_property (X_("id"), state_id ());
+ c->set_property (X_("visible"), _visible);
node->add_child_nocopy (*c);
}
{
XMLNode* n = GUIObjectState::get_node (node, state_id ());
if (n) {
- XMLProperty const * p = n->property (X_("visible"));
- set_visible (p && string_is_affirmative (p->value ()));
+ bool visible;
+ if (n->get_property (X_("visible"), visible)) {
+ set_visible (visible);
+ }
} else {
set_visible (false);
}
}
}
-ProcessorEntry::PluginDisplay::PluginDisplay (ProcessorEntry& e, boost::shared_ptr<ARDOUR::Plugin> p, uint32_t max_height)
- : _entry (e)
- , _plug (p)
- , _surf (0)
- , _max_height (max_height)
- , _cur_height (1)
+ProcessorEntry::PluginInlineDisplay::PluginInlineDisplay (ProcessorEntry& e, boost::shared_ptr<ARDOUR::Plugin> p, uint32_t max_height)
+ : PluginDisplay (p, max_height)
+ , _entry (e)
, _scroll (false)
{
- set_name ("processor prefader");
- add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
- _plug->DropReferences.connect (_death_connection, invalidator (*this), boost::bind (&PluginDisplay::plugin_going_away, this), gui_context());
- _plug->QueueDraw.connect (_qdraw_connection, invalidator (*this),
- boost::bind (&Gtk::Widget::queue_draw, this), gui_context ());
+ std::string postfix = string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
- std::string postfix = "";
if (_plug->has_editor()) {
- ARDOUR_UI_UTILS::set_tooltip (*this,
+ set_tooltip (*this,
string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), e.name (Wide), Keyboard::primary_modifier_name (), postfix));
} else {
- ARDOUR_UI_UTILS::set_tooltip (*this,
+ set_tooltip (*this,
string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), e.name (Wide), postfix));
}
}
-ProcessorEntry::PluginDisplay::~PluginDisplay ()
-{
- if (_surf) {
- cairo_surface_destroy (_surf);
- }
-}
bool
-ProcessorEntry::PluginDisplay::on_button_press_event (GdkEventButton *ev)
+ProcessorEntry::PluginInlineDisplay::on_button_press_event (GdkEventButton *ev)
{
assert (_entry.processor ());
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_entry.processor());
+ // duplicated code :(
// consider some tweaks to pass this up to the DnDVBox somehow:
// select processor, then call (private)
//_entry._parent->processor_button_press_event (ev, &_entry);
- if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
+ if (pi && pi->plugin() && pi->plugin()->has_inline_display()
+ && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
+ && ev->button == 1
+ && ev->type == GDK_2BUTTON_PRESS) {
+ _entry.toggle_inline_display_visibility ();
+ return true;
+ }
+ else if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
_entry._parent->generic_edit_processor (_entry.processor ());
} else {
return false;
}
-bool
-ProcessorEntry::PluginDisplay::on_button_release_event (GdkEventButton *ev)
-{
- return false;
-}
-
void
-ProcessorEntry::PluginDisplay::on_size_request (Requisition* req)
+ProcessorEntry::PluginInlineDisplay::on_size_request (Requisition* req)
{
req->width = 56;
req->height = _cur_height;
void
-ProcessorEntry::PluginDisplay::update_height_alloc (uint32_t inline_height)
+ProcessorEntry::PluginInlineDisplay::update_height_alloc (uint32_t inline_height)
{
/* work-around scroll-bar + aspect ratio
* show inline-view -> height changes -> scrollbar gets added
_scroll = sc;
}
-uint32_t
-ProcessorEntry::PluginDisplay::render_inline (cairo_t* cr, uint32_t width)
-{
- Plugin::Display_Image_Surface* dis = _plug->render_inline_display (width, _max_height);
- if (!dis) {
- return 0;
- }
-
- /* allocate a local image-surface,
- * We cannot re-use the data via cairo_image_surface_create_for_data(),
- * since pixman keeps a reference to it.
- * we'd need to hand over the data and ha cairo_surface_destroy to free it.
- * it might be possible to work around via cairo_surface_set_user_data().
- */
- if (!_surf
- || dis->width != cairo_image_surface_get_width (_surf)
- || dis->height != cairo_image_surface_get_height (_surf)
- ) {
- if (_surf) {
- cairo_surface_destroy (_surf);
- }
- _surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, dis->width, dis->height);
- }
-
- if (cairo_image_surface_get_stride (_surf) == dis->stride) {
- memcpy (cairo_image_surface_get_data (_surf), dis->data, dis->stride * dis->height);
- } else {
- unsigned char *src = dis->data;
- unsigned char *dst = cairo_image_surface_get_data (_surf);
- const int dst_stride = cairo_image_surface_get_stride (_surf);
- for (int y = 0; y < dis->height; ++y) {
- memcpy (dst, src, dis->width * 4 /*ARGB32*/);
- src += dis->stride;
- dst += dst_stride;
- }
- }
-
- cairo_surface_flush(_surf);
- cairo_surface_mark_dirty(_surf);
- const double xc = floor ((width - dis->width) * .5);
- cairo_set_source_surface(cr, _surf, xc, 0);
- cairo_paint (cr);
-
- return dis->height;
-}
-
-bool
-ProcessorEntry::PluginDisplay::on_expose_event (GdkEventExpose* ev)
+void
+ProcessorEntry::PluginInlineDisplay::display_frame (cairo_t* cr, double w, double h)
{
- Gtk::Allocation a = get_allocation();
- double const width = a.get_width();
- double const height = a.get_height();
-
- cairo_t* cr = gdk_cairo_create (get_window()->gobj());
- cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- cairo_clip (cr);
-
- Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
- cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_fill (cr);
-
- cairo_save (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- Gtkmm2ext::rounded_rectangle (cr, .5, -1.5, width - 1, height + 1, 7);
- cairo_clip (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-
- uint32_t ht = render_inline (cr, width);
- cairo_restore (cr);
-
- if (ht == 0) {
- hide ();
- if (_cur_height != 1) {
- _cur_height = 1;
- queue_resize ();
- }
- cairo_destroy (cr);
- return true;
- } else {
- update_height_alloc (ht);
- }
-
- bool failed = false;
- std::string name = get_name();
- ArdourCanvas::Color fill_color = UIConfiguration::instance().color (string_compose ("%1: fill active", name), &failed);
-
- Gtkmm2ext::rounded_rectangle (cr, .5, -1.5, width - 1, height + 1, 7);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_set_line_width(cr, 1.0);
- ArdourCanvas::set_source_rgb_a (cr, fill_color, 1.0);
- cairo_stroke (cr);
-
- cairo_destroy(cr);
- return true;
+ Gtkmm2ext::rounded_rectangle (cr, .5, -1.5, w - 1, h + 1, 7);
}
ProcessorEntry::LuaPluginDisplay::LuaPluginDisplay (ProcessorEntry& e, boost::shared_ptr<ARDOUR::LuaProc> p, uint32_t max_height)
- : PluginDisplay (e, p, max_height)
+ : PluginInlineDisplay (e, p, max_height)
, _luaproc (p)
, _lua_render_inline (0)
{
}
ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
- RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
+ ProcessorSelection& psel, MixerStrip* parent, bool owner_is_mixer)
: _parent_strip (parent)
, _owner_is_mixer (owner_is_mixer)
, ab_direction (true)
, _get_plugin_selector (get_plugin_selector)
, _placement (-1)
- , _visible_prefader_processors (0)
- , _rr_selection(rsel)
+ , _p_selection(psel)
, processor_display (drop_targets())
, _redisplay_pending (false)
{
);
}
- ARDOUR_UI_UTILS::set_tooltip (processor_display, _("Right-click to add/remove/edit\nplugins,inserts,sends and more"));
+ set_tooltip (processor_display, _("Right-click to add/remove/edit\nplugins,inserts,sends and more"));
}
ProcessorBox::~ProcessorBox ()
boost::shared_ptr<Processor> p = find_drop_position (position);
- list<ProcessorEntry*> children = source->selection ();
+ list<ProcessorEntry*> children = source->selection (true);
list<boost::shared_ptr<Processor> > procs;
for (list<ProcessorEntry*>::const_iterator i = children.begin(); i != children.end(); ++i) {
if ((*i)->processor ()) {
for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
if (!_route->internal_send_for (*r) && *r != _route) {
- items.push_back (MenuElem ((*r)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
+ items.push_back (MenuElemNoMnemonic ((*r)->name(), sigc::bind (sigc::ptr_fun (ProcessorBox::rb_choose_aux), boost::weak_ptr<Route>(*r))));
}
}
}
- if (!ARDOUR::Profile->get_mixbus()) {
- Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
- if (send_menu_item) {
- if (single_selection && !_route->is_monitor()) {
- Menu* m = single_selection->build_send_options_menu ();
- if (m && !m->items().empty()) {
- send_menu_item->set_submenu (*m);
- send_menu_item->set_sensitive (true);
- } else {
- gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
- send_menu_item->set_sensitive (false);
- }
+ Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
+ if (send_menu_item) {
+ if (single_selection && !_route->is_monitor()) {
+ Menu* m = single_selection->build_send_options_menu ();
+ if (m && !m->items().empty()) {
+ send_menu_item->set_submenu (*m);
+ send_menu_item->set_sensitive (true);
} else {
+ gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
send_menu_item->set_sensitive (false);
}
+ } else {
+ send_menu_item->set_sensitive (false);
}
}
const bool sensitive = !processor_display.selection().empty() && ! stub_processor_selected ();
- paste_action->set_sensitive (!_rr_selection.processors.empty());
+ paste_action->set_sensitive (!_p_selection.processors.empty());
cut_action->set_sensitive (sensitive && can_cut ());
copy_action->set_sensitive (sensitive);
delete_action->set_sensitive (sensitive || stub_processor_selected ());
int x, y;
processor_display.get_pointer (x, y);
_placement = processor_display.add_placeholder (y);
-
- if (_visible_prefader_processors == 0 && _placement > 0) {
- --_placement;
- }
}
bool
case ProcessorsToggleActive:
for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
+ if (!(*i)->display_to_user ()) {
+ assert (0); // these should not be selectable to begin with.
+ continue;
+ }
+ if (!boost::dynamic_pointer_cast<PluginInsert> (*i)) {
+ continue;
+ }
+#ifdef MIXBUS
+ if (boost::dynamic_pointer_cast<PluginInsert> (*i)->is_channelstrip()) {
+ continue;
+ }
+#endif
(*i)->enable (!(*i)->enabled ());
}
break;
int ret = false;
bool selected = processor_display.selected (child);
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
+ if (pi && pi->plugin() && pi->plugin()->has_inline_display()
+ && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
+ && ev->button == 1
+ && ev->type == GDK_2BUTTON_PRESS) {
+ child->toggle_inline_display_visibility ();
+ return true;
+ }
+
if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
if (_session->engine().connected()) {
} else if (_session->engine().connected () && processor_can_be_edited (processor)) {
if ((*p)->has_editor ()) {
edit_processor (processor);
- } else {
+ } else if (boost::dynamic_pointer_cast<PluginInsert>(processor)->plugin()->parameter_count() > 0) {
generic_edit_processor (processor);
}
}
}
+ /* add next processor below the currently added.
+ * Note: placement < 0: add the bottom */
+ if (_placement >= 0) {
+ ++_placement;
+ }
}
return false;
ProcessorBox::redisplay_processors ()
{
ENSURE_GUI_THREAD (*this, &ProcessorBox::redisplay_processors);
- bool fader_seen;
if (no_processor_redisplay) {
return;
processor_display.clear ();
- _visible_prefader_processors = 0;
- fader_seen = false;
-
- _route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &ProcessorBox::help_count_visible_prefader_processors),
- &_visible_prefader_processors, &fader_seen));
-
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list));
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_pin_mgr));
wp->set_state (*ui_xml, 0);
}
- void* existing_ui = p->get_ui ();
-
- if (existing_ui) {
- wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
- }
-
p->set_window_proxy (wp);
WM::Manager::instance().register_window (wp);
}
p->set_pingmgr_proxy (wp);
WM::Manager::instance().register_window (wp);
}
-void
-ProcessorBox::help_count_visible_prefader_processors (boost::weak_ptr<Processor> p, uint32_t* cnt, bool* amp_seen)
-{
- boost::shared_ptr<Processor> processor (p.lock ());
-
- if (processor && ( processor->display_to_user()
-#ifndef NDEBUG
- || show_all_processors
-#endif
- )
- ) {
-
- if (boost::dynamic_pointer_cast<Amp>(processor) &&
- boost::dynamic_pointer_cast<Amp>(processor)->gain_control()->parameter().type() == GainAutomation) {
- *amp_seen = true;
- } else {
- if (!*amp_seen) {
- (*cnt)++;
- }
- }
- }
-}
void
ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
(*i)->input_icon.set_ports (p->input_streams());
(*i)->output_icon.set_ports (p->output_streams());
ChanMapping inmap (p->input_streams ());
- ChanMapping outmap (p->input_streams ());
+ ChanMapping outmap (p->output_streams ());
ChanMapping thrumap;
(*i)->routing_icon.set (
p->input_streams(),
return;
}
- _rr_selection.set (node);
+ _p_selection.set (node);
no_processor_redisplay = false;
redisplay_processors ();
}
}
- _rr_selection.set (node);
+ _p_selection.set (node);
}
void
void
ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
{
- ArdourPrompter name_prompter (true);
+ Prompter name_prompter (true);
string result;
name_prompter.set_title (_("Rename Processor"));
name_prompter.set_prompt (_("New name:"));
name_prompter.get_result (result);
if (result.length()) {
- int tries = 0;
- string test = result;
-
- while (tries < 100) {
- if (_session->io_name_is_legal (test)) {
- result = test;
- break;
- }
- tries++;
-
- test = string_compose ("%1-%2", result, tries);
- }
-
- if (tries < 100) {
- processor->set_name (result);
- } else {
- /* unlikely! */
- ARDOUR_UI::instance()->popup_error
- (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
- }
+ int tries = 0;
+ string test = result;
+
+ while (tries < 100) {
+ if (_session->io_name_is_legal (test)) {
+ result = test;
+ break;
+ }
+ tries++;
+
+ test = string_compose ("%1-%2", result, tries);
+ }
+
+ if (tries < 100) {
+ processor->set_name (result);
+ } else {
+ /* unlikely! */
+ ARDOUR_UI::instance()->popup_error
+ (string_compose (_("At least 100 IO objects exist with a name like %1 - name not changed"), result));
+ }
}
break;
}
void
ProcessorBox::paste_processors ()
{
- if (_rr_selection.processors.empty()) {
+ if (_p_selection.processors.empty()) {
return;
}
- paste_processor_state (_rr_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
+ paste_processor_state (_p_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
}
void
ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
{
- if (_rr_selection.processors.empty()) {
+ if (_p_selection.processors.empty()) {
return;
}
- paste_processor_state (_rr_selection.processors.get_node().children(), before);
+ paste_processor_state (_p_selection.processors.get_node().children(), before);
}
void
IOProcessor::prepare_for_reset (n, s->name());
- if (s->set_state (n, Stateful::loading_state_version)) {
- delete s;
- return;
- }
+ if (s->set_state (n, Stateful::loading_state_version)) {
+ delete s;
+ return;
+ }
p.reset (s);
IOProcessor::prepare_for_reset (n, s->name());
- if (s->set_state (n, Stateful::loading_state_version)) {
- delete s;
- return;
- }
+ if (s->set_state (n, Stateful::loading_state_version)) {
+ delete s;
+ return;
+ }
p.reset (s);
} else if (type->value() == "return") {
XMLNode n (**niter);
- Return* r = new Return (*_session);
+ Return* r = new Return (*_session);
IOProcessor::prepare_for_reset (n, r->name());
- if (r->set_state (n, Stateful::loading_state_version)) {
- delete r;
- return;
- }
+ if (r->set_state (n, Stateful::loading_state_version)) {
+ delete r;
+ return;
+ }
p.reset (r);
void
ProcessorBox::get_selected_processors (ProcSelection& processors) const
{
- const list<ProcessorEntry*> selection = processor_display.selection ();
+ const list<ProcessorEntry*> selection = processor_display.selection (true);
for (list<ProcessorEntry*>::const_iterator i = selection.begin(); i != selection.end(); ++i) {
processors.push_back ((*i)->processor ());
}
choices.push_back (_("Cancel"));
choices.push_back (_("Yes, remove them all"));
- Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
+ ArdourWidgets::Choice prompter (_("Remove processors"), prompt, choices);
if (prompter.run () == 1) {
_route->clear_processors (PreFader);
choices.push_back (_("Cancel"));
choices.push_back (_("Yes, remove them all"));
- Gtkmm2ext::Choice prompter (_("Remove processors"), prompt, choices);
+ ArdourWidgets::Choice prompter (_("Remove processors"), prompt, choices);
if (prompter.run () == 1) {
_route->clear_processors (p);
ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
{
assert (p->window_proxy());
- p->set_ui (w);
p->window_proxy()->use_window (*w);
}
: WM::ProxyBase (name, string())
, _processor_box (box)
, _processor (processor)
- , is_custom (false)
- , want_custom (false)
+ , is_custom (true)
+ , want_custom (true)
{
boost::shared_ptr<Processor> p = _processor.lock ();
if (!p) {
return;
}
p->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&ProcessorWindowProxy::processor_going_away, this), gui_context());
+
+ p->ToggleUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::show_the_right_window, this, false), gui_context());
+ p->ShowUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::show_the_right_window, this, true), gui_context());
+ p->HideUI.connect (gui_connections, invalidator (*this), boost::bind (&ProcessorWindowProxy::hide, this), gui_context());
}
ProcessorWindowProxy::~ProcessorWindowProxy()
void
ProcessorWindowProxy::processor_going_away ()
{
+ gui_connections.drop_connections ();
delete _window;
_window = 0;
WM::Manager::instance().remove (this);
send DropReferences is about to be deleted, but lets do it anyway.
*/
going_away_connection.disconnect();
+ delete this;
}
ARDOUR::SessionHandlePtr*
{
XMLNode *node;
node = &ProxyBase::get_state();
- node->add_property (X_("custom-ui"), is_custom? X_("yes") : X_("no"));
+ node->set_property (X_("custom-ui"), is_custom);
return *node;
}
XMLNodeList children = node.children ();
XMLNodeList::const_iterator i = children.begin ();
while (i != children.end()) {
- XMLProperty const * prop = (*i)->property (X_("name"));
- if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
+ std::string name;
+ if ((*i)->name() == X_("Window") && (*i)->get_property (X_("name"), name) && name == _name) {
break;
}
++i;
}
if (i != children.end()) {
- XMLProperty const * prop;
- if ((prop = (*i)->property (X_("custom-ui"))) != 0) {
- want_custom = PBD::string_is_affirmative (prop->value ());
- }
+ (*i)->get_property (X_("custom-ui"), want_custom);
}
return ProxyBase::set_state (node, 0);
}
if (_window && (is_custom != want_custom)) {
/* drop existing window - wrong type */
+ set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
if (_window) {
setup ();
+ _window->show_all ();
}
- _window->show_all ();
}
return _window;
}
void
-ProcessorWindowProxy::show_the_right_window ()
+ProcessorWindowProxy::show_the_right_window (bool show_not_toggle)
{
if (_window && (is_custom != want_custom)) {
/* drop existing window - wrong type */
+ set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
drop_window ();
}
+ if (_window && fully_visible () && show_not_toggle) {
+ return;
+ }
toggle ();
}
_window = 0;
WM::Manager::instance().remove (this);
going_away_connection.disconnect();
+ delete this;
}
void