Enable some code to make plugin ui bounds more sensible.
[ardour.git] / gtk2_ardour / port_matrix.cc
index f47a4ff191a8b1c64467d3c9fd6e157da79e9250..cff4a3328ee328c6f9802c74241e0ce14757b324 100644 (file)
 #include "ardour/midi_track.h"
 #include "ardour/data_type.h"
 #include "io_selector.h"
+#include "keyboard.h"
 #include "utils.h"
 #include "gui_thread.h"
 #include "i18n.h"
 
+using namespace Gtk;
+
 /** Add a port to a group.
  *  @param p Port name, with or without prefix.
  */
@@ -61,8 +64,10 @@ PortGroup::add (std::string const & p)
  */
 
 PortGroupUI::PortGroupUI (PortMatrix& m, PortGroup& g)
-       : _port_matrix (m), _port_group (g), _ignore_check_button_toggle (false),
-         _visibility_checkbutton (g.name)
+       : _port_matrix (m)
+       , _port_group (g)
+       , _ignore_check_button_toggle (false)
+       , _visibility_checkbutton (g.name)
 {
        int const ports = _port_group.ports.size();
        int const rows = _port_matrix.n_rows ();
@@ -79,19 +84,26 @@ PortGroupUI::PortGroupUI (PortMatrix& m, PortGroup& g)
                _port_checkbuttons[i].resize (ports);
        }
 
+
        for (int i = 0; i < rows; ++i) {
                for (uint32_t j = 0; j < _port_group.ports.size(); ++j) {
-                       Gtk::CheckButton* b = new Gtk::CheckButton;
+                       CheckButton* b = new CheckButton;
                        
                        b->signal_toggled().connect (
-                               sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_toggled), b, i, j)
-                               );
+                               sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_toggled), b, i, j));
                        
+                       b->signal_button_release_event().connect (
+                               sigc::bind (sigc::mem_fun (*this, &PortGroupUI::port_checkbutton_release), b, i, j), false);
+
                        _port_checkbuttons[i][j] = b;
+
+                       cerr << this << " bind to " << &_port_checkbuttons << " via " << b 
+                            << endl;
+
                        _table.attach (*b, j, j + 1, i, i + 1);
                }
        }
-
+       
        _table_box.add (_table);
 
        _ignore_check_button_toggle = true;
@@ -118,7 +130,6 @@ void
 PortGroupUI::visibility_checkbutton_toggled ()
 {
        _port_group.visible = _visibility_checkbutton.get_active ();
-       setup_visibility ();
 }
 
 /** @return Width and height of a single checkbutton in a port group table */
@@ -143,14 +154,14 @@ PortGroupUI::unit_size () const
 }
 
 /** @return Table widget containing the port checkbuttons */
-Gtk::Widget&
+Widget&
 PortGroupUI::get_table ()
 {
        return _table_box;
 }
 
 /** @return Checkbutton used to toggle visibility */
-Gtk::Widget&
+Widget&
 PortGroupUI::get_visibility_checkbutton ()
 {
        return _visibility_checkbutton;
@@ -159,34 +170,93 @@ PortGroupUI::get_visibility_checkbutton ()
 
 /** Handle a toggle of a port check button */
 void
-PortGroupUI::port_checkbutton_toggled (Gtk::CheckButton* b, int r, int c)
+PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c)
 {
        if (_ignore_check_button_toggle == false) {
-               _port_matrix.set_state (r, _port_group.prefix + _port_group.ports[c], b->get_active());
+               _port_matrix.set_state (r, _port_group.prefix + _port_group.ports[c], b->get_active(), 0);
        }
 }
 
+bool
+PortGroupUI::port_checkbutton_release (GdkEventButton* ev, CheckButton* b, int r, int c)
+{
+       cerr << this << " RELEASE on " << b << " state = " << ev->state << endl;
+
+       if (ev->state == 0) {
+               /* let usual toggle handler take care of it */
+               return false;
+       }
+
+       /* The fun starts here 
+        */
+
+       const size_t ports = _port_group.ports.size();
+       const size_t rows = _port_matrix.n_rows ();
+
+       if (rows == 0 || ports == 0) {
+               return true;
+       }
+
+       /* For each port in the group, change the state of
+          the connection for the corresponding "connector" port.
+       */
+       
+       for (size_t j = c; j < ports; ++j) {
+
+               /* we've got a port to connect, now lets find the thing to 
+                  connect it too ... (search "down" the rows)
+               */
+
+               cerr << "we're going to connect port " << j << " of " << ports << endl;
+
+               for (size_t i = r; i < rows; ++i) {
+
+                       cerr << this << " going to connect to row " << i << " of " << rows << endl;
+                       cerr << "access [" << i << "][" << j << "]\n";
+                       cerr << " @ " << &_port_checkbuttons << endl;
+
+                       _port_checkbuttons[i][j]->set_active (!_port_checkbuttons[i][j]->get_active());
+
+                       /* next time, get at least as far as this port before looking
+                          for more.
+                       */
+
+                       r = i + 1;
+
+                       /* changed connection state, stop looking for more */
+
+                       break;
+               }
+       }
+
+       return true;
+}
+
 /** Set up visibility of the port group according to PortGroup::visible */
 void
 PortGroupUI::setup_visibility ()
 {
-       if (_port_group.visible) {
+       if (!_port_group.ports.empty() && _port_group.visible) {
                _table_box.show ();
        } else {
                _table_box.hide ();
        }
 
        if (_visibility_checkbutton.get_active () != _port_group.visible) {
+
                _visibility_checkbutton.set_active (_port_group.visible);
        }
 }
 
-
 RotatedLabelSet::RotatedLabelSet (PortGroupList& g)
-       : Glib::ObjectBase ("RotatedLabelSet"), Gtk::Widget (), _port_group_list (g), _base_width (128)
+       : Glib::ObjectBase ("RotatedLabelSet"), Widget (), _port_group_list (g), _base_width (128)
 {
-       set_flags (Gtk::NO_WINDOW);
-       set_angle (30);
+       set_flags (NO_WINDOW);
+       if (getenv ("AD_ANGLE") != 0) {
+               set_angle (atoi (getenv ("AD_ANGLE")));
+       } else {
+               set_angle (45);
+       }
 }
 
 RotatedLabelSet::~RotatedLabelSet ()
@@ -209,9 +279,9 @@ RotatedLabelSet::set_angle (int degrees)
 }
 
 void
-RotatedLabelSet::on_size_request (Gtk::Requisition* requisition)
+RotatedLabelSet::on_size_request (Requisition* requisition)
 {
-       *requisition = Gtk::Requisition ();
+       *requisition = Requisition ();
 
        if (_pango_layout == 0) {
                return;
@@ -235,32 +305,32 @@ RotatedLabelSet::on_size_request (Gtk::Requisition* requisition)
                std::pair<int, int> const d = setup_layout (_port_group_list.get_port_by_index (n - 1, false));
                requisition->width += d.first;
        }
+
+       cerr << "Labels will be " << requisition->width << " x " << requisition->height << endl;
 }
 
 void
-RotatedLabelSet::on_size_allocate (Gtk::Allocation& allocation)
+RotatedLabelSet::on_size_allocate (Allocation& allocation)
 {
        set_allocation (allocation);
 
        if (_gdk_window) {
-               _gdk_window->move_resize (
-                       allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height()
-                       );
+               _gdk_window->move_resize (allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height());
        }
 }
 
 void
 RotatedLabelSet::on_realize ()
 {
-       Gtk::Widget::on_realize ();
+       Widget::on_realize ();
 
-       Glib::RefPtr<Gtk::Style> style = get_style ();
+       Glib::RefPtr<Style> style = get_style ();
 
        if (!_gdk_window) {
                GdkWindowAttr attributes;
                memset (&attributes, 0, sizeof (attributes));
 
-               Gtk::Allocation allocation = get_allocation ();
+               Allocation allocation = get_allocation ();
                attributes.x = allocation.get_x ();
                attributes.y = allocation.get_y ();
                attributes.width = allocation.get_width ();
@@ -271,13 +341,13 @@ RotatedLabelSet::on_realize ()
                attributes.wclass = GDK_INPUT_OUTPUT;
 
                _gdk_window = Gdk::Window::create (get_window (), &attributes, GDK_WA_X | GDK_WA_Y);
-               unset_flags (Gtk::NO_WINDOW);
+               unset_flags (NO_WINDOW);
                set_window (_gdk_window);
 
-               _bg_colour = style->get_bg (Gtk::STATE_NORMAL );
-               modify_bg (Gtk::STATE_NORMAL, _bg_colour);
-               _fg_colour = style->get_fg (Gtk::STATE_NORMAL);
-;
+               _bg_colour = style->get_bg (STATE_NORMAL );
+               modify_bg (STATE_NORMAL, _bg_colour);
+               _fg_colour = style->get_fg (STATE_NORMAL);
+
                _gdk_window->set_user_data (gobj ());
 
                /* Set up Pango stuff */
@@ -297,7 +367,7 @@ RotatedLabelSet::on_unrealize()
 {
        _gdk_window.clear ();
 
-       Gtk::Widget::on_unrealize ();
+       Widget::on_unrealize ();
 }
 
 
@@ -318,10 +388,17 @@ RotatedLabelSet::setup_layout (std::string const & s)
        _pango_layout->get_pixel_size (w, h);
 
        /* Rotate the width and height as appropriate.  I thought Pango might be able
-          to do this for us, but I can't find out how... */
+          to do this for us, but I can't find out how... 
+       */
+
        std::pair<int, int> d;
-       d.first = int (w * cos (_angle_radians) - h * sin (_angle_radians));
-       d.second = int (w * sin (_angle_radians) + h * cos (_angle_radians));
+
+       // cerr << "\"" << s << "\" was " << w << " x " << h << endl;
+
+       d.first = int (fabs (w * cos (_angle_radians) + h * sin (_angle_radians)));
+       d.second = int (fabs (w * sin (_angle_radians) + h * cos (_angle_radians)));
+
+       // cerr << "\trotated by " << _angle_degrees << " = " << d.first << " x " << d.second << endl;
 
        return d;
 }
@@ -342,7 +419,18 @@ RotatedLabelSet::on_expose_event (GdkEventExpose* event)
                if ((*i)->visible) {
                        for (uint32_t j = 0; j < (*i)->ports.size(); ++j) {
                                std::pair<int, int> const d = setup_layout ((*i)->ports[j]);
-                               get_window()->draw_layout (_gc, int ((n + 0.25) * spacing), height - d.second, _pango_layout, _fg_colour, _bg_colour);
+                               int x, y;
+                               if (getenv ("AD_X_SHIFT") != 0) {
+                                       x = atoi (getenv ("AD_X_SHIFT"));
+                               } else {
+                                       x = 0;
+                               }
+                               if (getenv ("AD_Y_SHIFT") != 0) {
+                                       y = atoi (getenv ("AD_Y_SHIFT"));
+                               } else {
+                                       y = 0;
+                               }
+                               get_window()->draw_layout (_gc, int ((n + 0.25) * spacing) + x, height - d.second + y, _pango_layout, _fg_colour, _bg_colour);
                                ++n;
                        }
                }
@@ -373,24 +461,45 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool of
        : _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type),
          _column_labels (_port_group_list)
 {
-       _row_labels_vbox[0] = _row_labels_vbox[1] = 0;
-       _side_vbox_pad[0] = _side_vbox_pad[1] = 0;
+       _row_labels_vbox = 0;
+       _side_vbox_pad = 0;
 
+       _visibility_checkbutton_box.pack_start (*(manage (new Label (_("Connections displayed: ")))), false, false, 10);
        pack_start (_visibility_checkbutton_box, false, false);
        
-       _side_vbox[0].pack_start (*Gtk::manage (new Gtk::Label ("")));
-       _overall_hbox.pack_start (_side_vbox[0], false, false);
-       _scrolled_window.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_NEVER);
-       _scrolled_window.set_shadow_type (Gtk::SHADOW_NONE);
-       Gtk::VBox* b = new Gtk::VBox;
-       b->pack_start (_column_labels, false, false);
-       b->pack_start (_port_group_hbox, false, false);
-       Gtk::Alignment* a = new Gtk::Alignment (0, 1, 0, 0);
-       a->add (*Gtk::manage (b));
-       _scrolled_window.add (*Gtk::manage (a));
-       _overall_hbox.pack_start (_scrolled_window);
-       _side_vbox[1].pack_start (*Gtk::manage (new Gtk::Label ("")));
-       _overall_hbox.pack_start (_side_vbox[1]);
+       _scrolled_window.set_policy (POLICY_ALWAYS, POLICY_AUTOMATIC);
+       _scrolled_window.set_shadow_type (SHADOW_NONE);
+
+       VBox* b = manage (new VBox);
+
+       if (offer_inputs) {
+               b->pack_start (_port_group_hbox, false, false);
+               b->pack_start (_column_labels, false, false);
+       } else {
+               b->pack_start (_column_labels, false, false);
+               b->pack_start (_port_group_hbox, false, false);
+       }
+
+       Alignment* a; 
+
+       if (offer_inputs) {
+               a = manage (new Alignment (1, 0, 0, 0));
+       } else {
+               a = manage (new Alignment (0, 1, 0, 0));
+       }
+
+       a->add (*b);
+
+       _scrolled_window.add (*a);
+
+       if (offer_inputs) {
+               _overall_hbox.pack_start (_side_vbox, false, false, 6);
+               _overall_hbox.pack_start (_scrolled_window, true, true);
+       } else {
+               _overall_hbox.pack_start (_scrolled_window, true, true, 6);
+               _overall_hbox.pack_start (_side_vbox, false, false);
+       }
+
        pack_start (_overall_hbox);
 
        _port_group_hbox.signal_size_allocate().connect (sigc::hide (sigc::mem_fun (*this, &IOSelector::setup_dimensions)));
@@ -405,24 +514,24 @@ PortMatrix::~PortMatrix ()
 void
 PortMatrix::clear ()
 {
-       for (int i = 0; i < 2; ++i) {
-
-               for (std::vector<Gtk::EventBox*>::iterator j = _row_labels[i].begin(); j != _row_labels[i].end(); ++j) {
-                       delete *j;
-               }
-               _row_labels[i].clear ();
-               
-               if (_row_labels_vbox[i]) {
-                       _side_vbox[i].remove (*_row_labels_vbox[i]);
-               }
-               delete _row_labels_vbox[i];
-               _row_labels_vbox[i] = 0;
+       for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
+               delete *j;
+       }
+       _row_labels.clear ();
                
-               if (_side_vbox_pad[i]) {
-                       _side_vbox[i].remove (*_side_vbox_pad[i]);
-               }
-               delete _side_vbox_pad[i];
-               _side_vbox_pad[i] = 0;
+       if (_row_labels_vbox) {
+               _side_vbox.remove (*_row_labels_vbox);
+               delete _row_labels_vbox;
+               _row_labels_vbox = 0;
+       }
+       
+       /* remove lurking, invisible label and padding */
+       
+       _side_vbox.children().clear ();
+
+       if (_side_vbox_pad) {
+               delete _side_vbox_pad;
+               _side_vbox_pad = 0;
        }
 
        for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
@@ -460,22 +569,29 @@ PortMatrix::setup_dimensions ()
 
        /* Scrolled window */
        /* XXX: really shouldn't set a minimum horizontal size here, but if we don't
-          the window starts up very small */
+          the window starts up very small.
+          The constant value in the set_size_request() computation will control
+          how big the scrolled window will be if we fill the port matrix will a gajillion
+          ports.
+       */
+
        _scrolled_window.set_size_request (
-               std::min (_column_labels.get_width(), 640),
+               std::min (_column_labels.get_width(), 400),
                _column_labels.get_height() + port_group_tables_height + scrollbar_height + 16
                );
        
        /* Row labels */
-       for (int i = 0; i < 2; ++i) {
-               for (std::vector<Gtk::EventBox*>::iterator j = _row_labels[i].begin(); j != _row_labels[i].end(); ++j) {
-                       (*j)->get_child()->set_size_request (-1, unit_size.second);
-               }
-
-               if (_side_vbox_pad[i]) {
-                       _side_vbox_pad[i]->set_size_request (-1, scrollbar_height + unit_size.second / 4);
-               }
+       for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
+               (*j)->get_child()->set_size_request (-1, unit_size.second);
        }
+       
+       if (_side_vbox_pad) {
+               if (_offer_inputs) {
+                       _side_vbox_pad->set_size_request (-1, unit_size.second / 4);
+               } else {
+                       _side_vbox_pad->set_size_request (-1, scrollbar_height + unit_size.second / 4);
+               }
+       } 
 }
 
 
@@ -488,51 +604,87 @@ PortMatrix::setup ()
        int const rows = n_rows ();
        
        /* Row labels */
-       for (int i = 0; i < 2; ++i) {
-               _row_labels_vbox[i] = new Gtk::VBox;
-               int const run_rows = std::max (1, rows);
-               for (int j = 0; j < run_rows; ++j) {
-                       Gtk::Label* label = new Gtk::Label (rows == 0 ? "Quim" : row_name (j));
-                       Gtk::EventBox* b = new Gtk::EventBox;
-                       b->set_events (Gdk::BUTTON_PRESS_MASK);
-                       b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &IOSelector::row_label_button_pressed), j));
-                       b->add (*Gtk::manage (label));
-                       _row_labels[i].push_back (b);
-                       _row_labels_vbox[i]->pack_start (*b, false, false);
-               }
 
-               _side_vbox[i].pack_start (*_row_labels_vbox[i], false, false);
-               _side_vbox_pad[i] = new Gtk::Label ("");
-               _side_vbox[i].pack_start (*_side_vbox_pad[i], false, false);
+       _row_labels_vbox = new VBox;
+       int const run_rows = std::max (1, rows);
+
+       for (int j = 0; j < run_rows; ++j) {
+               
+               /* embolden the port/channel name */
+               
+               string s = "<b>";
+               s += row_name (j);
+               s += "</b>";
+               
+               Label* label = manage (new Label (s));
+               EventBox* b = manage (new EventBox);
+               
+               label->set_use_markup (true);
+               
+               b->set_events (Gdk::BUTTON_PRESS_MASK);
+               b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &IOSelector::row_label_button_pressed), j));
+               b->add (*label);
+               
+               _row_labels.push_back (b);
+               _row_labels_vbox->pack_start (*b, false, false);
+       }
+
+       _side_vbox_pad = new Label (""); /* unmanaged, explicitly deleted */
+
+       if (_offer_inputs) {
+               _side_vbox.pack_start (*_side_vbox_pad, false, false);
+               _side_vbox.pack_start (*_row_labels_vbox, false, false);
+               _side_vbox.pack_start (*manage (new Label ("")));
+       } else {
+               _side_vbox.pack_start (*manage (new Label ("")));
+               _side_vbox.pack_start (*_row_labels_vbox, false, false);
+               _side_vbox.pack_start (*_side_vbox_pad, false, false);
        }
 
        /* Checkbutton tables and visibility checkbuttons */
-       int n = 0;
        for (PortGroupList::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
-               if ((*i)->visible) {
-                       PortGroupUI* t = new PortGroupUI (*this, **i);
 
-                       /* XXX: this is a bit of a hack; should probably use a configurable colour here */
-                       Gdk::Color alt_bg = get_style()->get_bg (Gtk::STATE_NORMAL);
-                       alt_bg.set_rgb (alt_bg.get_red() + 4096, alt_bg.get_green() + 4096, alt_bg.get_blue () + 4096);
-                       if ((n % 2) == 0) {
-                               t->get_table().modify_bg (Gtk::STATE_NORMAL, alt_bg);
-                       }
+               PortGroupUI* t = new PortGroupUI (*this, **i);
+               
+               _port_group_ui.push_back (t);
+               _port_group_hbox.pack_start (t->get_table(), false, false);
+               
+               _visibility_checkbutton_box.pack_start (t->get_visibility_checkbutton(), false, false);
 
-                       _port_group_ui.push_back (t);
-                       _port_group_hbox.pack_start (t->get_table(), false, false);
+               CheckButton* chk = dynamic_cast<CheckButton*>(&t->get_visibility_checkbutton());
 
-                       _visibility_checkbutton_box.pack_start (t->get_visibility_checkbutton(), false, false);
-                       ++n;
-               }
-       }
+               if (chk) { 
+                       chk->signal_toggled().connect (sigc::mem_fun (*this, &PortMatrix::reset_visibility));
+               }
+       }
 
        show_all ();
 
+       reset_visibility ();
+}
+
+void
+PortMatrix::reset_visibility ()
+{
+       /* now adjust visibility and coloring */
+
+       bool even = true;
+       Gdk::Color odd_bg (color_from_style ("OddPortGroups", STATE_NORMAL, "fg"));
+       Gdk::Color even_bg (color_from_style ("EvenPortGroups", STATE_NORMAL, "fg"));
+
        for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
+
                (*i)->setup_visibility ();
+               
+               if ((*i)->port_group().visible) {
+                       if (even) {
+                               (*i)->get_table().modify_bg (STATE_NORMAL, even_bg);
+                       } else {
+                               (*i)->get_table().modify_bg (STATE_NORMAL, odd_bg);
+                       }
+                       even = !even;
+               }
        }
-       
 }
 
 void
@@ -551,8 +703,8 @@ PortMatrix::row_label_button_pressed (GdkEventButton* e, int r)
                return false;
        }
 
-       Gtk::Menu* menu = Gtk::manage (new Gtk::Menu);
-       Gtk::Menu_Helpers::MenuList& items = menu->items ();
+       Menu* menu = manage (new Menu);
+       Menu_Helpers::MenuList& items = menu->items ();
        menu->set_name ("ArdourContextMenu");
 
        bool const can_add = maximum_rows () > n_rows ();
@@ -560,13 +712,13 @@ PortMatrix::row_label_button_pressed (GdkEventButton* e, int r)
        std::string const name = row_name (r);
        
        items.push_back (
-               Gtk::Menu_Helpers::MenuElem (string_compose(_("Add %1"), row_descriptor()), sigc::mem_fun (*this, &PortMatrix::add_row))
+               Menu_Helpers::MenuElem (string_compose(_("Add %1"), row_descriptor()), sigc::mem_fun (*this, &PortMatrix::add_row))
                );
 
        items.back().set_sensitive (can_add);
 
        items.push_back (
-               Gtk::Menu_Helpers::MenuElem (string_compose(_("Remove %1 \"%2\""), row_descriptor(), name), sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_row), r))
+               Menu_Helpers::MenuElem (string_compose(_("Remove %1 \"%2\""), row_descriptor(), name), sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_row), r))
                );
 
        items.back().set_sensitive (can_remove);
@@ -601,7 +753,7 @@ PortMatrix::set_offer_inputs (bool i)
 
 PortGroupList::PortGroupList (ARDOUR::Session & session, ARDOUR::DataType type, bool offer_inputs, Mask mask)
        : _session (session), _type (type), _offer_inputs (offer_inputs),
-         buss (_("Buss"), "ardour:", mask & BUSS),
+         buss (_("Bus"), "ardour:", mask & BUSS),
          track (_("Track"), "ardour:", mask & TRACK),
          system (_("System"), "system:", mask & SYSTEM),
          other (_("Other"), "", mask & OTHER)
@@ -620,24 +772,33 @@ PortGroupList::refresh ()
        other.ports.clear ();
 
        /* Find the ports provided by ardour; we can't derive their type just from their
-          names, so we'll have to be more devious. */
+          names, so we'll have to be more devious. 
+       */
 
        boost::shared_ptr<ARDOUR::Session::RouteList> routes = _session.get_routes ();
 
        for (ARDOUR::Session::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
 
                PortGroup* g = 0;
-               if (_type == ARDOUR::DataType::AUDIO && dynamic_cast<ARDOUR::AudioTrack*> ((*i).get())) {
-                       /* Audio track for an audio IO */
-                       g = &track;
-               } else if (_type == ARDOUR::DataType::MIDI && dynamic_cast<ARDOUR::MidiTrack*> ((*i).get())) {
-                       /* Midi track for a MIDI IO */
-                       g = &track;
-               } else if (_type == ARDOUR::DataType::AUDIO && dynamic_cast<ARDOUR::MidiTrack*> ((*i).get()) == 0) {
-                       /* Non-MIDI track for an Audio IO; must be an audio buss */
-                       g = &buss;
-               }
 
+               if (_type == ARDOUR::DataType::AUDIO) {
+
+                       if (boost::dynamic_pointer_cast<ARDOUR::AudioTrack> (*i)) {
+                               g = &track;
+                       } else if (!boost::dynamic_pointer_cast<ARDOUR::MidiTrack>(*i)) {
+                               g = &buss;
+                       } 
+
+
+               } else if (_type == ARDOUR::DataType::MIDI) {
+
+                       if (boost::dynamic_pointer_cast<ARDOUR::MidiTrack> (*i)) {
+                               g = &track;
+                       }
+
+                       /* No MIDI busses yet */
+               } 
+                       
                if (g) {
                        ARDOUR::PortSet const & p = _offer_inputs ? ((*i)->inputs()) : ((*i)->outputs());
                        for (uint32_t j = 0; j < p.num_ports(); ++j) {
@@ -648,18 +809,22 @@ PortGroupList::refresh ()
                }
        }
        
-
        /* XXX: inserts, sends, plugin inserts? */
        
        /* Now we need to find the non-ardour ports; we do this by first
-          finding all the ports that we can connect to. */
-       const char **ports = _session.engine().get_ports (
-               "", _type.to_jack_type(), _offer_inputs ? JackPortIsInput : JackPortIsOutput
-               );
+          finding all the ports that we can connect to. 
+       */
 
+       const char **ports = _session.engine().get_ports ("", _type.to_jack_type(), _offer_inputs ? 
+                                                         JackPortIsInput : JackPortIsOutput);
        if (ports) {
 
                int n = 0;
+               string client_matching_string;
+
+               client_matching_string = _session.engine().client_name();
+               client_matching_string += ':';
+
                while (ports[n]) {
                        std::string const p = ports[n];
 
@@ -667,7 +832,7 @@ PortGroupList::refresh ()
                                /* system: prefix */
                                system.add (p);
                        } else {
-                               if (p.substr(0, strlen("ardour:")) != "ardour:") {
+                               if (p.substr(0, client_matching_string.length()) != client_matching_string) {
                                        /* other (non-ardour) prefix */
                                        other.add (p);
                                }
@@ -675,11 +840,13 @@ PortGroupList::refresh ()
 
                        ++n;
                }
+
+               free (ports);
        }
 
+       push_back (&system);
        push_back (&buss);
        push_back (&track);
-       push_back (&system);
        push_back (&other);
 }