+/** @param p Processor.
+ * @return the UI window for \a p.
+ */
+Window *
+ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
+{
+ list<ProcessorWindowProxy*>::const_iterator i = _processor_window_info.begin ();
+ while (i != _processor_window_info.end()) {
+ boost::shared_ptr<Processor> t = (*i)->processor().lock ();
+ if (t && t == p) {
+ return (*i)->get ();
+ }
+
+ ++i;
+ }
+
+ return 0;
+}
+
+/** Make a note of the UI window that a processor is using.
+ * @param p Processor.
+ * @param w UI window.
+ */
+void
+ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
+{
+ list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin ();
+
+ p->set_ui (w);
+
+ while (i != _processor_window_info.end()) {
+ boost::shared_ptr<Processor> t = (*i)->processor().lock ();
+ if (t && t == p) {
+ (*i)->use_window (*w);
+ return;
+ }
+
+ ++i;
+ }
+
+ /* we shouldn't get here, because the ProcessorUIList should always contain
+ an entry for each processor.
+ */
+ assert (false);
+}
+
+void
+ProcessorBox::mixer_strip_delivery_changed (boost::weak_ptr<Delivery> w)
+{
+ boost::shared_ptr<Delivery> d = w.lock ();
+ if (!d) {
+ return;
+ }
+
+ list<ProcessorEntry*> children = processor_display.children ();
+ list<ProcessorEntry*>::const_iterator i = children.begin();
+ while (i != children.end() && (*i)->processor() != d) {
+ ++i;
+ }
+
+ if (i == children.end()) {
+ processor_display.set_active (0);
+ } else {
+ processor_display.set_active (*i);
+ }
+}
+
+/** Called to repair the damage of Editor::show_window doing a show_all() */
+void
+ProcessorBox::hide_things ()
+{
+ list<ProcessorEntry*> c = processor_display.children ();
+ for (list<ProcessorEntry*>::iterator i = c.begin(); i != c.end(); ++i) {
+ (*i)->hide_things ();
+ }
+}
+
+void
+ProcessorBox::processor_menu_unmapped ()
+{
+ processor_display.remove_placeholder ();
+}
+
+XMLNode *
+ProcessorBox::entry_gui_object_state (ProcessorEntry* entry)
+{
+ if (!_parent_strip) {
+ return 0;
+ }
+
+ GUIObjectState& st = _parent_strip->gui_object_state ();
+
+ XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
+ assert (strip);
+ return st.get_or_add_node (strip, entry->state_id());
+}
+
+void
+ProcessorBox::update_gui_object_state (ProcessorEntry* entry)
+{
+ XMLNode* proc = entry_gui_object_state (entry);
+ if (!proc) {
+ return;
+ }
+
+ /* XXX: this is a bit inefficient; we just remove all child nodes and re-add them */
+ proc->remove_nodes_and_delete (X_("Object"));
+ entry->add_control_state (proc);
+}
+
+ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor)
+ : WM::ProxyBase (name, string())
+ , marked (false)
+ , _processor_box (box)
+ , _processor (processor)
+ , is_custom (false)
+ , want_custom (false)
+{
+
+}
+
+ARDOUR::SessionHandlePtr*
+ProcessorWindowProxy::session_handle()
+{
+ /* we don't care */
+ return 0;
+}
+
+XMLNode&
+ProcessorWindowProxy::get_state () const
+{
+ XMLNode *node;
+ node = &ProxyBase::get_state();
+ node->add_property (X_("custom-ui"), is_custom? X_("yes") : X_("no"));
+ return *node;
+}
+
+void
+ProcessorWindowProxy::set_state (const XMLNode& node)
+{
+ XMLNodeList children = node.children ();
+ XMLNodeList::const_iterator i = children.begin ();
+ while (i != children.end()) {
+ XMLProperty* prop = (*i)->property (X_("name"));
+ if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
+ break;
+ }
+ ++i;
+ }
+
+ if (i != children.end()) {
+ XMLProperty* prop;
+ if ((prop = (*i)->property (X_("custom-ui"))) != 0) {
+ want_custom = PBD::string_is_affirmative (prop->value ());
+ }
+ }
+
+ ProxyBase::set_state(node);
+}
+
+Gtk::Window*
+ProcessorWindowProxy::get (bool create)
+{
+ boost::shared_ptr<Processor> p = _processor.lock ();
+
+ if (!p) {
+ return 0;
+ }
+ if (_window && (is_custom != want_custom)) {
+ /* drop existing window - wrong type */
+ drop_window ();
+ }
+
+ if (!_window) {
+ if (!create) {
+ return 0;
+ }
+
+ is_custom = want_custom;
+ _window = _processor_box->get_editor_window (p, is_custom);
+
+ if (_window) {
+ setup ();
+ }
+ }
+
+ return _window;
+}
+
+void
+ProcessorWindowProxy::toggle ()
+{
+ if (_window && (is_custom != want_custom)) {
+ /* drop existing window - wrong type */
+ drop_window ();
+ }
+ is_custom = want_custom;
+
+ WM::ProxyBase::toggle ();
+}