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:
parent
3b96ad2a97
commit
954e1a6e79
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue