Improvements to the port matrix (I think). Sizing of the cairo section should be better. Clicking on nodes performs port connects / disconnects.

git-svn-id: svn://localhost/ardour2/branches/3.0@4402 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-01-13 01:15:19 +00:00
parent 3b96ad2a97
commit 954e1a6e79
9 changed files with 261 additions and 415 deletions

View File

@ -217,6 +217,7 @@ playlist_selector.cc
plugin_selector.cc
plugin_ui.cc
port_matrix.cc
port_group.cc
processor_box.cc
prompter.cc
public_editor.cc

View File

@ -89,14 +89,14 @@ void
BundleEditorMatrix::add_row ()
{
_bundle->add_channel ();
redisplay ();
setup ();
}
void
BundleEditorMatrix::remove_row (int r)
{
_bundle->remove_channel (r);
redisplay ();
setup ();
}
std::string
@ -205,7 +205,7 @@ BundleEditor::type_changed ()
void
BundleEditor::on_map ()
{
_matrix.redisplay ();
_matrix.setup ();
Window::on_map ();
}

View File

@ -55,7 +55,7 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
const PortSet& ps (_io->outputs());
for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) {
our_ports.push_back ((*i).name());
our_ports.push_back (i->name());
}
} else {
@ -64,12 +64,14 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
const PortSet& ps (_io->inputs());
for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) {
our_ports.push_back ((*i).name());
our_ports.push_back (i->name());
}
}
set_ports (our_ports);
setup ();
}
void
@ -77,7 +79,7 @@ IOSelector::ports_changed (ARDOUR::IOChange change, void *src)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &IOSelector::ports_changed), change, src));
redisplay ();
setup ();
}
void
@ -109,17 +111,7 @@ IOSelector::get_state (int r, std::string const & p) const
_io->input(r)->get_connections (connections);
}
int k = 0;
for (vector<string>::iterator i = connections.begin(); i != connections.end(); ++i) {
if ((*i)== p) {
return true;
}
++k;
}
return false;
return (std::find (connections.begin (), connections.end (), p) != connections.end ());
}
uint32_t
@ -160,9 +152,9 @@ IOSelector::row_name (int r) const
string::size_type pos;
if (!_offer_inputs) {
n = _io->input(r)->short_name();
n = _io->input(r)->name();
} else {
n = _io->output(r)->short_name();
n = _io->output(r)->name();
}
if ((pos = n.find ('/')) != string::npos) {
@ -270,11 +262,11 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
get_action_area()->pack_start (ok_button, false, false);
get_vbox()->set_spacing (8);
get_vbox()->pack_start (_selector);
get_vbox()->pack_start (_selector, true, true);
suggestion.set_alignment (0.5, 0.5);
suggestion_box.pack_start (suggestion, true, true);
get_vbox()->pack_start (suggestion_box);
get_vbox()->pack_start (suggestion_box, false, false);
ok_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::accept));
cancel_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::cancel));
@ -329,7 +321,7 @@ IOSelectorWindow::ports_changed (ARDOUR::IOChange change, void *src)
void
IOSelectorWindow::rescan ()
{
_selector.redisplay ();
_selector.setup ();
}
void
@ -349,7 +341,7 @@ IOSelectorWindow::accept ()
void
IOSelectorWindow::on_map ()
{
_selector.redisplay ();
_selector.setup ();
Window::on_map ();
}
@ -382,8 +374,8 @@ PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::Por
void
PortInsertUI::redisplay ()
{
input_selector.redisplay();
output_selector.redisplay();
input_selector.setup ();
output_selector.setup ();
}
void

View File

@ -9,12 +9,13 @@
#include <vector>
#include "matrix.h"
#include "port_matrix.h"
using namespace std;
using namespace Gtk;
using namespace ARDOUR;
Matrix::Matrix ()
Matrix::Matrix (PortMatrix* p) : _port_matrix (p)
{
alloc_width = 0;
alloc_height = 0;
@ -27,10 +28,12 @@ Matrix::Matrix ()
ystep = 0;
pixmap = 0;
drawn = false;
angle_radians = M_PI/4.0;
angle_radians = M_PI / 4.0;
motion_x = -1;
motion_y = -1;
border = 10;
add_events (Gdk::POINTER_MOTION_MASK|Gdk::LEAVE_NOTIFY_MASK);
}
@ -47,7 +50,10 @@ Matrix::add_group (PortGroup& pg)
for (vector<string>::const_iterator s = pg.ports.begin(); s != pg.ports.end(); ++s) {
others.push_back (OtherPort (*s, pg));
}
reset_size ();
if (pg.visible) {
reset_size ();
}
}
@ -68,7 +74,10 @@ Matrix::remove_group (PortGroup& pg)
++o;
}
}
reset_size ();
if (pg.visible) {
reset_size ();
}
}
void
@ -86,29 +95,23 @@ Matrix::show_group (PortGroup& pg)
void
Matrix::setup_nodes ()
{
int n, x, y;
list<string>::iterator m;
list<OtherPort>::iterator s;
for (vector<MatrixNode*>::iterator p = nodes.begin(); p != nodes.end(); ++p) {
delete *p;
}
nodes.clear ();
list<OtherPort>::size_type visible_others = 0;
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
if ((*s).visible()) {
++visible_others;
}
}
nodes.assign (ours.size() * visible_others, 0);
nodes.assign (ours.size() * get_visible_others (), 0);
int n, x, y;
list<string>::iterator m;
list<OtherPort>::iterator s;
for (n = 0, y = 0, m = ours.begin(); m != ours.end(); ++m, ++y) {
for (x = 0, s = others.begin(); s != others.end(); ++s) {
if ((*s).visible()) {
nodes[n] = new MatrixNode (*m, *s, x, y);
if (s->visible ()) {
bool const c = _port_matrix->get_state (y, s->name());
nodes[n] = new MatrixNode (*m, *s, c, x, y);
n++;
x++;
}
@ -116,78 +119,27 @@ Matrix::setup_nodes ()
}
}
void
Matrix::reset_size ()
Matrix::other_name_size_information (double* rotated_width, double* rotated_height, double* typical_height) const
{
list<OtherPort>::size_type visible_others = 0;
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
if ((*s).visible()) {
++visible_others;
}
}
double w = 0;
double h = 0;
if (!visible_others) {
cerr << "There are no visible others!\n";
xstep = 1;
ystep = 1;
line_width = 1;
line_height = 1;
border = 10;
arc_radius = 3;
labels_x_shift = 0;
labels_y_shift = 0;
return;
}
border = 10;
if (alloc_width > line_width) {
xstep = (alloc_width - labels_x_shift - (2 * border) - (2 * arc_radius)) / visible_others;
line_width = xstep * (others.size() - 1);
ystep = (alloc_height - labels_y_shift - (2 * border) - (2 * arc_radius)) / (ours.size() - 1);
line_height = ystep * (ours.size() - 1);
} else {
xstep = 20;
ystep = 20;
line_height = (ours.size() - 1) * ystep;
line_width = visible_others * xstep;
}
int half_step = min (ystep/2,xstep/2);
if (half_step > 3) {
arc_radius = half_step - 5;
} else {
arc_radius = 3;
}
arc_radius = min (arc_radius, 10);
/* scan all the port names that will be rotated, and compute
how much space we need for them
*/
float w = 0;
float h = 0;
cairo_text_extents_t extents;
cairo_t* cr;
GdkPixmap* pm;
pm = gdk_pixmap_new (NULL, 1, 1, 24);
GdkPixmap* pm = gdk_pixmap_new (NULL, 1, 1, 24);
gdk_drawable_set_colormap (pm, gdk_colormap_get_system());
cairo_t* cr = gdk_cairo_create (pm);
cr = gdk_cairo_create (pm);
for (list<OtherPort>::iterator s = others.begin(); s != others.end(); ++s) {
if ((*s).visible()) {
cairo_text_extents (cr, (*s).name().c_str(), &extents);
w = max ((float) extents.width, w);
h = max ((float) extents.height, h);
for (list<OtherPort>::const_iterator s = others.begin(); s != others.end(); ++s) {
if (s->visible()) {
cairo_text_extents_t extents;
cairo_text_extents (cr, s->short_name().c_str(), &extents);
if (extents.width > w) {
w = extents.width;
h = extents.height;
}
}
}
@ -196,25 +148,99 @@ Matrix::reset_size ()
/* transform */
w = fabs (w * cos (angle_radians) + h * sin (angle_radians));
h = fabs (w * sin (angle_radians) + h * cos (angle_radians));
*rotated_width = fabs (w * cos (angle_radians) + h * sin (angle_radians));
*rotated_height = fabs (w * sin (angle_radians) + h * cos (angle_radians));
*typical_height = h;
}
std::pair<int, int>
Matrix::ideal_size () const
{
double rw;
double rh;
double th;
other_name_size_information (&rw, &rh, &th);
double const ideal_xstep = th * 2;
double const ideal_ystep = 16;
uint32_t const visible_others = get_visible_others ();
return std::make_pair (
int (rw + (2 * border) + ideal_xstep * visible_others),
int (rh + (2 * border) + ideal_ystep * ours.size ())
);
}
void
Matrix::reset_size ()
{
double rw;
double rh;
double th;
other_name_size_information (&rw, &rh, &th);
/* y shift is the largest transformed text height plus a bit for luck */
labels_y_shift = int (ceil (rh) + 10);
/* x shift is the width of the leftmost label */
labels_x_shift = int (ceil (rw));
uint32_t const visible_others = get_visible_others ();
if (!visible_others) {
xstep = 1;
ystep = 1;
line_width = 1;
line_height = 1;
arc_radius = 3;
return;
}
if (ours.size () > 1) {
xstep = (alloc_width - labels_x_shift - (2 * border)) / visible_others;
line_width = xstep * (visible_others - 1);
ystep = (alloc_height - labels_y_shift - (2 * border)) / (ours.size() - 1);
line_height = ystep * (ours.size() - 1);
} else {
/* we have <= 1 of our ports, so steps don't matter */
xstep = 20;
ystep = 20;
line_height = (ours.size() - 1) * ystep;
line_width = visible_others * xstep;
}
int half_step = min (ystep / 2, xstep / 2);
if (half_step > 3) {
arc_radius = half_step - 5;
} else {
arc_radius = 3;
}
arc_radius = min (arc_radius, 10);
labels_y_shift = (int) ceil (h) + 10;
labels_x_shift = (int) ceil (w);
setup_nodes ();
cerr << "Based on ours = " << ours.size() << " others = " << others.size()
<< " dimens = "
<< " xstep " << xstep << endl
<< " ystep " << ystep << endl
<< " line_width " << line_width << endl
<< " line_height " << line_height << endl
<< " border " << border << endl
<< " arc_radius " << arc_radius << endl
<< " labels_x_shift " << labels_x_shift << endl
<< " labels_y_shift " << labels_y_shift << endl;
// cerr << "Based on ours = " << ours.size() << " others = " << others.size()
// << " dimens = "
// << " xstep " << xstep << endl
// << " ystep " << ystep << endl
// << " line_width " << line_width << endl
// << " line_height " << line_height << endl
// << " border " << border << endl
// << " arc_radius " << arc_radius << endl
// << " labels_x_shift " << labels_x_shift << endl
// << " labels_y_shift " << labels_y_shift << endl;
}
bool
@ -238,32 +264,33 @@ Matrix::on_leave_notify_event (GdkEventCrossing *ev)
void
Matrix::on_size_request (Requisition* req)
{
req->width = labels_x_shift + line_width + (2*border) + (2*arc_radius);
req->height = labels_y_shift + line_height + (2*border) + (2*arc_radius);
std::pair<int, int> const is = ideal_size ();
req->width = is.first;
req->height = is.second;
}
MatrixNode*
Matrix::get_node (int32_t x, int32_t y)
{
int half_xstep = xstep / 2;
int half_ystep = ystep / 2;
int const half_xstep = xstep / 2;
int const half_ystep = ystep / 2;
x -= labels_x_shift - border;
if (x < half_xstep) {
x -= labels_x_shift + border;
if (x < -half_xstep) {
return 0;
}
y -= labels_y_shift - border;
if (y < half_ystep) {
y -= labels_y_shift + border;
if (y < -half_ystep) {
return 0;
}
x = (x - half_xstep) / xstep;
y = (y - half_ystep) / ystep;
x = (x + half_xstep) / xstep;
y = (y + half_ystep) / ystep;
x = y*ours.size() + x;
x = y * get_visible_others () + x;
if (x >= nodes.size()) {
if (x >= int32_t (nodes.size())) {
return 0;
}
@ -276,11 +303,14 @@ Matrix::on_button_press_event (GdkEventButton* ev)
MatrixNode* node;
if ((node = get_node (ev->x, ev->y)) != 0) {
cerr << "Event in node " << node->our_name() << " x " << node->their_name () << endl;
node->set_connected (!node->connected());
_port_matrix->set_state (node->y (), node->their_name (), node->connected (), 0);
drawn = false;
queue_draw();
}
return true;
}
return false;
}
void
@ -328,10 +358,8 @@ Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
list<string>::iterator o;
list<OtherPort>::iterator t;
int x, y;
uint32_t top_shift, bottom_shift, left_shift, right_shift;
cairo_t* cr;
cr = gdk_cairo_create (drawable);
cairo_t* cr = gdk_cairo_create (drawable);
cairo_set_source_rgb (cr, 0.83, 0.83, 0.83);
cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height);
@ -339,10 +367,8 @@ Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
cairo_set_line_width (cr, 0.5);
top_shift = labels_y_shift + border;
left_shift = labels_x_shift + border;
bottom_shift = 0;
right_shift = 0;
int32_t const top_shift = labels_y_shift + border;
int32_t const left_shift = labels_x_shift + border;
/* horizontal grid lines and side labels */
@ -376,7 +402,7 @@ Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
cairo_save (cr);
cairo_rotate (cr, angle_radians);
cairo_show_text (cr, (*t).name().c_str());
cairo_show_text (cr, t->short_name().c_str());
cairo_restore (cr);
}
@ -394,10 +420,10 @@ Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
cairo_arc (cr, left_shift+x, top_shift+y, arc_radius, 0, 2.0 * M_PI);
if ((*n)->connected()) {
cairo_set_source_rgba (cr, 1.0, 0, 0, 1.0);
cairo_stroke (cr);
cairo_fill (cr);
} else {
cairo_set_source_rgba (cr, 1.0, 0, 0, 0.7);
cairo_fill (cr);
cairo_stroke (cr);
}
}
}
@ -406,8 +432,8 @@ Matrix::redraw (GdkDrawable* drawable, GdkRectangle* rect)
if (motion_x >= left_shift && motion_y >= top_shift) {
int col_left = left_shift + ((motion_x - left_shift) / xstep) * xstep;
int row_top = top_shift + ((motion_y - top_shift) / ystep) * ystep;
int col_left = left_shift + ((motion_x + (xstep / 2) + - left_shift) / xstep) * xstep;
int row_top = top_shift + ((motion_y + (ystep / 2) - top_shift) / ystep) * ystep;
cairo_set_line_width (cr, 5);
cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.3);
@ -457,3 +483,29 @@ Matrix::on_expose_event (GdkEventExpose* event)
return true;
}
uint32_t
Matrix::get_visible_others () const
{
uint32_t v = 0;
for (list<OtherPort>::const_iterator s = others.begin(); s != others.end(); ++s) {
if (s->visible()) {
++v;
}
}
return v;
}
MatrixNode::MatrixNode (std::string a, OtherPort o, bool c, int32_t x, int32_t y)
: _name (a), them (o), _connected (c), _x(x), _y(y)
{
}
std::string
OtherPort::name () const
{
return _group.prefix + _short_name;
}

View File

@ -11,24 +11,26 @@
#include "port_group.h"
/// One of the other ports that we're connecting ours to
class OtherPort {
public:
OtherPort (const std::string& n, PortGroup& g)
: _name (n), _group (g) {}
: _short_name (n), _group (g) {}
std::string name() const { return _name; }
std::string name () const;
std::string short_name () const { return _short_name; }
PortGroup& group() const { return _group; }
bool visible() const { return _group.visible; }
public:
std::string _name;
std::string _short_name;
PortGroup& _group;
};
/// A node on the matrix
class MatrixNode {
public:
MatrixNode (std::string a, OtherPort o, int32_t x, int32_t y)
: _name (a), them (o), _connected (random()%3), _x(x), _y(y) {}
MatrixNode (std::string, OtherPort, bool, int32_t, int32_t);
~MatrixNode() {}
PortGroup& get_group() const { return them.group(); }
@ -52,7 +54,7 @@ class MatrixNode {
class Matrix : public Gtk::EventBox
{
public:
Matrix();
Matrix (PortMatrix*);
void set_ports (const std::list<std::string>&);
void add_group (PortGroup&);
@ -74,7 +76,8 @@ class Matrix : public Gtk::EventBox
MatrixNode* get_node (int32_t x, int32_t y);
private:
private:
PortMatrix* _port_matrix; ///< the PortMatrix that we're working for
int height;
int width;
int alloc_width;
@ -100,6 +103,9 @@ private:
void redraw (GdkDrawable*, GdkRectangle*);
void alloc_pixmap ();
void setup_nodes ();
uint32_t get_visible_others () const;
void other_name_size_information (double *, double *, double *) const;
std::pair<int, int> ideal_size () const;
GdkPixmap* pixmap;
};

View File

@ -1,3 +1,22 @@
/*
Copyright (C) 2002-2009 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __gtk_ardour_port_group_h__
#define __gtk_ardour_port_group_h__
@ -23,15 +42,16 @@ class PortGroup
public:
/** PortGroup constructor.
* @param n Name.
* @param p Port name prefix.
* @param p Port name prefix (including trailing :)
* @param v true if group should be visible in the UI, otherwise false.
*/
PortGroup (std::string const & n, std::string const & p, bool v) : name (n), prefix (p), visible (v) {}
PortGroup (std::string const & n, std::string const & p, bool v)
: name (n), prefix (p), visible (v) {}
void add (std::string const & p);
std::string name; ///< name for the group
std::string prefix; ///< prefix (before colon) e.g. "ardour:"
std::string prefix; ///< prefix e.g. "ardour:"
std::vector<std::string> ports; ///< port names
bool visible; ///< true if the group is visible in the UI
};
@ -81,10 +101,10 @@ class PortGroupList : public std::list<PortGroup*>
ARDOUR::DataType _type;
bool _offer_inputs;
PortGroup buss;
PortGroup track;
PortGroup system;
PortGroup other;
PortGroup _buss;
PortGroup _track;
PortGroup _system;
PortGroup _other;
};
#endif /* __gtk_ardour_port_group_h__ */

View File

@ -19,96 +19,20 @@
#include <gtkmm/label.h>
#include <gtkmm/enums.h>
#include <gtkmm/image.h>
#include <gtkmm/stock.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/menu.h>
#include <gtkmm/menu_elems.h>
#include <gtkmm/menuitem.h>
#include <gtkmm/menushell.h>
#include <glibmm/objectbase.h>
#include <gtkmm2ext/doi.h>
#include <ardour/port_insert.h>
#include "ardour/session.h"
#include "ardour/io.h"
#include "ardour/audioengine.h"
#include "ardour/track.h"
#include "ardour/audio_track.h"
#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"
#include "port_matrix.h"
using namespace Gtk;
/** Add a port to a group.
* @param p Port name, with or without prefix.
*/
void
PortGroup::add (std::string const & p)
{
if (prefix.empty() == false && p.substr (0, prefix.length()) == prefix) {
ports.push_back (p.substr (prefix.length()));
} else {
ports.push_back (p);
}
}
/** PortGroupUI constructor.
* @param m PortMatrix to work for.
* @Param g PortGroup to represent.
*/
PortGroupUI::PortGroupUI (PortMatrix& m, PortGroup& g)
: _port_matrix (m)
, _port_group (g)
, _ignore_check_button_toggle (false)
, _visibility_checkbutton (g.name)
{
_port_group.visible = true;
_ignore_check_button_toggle = false;
_visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled));
}
/** The visibility of a PortGroupUI has been toggled */
void
PortGroupUI::visibility_checkbutton_toggled ()
{
_port_group.visible = _visibility_checkbutton.get_active ();
}
/** @return Checkbutton used to toggle visibility */
Widget&
PortGroupUI::get_visibility_checkbutton ()
{
return _visibility_checkbutton;
}
/** Handle a toggle of a port check button */
void
PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c)
{
if (_ignore_check_button_toggle == false) {
// _port_matrix.hide_group (_port_group);
}
}
/** Set up visibility of the port group according to PortGroup::visible */
void
PortGroupUI::setup_visibility ()
{
if (_visibility_checkbutton.get_active () != _port_group.visible) {
_visibility_checkbutton.set_active (_port_group.visible);
}
}
PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask)
: _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type)
: _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type), matrix (this)
{
_side_vbox_pad = 0;
@ -165,6 +89,9 @@ PortMatrix::clear ()
void
PortMatrix::setup ()
{
/* sort out the ports that we'll offer to connect to */
_port_group_list.refresh ();
clear ();
_side_vbox_pad = new Label (""); /* unmanaged, explicitly deleted */
@ -174,7 +101,7 @@ PortMatrix::setup ()
matrix.clear ();
/* Checkbutton tables and visibility checkbuttons */
/* Matrix and visibility checkbuttons */
for (PortGroupList::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
PortGroupUI* t = new PortGroupUI (*this, **i);
@ -212,13 +139,6 @@ PortMatrix::reset_visibility ()
}
}
void
PortMatrix::redisplay ()
{
_port_group_list.refresh ();
setup ();
}
/** Handle a button press on a row label */
bool
@ -258,7 +178,7 @@ PortMatrix::set_type (ARDOUR::DataType t)
{
_type = t;
_port_group_list.set_type (t);
redisplay ();
setup ();
}
void
@ -266,161 +186,6 @@ PortMatrix::set_offer_inputs (bool i)
{
_offer_inputs = i;
_port_group_list.set_offer_inputs (i);
redisplay ();
}
/** PortGroupList constructor.
* @param session Session to get ports from.
* @param type Type of ports to offer (audio or MIDI)
* @param offer_inputs true to offer output ports, otherwise false.
* @param mask Mask of groups to make visible by default.
*/
PortGroupList::PortGroupList (ARDOUR::Session & session, ARDOUR::DataType type, bool offer_inputs, Mask mask)
: _session (session), _type (type), _offer_inputs (offer_inputs),
buss (_("Bus"), "ardour:", mask & BUSS),
track (_("Track"), "ardour:", mask & TRACK),
system (_("System"), "system:", mask & SYSTEM),
other (_("Other"), "", mask & OTHER)
{
refresh ();
}
void
PortGroupList::refresh ()
{
clear ();
buss.ports.clear ();
track.ports.clear ();
system.ports.clear ();
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.
*/
boost::shared_ptr<ARDOUR::Session::RouteList> routes = _session.get_routes ();
cerr << "Looking for arour routes\n";
for (ARDOUR::Session::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
PortGroup* g = 0;
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) {
g->add (p.port(j)->name ());
}
std::sort (g->ports.begin(), g->ports.end());
}
}
/* 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);
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];
if (p.substr(0, strlen ("system:")) == "system:") {
/* system: prefix */
system.add (p);
} else {
if (p.substr(0, client_matching_string.length()) != client_matching_string) {
/* other (non-ardour) prefix */
other.add (p);
}
}
++n;
}
free (ports);
}
push_back (&system);
push_back (&buss);
push_back (&track);
push_back (&other);
}
int
PortGroupList::n_visible_ports () const
{
int n = 0;
for (const_iterator i = begin(); i != end(); ++i) {
if ((*i)->visible) {
n += (*i)->ports.size();
}
}
return n;
}
std::string
PortGroupList::get_port_by_index (int n, bool with_prefix) const
{
/* XXX: slightly inefficient algorithm */
for (const_iterator i = begin(); i != end(); ++i) {
for (std::vector<std::string>::const_iterator j = (*i)->ports.begin(); j != (*i)->ports.end(); ++j) {
if (n == 0) {
if (with_prefix) {
return (*i)->prefix + *j;
} else {
return *j;
}
}
--n;
}
}
return "";
}
void
PortGroupList::set_type (ARDOUR::DataType t)
{
_type = t;
}
void
PortGroupList::set_offer_inputs (bool i)
{
_offer_inputs = i;
setup ();
}

View File

@ -42,7 +42,7 @@ class PortMatrix : public Gtk::VBox {
PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool, PortGroupList::Mask);
~PortMatrix ();
void redisplay ();
void setup ();
enum Result {
Cancelled,
@ -55,8 +55,19 @@ class PortMatrix : public Gtk::VBox {
void set_offer_inputs (bool);
bool offering_input() const { return _offer_inputs; }
virtual void set_state (int, std::string const &, bool, uint32_t) = 0;
virtual bool get_state (int, std::string const &) const = 0;
/** @param r Our row index.
* @param p Other port.
* @param s New state.
* @param k XXX
*/
virtual void set_state (int r, std::string const & p, bool s, uint32_t k) = 0;
/** @param r Our row index.
* @param p Other port.
* @return true if r is connected to p, otherwise false.
*/
virtual bool get_state (int r, std::string const &p) const = 0;
virtual uint32_t n_rows () const = 0;
virtual uint32_t maximum_rows () const = 0;
virtual uint32_t minimum_rows () const = 0;
@ -86,7 +97,6 @@ class PortMatrix : public Gtk::VBox {
Gtk::Label* _side_vbox_pad;
Gtk::HBox _visibility_checkbutton_box;
void setup ();
void clear ();
bool row_label_button_pressed (GdkEventButton*, int);
void reset_visibility ();

View File

@ -321,13 +321,13 @@ RouteParams_UI::setup_io_frames()
// input
_input_iosel = new IOSelector (*session, _route, true);
_input_iosel->redisplay ();
_input_iosel->setup ();
input_frame.add (*_input_iosel);
input_frame.show_all();
// output
_output_iosel = new IOSelector (*session, _route, false);
_output_iosel->redisplay ();
_output_iosel->setup ();
output_frame.add (*_output_iosel);
output_frame.show_all();
}