summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-10-02 20:56:28 +0000
committerDavid Robillard <d@drobilla.net>2006-10-02 20:56:28 +0000
commit682a43546becbc86a210003846778ebb0c38718a (patch)
tree319e4b01347490d43a20e6ccc6b85cef94ee5288 /src
parent5812053fd22499251e2e2cedaa90fdd80c0d0988 (diff)
downloadpatchage-682a43546becbc86a210003846778ebb0c38718a.tar.gz
patchage-682a43546becbc86a210003846778ebb0c38718a.tar.bz2
patchage-682a43546becbc86a210003846778ebb0c38718a.zip
boost::shared_ptr-ification of FlowCanvas.
Extreme performance enhancements in Patchage (eg don't redraw the whole canvas every time). Patchage work towards being a control centre. Broken commit (ingen doesn't even compile) for machine transfer, don't even bother trying this revision. git-svn-id: http://svn.drobilla.net/lad/patchage@147 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/AlsaDriver.cpp163
-rw-r--r--src/AlsaDriver.h16
-rw-r--r--src/Driver.h26
-rw-r--r--src/JackDriver.cpp266
-rw-r--r--src/JackDriver.h31
-rw-r--r--src/LashDriver.cpp20
-rw-r--r--src/LashDriver.h10
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Patchage.cpp231
-rw-r--r--src/Patchage.h24
-rw-r--r--src/PatchageFlowCanvas.cpp63
-rw-r--r--src/PatchageFlowCanvas.h8
-rw-r--r--src/PatchageModule.h12
-rw-r--r--src/PatchagePort.h11
-rw-r--r--src/StateManager.cpp4
-rw-r--r--src/StateManager.h4
-rw-r--r--src/main.cpp10
-rw-r--r--src/patchage.glade522
18 files changed, 811 insertions, 611 deletions
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp
index 909a710..43ee297 100644
--- a/src/AlsaDriver.cpp
+++ b/src/AlsaDriver.cpp
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -49,25 +49,24 @@ AlsaDriver::~AlsaDriver()
* @a launch_daemon is ignored, as ALSA has no daemon to launch/connect to.
*/
void
-AlsaDriver::attach(bool launch_daemon)
+AlsaDriver::attach(bool /*launch_daemon*/)
{
- cout << "Connecting to Alsa... ";
- cout.flush();
-
int ret = snd_seq_open(&m_seq, "default",
SND_SEQ_OPEN_DUPLEX,
SND_SEQ_NONBLOCK);
if (ret) {
- cout << "Failed" << endl;
+ m_app->status_message("[ALSA] Unable to attach");
m_seq = NULL;
} else {
- cout << "Connected" << endl;
+ m_app->status_message("[ALSA] Attached");
snd_seq_set_client_name(m_seq, "Patchage");
ret = pthread_create(&m_refresh_thread, NULL, &AlsaDriver::refresh_main, this);
if (ret)
cerr << "Couldn't start refresh thread" << endl;
+
+ signal_attached.emit();
}
}
@@ -80,7 +79,8 @@ AlsaDriver::detach()
pthread_join(m_refresh_thread, NULL);
snd_seq_close(m_seq);
m_seq = NULL;
- cout << "Disconnected from Alsa" << endl;
+ signal_detached.emit();
+ m_app->status_message("[ALSA] Detached");
}
}
@@ -102,6 +102,18 @@ AlsaDriver::refresh()
}
+boost::shared_ptr<PatchagePort>
+AlsaDriver::create_port(boost::shared_ptr<PatchageModule> parent,
+ const string& name, bool is_input, snd_seq_addr_t addr)
+{
+ boost::shared_ptr<PatchagePort> ret(
+ new PatchagePort(parent, ALSA_MIDI, name, is_input,
+ m_app->state_manager()->get_port_color(ALSA_MIDI)));
+ ret->alsa_addr(addr);
+ return ret;
+}
+
+
/** Refresh all Alsa Midi ports.
*/
void
@@ -159,7 +171,7 @@ AlsaDriver::refresh_ports()
is_application = (type & SND_SEQ_PORT_TYPE_APPLICATION);
port_name = snd_seq_port_info_get_name(pinfo);
- PatchageModule* m = NULL;
+ boost::shared_ptr<PatchageModule> m;
//cout << client_name << " : " << port_name << " is_application = " << is_application
// << " is_duplex = " << is_duplex << endl;
@@ -168,22 +180,23 @@ AlsaDriver::refresh_ports()
// Application input/output ports go on the same module
if (!split) {
- m = (PatchageModule*)m_canvas->find_module(client_name, InputOutput);
- if (m == NULL) {
- m = new PatchageModule(m_app, client_name, InputOutput);
+ m = m_canvas->find_module(client_name, InputOutput);
+ if (!m) {
+ m = boost::shared_ptr<PatchageModule>(new PatchageModule(m_app, client_name, InputOutput));
m->load_location();
m->store_location();
- m->show();
+ m_app->canvas()->add_module(m);
}
- if (!is_duplex) {
- m->add_patchage_port(port_name, is_input, ALSA_MIDI, addr);
- } else {
- m->add_patchage_port(port_name, true, ALSA_MIDI, addr);
- m->add_patchage_port(port_name, false, ALSA_MIDI, addr);
+ if (!m->get_port(port_name)) {
+ if (!is_duplex) {
+ m->add_port(create_port(m, port_name, is_input, addr));
+ } else {
+ m->add_port(create_port(m, port_name, true, addr));
+ m->add_port(create_port(m, port_name, false, addr));
+ }
}
} else { // non-application input/output ports (hw interface, etc) go on separate modules
- PatchageModule* m = NULL;
ModuleType type = InputOutput;
// The 'application' hint isn't always set by clients, so this bit
@@ -194,46 +207,61 @@ AlsaDriver::refresh_ports()
else type = Output;
// See if an InputOutput module exists (maybe with Jack ports on it)
- m = (PatchageModule*)m_canvas->find_module(client_name, InputOutput);
+ m = m_canvas->find_module(client_name, InputOutput);
- if (m == NULL)
- m = (PatchageModule*)m_canvas->find_module(client_name, type);
- if (m == NULL) {
- m = new PatchageModule(m_app, client_name, type);
+ if (!m)
+ m = m_canvas->find_module(client_name, type);
+
+ if (!m) {
+ m = boost::shared_ptr<PatchageModule>(
+ new PatchageModule(m_app, client_name, type));
m->load_location();
m->store_location();
+ m_app->canvas()->add_module(m);
}
- m->add_patchage_port(port_name, is_input, ALSA_MIDI, addr);
+ if (!m->get_port(port_name))
+ m->add_port(create_port(m, port_name, is_input, addr));
} else { // two ports to add
type = Input;
// See if an InputOutput module exists (maybe with Jack ports on it)
- m = (PatchageModule*)m_canvas->find_module(client_name, InputOutput);
+ m = m_canvas->find_module(client_name, InputOutput);
- if (m == NULL)
- m = (PatchageModule*)m_canvas->find_module(client_name, type);
- if (m == NULL) {
- m = new PatchageModule(m_app, client_name, type);
+ if (!m)
+ m = m_canvas->find_module(client_name, type);
+
+ if (!m) {
+ m = boost::shared_ptr<PatchageModule>(
+ new PatchageModule(m_app, client_name, type));
m->load_location();
m->store_location();
}
- m->add_patchage_port(port_name, true, ALSA_MIDI, addr);
+
+ assert(m);
+
+ if (!m->get_port(port_name))
+ m->add_port(create_port(m, port_name, true, addr));
type = Output;
// See if an InputOutput module exists (maybe with Jack ports on it)
- m = (PatchageModule*)m_canvas->find_module(client_name, InputOutput);
+ m = m_canvas->find_module(client_name, InputOutput);
- if (m == NULL)
- m = (PatchageModule*)m_canvas->find_module(client_name, type);
- if (m == NULL) {
- m = new PatchageModule(m_app, client_name, type);
+ if (!m)
+ m = m_canvas->find_module(client_name, type);
+
+ if (!m) {
+ m = boost::shared_ptr<PatchageModule>(
+ new PatchageModule(m_app, client_name, type));
+
m->load_location();
m->store_location();
}
- m->add_patchage_port(port_name, false, ALSA_MIDI, addr);
+ if (!m->get_port(port_name))
+ m->add_port(create_port(m, port_name, false, addr));
}
- m->show();
+ m->resize();
+ m_app->canvas()->add_module(m);
}
}
}
@@ -248,16 +276,18 @@ AlsaDriver::refresh_connections()
assert(is_attached());
assert(m_seq);
- PatchageModule* m = NULL;
- PatchagePort* p = NULL;
+ boost::shared_ptr<PatchageModule> m;
+ boost::shared_ptr<PatchagePort> p;
for (ModuleMap::iterator i = m_canvas->modules().begin();
i != m_canvas->modules().end(); ++i) {
- m = (PatchageModule*)((*i).second);
- for (PortList::iterator j = m->ports().begin(); j != m->ports().end(); ++j) {
- p = (PatchagePort*)(*j);
- if (p->type() == ALSA_MIDI)
- add_connections(p);
+ m = boost::dynamic_pointer_cast<PatchageModule>((*i).second);
+ if (m) {
+ for (PortVector::const_iterator j = m->ports().begin(); j != m->ports().end(); ++j) {
+ p = boost::dynamic_pointer_cast<PatchagePort>(*j);
+ if (p->type() == ALSA_MIDI)
+ add_connections(p);
+ }
}
}
}
@@ -266,13 +296,13 @@ AlsaDriver::refresh_connections()
/** Add all connections for the given port.
*/
void
-AlsaDriver::add_connections(PatchagePort* port)
+AlsaDriver::add_connections(boost::shared_ptr<PatchagePort> port)
{
assert(is_attached());
assert(m_seq);
- const snd_seq_addr_t* addr = port->alsa_addr();
- PatchagePort* connected_port = NULL;
+ const snd_seq_addr_t* addr = port->alsa_addr();
+ boost::shared_ptr<PatchagePort> connected_port;
// Fix a problem with duplex->duplex connections (would show up twice)
// No sense doing them all twice anyway..
@@ -287,10 +317,15 @@ AlsaDriver::add_connections(PatchagePort* port)
while(!snd_seq_query_port_subscribers(m_seq, subsinfo)) {
const snd_seq_addr_t* connected_addr = snd_seq_query_subscribe_get_addr(subsinfo);
- connected_port = m_canvas->find_port(connected_addr, !port->is_input());
-
- if (connected_port != NULL) {
- m_canvas->add_connection(port, connected_port);
+ connected_port = m_canvas->find_port(connected_addr);
+
+ if (connected_port) {
+ boost::shared_ptr<Connection> existing = m_canvas->get_connection(port, connected_port);
+ if (existing) {
+ existing->set_flagged(false);
+ } else {
+ m_canvas->add_connection(port, connected_port);
+ }
}
snd_seq_query_subscribe_set_index(subsinfo, snd_seq_query_subscribe_get_index(subsinfo) + 1);
@@ -304,12 +339,12 @@ AlsaDriver::add_connections(PatchagePort* port)
* \return Whether connection succeeded.
*/
bool
-AlsaDriver::connect(const PatchagePort* const src_port, const PatchagePort* const dst_port)
+AlsaDriver::connect(boost::shared_ptr<PatchagePort> src_port, boost::shared_ptr<PatchagePort> dst_port)
{
const snd_seq_addr_t* src = src_port->alsa_addr();
const snd_seq_addr_t* dst = dst_port->alsa_addr();
- bool result = false;
+ bool result = true;
if (src && dst) {
snd_seq_port_subscribe_t* subs;
@@ -332,6 +367,13 @@ AlsaDriver::connect(const PatchagePort* const src_port, const PatchagePort* cons
result = false;
}
}
+
+ if (result)
+ m_app->status_message(string("[ALSA] Connected ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
+ else
+ m_app->status_message(string("[ALSA] Unable to connect ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
return (!result);
}
@@ -342,12 +384,12 @@ AlsaDriver::connect(const PatchagePort* const src_port, const PatchagePort* cons
* \return Whether disconnection succeeded.
*/
bool
-AlsaDriver::disconnect(const PatchagePort* const src_port, const PatchagePort* const dst_port)
+AlsaDriver::disconnect(boost::shared_ptr<PatchagePort> src_port, boost::shared_ptr<PatchagePort> dst_port)
{
const snd_seq_addr_t* src = src_port->alsa_addr();
const snd_seq_addr_t* dst = dst_port->alsa_addr();
- bool result = false;
+ bool result = true;
snd_seq_port_subscribe_t* subs;
snd_seq_port_subscribe_malloc(&subs);
@@ -368,6 +410,13 @@ AlsaDriver::disconnect(const PatchagePort* const src_port, const PatchagePort* c
cerr << "Alsa unsubscription failed: " << snd_strerror(ret) << endl;
result = false;
}
+
+ if (result)
+ m_app->status_message(string("[ALSA] Disconnected ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
+ else
+ m_app->status_message(string("[ALSA] Unable to disconnect ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
return (!result);
}
diff --git a/src/AlsaDriver.h b/src/AlsaDriver.h
index d6e910f..27ddee9 100644
--- a/src/AlsaDriver.h
+++ b/src/AlsaDriver.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -45,8 +45,11 @@ public:
void refresh();
- bool connect(const PatchagePort* const src_port, const PatchagePort* const dst_port);
- bool disconnect(const PatchagePort* const src_port, const PatchagePort* const dst_port);
+ bool connect(boost::shared_ptr<PatchagePort> src_port,
+ boost::shared_ptr<PatchagePort> dst_port);
+
+ bool disconnect(boost::shared_ptr<PatchagePort> src_port,
+ boost::shared_ptr<PatchagePort> dst_port);
PatchageFlowCanvas* canvas() { return m_canvas; }
@@ -54,12 +57,15 @@ private:
void refresh_ports();
void refresh_connections();
- void add_connections(PatchagePort* port);
+ void add_connections(boost::shared_ptr<PatchagePort> port);
bool create_refresh_port();
static void* refresh_main(void* me);
void m_refresh_main();
+ boost::shared_ptr<PatchagePort> create_port(boost::shared_ptr<PatchageModule> parent,
+ const string& name, bool is_input, snd_seq_addr_t addr);
+
Patchage* m_app;
PatchageFlowCanvas* m_canvas;
diff --git a/src/Driver.h b/src/Driver.h
index 1b7ad80..1945286 100644
--- a/src/Driver.h
+++ b/src/Driver.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -17,6 +17,9 @@
#ifndef DRIVER_H
#define DRIVER_H
+#include <boost/shared_ptr.hpp>
+#include <sigc++/sigc++.h>
+
class PatchagePort;
/** Trival driver base class */
@@ -30,19 +33,20 @@ public:
virtual void refresh() = 0;
- virtual bool connect(const PatchagePort* src_port,
- const PatchagePort* dst_port)
- { return false; }
+ virtual bool connect(boost::shared_ptr<PatchagePort> src_port,
+ boost::shared_ptr<PatchagePort> dst_port) = 0;
- virtual bool disconnect(const PatchagePort* src_port,
- const PatchagePort* dst_port)
- { return false; }
+ virtual bool disconnect(boost::shared_ptr<PatchagePort> src_port,
+ boost::shared_ptr<PatchagePort> dst_port) = 0;
- /** Returns whether or not a refresh is required. */
- bool is_dirty() const { return m_is_dirty; }
+ /** Returns whether or not a refresh is required (pending). */
+ inline bool is_dirty() const { return m_is_dirty; }
/** Clear 'dirty' status after a refresh. */
- void undirty() { m_is_dirty = false; }
+ inline void undirty() { m_is_dirty = false; }
+
+ sigc::signal<void> signal_attached;
+ sigc::signal<void> signal_detached;
protected:
Driver() : m_is_dirty(false) {}
diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp
index c40e589..8147678 100644
--- a/src/JackDriver.cpp
+++ b/src/JackDriver.cpp
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -24,7 +24,7 @@
#include "Patchage.h"
#include "PatchageModule.h"
-using std::cerr; using std::endl; using std::cout;
+using std::cerr; using std::endl;
using std::string;
using namespace LibFlowCanvas;
@@ -49,30 +49,25 @@ JackDriver::~JackDriver()
void
JackDriver::attach(bool launch_daemon)
{
- cout << "Connecting to Jack... ";
- cout.flush();
-
- if (m_client != NULL) {
- cout << "already connected. " << endl;
+ // Already connected
+ if (m_client)
return;
- }
jack_options_t options = (!launch_daemon) ? JackNoStartServer : JackNullOption;
m_client = jack_client_open("Patchage", options, NULL);
if (m_client == NULL) {
- cout << "Failed" << endl;
+ m_app->status_message("[JACK] Unable to attach");
} else {
+ jack_on_shutdown(m_client, jack_shutdown_cb, this);
jack_set_port_registration_callback(m_client, jack_port_registration_cb, this);
jack_set_graph_order_callback(m_client, jack_graph_order_cb, this);
- jack_on_shutdown(m_client, jack_shutdown_cb, this);
- jack_activate(m_client);
-
- cout << "Connected" << endl;
-
- m_canvas->destroy();
-
m_is_dirty = true;
+
+ jack_activate(m_client);
+
+ signal_attached.emit();
+ m_app->status_message("[JACK] Attached");
}
}
@@ -84,33 +79,88 @@ JackDriver::detach()
jack_deactivate(m_client);
jack_client_close(m_client);
m_client = NULL;
- cout << "Disconnected from Jack" << endl;
+ signal_detached.emit();
+ destroy_all_ports();
+ m_app->status_message("[JACK] Detached");
+ }
+}
+
+
+/** Destroy all JACK (canvas) ports.
+ */
+void
+JackDriver::destroy_all_ports()
+{
+ ModuleMap modules = m_canvas->modules(); // copy
+ for (ModuleMap::iterator m = modules.begin(); m != modules.end(); ++m) {
+ PortVector ports = m->second->ports(); // copy
+ for (PortVector::iterator p = ports.begin(); p != ports.end(); ++p) {
+ boost::shared_ptr<PatchagePort> port = boost::dynamic_pointer_cast<PatchagePort>(*p);
+ if (port && port->type() == JACK_AUDIO || port->type() == JACK_MIDI) {
+ port.reset();
+ }
+ }
+
+ if (m->second->ports().empty())
+ m->second.reset();
}
}
+boost::shared_ptr<PatchagePort>
+JackDriver::create_port(boost::shared_ptr<PatchageModule> parent, jack_port_t* port)
+{
+ const char* const type_str = jack_port_type(port);
+ PortType port_type;
+ if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) {
+ port_type = JACK_MIDI;
+ } else if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) {
+ port_type = JACK_AUDIO;
+ } else {
+ cerr << "WARNING: " << jack_port_name(port) << " has unknown type \'" << type_str << "\'" << endl;
+ return boost::shared_ptr<PatchagePort>();
+ }
+
+ boost::shared_ptr<PatchagePort> ret(
+ new PatchagePort(parent, port_type, jack_port_short_name(port),
+ (jack_port_flags(port) & JackPortIsInput),
+ m_app->state_manager()->get_port_color(port_type)));
+
+ return ret;
+}
+
+
/** Refresh all Jack audio ports/connections.
* To be called from GTK thread only.
*/
void
JackDriver::refresh()
{
- if (m_client == NULL)
+ m_mutex.lock();
+
+ if (m_client == NULL) {
+ // Shutdown
+ if (m_is_dirty) {
+ signal_detached.emit();
+ destroy_all_ports();
+ }
+ m_is_dirty = false;
+ m_mutex.unlock();
return;
-
+ }
+
const char** ports;
jack_port_t* port;
-
+
ports = jack_get_ports(m_client, NULL, NULL, 0); // get all existing ports
string client1_name;
string port1_name;
string client2_name;
string port2_name;
- PatchageModule* m = NULL;
-
+
// Add all ports
- if (ports != NULL)
+ if (ports)
for (int i=0; ports[i]; ++i) {
port = jack_port_by_name(m_client, ports[i]);
client1_name = ports[i];
@@ -118,9 +168,9 @@ JackDriver::refresh()
ModuleType type = InputOutput;
//if (m_app->state_manager()->get_module_split(client1_name)
- // || jack_port_flags(port) & JackPortIsTerminal) {
+ // || jack_port_flags(port) & JackPortIsTerminal)
if (m_app->state_manager()->get_module_split(client1_name,
- (jack_port_flags(port) & JackPortIsTerminal))) {
+ (jack_port_flags(port) & JackPortIsTerminal))) {
if (jack_port_flags(port) & JackPortIsInput) {
type = Input;
} else {
@@ -128,56 +178,84 @@ JackDriver::refresh()
}
}
- m = (PatchageModule*)m_canvas->find_module(client1_name, type);
+ boost::shared_ptr<PatchageModule> m = m_canvas->find_module(client1_name, type);
- if (m == NULL) {
- m = new PatchageModule(m_app, client1_name, type);
+ if (!m) {
+ m = boost::shared_ptr<PatchageModule>(new PatchageModule(m_app, client1_name, type));
m->load_location();
m->store_location();
- m->show();
+ m_app->canvas()->add_module(m);
}
-
+
// FIXME: leak? jack docs don't say
const char* const type_str = jack_port_type(port);
- PortType port_type = JACK_AUDIO;
- if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE))
+ PortType port_type;
+ if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) {
port_type = JACK_MIDI;
- else if (strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE))
- throw "Unknown JACK port type?";
+ } else if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) {
+ port_type = JACK_AUDIO;
+ } else {
+ cerr << "WARNING: " << ports[i] << " has unknown type \'" << type_str << "\'" << endl;
+ continue;
+ }
- m->add_patchage_port(jack_port_short_name(port),
- (jack_port_flags(port) & JackPortIsInput),
- port_type);
+ if (!m->get_port(jack_port_short_name(port))) {
+ m->add_port(create_port(m, port));
+ }
+
+ m->resize();
}
+
+ // Remove any since-removed ports
+ for (list<string>::iterator i = m_removed_ports.begin(); i != m_removed_ports.end(); ++i) {
+ const string module_name = (*i).substr(0, i->find(":"));
+ const string port_name = (*i).substr(i->find(":")+1);
+
+ for (ModuleMap::iterator m = m_canvas->modules().begin(); m != m_canvas->modules().end(); ++m) {
+ if (m->second->name() == module_name)
+ m->second->remove_port(port_name);
+ }
+ }
+
+
// Add all connections
- if (ports != NULL) {
- for (int i=0; ports[i]; ++i) {
- port = jack_port_by_name(m_client, ports[i]);
- const char** connected_ports = jack_port_get_all_connections(m_client, port);
-
- if (connected_ports != NULL)
+ if (ports)
+ for (int i=0; ports[i]; ++i) {
+ port = jack_port_by_name(m_client, ports[i]);
+ const char** connected_ports = jack_port_get_all_connections(m_client, port);
+
+ if (connected_ports) {
for (int j=0; connected_ports[j]; ++j) {
client1_name = ports[i];
port1_name = client1_name.substr(client1_name.find(':')+1);
client1_name = client1_name.substr(0, client1_name.find(':'));
-
+
client2_name = connected_ports[j];
port2_name = client2_name.substr(client2_name.find(':')+1);
client2_name = client2_name.substr(0, client2_name.find(':'));
-
- Port* const port1 = m_canvas->get_port(client1_name, port1_name);
- Port* const port2 = m_canvas->get_port(client2_name, port2_name);
-
- if (port1 && port2)
- m_canvas->add_connection(port1, port2);
+
+ boost::shared_ptr<Port> port1 = m_canvas->get_port(client1_name, port1_name);
+ boost::shared_ptr<Port> port2 = m_canvas->get_port(client2_name, port2_name);
+
+ if (port1 && port2) {
+ boost::shared_ptr<Connection> existing = m_canvas->get_connection(port1, port2);
+ if (existing) {
+ existing->set_flagged(false);
+ } else {
+ m_canvas->add_connection(port1, port2);
+ }
+ }
}
+
free(connected_ports);
- }
- free(ports);
+ }
}
+ free(ports);
undirty();
+
+ m_mutex.unlock();
}
@@ -186,22 +264,19 @@ JackDriver::refresh()
* \return Whether connection succeeded.
*/
bool
-JackDriver::connect(const PatchagePort* const src_port, const PatchagePort* const dst_port)
+JackDriver::connect(boost::shared_ptr<PatchagePort> src_port, boost::shared_ptr<PatchagePort> dst_port)
{
if (m_client == NULL)
return false;
int result = jack_connect(m_client, src_port->full_name().c_str(), dst_port->full_name().c_str());
- string msg;
-
- if (result == 0) {
- msg = "Successfully connected jack ports";
- } else {
- msg = "Unable to connect ";
- msg += src_port->full_name() + " -> " + dst_port->full_name();
- }
- m_app->status_message(msg);
+ if (result == 0)
+ m_app->status_message(string("[JACK] Connected ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
+ else
+ m_app->status_message(string("[JACK] Unable to connect ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
return (!result);
}
@@ -212,53 +287,74 @@ JackDriver::connect(const PatchagePort* const src_port, const PatchagePort* cons
* \return Whether disconnection succeeded.
*/
bool
-JackDriver::disconnect(const PatchagePort* const src_port, const PatchagePort* const dst_port)
+JackDriver::disconnect(boost::shared_ptr<PatchagePort> const src_port, boost::shared_ptr<PatchagePort> const dst_port)
{
if (m_client == NULL)
return false;
int result = jack_disconnect(m_client, src_port->full_name().c_str(), dst_port->full_name().c_str());
- string msg;
-
- if (result == 0) {
- msg = "Successfully disconnected jack ports";
- } else {
- msg = "Unable to disconnect ";
- msg += src_port->full_name() + " -> " + dst_port->full_name();
- }
- m_app->status_message(msg);
+ if (result == 0)
+ m_app->status_message(string("[JACK] Disconnected ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
+ else
+ m_app->status_message(string("[JACK] Unable to disconnect ")
+ + src_port->full_name() + " -> " + dst_port->full_name());
return (!result);
}
void
-JackDriver::jack_port_registration_cb(jack_port_id_t port_id, int registered, void* me)
+JackDriver::jack_port_registration_cb(jack_port_id_t port_id, int /*registered*/, void* jack_driver)
{
- assert(me != NULL);
- assert(((JackDriver*)me)->m_client != NULL);
- ((JackDriver*)me)->m_is_dirty = true;
+ assert(jack_driver);
+ JackDriver* me = reinterpret_cast<JackDriver*>(jack_driver);
+ assert(me->m_client);
+
+ jack_port_t* const port = jack_port_by_id(me->m_client, port_id);
+ const string full_name = jack_port_name(port);
+
+ //(me->m_mutex).lock();
+
+ /*if (registered) {
+ me->m_added_ports.push_back(full_name);
+ } else {
+ me->m_removed_ports.push_back(full_name);
+ }*/
+
+ me->m_is_dirty = true;
+
+ //(me->m_mutex).unlock();
}
int
-JackDriver::jack_graph_order_cb(void* me)
+JackDriver::jack_graph_order_cb(void* jack_driver)
{
- assert(me != NULL);
- assert(((JackDriver*)me)->m_client != NULL);
- ((JackDriver*)me)->m_is_dirty = true;
+ assert(jack_driver);
+ JackDriver* me = reinterpret_cast<JackDriver*>(jack_driver);
+ assert(me->m_client);
+
+ //(me->m_mutex).lock();
+ me->m_is_dirty = true;
+ //(me->m_mutex).unlock();
return 0;
}
void
-JackDriver::jack_shutdown_cb(void* me)
+JackDriver::jack_shutdown_cb(void* jack_driver)
{
- assert(me != NULL);
- ((JackDriver*)me)->m_client = NULL;
- ((JackDriver*)me)->m_is_dirty = true;
+ assert(jack_driver);
+ JackDriver* me = reinterpret_cast<JackDriver*>(jack_driver);
+ assert(me->m_client);
+
+ //(me->m_mutex).lock();
+ me->m_client = NULL;
+ me->m_is_dirty = true;
+ //(me->m_mutex).unlock();
}
diff --git a/src/JackDriver.h b/src/JackDriver.h
index 6b69900..db74f77 100644
--- a/src/JackDriver.h
+++ b/src/JackDriver.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -18,12 +18,15 @@
#define JACKDRIVER_H
#include <iostream>
-#include <jack/jack.h>
#include <string>
+#include <boost/shared_ptr.hpp>
+#include <jack/jack.h>
+#include "Mutex.h"
#include "Driver.h"
class Patchage;
class PatchageFlowCanvas;
class PatchagePort;
+class PatchageModule;
using std::string;
@@ -45,13 +48,11 @@ public:
bool is_attached() const { return (m_client != NULL); }
void refresh();
- bool connect(const PatchagePort* const src_port, const PatchagePort* const dst_port);
- bool disconnect(const PatchagePort* const src_port, const PatchagePort* const dst_port);
- /*bool connect(const string& src_module_name, const string& src_port_name,
- const string& dst_module_name, const string& dest_port_name);
-
- bool disconnect(const string& src_module_name, const string& src_port_name,
- const string& dst_module_name, const string& dest_port_name);*/
+ bool connect(boost::shared_ptr<PatchagePort> src,
+ boost::shared_ptr<PatchagePort> dst);
+
+ bool disconnect(boost::shared_ptr<PatchagePort> src,
+ boost::shared_ptr<PatchagePort> dst);
private:
Patchage* m_app;
@@ -59,6 +60,16 @@ private:
jack_client_t* m_client;
+ Mutex m_mutex;
+
+ list<string> m_added_ports;
+ list<string> m_removed_ports;
+
+ boost::shared_ptr<PatchagePort> create_port(boost::shared_ptr<PatchageModule> parent,
+ jack_port_t* port);
+
+ void destroy_all_ports();
+
static void jack_port_registration_cb(jack_port_id_t port_id, int registered, void* controller);
static int jack_graph_order_cb(void* controller);
static void jack_shutdown_cb(void* controller);
diff --git a/src/LashDriver.cpp b/src/LashDriver.cpp
index c4a89b2..7989aa9 100644
--- a/src/LashDriver.cpp
+++ b/src/LashDriver.cpp
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -44,25 +44,22 @@ LashDriver::~LashDriver()
void
LashDriver::attach(bool launch_daemon)
{
- cout << "Connecting to Lash... ";
- cout.flush();
-
- if (m_client != NULL) {
- cout << "already connected." << endl;
+ // Already connected
+ if (m_client)
return;
- }
int lash_flags = LASH_Config_File;
if (launch_daemon)
lash_flags |= LASH_No_Start_Server;
m_client = lash_init(m_args, PACKAGE_NAME, lash_flags, LASH_PROTOCOL(2, 0));
if (m_client == NULL) {
- cout << "Failed. Session management will not occur." << endl;
+ m_app->status_message("[LASH] Unable to attach to server");
} else {
lash_event_t* event = lash_event_new_with_type(LASH_Client_Name);
lash_event_set_string(event, "Patchage");
lash_send_event(m_client, event);
- cout << "Connected" << endl;
+ signal_attached.emit();
+ m_app->status_message("[LASH] Attached");
}
}
@@ -72,7 +69,8 @@ LashDriver::detach()
{
// FIXME: send some notification that we're gone??
m_client = NULL;
- cout << "Disconnected from Lash" << endl;
+ m_app->status_message("[LASH] Detached");
+ signal_detached.emit();
}
diff --git a/src/LashDriver.h b/src/LashDriver.h
index 742c249..9f361d7 100644
--- a/src/LashDriver.h
+++ b/src/LashDriver.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -32,6 +32,12 @@ public:
void detach();
bool is_attached() const { return lash_enabled(m_client); }
+
+ bool connect(boost::shared_ptr<PatchagePort>, boost::shared_ptr<PatchagePort>)
+ { return false; }
+
+ bool disconnect(boost::shared_ptr<PatchagePort>, boost::shared_ptr<PatchagePort>)
+ { return false; }
void refresh() {}
diff --git a/src/Makefile.am b/src/Makefile.am
index 6e6eb5f..81529ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ dist_sharefiles_DATA = patchage.glade
bin_PROGRAMS = patchage
patchage_SOURCES = \
main.cpp \
+ Mutex.h \
Patchage.h \
Patchage.cpp \
StateManager.h \
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index d6e3a55..0a37e58 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -1,11 +1,11 @@
-/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
+/* This file is part of Patchage. Copyright (C) 2006 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -58,7 +58,7 @@ Patchage::Patchage(int argc, char** argv)
m_lash_driver = new LashDriver(this, argc, argv);
#endif
- Glib::RefPtr<Gnome::Glade::Xml> refXml;
+ Glib::RefPtr<Gnome::Glade::Xml> xml;
// Check for the .glade file in current directory
string glade_filename = "./patchage.glade";
@@ -77,57 +77,59 @@ Patchage::Patchage(int argc, char** argv)
}
try {
- refXml = Gnome::Glade::Xml::create(glade_filename);
+ xml = Gnome::Glade::Xml::create(glade_filename);
} catch(const Gnome::Glade::XmlError& ex) {
std::cerr << ex.what() << std::endl;
throw;
}
- refXml->get_widget("patchage_win", m_main_window);
- refXml->get_widget("about_win", m_about_window);
- refXml->get_widget("about_project_label", m_about_project_label);
- refXml->get_widget("launch_jack_menuitem", m_menu_jack_launch);
- refXml->get_widget("connect_to_jack_menuitem", m_menu_jack_connect);
- refXml->get_widget("disconnect_from_jack_menuitem", m_menu_jack_disconnect);
+ xml->get_widget("patchage_win", m_main_window);
+ xml->get_widget("about_win", m_about_window);
+ xml->get_widget("launch_jack_menuitem", m_menu_jack_launch);
+ xml->get_widget("connect_to_jack_menuitem", m_menu_jack_connect);
+ xml->get_widget("disconnect_from_jack_menuitem", m_menu_jack_disconnect);
#ifdef HAVE_LASH
- refXml->get_widget("launch_lash_menuitem", m_menu_lash_launch);
- refXml->get_widget("connect_to_lash_menuitem", m_menu_lash_connect);
- refXml->get_widget("disconnect_from_lash_menuitem", m_menu_lash_disconnect);
+ xml->get_widget("launch_lash_menuitem", m_menu_lash_launch);
+ xml->get_widget("connect_to_lash_menuitem", m_menu_lash_connect);
+ xml->get_widget("disconnect_from_lash_menuitem", m_menu_lash_disconnect);
#endif
#ifdef HAVE_ALSA
- refXml->get_widget("connect_to_alsa_menuitem", m_menu_alsa_connect);
- refXml->get_widget("disconnect_from_alsa_menuitem", m_menu_alsa_disconnect);
+ xml->get_widget("connect_to_alsa_menuitem", m_menu_alsa_connect);
+ xml->get_widget("disconnect_from_alsa_menuitem", m_menu_alsa_disconnect);
#endif
- refXml->get_widget("file_save_menuitem", m_menu_file_save);
- refXml->get_widget("file_quit_menuitem", m_menu_file_quit);
- refXml->get_widget("view_refresh_menuitem", m_menu_view_refresh);
- refXml->get_widget("help_about_menuitem", m_menu_help_about);
- refXml->get_widget("canvas_scrolledwindow", m_canvas_scrolledwindow);
- refXml->get_widget("zoom_scale", m_zoom_slider);
- refXml->get_widget("about_close_button", m_about_close_button);
- refXml->get_widget("status_lab", m_status_label);
+ xml->get_widget("store_positions_menuitem", m_menu_store_positions);
+ xml->get_widget("file_quit_menuitem", m_menu_file_quit);
+ xml->get_widget("view_refresh_menuitem", m_menu_view_refresh);
+ xml->get_widget("help_about_menuitem", m_menu_help_about);
+ xml->get_widget("canvas_scrolledwindow", m_canvas_scrolledwindow);
+ xml->get_widget("zoom_scale", m_zoom_slider);
+ xml->get_widget("status_text", m_status_text);
+ xml->get_widget("main_paned", m_main_paned);
+ xml->get_widget("zoom_full_but", m_zoom_full_button);
+ xml->get_widget("zoom_normal_but", m_zoom_normal_button);
- m_main_window->resize(
- static_cast<int>(m_state_manager->get_window_size().x),
- static_cast<int>(m_state_manager->get_window_size().y));
-
- m_main_window->move(
- static_cast<int>(m_state_manager->get_window_location().x),
- static_cast<int>(m_state_manager->get_window_location().y));
+ update_state();
m_canvas_scrolledwindow->add(*m_canvas);
//m_canvas_scrolledwindow->signal_event().connect(sigc::mem_fun(m_canvas, &FlowCanvas::scroll_event_handler));
m_canvas->scroll_to(static_cast<int>(m_canvas->width()/2 - 320),
static_cast<int>(m_canvas->height()/2 - 240)); // FIXME: hardcoded
- m_canvas->show();
- // Idle callback, check if we need to refresh (every 250msec)
- Glib::signal_timeout().connect(sigc::mem_fun(this, &Patchage::idle_callback), 250);
+ // Idle callback, check if we need to refresh
+ Glib::signal_timeout().connect(sigc::mem_fun(this, &Patchage::idle_callback), 100);
+
+ m_zoom_slider->signal_value_changed().connect(sigc::mem_fun(this, &Patchage::zoom_changed));
+ m_zoom_normal_button->signal_clicked().connect(sigc::bind(
+ sigc::mem_fun(this, &Patchage::zoom), 1.0));
+
+ m_menu_jack_launch->signal_activate().connect(sigc::bind(
+ sigc::mem_fun(m_jack_driver, &JackDriver::attach), true));
+
+ m_menu_jack_connect->signal_activate().connect(sigc::bind(
+ sigc::mem_fun(m_jack_driver, &JackDriver::attach), false));
- m_zoom_slider->signal_value_changed().connect( sigc::mem_fun(this, &Patchage::zoom_changed));
- m_menu_jack_launch->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_jack_launch));
- m_menu_jack_connect->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_jack_connect));
- m_menu_jack_disconnect->signal_activate().connect(sigc::mem_fun(this, &Patchage::menu_jack_disconnect));
+ m_menu_jack_disconnect->signal_activate().connect(sigc::mem_fun(m_jack_driver, &JackDriver::detach));
+
#ifdef HAVE_LASH
m_menu_lash_launch->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_lash_launch));
m_menu_lash_connect->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_lash_connect));
@@ -135,26 +137,29 @@ Patchage::Patchage(int argc, char** argv)
#endif
m_menu_alsa_connect->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_alsa_connect));
m_menu_alsa_disconnect->signal_activate().connect(sigc::mem_fun(this, &Patchage::menu_alsa_disconnect));
- m_menu_file_save->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_file_save));
+ m_menu_store_positions->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_store_positions));
m_menu_file_quit->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_file_quit));
m_menu_view_refresh->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_view_refresh));
m_menu_help_about->signal_activate().connect( sigc::mem_fun(this, &Patchage::menu_help_about));
- m_about_close_button->signal_clicked().connect( sigc::mem_fun(this, &Patchage::close_about));
- //_about_project_label->use_markup(true);
- m_about_project_label->set_markup("<span size=\"xx-large\" weight=\"bold\">Patchage " PACKAGE_VERSION "</span>");
+ attach_menu_items();
+ m_main_paned->set_position(m_main_paned->get_height() - 20);
+
+ m_canvas->show();
}
Patchage::~Patchage()
{
+ delete m_jack_driver;
+#ifdef HAVE_ALSA
+ delete m_alsa_driver;
+#endif
#ifdef HAVE_LASH
delete m_lash_driver;
#endif
- delete m_jack_driver;
- delete m_alsa_driver;
- delete m_canvas;
delete m_state_manager;
+ delete m_canvas;
}
@@ -170,7 +175,6 @@ Patchage::attach()
m_alsa_driver->attach();
#endif
- update_menu_items();
menu_view_refresh();
}
@@ -178,19 +182,20 @@ Patchage::attach()
bool
Patchage::idle_callback()
{
- // FIXME: no need to destroy the whole canvas every time
- if (m_refresh || (m_jack_driver && m_jack_driver->is_dirty())
+ bool refresh = m_refresh;
+
+ refresh = refresh || (m_jack_driver && m_jack_driver->is_dirty());
#ifdef HAVE_ALSA
- || (m_alsa_driver && m_alsa_driver->is_dirty())
+ refresh = refresh || (m_alsa_driver && m_alsa_driver->is_dirty());
#endif
- ) {
- m_canvas->destroy();
+
+ if (refresh) {
+ m_canvas->flag_all_connections();
+
m_jack_driver->refresh();
#ifdef HAVE_ALSA
m_alsa_driver->refresh();
#endif
- update_menu_items();
- m_refresh = false;
}
#ifdef HAVE_LASH
@@ -198,21 +203,31 @@ Patchage::idle_callback()
m_lash_driver->process_events();
#endif
+ if (refresh) {
+ m_canvas->destroy_all_flagged_connections();
+ m_refresh = false;
+ }
+
return true;
}
void
-Patchage::zoom_changed()
+Patchage::zoom(double z)
{
- const double z = m_zoom_slider->get_value();
-
m_canvas->set_zoom(z);
m_state_manager->set_zoom(z);
}
void
+Patchage::zoom_changed()
+{
+ zoom(m_zoom_slider->get_value());
+}
+
+
+void
Patchage::update_state()
{
for (ModuleMap::iterator i = m_canvas->modules().begin(); i != m_canvas->modules().end(); ++i)
@@ -236,10 +251,12 @@ Patchage::update_state()
void
Patchage::status_message(const string& msg)
{
- m_status_label->set_text(msg);
-}
-
+ if (m_status_text->get_buffer()->size() > 0)
+ m_status_text->get_buffer()->insert(m_status_text->get_buffer()->end(), "\n");
+ m_status_text->get_buffer()->insert(m_status_text->get_buffer()->end(), msg);
+ m_status_text->scroll_to_mark(m_status_text->get_buffer()->get_insert(), 0);
+}
/** Update the sensitivity status of menus to reflect the present.
@@ -247,61 +264,53 @@ Patchage::status_message(const string& msg)
* (eg. disable "Connect to Jack" when Patchage is already connected to Jack)
*/
void
-Patchage::update_menu_items()
+Patchage::attach_menu_items()
{
- // Update Jack menu items
- const bool jack_attached = m_jack_driver->is_attached();
- m_menu_jack_launch->set_sensitive(!jack_attached);
- m_menu_jack_connect->set_sensitive(!jack_attached);
- m_menu_jack_disconnect->set_sensitive(jack_attached);
+ m_lash_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_launch, &Gtk::MenuItem::set_sensitive), false));
+ m_lash_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_connect, &Gtk::MenuItem::set_sensitive), false));
+ m_lash_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_disconnect, &Gtk::MenuItem::set_sensitive), true));
- // Update Lash menu items
-#ifdef HAVE_LASH
- const bool lash_attached = m_lash_driver->is_attached();
- m_menu_lash_launch->set_sensitive(!lash_attached);
- m_menu_lash_connect->set_sensitive(!lash_attached);
- m_menu_lash_disconnect->set_sensitive(lash_attached);
-#endif
-
-#ifdef HAVE_ALSA
- // Update Alsa menu items
- const bool alsa_attached = m_alsa_driver->is_attached();
- m_menu_alsa_connect->set_sensitive(!alsa_attached);
- m_menu_alsa_disconnect->set_sensitive(alsa_attached);
-#endif
-}
-
-
-void
-Patchage::menu_jack_launch()
-{
- m_jack_driver->attach(true);
- update_menu_items();
-}
-
-
-void
-Patchage::menu_jack_connect()
-{
- m_jack_driver->attach(false);
- update_menu_items();
+ m_lash_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_launch, &Gtk::MenuItem::set_sensitive), true));
+ m_lash_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_connect, &Gtk::MenuItem::set_sensitive), true));
+ m_lash_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_lash_disconnect, &Gtk::MenuItem::set_sensitive), false));
+
+ m_jack_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_launch, &Gtk::MenuItem::set_sensitive), false));
+ m_jack_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_connect, &Gtk::MenuItem::set_sensitive), false));
+ m_jack_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_disconnect, &Gtk::MenuItem::set_sensitive), true));
+
+ m_jack_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_launch, &Gtk::MenuItem::set_sensitive), true));
+ m_jack_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_connect, &Gtk::MenuItem::set_sensitive), true));
+ m_jack_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_jack_disconnect, &Gtk::MenuItem::set_sensitive), false));
+
+ m_alsa_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_alsa_connect, &Gtk::MenuItem::set_sensitive), false));
+ m_alsa_driver->signal_attached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_alsa_disconnect, &Gtk::MenuItem::set_sensitive), true));
+
+ m_alsa_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_alsa_connect, &Gtk::MenuItem::set_sensitive), true));
+ m_alsa_driver->signal_detached.connect(sigc::bind(
+ sigc::mem_fun(m_menu_alsa_disconnect, &Gtk::MenuItem::set_sensitive), false));
}
-void
-Patchage::menu_jack_disconnect()
-{
- m_jack_driver->detach();
- menu_view_refresh();
- update_menu_items();
-}
-
#ifdef HAVE_LASH
void
Patchage::menu_lash_launch()
{
m_lash_driver->attach(true);
- update_menu_items();
}
@@ -309,7 +318,6 @@ void
Patchage::menu_lash_connect()
{
m_lash_driver->attach(false);
- update_menu_items();
}
@@ -317,7 +325,6 @@ void
Patchage::menu_lash_disconnect()
{
m_lash_driver->detach();
- update_menu_items();
}
#endif
@@ -326,7 +333,6 @@ void
Patchage::menu_alsa_connect()
{
m_alsa_driver->attach(false);
- update_menu_items();
}
@@ -335,12 +341,11 @@ Patchage::menu_alsa_disconnect()
{
m_alsa_driver->detach();
menu_view_refresh();
- update_menu_items();
}
#endif
void
-Patchage::menu_file_save()
+Patchage::menu_store_positions()
{
store_window_location();
m_state_manager->save(m_settings_filename);
@@ -363,7 +368,6 @@ Patchage::menu_view_refresh()
{
assert(m_canvas);
- // FIXME: rebuilding the entire canvas each time is garbage
m_canvas->destroy();
if (m_jack_driver)
@@ -383,13 +387,6 @@ Patchage::menu_help_about()
}
-void
-Patchage::close_about()
-{
- m_about_window->hide();
-}
-
-
/** Update the stored window location and size in the StateManager (in memory).
*/
void
diff --git a/src/Patchage.h b/src/Patchage.h
index f686e49..c7a3e0e 100644
--- a/src/Patchage.h
+++ b/src/Patchage.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -57,16 +57,13 @@ public:
inline void queue_refresh() { m_refresh = true; }
protected:
- void update_menu_items();
+ void attach_menu_items();
- void menu_jack_launch();
- void menu_jack_connect();
- void menu_jack_disconnect();
- void menu_file_save();
+ void menu_store_positions();
void menu_file_quit();
void menu_view_refresh();
void menu_help_about();
- void close_about();
+ void zoom(double z);
void zoom_changed();
bool idle_callback();
@@ -98,19 +95,20 @@ protected:
bool m_refresh;
Gtk::Window* m_main_window;
- Gtk::Window* m_about_window;
- Gtk::Label* m_about_project_label;
+ Gtk::AboutDialog* m_about_window;
Gtk::MenuItem* m_menu_jack_launch;
Gtk::MenuItem* m_menu_jack_connect;
Gtk::MenuItem* m_menu_jack_disconnect;
- Gtk::MenuItem* m_menu_file_save;
+ Gtk::MenuItem* m_menu_store_positions;
Gtk::MenuItem* m_menu_file_quit;
Gtk::MenuItem* m_menu_view_refresh;
Gtk::MenuItem* m_menu_help_about;
Gtk::ScrolledWindow* m_canvas_scrolledwindow;
Gtk::HScale* m_zoom_slider;
- Gtk::Button* m_about_close_button;
- Gtk::Label* m_status_label;
+ Gtk::TextView* m_status_text;
+ Gtk::Paned* m_main_paned;
+ Gtk::Button* m_zoom_normal_button;
+ Gtk::Button* m_zoom_full_button;
};
#endif // PATCHAGE_H
diff --git a/src/PatchageFlowCanvas.cpp b/src/PatchageFlowCanvas.cpp
index 2b9b19d..7485b6e 100644
--- a/src/PatchageFlowCanvas.cpp
+++ b/src/PatchageFlowCanvas.cpp
@@ -29,73 +29,72 @@ PatchageFlowCanvas::PatchageFlowCanvas(Patchage* app, int width, int height)
}
-PatchageModule*
+boost::shared_ptr<PatchageModule>
PatchageFlowCanvas::find_module(const string& name, ModuleType type)
{
- PatchageModule* pm = NULL;
-
for (ModuleMap::iterator m = m_modules.begin(); m != m_modules.end(); ++m) {
- pm = (PatchageModule*)(*m).second;
- if (pm->name() == name && pm->type() == type) {
+ boost::shared_ptr<PatchageModule> pm = boost::dynamic_pointer_cast<PatchageModule>((*m).second);
+ if (pm && pm->name() == name && pm->type() == type) {
return pm;
}
}
- return NULL;
+ return boost::shared_ptr<PatchageModule>();
}
-PatchagePort*
-PatchageFlowCanvas::find_port(const snd_seq_addr_t* alsa_addr, bool is_input)
+boost::shared_ptr<PatchagePort>
+PatchageFlowCanvas::find_port(const snd_seq_addr_t* alsa_addr)
{
- PatchagePort* pp = NULL;
+ boost::shared_ptr<PatchagePort> pp;
for (ModuleMap::iterator m = m_modules.begin(); m != m_modules.end(); ++m) {
- for (PortList::iterator p = (*m).second->ports().begin(); p != (*m).second->ports().end(); ++p) {
- pp = (PatchagePort*)(*p);
- if (pp->type() == ALSA_MIDI && pp->alsa_addr()
+ for (PortVector::const_iterator p = (*m).second->ports().begin(); p != (*m).second->ports().end(); ++p) {
+ pp = boost::dynamic_pointer_cast<PatchagePort>(*p);
+ if (pp && pp->type() == ALSA_MIDI && pp->alsa_addr()
&& pp->alsa_addr()->client == alsa_addr->client
&& pp->alsa_addr()->port == alsa_addr->port)
- if (is_input == pp->is_input())
return pp;
}
}
- return NULL;
+ return boost::shared_ptr<PatchagePort>();
}
void
-PatchageFlowCanvas::connect(const Port* port1, const Port* port2)
+PatchageFlowCanvas::connect(boost::shared_ptr<Port> port1, boost::shared_ptr<Port> port2)
{
- PatchagePort* p1 = (PatchagePort*)port1;
- PatchagePort* p2 = (PatchagePort*)port2;
-
+ boost::shared_ptr<PatchagePort> p1 = boost::dynamic_pointer_cast<PatchagePort>(port1);
+ boost::shared_ptr<PatchagePort> p2 = boost::dynamic_pointer_cast<PatchagePort>(port2);
+ if (!p1 || !p2)
+ return;
+
if (p1->type() == JACK_AUDIO && p2->type() == JACK_AUDIO
|| (p1->type() == JACK_MIDI && p2->type() == JACK_MIDI))
- /*m_app->jack_driver()->connect(p1->module()->name(), p1->name(),
- p2->module()->name(), p2->name());*/
m_app->jack_driver()->connect(p1, p2);
else if (p1->type() == ALSA_MIDI && p2->type() == ALSA_MIDI)
m_app->alsa_driver()->connect(p1, p2);
else
- m_app->status_message("Cannot make connection, incompatible port types.");
+ status_message("WARNING: Cannot make connection, incompatible port types.");
}
void
-PatchageFlowCanvas::disconnect(const Port* port1, const Port* port2)
+PatchageFlowCanvas::disconnect(boost::shared_ptr<Port> port1, boost::shared_ptr<Port> port2)
{
- PatchagePort* input = NULL;
- PatchagePort* output = NULL;
+ boost::shared_ptr<PatchagePort> input;
+ boost::shared_ptr<PatchagePort> output;
if (port1->is_input() && !port2->is_input()) {
- input = (PatchagePort*)port1;
- output = (PatchagePort*)port2;
+ input = boost::dynamic_pointer_cast<PatchagePort>(port1);
+ output = boost::dynamic_pointer_cast<PatchagePort>(port2);
} else if (port2->is_input() && !port1->is_input()) {
- input = (PatchagePort*)port2;
- output = (PatchagePort*)port1;
- } else {
- m_app->status_message("Attempt to disconnect two input (or output) ports?? Please report bug.");
+ input = boost::dynamic_pointer_cast<PatchagePort>(port2);
+ output = boost::dynamic_pointer_cast<PatchagePort>(port1);
+ }
+
+ if (!input || !output) {
+ status_message("ERROR: Attempt to disconnect mismatched/unknown ports");
return;
}
@@ -105,13 +104,13 @@ PatchageFlowCanvas::disconnect(const Port* port1, const Port* port2)
else if (input->type() == ALSA_MIDI && output->type() == ALSA_MIDI)
m_app->alsa_driver()->disconnect(output, input);
else
- m_app->status_message("Attempt to disconnect Jack audio port from Alsa Midi port?? Please report bug.");
+ status_message("ERROR: Attempt to disconnect ports with mismatched types");
}
void
PatchageFlowCanvas::status_message(const string& msg)
{
- m_app->status_message(msg);
+ m_app->status_message(string("[Canvas] ").append(msg));
}
diff --git a/src/PatchageFlowCanvas.h b/src/PatchageFlowCanvas.h
index 2636920..a99d658 100644
--- a/src/PatchageFlowCanvas.h
+++ b/src/PatchageFlowCanvas.h
@@ -33,11 +33,11 @@ class PatchageFlowCanvas : public FlowCanvas
public:
PatchageFlowCanvas(Patchage* m_app, int width, int height);
- PatchageModule* find_module(const string& name, ModuleType type);
- PatchagePort* find_port(const snd_seq_addr_t* alsa_addr, bool is_input);
+ boost::shared_ptr<PatchageModule> find_module(const string& name, ModuleType type);
+ boost::shared_ptr<PatchagePort> find_port(const snd_seq_addr_t* alsa_addr);
- void connect(const Port* port1, const Port* port2);
- void disconnect(const Port* port1, const Port* port2);
+ void connect(boost::shared_ptr<Port> port1, boost::shared_ptr<Port> port2);
+ void disconnect(boost::shared_ptr<Port> port1, boost::shared_ptr<Port> port2);
void status_message(const string& msg);
diff --git a/src/PatchageModule.h b/src/PatchageModule.h
index 4400a68..58fa096 100644
--- a/src/PatchageModule.h
+++ b/src/PatchageModule.h
@@ -35,7 +35,7 @@ class PatchageModule : public Module
{
public:
PatchageModule(Patchage* app, const string& title, ModuleType type, double x=0, double y=0)
- : Module(app->canvas(), title, x, y),
+ : Module(*app->canvas(), title, x, y),
m_app(app),
m_type(type)
{
@@ -53,7 +53,7 @@ public:
virtual ~PatchageModule() { }
- virtual void add_patchage_port(const string& port_name, bool is_input, PortType type)
+ /*virtual void add_patchage_port(const string& port_name, bool is_input, PortType type)
{
new PatchagePort(this, type, port_name, is_input, m_app->state_manager()->get_port_color(type));
@@ -68,7 +68,7 @@ public:
port->alsa_addr(addr);
resize();
- }
+ }*/
virtual void load_location() {
@@ -79,8 +79,8 @@ public:
if (loc.x != -1)
move_to(loc.x, loc.y);
else
- move_to((m_canvas->width()/2) - 100 + rand() % 400,
- (m_canvas->height()/2) - 100 + rand() % 400);
+ move_to((m_canvas.width()/2) - 100 + rand() % 400,
+ (m_canvas.height()/2) - 100 + rand() % 400);
}
void split() {
@@ -103,7 +103,7 @@ public:
virtual void show_dialog() {}
virtual void on_right_click(GdkEventButton* ev) { m_menu.popup(ev->button, ev->time); }
virtual void menu_disconnect_all() {
- for (PortList::iterator p = m_ports.begin(); p != m_ports.end(); ++p)
+ for (PortVector::iterator p = m_ports.begin(); p != m_ports.end(); ++p)
(*p)->disconnect_all();
}
diff --git a/src/PatchagePort.h b/src/PatchagePort.h
index 601bce9..7ebc995 100644
--- a/src/PatchagePort.h
+++ b/src/PatchagePort.h
@@ -1,11 +1,11 @@
-/* This file is part of Om. Copyright (C) 2004 Dave Robillard.
+/* This file is part of Patchage. Copyright (C) 2004 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -14,7 +14,6 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
#ifndef PATCHAGEPORT_H
#define PATCHAGEPORT_H
@@ -37,7 +36,7 @@ enum PortType { JACK_AUDIO, JACK_MIDI, ALSA_MIDI };
class PatchagePort : public LibFlowCanvas::Port
{
public:
- PatchagePort(LibFlowCanvas::Module* module, PortType type, const string& name, bool is_input, int color)
+ PatchagePort(boost::shared_ptr<Module> module, PortType type, const string& name, bool is_input, int color)
: Port(module, name, is_input, color),
m_type(type)
{
@@ -53,7 +52,7 @@ public:
{ return (m_type == ALSA_MIDI) ? &m_alsa_addr : NULL; }
/** Returns the full name of this port, as "modulename:portname" */
- string full_name() const { return m_module->name() + ":" + m_name; }
+ string full_name() const { return m_module.lock()->name() + ":" + m_name; }
PortType type() const { return m_type; }
diff --git a/src/StateManager.cpp b/src/StateManager.cpp
index 50429e1..f4bab3a 100644
--- a/src/StateManager.cpp
+++ b/src/StateManager.cpp
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
diff --git a/src/StateManager.h b/src/StateManager.h
index b584308..06843bd 100644
--- a/src/StateManager.h
+++ b/src/StateManager.h
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
diff --git a/src/main.cpp b/src/main.cpp
index 5646b1c..a2da0ef 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,11 +1,11 @@
/* This file is part of Patchage. Copyright (C) 2005 Dave Robillard.
*
- * Om is free software; you can redistribute it and/or modify it under the
+ * Patchage 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.
*
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * Patchage 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 details.
*
@@ -29,6 +29,12 @@
int main(int argc, char** argv)
{
try {
+
+ //lash_args_t* const lash_args = lash_extract_args(&argc, &argv);
+
+ //lash_client_t* const lash_server_client = lash_init(lash_args, "Patchage Server Interface",
+ // LASH_Server_Interface, LASH_PROTOCOL(2, 0));
+
Gnome::Canvas::init();
Gtk::Main app(argc, argv);
diff --git a/src/patchage.glade b/src/patchage.glade
index 322a714..9bed33c 100644
--- a/src/patchage.glade
+++ b/src/patchage.glade
@@ -44,17 +44,17 @@
<widget class="GtkMenu" id="file_menu_menu">
<child>
- <widget class="GtkImageMenuItem" id="launch_jack_menuitem">
+ <widget class="GtkImageMenuItem" id="open_session_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Launch Jack</property>
+ <property name="label" translatable="yes">_Open Session</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_launch_jack_menuitem_activate" last_modification_time="Wed, 05 Apr 2006 04:52:35 GMT"/>
- <accelerator key="J" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ <signal name="activate" handler="on_open_session_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:00:37 GMT"/>
+ <accelerator key="O" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image143">
+ <widget class="GtkImage" id="image375">
<property name="visible">True</property>
- <property name="stock">gtk-execute</property>
+ <property name="stock">gtk-open</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
@@ -66,17 +66,17 @@
</child>
<child>
- <widget class="GtkImageMenuItem" id="connect_to_jack_menuitem">
+ <widget class="GtkImageMenuItem" id="save_session_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Connect to _Jack</property>
+ <property name="label" translatable="yes">_Save Session</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_connect_to_jack_menuitem_activate" last_modification_time="Wed, 05 Apr 2006 04:27:40 GMT"/>
- <accelerator key="J" modifiers="GDK_MOD1_MASK" signal="activate"/>
+ <signal name="activate" handler="on_save_session_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:01:40 GMT"/>
+ <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image144">
+ <widget class="GtkImage" id="image376">
<property name="visible">True</property>
- <property name="stock">gtk-connect</property>
+ <property name="stock">gtk-save</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
@@ -88,17 +88,17 @@
</child>
<child>
- <widget class="GtkImageMenuItem" id="disconnect_from_jack_menuitem">
+ <widget class="GtkImageMenuItem" id="save_session_as_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Disconnect from Jack</property>
+ <property name="label" translatable="yes">Save Session _As</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_disconnect_from_jack1_activate" last_modification_time="Sun, 21 May 2006 23:48:26 GMT"/>
- <accelerator key="J" modifiers="GDK_SHIFT_MASK | GDK_MOD1_MASK" signal="activate"/>
+ <signal name="activate" handler="on_save_session_as_menuitem_activate" last_modification_time="Sun, 01 Oct 2006 07:01:40 GMT"/>
+ <accelerator key="S" modifiers="GDK_CONTROL_MASK | GDK_SHIFT_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image145">
+ <widget class="GtkImage" id="image377">
<property name="visible">True</property>
- <property name="stock">gtk-disconnect</property>
+ <property name="stock">gtk-save-as</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
@@ -110,7 +110,7 @@
</child>
<child>
- <widget class="GtkSeparatorMenuItem" id="separator1">
+ <widget class="GtkSeparatorMenuItem" id="separator5">
<property name="visible">True</property>
</widget>
</child>
@@ -118,13 +118,13 @@
<child>
<widget class="GtkImageMenuItem" id="launch_lash_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Launch Lash</property>
+ <property name="label" translatable="yes">Launch LASH</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_launch_lash1_activate" last_modification_time="Mon, 22 May 2006 01:14:33 GMT"/>
- <accelerator key="L" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ <accelerator key="L" modifiers="GDK_CONTROL_MASK | GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image146">
+ <widget class="GtkImage" id="image378">
<property name="visible">True</property>
<property name="stock">gtk-execute</property>
<property name="icon_size">1</property>
@@ -140,13 +140,13 @@
<child>
<widget class="GtkImageMenuItem" id="connect_to_lash_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Connect to _Lash</property>
+ <property name="label" translatable="yes">Connect to _LASH</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_connect_to_lash1_activate" last_modification_time="Mon, 22 May 2006 01:14:33 GMT"/>
<accelerator key="L" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image147">
+ <widget class="GtkImage" id="image379">
<property name="visible">True</property>
<property name="stock">gtk-connect</property>
<property name="icon_size">1</property>
@@ -162,13 +162,85 @@
<child>
<widget class="GtkImageMenuItem" id="disconnect_from_lash_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Disconnect from Lash</property>
+ <property name="label" translatable="yes">Disconnect from LASH</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_disconnect_from_lash1_activate" last_modification_time="Mon, 22 May 2006 01:14:33 GMT"/>
<accelerator key="L" modifiers="GDK_SHIFT_MASK | GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image148">
+ <widget class="GtkImage" id="image380">
+ <property name="visible">True</property>
+ <property name="stock">gtk-disconnect</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="launch_jack_menuitem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Launch JACK</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_launch_jack_menuitem_activate" last_modification_time="Wed, 05 Apr 2006 04:52:35 GMT"/>
+ <accelerator key="J" modifiers="GDK_CONTROL_MASK | GDK_MOD1_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image381">
+ <property name="visible">True</property>
+ <property name="stock">gtk-execute</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="connect_to_jack_menuitem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Connect to _JACK</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_connect_to_jack_menuitem_activate" last_modification_time="Wed, 05 Apr 2006 04:27:40 GMT"/>
+ <accelerator key="J" modifiers="GDK_MOD1_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image382">
+ <property name="visible">True</property>
+ <property name="stock">gtk-connect</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="disconnect_from_jack_menuitem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Disconnect from JACK</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_disconnect_from_jack1_activate" last_modification_time="Sun, 21 May 2006 23:48:26 GMT"/>
+ <accelerator key="J" modifiers="GDK_SHIFT_MASK | GDK_MOD1_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image383">
<property name="visible">True</property>
<property name="stock">gtk-disconnect</property>
<property name="icon_size">1</property>
@@ -190,13 +262,13 @@
<child>
<widget class="GtkImageMenuItem" id="connect_to_alsa_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Connect to _Alsa</property>
+ <property name="label" translatable="yes">Connect to _ALSA</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_connect_to_alsa_menuitem_activate" last_modification_time="Mon, 22 May 2006 00:10:31 GMT"/>
<accelerator key="A" modifiers="GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image149">
+ <widget class="GtkImage" id="image384">
<property name="visible">True</property>
<property name="stock">gtk-connect</property>
<property name="icon_size">1</property>
@@ -212,13 +284,13 @@
<child>
<widget class="GtkImageMenuItem" id="disconnect_from_alsa_menuitem">
<property name="visible">True</property>
- <property name="label" translatable="yes">Disconnect from Alsa</property>
+ <property name="label" translatable="yes">Disconnect from ALSA</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_disconnect_from_alsa_menuitem_activate" last_modification_time="Mon, 22 May 2006 00:10:31 GMT"/>
<accelerator key="A" modifiers="GDK_SHIFT_MASK | GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image150">
+ <widget class="GtkImage" id="image385">
<property name="visible">True</property>
<property name="stock">gtk-disconnect</property>
<property name="icon_size">1</property>
@@ -238,7 +310,7 @@
</child>
<child>
- <widget class="GtkImageMenuItem" id="file_save_menuitem">
+ <widget class="GtkImageMenuItem" id="store_positions_menuitem">
<property name="visible">True</property>
<property name="label" translatable="yes">_Store Positions</property>
<property name="use_underline">True</property>
@@ -246,7 +318,7 @@
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
- <widget class="GtkImage" id="image151">
+ <widget class="GtkImage" id="image386">
<property name="visible">True</property>
<property name="stock">gtk-save</property>
<property name="icon_size">1</property>
@@ -290,9 +362,22 @@
<child>
<widget class="GtkImageMenuItem" id="view_refresh_menuitem">
<property name="visible">True</property>
- <property name="label">gtk-refresh</property>
- <property name="use_stock">True</property>
- <signal name="activate" handler="on_item1_activate" last_modification_time="Sat, 11 Sep 2004 20:05:50 GMT"/>
+ <property name="label" translatable="yes">_Refresh</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_refresh2_activate" last_modification_time="Sat, 11 Sep 2004 20:05:50 GMT"/>
+ <accelerator key="R" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image387">
+ <property name="visible">True</property>
+ <property name="stock">gtk-refresh</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
</widget>
</child>
</widget>
@@ -330,272 +415,192 @@
</child>
<child>
- <widget class="GtkScrolledWindow" id="canvas_scrolledwindow">
+ <widget class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
- <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="toolbar_style">GTK_TOOLBAR_ICONS</property>
+ <property name="tooltips">True</property>
+ <property name="show_arrow">True</property>
<child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
+ <widget class="GtkToolItem" id="toolitem7">
+ <property name="visible">True</property>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
- <child>
- <widget class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
+ <child>
+ <widget class="GtkButton" id="zoom_normal_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
- <child>
- <widget class="GtkLabel" id="status_lab">
- <property name="visible">True</property>
- <property name="label" translatable="yes"></property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <child>
+ <widget class="GtkImage" id="zoom_normal_but_icon">
+ <property name="visible">True</property>
+ <property name="stock">gtk-zoom-100</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
</widget>
<packing>
- <property name="padding">2</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
</packing>
</child>
<child>
- <widget class="GtkSeparatorToolItem" id="separatortoolitem1">
+ <widget class="GtkToolItem" id="toolitem10">
<property name="visible">True</property>
- <property name="draw">True</property>
- <property name="visible_horizontal">False</property>
+ <property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
+
+ <child>
+ <widget class="GtkButton" id="zoom_full_but">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkImage" id="image361">
+ <property name="visible">True</property>
+ <property name="stock">gtk-zoom-fit</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
</widget>
<packing>
- <property name="padding">0</property>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="homogeneous">False</property>
</packing>
</child>
<child>
- <widget class="GtkHBox" id="hbox2">
+ <widget class="GtkToolItem" id="toolitem1">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Zoom: </property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
+ <property name="visible_horizontal">True</property>
+ <property name="visible_vertical">True</property>
+ <property name="is_important">False</property>
<child>
<widget class="GtkHScale" id="zoom_scale">
<property name="width_request">150</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="draw_value">True</property>
+ <property name="draw_value">False</property>
<property name="value_pos">GTK_POS_RIGHT</property>
<property name="digits">1</property>
<property name="update_policy">GTK_UPDATE_CONTINUOUS</property>
<property name="inverted">False</property>
- <property name="adjustment">1 0.1 2 0 0 0</property>
+ <property name="adjustment">1 0.10000000149 2 0 0 0</property>
</widget>
- <packing>
- <property name="padding">5</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
</child>
</widget>
<packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="expand">True</property>
+ <property name="homogeneous">False</property>
</packing>
</child>
</widget>
<packing>
- <property name="padding">2</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
-</widget>
-
-<widget class="GtkWindow" id="about_win">
- <property name="width_request">320</property>
- <property name="height_request">200</property>
- <property name="title" translatable="yes">About Patchage</property>
- <property name="type">GTK_WINDOW_TOPLEVEL</property>
- <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
- <property name="modal">False</property>
- <property name="resizable">False</property>
- <property name="destroy_with_parent">False</property>
- <property name="decorated">True</property>
- <property name="skip_taskbar_hint">True</property>
- <property name="skip_pager_hint">True</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
- <property name="focus_on_map">True</property>
- <property name="urgency_hint">False</property>
-
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkLabel" id="about_project_label">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;span size=&quot;xx-large&quot; weight=&quot;bold&quot;&gt;Patchage&lt;/span&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="label" translatable="yes">A modular patch bay for:
-
-Jack Audio Connection Kit
-ALSA Sequencer</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_CENTER</property>
- <property name="wrap">True</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Copyright © 2005 Dave Robillard</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">10</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkHButtonBox" id="hbuttonbox1">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
- <property name="spacing">0</property>
- </widget>
- <packing>
<property name="padding">0</property>
<property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="fill">True</property>
</packing>
</child>
<child>
- <widget class="GtkHButtonBox" id="hbuttonbox2">
+ <widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
+ <property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
- <widget class="GtkButton" id="about_close_button">
- <property name="width_request">66</property>
- <property name="height_request">26</property>
+ <widget class="GtkVPaned" id="main_paned">
+ <property name="height_request">407</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="label">gtk-close</property>
- <property name="use_stock">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
+ <property name="position">1</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="canvas_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">False</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="status_text">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="overwrite">False</property>
+ <property name="accepts_tab">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_WORD</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
</widget>
+ <packing>
+ <property name="padding">2</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
</child>
</widget>
<packing>
- <property name="padding">0</property>
+ <property name="padding">2</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
@@ -604,4 +609,29 @@ ALSA Sequencer</property>
</child>
</widget>
+<widget class="GtkAboutDialog" id="about_win">
+ <property name="destroy_with_parent">True</property>
+ <property name="name" translatable="yes">Patchage</property>
+ <property name="copyright" translatable="yes">© 2006 Dave Robillard</property>
+ <property name="comments" translatable="yes">A control centre for audio and music production systems</property>
+ <property name="license" translatable="yes">Patchage 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.
+
+Patchage 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 Patchage; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+</property>
+ <property name="wrap_license">False</property>
+ <property name="website">http://codeson.net/software/patchage</property>
+ <property name="authors">Dave Robillard &lt;dave@codeson.net&gt;</property>
+ <property name="translator_credits" translatable="yes" comments="TRANSLATORS: Replace this string with your names, one name per line.">translator-credits</property>
+</widget>
+
</glade-interface>