#include "canvastestapp.h" #include "ui_canvastestapp.h" #include #include #include #include struct group_name_to_id_t { int id; QString name; }; struct port_name_to_id_t { int group_id; int port_id; QString name; }; struct connection_to_id_t { int id; int port_out; int port_in; }; static int last_group_id = 0; static int last_port_id = 0; static int last_connection_id = 0; static CanvasTestApp* main_gui = 0; static jack_client_t* jack_client = 0; static QList used_group_names; static QList used_port_names; static QList used_connections; int get_group_id(QString group_name) { for (int i=0; i < used_group_names.count(); i++) { if (used_group_names[i].name == group_name) { return used_group_names[i].id; } } return -1; } int get_port_id(QString full_port_name) { QString group_name = full_port_name.split(":").at(0); QString port_name = full_port_name.replace(group_name+":", ""); int group_id = get_group_id(group_name); for (int i=0; i < used_port_names.count(); i++) { if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name) { return used_port_names[i].port_id; } } return -1; } QString get_full_port_name(int port_id) { int group_id = -1; QString group_name; QString port_name; for (int i=0; i < used_port_names.count(); i++) { if (used_port_names[i].port_id == port_id) { group_id = used_port_names[i].group_id; port_name = used_port_names[i].name; } } for (int i=0; i < used_group_names.count(); i++) { if (used_group_names[i].id == group_id) { group_name = used_group_names[i].name; } } return group_name+":"+port_name; } void canvas_callback(PatchCanvas::CallbackAction action, int value1, int value2, QString value_str) { qDebug("--------------------------- Callback called %i|%i|%i|%s", action, value1, value2, value_str.toStdString().data()); switch (action) { case PatchCanvas::ACTION_PORT_INFO: QMessageBox::information(main_gui, "port info dialog", "dummy text here"); break; case PatchCanvas::ACTION_PORT_RENAME: // Unused break; case PatchCanvas::ACTION_PORTS_CONNECT: jack_connect(jack_client, get_full_port_name(value1).toStdString().data(), get_full_port_name(value2).toStdString().data()); break; case PatchCanvas::ACTION_PORTS_DISCONNECT: for (int i=0; i < used_connections.count(); i++) { if (used_connections[i].id == value1) { jack_disconnect(jack_client, get_full_port_name(used_connections[i].port_out).toStdString().data(), get_full_port_name(used_connections[i].port_in).toStdString().data()); break; } } break; case PatchCanvas::ACTION_GROUP_INFO: QMessageBox::information(main_gui, "group info dialog", "dummy text here"); break; case PatchCanvas::ACTION_GROUP_RENAME: // Unused break; case PatchCanvas::ACTION_GROUP_SPLIT: PatchCanvas::splitGroup(value1); break; case PatchCanvas::ACTION_GROUP_JOIN: PatchCanvas::joinGroup(value1); break; default: break; } } CanvasTestApp::CanvasTestApp(QWidget *parent) : QMainWindow(parent), ui(new Ui::CanvasTestApp) { ui->setupUi(this); settings = new QSettings("PatchCanvas", "Canvas-test-app"); restoreGeometry(settings->value("Geometry").toByteArray()); main_gui = this; used_group_names.clear(); used_port_names.clear(); used_connections.clear(); scene = new PatchScene(this, ui->graphicsView); ui->graphicsView->setScene(scene); ui->graphicsView->setRenderHint(QPainter::Antialiasing, true); ui->graphicsView->setRenderHint(QPainter::TextAntialiasing, true); //ui->graphicsView->setRenderHint(QPainter::HighQualityAntialiasing, true); //ui->graphicsView->setViewport(new QGLWidget(ui->graphicsView)); PatchCanvas::options_t options; options.auto_hide_groups = false; options.use_bezier_lines = true; options.antialiasing = PatchCanvas::ANTIALIASING_SMALL; options.eyecandy = PatchCanvas::EYECANDY_SMALL; options.theme_name = PatchCanvas::getDefaultThemeName(); PatchCanvas::features_t features; features.group_info = false; features.group_rename = false; features.port_info = false; features.port_rename = false; features.handle_group_pos = true; PatchCanvas::setOptions(&options); PatchCanvas::setFeatures(&features); PatchCanvas::init(scene, canvas_callback, true); connect(this, SIGNAL(clientRegisterCallback(QString,bool)), SLOT(handle_clientRegisterCallback(QString,bool))); connect(this, SIGNAL(portRegisterCallback(int,bool)), SLOT(handle_portRegisterCallback(int,bool))); connect(this, SIGNAL(connectionCallback(int,int,bool)), SLOT(handle_connectionCallback(int,int,bool))); jack_client = jack_client_open("canvas-test-app", JackNullOption, 0); jack_set_client_registration_callback(jack_client, client_register_callback, 0); jack_set_port_registration_callback(jack_client, port_register_callback, 0); jack_set_port_connect_callback(jack_client, port_connect_callback, 0); jack_activate(jack_client); // query initial jack ports QList parsed_groups; const char** ports = jack_get_ports(jack_client, 0, 0, 0); if (ports) { for (int i=0; ports[i]; i++) { QString full_name(ports[i]); QString group_name = full_name.split(":").at(0); QString port_name = full_name.replace(group_name+":", ""); int group_id = -1; if (parsed_groups.contains(group_name)) { group_id = get_group_id(group_name); } else { group_id = last_group_id; group_name_to_id_t group_name_to_id; group_name_to_id.id = group_id; group_name_to_id.name = group_name; used_group_names.append(group_name_to_id); parsed_groups.append(group_name); PatchCanvas::addGroup(group_id, group_name); last_group_id++; } PatchCanvas::PortMode port_mode; PatchCanvas::PortType port_type; jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]); if (jack_port_flags(jack_port) & JackPortIsInput) port_mode = PatchCanvas::PORT_MODE_INPUT; else port_mode = PatchCanvas::PORT_MODE_OUTPUT; if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0) port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK; else port_type = PatchCanvas::PORT_TYPE_MIDI_JACK; port_name_to_id_t port_name_to_id; port_name_to_id.group_id = group_id; port_name_to_id.port_id = last_port_id; port_name_to_id.name = port_name; used_port_names.append(port_name_to_id); PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type); last_port_id++; } jack_free(ports); } // query connections, after all ports are in place ports = jack_get_ports(jack_client, 0, 0, JackPortIsOutput); if (ports) { for (int i=0; ports[i]; i++) { QString this_full_name(ports[i]); int this_port_id = get_port_id(this_full_name); jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]); const char** connections = jack_port_get_connections(jack_port); if (connections) { for (int j=0; connections[j]; j++) { QString target_full_name(connections[j]); int target_port_id = get_port_id(target_full_name); connection_to_id_t connection; connection.id = last_connection_id; connection.port_out = this_port_id; connection.port_in = target_port_id; used_connections.append(connection); PatchCanvas::connectPorts(last_connection_id, this_port_id, target_port_id); last_connection_id++; } jack_free(connections); } } jack_free(ports); } } CanvasTestApp::~CanvasTestApp() { delete settings; delete scene; delete ui; } void CanvasTestApp::client_register_callback(const char* name, int register_, void*) { main_gui->emit clientRegisterCallback(QString(name), bool(register_)); } void CanvasTestApp::port_register_callback(jack_port_id_t port_id_jack, int register_, void*) { main_gui->emit portRegisterCallback(port_id_jack, bool(register_)); } void CanvasTestApp::port_connect_callback(jack_port_id_t port_a, jack_port_id_t port_b, int connect, void*) { main_gui->emit connectionCallback(port_a, port_b, bool(connect)); } void CanvasTestApp::handle_clientRegisterCallback(QString name, bool yesno) { QString qname(name); if (yesno) { group_name_to_id_t group_name_to_id; group_name_to_id.id = last_group_id; group_name_to_id.name = qname; used_group_names.append(group_name_to_id); PatchCanvas::addGroup(last_group_id, qname); last_group_id++; } else { for (int i=0; i < used_group_names.count(); i++) { if (used_group_names[i].name == qname) { PatchCanvas::removeGroup(used_group_names[i].id); used_group_names.takeAt(i); break; } } } } void CanvasTestApp::handle_portRegisterCallback(int port, bool yesno) { jack_port_t* jack_port = jack_port_by_id(jack_client, port); QString full_name(jack_port_name(jack_port)); QString group_name = full_name.split(":").at(0); QString port_name = full_name.replace(group_name+":", ""); int group_id = get_group_id(group_name); if (yesno) { PatchCanvas::PortMode port_mode; PatchCanvas::PortType port_type; if (jack_port_flags(jack_port) & JackPortIsInput) port_mode = PatchCanvas::PORT_MODE_INPUT; else port_mode = PatchCanvas::PORT_MODE_OUTPUT; if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0) port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK; else port_type = PatchCanvas::PORT_TYPE_MIDI_JACK; port_name_to_id_t port_name_to_id; port_name_to_id.group_id = group_id; port_name_to_id.port_id = last_port_id; port_name_to_id.name = port_name; used_port_names.append(port_name_to_id); PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type); last_port_id++; } else { for (int i=0; i < used_port_names.count(); i++) { if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name) { PatchCanvas::removePort(used_port_names[i].port_id); used_port_names.takeAt(i); break; } } } } void CanvasTestApp::handle_connectionCallback(int port_a, int port_b, bool yesno) { jack_port_t* jack_port_a = jack_port_by_id(jack_client, port_a); jack_port_t* jack_port_b = jack_port_by_id(jack_client, port_b); int port_id_a = get_port_id(QString(jack_port_name(jack_port_a))); int port_id_b = get_port_id(QString(jack_port_name(jack_port_b))); if (yesno) { connection_to_id_t connection; connection.id = last_connection_id; connection.port_out = port_id_a; connection.port_in = port_id_b; used_connections.append(connection); PatchCanvas::connectPorts(last_connection_id, port_id_a, port_id_b); last_connection_id++; } else { for (int i=0; i < used_connections.count(); i++) { if (used_connections[i].port_out == port_id_a && used_connections[i].port_in == port_id_b) { PatchCanvas::disconnectPorts(used_connections[i].id); used_connections.takeAt(i); break; } } } } void CanvasTestApp::closeEvent(QCloseEvent* event) { jack_deactivate(jack_client); jack_client_close(jack_client); PatchCanvas::clear(); settings->setValue("Geometry", QVariant(saveGeometry())); QMainWindow::closeEvent(event); }