[SCM] calf/master: + Big Bull: add get_type() to JackPort, make a separate module out of graph editor thingy, implement lousy connection and disconnection logic, add a small JACK connection graph toy program
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:34 UTC 2013
The following commit has been merged in the master branch:
commit 36503df11d54d58cea70a94068eb808d1da81743
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Mon Sep 8 22:26:11 2008 +0000
+ Big Bull: add get_type() to JackPort, make a separate module out of graph editor thingy, implement lousy connection and disconnection logic, add a small JACK connection graph toy program
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@284 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/bigbull/calfgtkutils.py b/bigbull/calfgtkutils.py
new file mode 100644
index 0000000..b62778f
--- /dev/null
+++ b/bigbull/calfgtkutils.py
@@ -0,0 +1,16 @@
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+def add_option(menu, option, handler, data = None):
+ item = gtk.MenuItem(option)
+ item.connect_object("activate", handler, data)
+ menu.add(item)
+
+def add_submenu(menu, option):
+ submenu = gtk.Menu()
+ item = gtk.MenuItem(option)
+ menu.append(item)
+ item.set_submenu(submenu)
+ return submenu
+
diff --git a/bigbull/calfpytools.cpp b/bigbull/calfpytools.cpp
index 68e2b76..bb53b0b 100644
--- a/bigbull/calfpytools.cpp
+++ b/bigbull/calfpytools.cpp
@@ -320,6 +320,17 @@ static PyObject *jackport_get_name(PyJackPort *self, PyObject *args)
return Py_BuildValue("s", jack_port_short_name(self->port));
}
+static PyObject *jackport_get_type(PyJackPort *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":get_type"))
+ return NULL;
+
+ CHECK_PORT_CLIENT
+ CHECK_PORT
+
+ return Py_BuildValue("s", jack_port_type(self->port));
+}
+
static PyObject *jackport_get_cobj(PyJackPort *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":get_cobj"))
@@ -408,6 +419,7 @@ static PyMethodDef jackport_methods[] = {
{"is_mine", (PyCFunction)jackport_is_mine, METH_VARARGS, "Checks if the port object is valid (registered)"},
{"get_full_name", (PyCFunction)jackport_get_full_name, METH_VARARGS, "Retrieve full port name (including client name)"},
{"get_name", (PyCFunction)jackport_get_name, METH_VARARGS, "Retrieve short port name (without client name)"},
+ {"get_type", (PyCFunction)jackport_get_type, METH_VARARGS, "Retrieve port type name"},
{"get_flags", (PyCFunction)jackport_get_flags, METH_VARARGS, "Retrieve port flags (defined in module, ie. calfpytools.JackPortIsInput)"},
{"set_name", (PyCFunction)jackport_set_name, METH_VARARGS, "Set short port name"},
{"get_aliases", (PyCFunction)jackport_get_aliases, METH_VARARGS, "Retrieve a list of port aliases"},
diff --git a/bigbull/mainwin.py b/bigbull/conndiagram.py
old mode 100755
new mode 100644
similarity index 63%
copy from bigbull/mainwin.py
copy to bigbull/conndiagram.py
index 7082817..649e57b
--- a/bigbull/mainwin.py
+++ b/bigbull/conndiagram.py
@@ -1,27 +1,10 @@
-#!/usr/bin/python
import pygtk
pygtk.require('2.0')
import gtk
-import lv2
-import fakeserv
-import client
import cairo
import goocanvas
import random
-import calfpytools
-def add_option(menu, option, handler, data = None):
- item = gtk.MenuItem(option)
- item.connect_object("activate", handler, data)
- menu.add(item)
-
-def add_submenu(menu, option):
- submenu = gtk.Menu()
- item = gtk.MenuItem(option)
- menu.append(item)
- item.set_submenu(submenu)
- return submenu
-
class Colors:
frame = 0xC0C0C0FF
text = 0xFFFFFFFF
@@ -31,36 +14,19 @@ class Colors:
controlPort = 0x008000FF
eventPort = 0x800000FF
activePort = 0x808080FF
+ draggedWire = 0xFFFFFFFF
+ connectedWire = 0x808080FF
-class LV2GraphParser():
- def get_port_color(self, portData):
- color = Colors.defPort
- if portData.isAudio:
- color = Colors.audioPort
- if portData.isControl:
- color = Colors.controlPort
- if portData.isEvent:
- color = Colors.eventPort
- return color
- def is_port_input(self, portData):
- return portData.isInput
- def get_port_name(self, portData):
- return portData.name
- def get_port_id(self, portData):
- return portData.uri
- def get_module_name(self, moduleData):
- return moduleData.name
- def get_module_port_list(self, moduleData):
- return [(port.uri, port) for port in moduleData.ports if lv2.epi + "notAutomatic" not in port.properties]
- def can_connect(self, first, second):
- return first.connectableTo(second)
-
class VisibleWire():
def __init__(self, src, dest, wire):
"""src is source ModulePort, dst is destination ModulePort, wire is a goocanvas.Path"""
self.src = src
self.dest = dest
self.wire = wire
+ def delete(self):
+ self.wire.remove()
+ self.src.module.remove_wire(self)
+ self.dest.module.remove_wire(self)
class ModulePort():
fontName = "DejaVu Sans Mono Book 10"
@@ -85,16 +51,20 @@ class ModulePort():
else:
al = "right"
portName = self.get_parser().get_port_name(self.portData)
- title = goocanvas.Text(parent = parent, text = portName, font = self.fontName, width = width - 2 * margin, x = margin, y = y, alignment = al, fill_color_rgba = Colors.text)
+ title = goocanvas.Text(parent = parent, text = portName, font = self.fontName, width = width - 2 * margin, x = margin, y = y, alignment = al, fill_color_rgba = Colors.text, hint_metrics = cairo.HINT_METRICS_ON)
height = 1 + int(title.get_requested_height(ctx, width - 2 * margin))
title.ensure_updated()
bnds = title.get_bounds()
- bw = bnds.x2 - bnds.x1 + 2 * margin
+ print "%d+%d - %d+%d" % (bnds.x1, bnds.y1, bnds.x2, bnds.y2)
+ if self.isInput:
+ bw = bnds.x2 - bnds.x1 + 2 * margin
+ else:
+ bw = width - bnds.x1 + 2 * margin
color = self.get_parser().get_port_color(self.portData)
if self.isInput:
box = goocanvas.Rect(parent = parent, x = 0, y = y - 1, width = bw, height = height + 2, line_width = 1, fill_color_rgba = color, stroke_color_rgba = Colors.frame)
else:
- box = goocanvas.Rect(parent = parent, x = bnds.x2 - margin, y = y - 1, width = width - bnds.x2 + margin, height = height + 2, line_width = 1, fill_color_rgba = color, stroke_color_rgba = Colors.frame)
+ box = goocanvas.Rect(parent = parent, x = width - bw, y = y - 1, width = bw, height = height + 2, line_width = 1, fill_color_rgba = color, stroke_color_rgba = Colors.frame)
box.lower(title)
y += height + spacing
box.type = "port"
@@ -133,7 +103,7 @@ class ModuleBox():
ctx = self.group.get_canvas().create_cairo_context()
self.portDict = {}
moduleName = self.get_parser().get_module_name(self.moduleData)
- self.title = goocanvas.Text(parent = self.group, font = self.fontName, text = "<b>" + moduleName + "</b>", width = self.width, x = 0, y = 0, alignment = "center", use_markup = True, fill_color_rgba = Colors.text)
+ self.title = goocanvas.Text(parent = self.group, font = self.fontName, text = "<b>" + moduleName + "</b>", width = self.width, x = 0, y = 0, alignment = "center", use_markup = True, fill_color_rgba = Colors.text, hint_metrics = cairo.HINT_METRICS_ON, antialias = cairo.ANTIALIAS_GRAY)
y = self.title.get_requested_height(ctx, self.width) + self.spacing
for (id, portData) in self.get_parser().get_module_port_list(self.moduleData):
y = self.create_port(ctx, id, portData, y)
@@ -155,22 +125,14 @@ class ModuleBox():
def delete_items(self):
self.group.remove()
- def port_endpoint(self, port):
- bounds = port.box.get_bounds()
- port = port.portData
- if self.get_parser().is_port_input(port):
- x = bounds.x1
- else:
- x = bounds.x2
- y = (bounds.y1 + bounds.y2) / 2
- return (x, y)
-
def port_button_press(self, mport, box, event):
if event.button == 1:
port_id = mport.get_id()
mport.box.props.fill_color_rgba = Colors.activePort
- (x, y) = self.port_endpoint(mport)
- self.drag_wire = goocanvas.Path(parent = self.parent, stroke_color_rgba = Colors.frame)
+ (x, y) = self.graph.port_endpoint(mport)
+ self.drag_wire = goocanvas.Path(parent = self.parent, stroke_color_rgba = Colors.draggedWire)
+ self.drag_wire.type = "tmp wire"
+ self.drag_wire.object = None
self.drag_wire.raise_(None)
self.graph.dragging = (self, port_id, self.drag_wire, x, y)
self.set_connect_candidate(None)
@@ -181,25 +143,24 @@ class ModuleBox():
def dragging(self, tuple, x2, y2):
boundsGrp = self.group.get_bounds()
self.update_drag_wire(tuple, x2 + boundsGrp.x1, y2 + boundsGrp.y1)
-
+
def dragged(self, tuple, x2, y2):
# self.update_drag_wire(tuple, x2, y2)
+ wireitem = tuple[2]
port = self.portDict[tuple[1]]
self.graph.dragging = None
port.box.props.fill_color_rgba = port.orig_color
if self.connect_candidate != None:
- print "Connect: " + tuple[1] + " with " + self.connect_candidate.get_id()
- if port.isInput:
- (src, dest) = (port, self.connect_candidate)
- else:
- (dest, src) = (port, self.connect_candidate)
- wire = VisibleWire(src, dest, tuple[2])
- self.wires.append(wire)
- self.update_wire(wire)
- self.connect_candidate.module.wires.append(VisibleWire(src, dest, tuple[2]))
- self.set_connect_candidate(None)
+ # print "Connect: " + tuple[1] + " with " + self.connect_candidate.get_id()
+ try:
+ self.graph.connect(port, self.connect_candidate, wireitem)
+ except:
+ wireitem.remove()
+ raise
+ finally:
+ self.set_connect_candidate(None)
else:
- tuple[2].remove()
+ wireitem.remove()
def set_connect_candidate(self, item):
if self.connect_candidate != item:
@@ -210,8 +171,8 @@ class ModuleBox():
item.box.props.fill_color_rgba = Colors.activePort
def update_drag_wire(self, tuple, x2, y2):
- (uri, x, y, dx, dy) = (tuple[1], tuple[3], tuple[4], x2 - tuple[3], y2 - tuple[4])
- tuple[2].props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x, y, x+dx/2, y, x+dx/2, y+dy, x+dx, y+dy)
+ (uri, x, y, dx, dy, wireitem) = (tuple[1], tuple[3], tuple[4], x2 - tuple[3], y2 - tuple[4], tuple[2])
+ wireitem.props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x, y, x+dx/2, y, x+dx/2, y+dy, x+dx, y+dy)
items = self.graph.get_data_items_at(x+dx, y+dy)
found = False
for type, obj, item in items:
@@ -224,13 +185,10 @@ class ModuleBox():
def update_wires(self):
for wire in self.wires:
- self.update_wire(wire)
+ self.graph.update_wire(wire)
- def update_wire(self, wire):
- (x1, y1) = self.port_endpoint(wire.src)
- (x2, y2) = self.port_endpoint(wire.dest)
- xm = (x1 + x2) / 2
- wire.wire.props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x1, y1, xm, y1, xm, y2, x2, y2)
+ def remove_wire(self, wire):
+ self.wires = [w for w in self.wires if w != wire]
class ConnectionGraphEditor:
def __init__(self, app, parser):
@@ -238,8 +196,12 @@ class ConnectionGraphEditor:
self.parser = parser
self.moving = None
self.dragging = None
+ self.modules = set()
pass
+ def get_parser(self):
+ return self.parser
+
def create(self):
self.create_canvas()
return self.canvas
@@ -251,14 +213,14 @@ class ConnectionGraphEditor:
self.canvas.set_scale(1)
#self.canvas.connect("size-allocate", self.update_canvas_bounds)
self.canvas.props.background_color_rgb = 0
- #self.canvas.props.integer_layout = True
+ self.canvas.props.integer_layout = False
self.canvas.update()
self.canvas.get_root_item().connect("motion-notify-event", self.canvas_motion_notify)
self.canvas.get_root_item().connect("button-release-event", self.canvas_button_release)
def get_items_at(self, x, y):
cr = self.canvas.create_cairo_context()
- items = self.canvas.get_root_item().get_items_at(x, y, cr, True, True)
+ items = self.canvas.get_items_in_area(goocanvas.Bounds(x - 3, y - 3, x + 3, y + 3), True, True, False)
return items
def get_data_items_at(self, x, y):
@@ -270,10 +232,17 @@ class ConnectionGraphEditor:
if hasattr(i, 'type'):
data_items.append((i.type, i.object, i))
return data_items
-
- def add_plugin(self, params):
- (plugin, x, y) = params
- mbox = ModuleBox(self.parser, self.canvas.get_root_item(), plugin, self)
+
+ def get_size(self):
+ bounds = self.canvas.get_bounds()
+ return (bounds[2] - bounds[0], bounds[3] - bounds[1])
+
+ def add_module_cb(self, params):
+ self.add_module(*params)
+
+ def add_module(self, moduleData, x, y):
+ mbox = ModuleBox(self.parser, self.canvas.get_root_item(), moduleData, self)
+ self.modules.add(mbox)
bounds = self.canvas.get_bounds()
if x == None:
(x, y) = (int(random.uniform(bounds[0], bounds[2] - 100)), int(random.uniform(bounds[1], bounds[3] - 50)))
@@ -282,8 +251,15 @@ class ConnectionGraphEditor:
mbox.group.connect("motion-notify-event", self.box_motion_notify)
mbox.group.connect("button-release-event", self.box_button_release)
- def delete_plugin(self, data):
- data.delete_items()
+ def delete_module(self, module):
+ self.modules.remove(mbox)
+ module.delete_items()
+
+ def get_port_map(self):
+ map = {}
+ for mod in self.modules:
+ map.update(mod.portDict)
+ return map
def canvas_motion_notify(self, group, widget, event):
if self.dragging != None:
@@ -310,72 +286,39 @@ class ConnectionGraphEditor:
self.moving.translate(event.x - self.motion_x, event.y - self.motion_y)
group.module.update_wires()
-class App:
- def __init__(self):
- fakeserv.start()
- self.lv2db = lv2.LV2DB()
- self.parser = LV2GraphParser()
- self.cgraph = ConnectionGraphEditor(self, self.parser)
-
- def canvas_popup_menu_handler(self, widget):
- self.canvas_popup_menu(0, 0, 0)
- return True
-
- def canvas_button_press_handler(self, widget, event):
- if event.button == 3:
- self.canvas_popup_menu(event.x, event.y, event.time)
- return True
-
- def canvas_popup_menu(self, x, y, time):
- menu = gtk.Menu()
- items = self.cgraph.get_data_items_at(x, y)
- types = set([di[0] for di in items])
- if 'port' in types:
- pass
- #add_option(menu, "-Port-", self.cgraph.delete_plugin, (None, x, y))
- elif 'module' in types:
- for mod in [di for di in items if di[0] == "module"]:
- add_option(menu, "Delete "+mod[1].plugin.name, self.cgraph.delete_plugin, mod[1])
+ def port_endpoint(self, port):
+ bounds = port.box.get_bounds()
+ port = port.portData
+ if self.get_parser().is_port_input(port):
+ x = bounds.x1
else:
- for uri in self.lv2db.getPluginList():
- plugin = self.lv2db.getPluginInfo(uri)
- add_option(menu, plugin.name, self.cgraph.add_plugin, (plugin, x, y))
- menu.show_all()
- menu.popup(None, None, None, 3, time)
-
- def create(self):
- self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
- self.window.connect("delete_event", self.delete_event)
- self.window.connect("destroy", self.destroy)
- self.main_vbox = gtk.VBox()
- self.create_main_menu()
- self.scroll = gtk.ScrolledWindow()
- self.scroll.add(self.cgraph.create())
- self.main_vbox.pack_start(self.menu_bar, expand = False, fill = False)
- self.main_vbox.add(self.scroll)
- self.window.add(self.main_vbox)
- self.window.show_all()
- self.main_vbox.connect("popup-menu", self.canvas_popup_menu_handler)
- self.cgraph.canvas.connect("button-press-event", self.canvas_button_press_handler)
-
- def create_main_menu(self):
- self.menu_bar = gtk.MenuBar()
-
- self.file_menu = add_submenu(self.menu_bar, "_File")
- add_option(self.file_menu, "_Exit", self.exit)
- self.plugin_menu = add_submenu(self.menu_bar, "_Plugins")
- for uri in self.lv2db.getPluginList():
- plugin = self.lv2db.getPluginInfo(uri)
- add_option(self.plugin_menu, plugin.name, self.cgraph.add_plugin, (plugin, None, None))
-
- def exit(self, data):
- self.window.destroy()
+ x = bounds.x2
+ y = (bounds.y1 + bounds.y2) / 2
+ return (x, y)
- def delete_event(self, widget, data = None):
- gtk.main_quit()
- def destroy(self, widget, data = None):
- gtk.main_quit()
+ def update_wire(self, wire):
+ (x1, y1) = self.port_endpoint(wire.src)
+ (x2, y2) = self.port_endpoint(wire.dest)
+ xm = (x1 + x2) / 2
+ wire.wire.props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x1, y1, xm, y1, xm, y2, x2, y2)
-app = App()
-app.create()
-gtk.main()
+ def connect(self, p1, p2, wireitem = None):
+ # p1, p2 are ModulePort objects
+ # if wireitem is set, then this is manual connection, and parser.connect() is called
+ # if wireitem is None, then this is automatic connection, and parser.connect() is bypassed
+ if p2.isInput:
+ (src, dest) = (p1, p2)
+ else:
+ (dest, src) = (p1, p2)
+ if wireitem == None:
+ wireitem = goocanvas.Path(parent = self.canvas.get_root_item())
+ else:
+ self.get_parser().connect(src.portData, dest.portData)
+ wire = VisibleWire(src, dest, wireitem)
+ wireitem.type = "wire"
+ wireitem.object = wire
+ wireitem.props.stroke_color_rgba = Colors.connectedWire
+ src.module.wires.append(wire)
+ dest.module.wires.append(wire)
+ self.update_wire(wire)
+
diff --git a/bigbull/jackvis.py b/bigbull/jackvis.py
new file mode 100755
index 0000000..c8c6142
--- /dev/null
+++ b/bigbull/jackvis.py
@@ -0,0 +1,131 @@
+#!/usr/bin/python
+import pygtk
+pygtk.require('2.0')
+import gtk
+import calfpytools
+import conndiagram
+from calfgtkutils import *
+Colors = conndiagram.Colors
+
+class JACKGraphParser():
+ def __init__(self):
+ self.client = calfpytools.JackClient()
+ self.client.open("jackvis")
+ def get_port_color(self, portData):
+ if portData.get_type() == calfpytools.JACK_DEFAULT_AUDIO_TYPE:
+ color = Colors.audioPort
+ if portData.get_type() == calfpytools.JACK_DEFAULT_MIDI_TYPE:
+ color = Colors.eventPort
+ return color
+ def is_port_input(self, portData):
+ return (portData.get_flags() & calfpytools.JackPortIsInput) != 0
+ def get_port_name(self, portData):
+ return portData.get_name()
+ def get_port_id(self, portData):
+ return portData.get_full_name()
+ def get_module_name(self, moduleData):
+ return moduleData.name
+ def get_module_port_list(self, moduleData):
+ return [(port, self.client.get_port(port)) for port in self.client.get_ports(moduleData.name+":.*", moduleData.type, moduleData.flags)]
+ def can_connect(self, first, second):
+ if self.is_port_input(first) == self.is_port_input(second):
+ return False
+ if first.get_type() != second.get_type():
+ return False
+ return True
+ def connect(self, first, second):
+ if self.client.connect(first.get_full_name(), second.get_full_name()) != True:
+ raise RuntimeError, "Connection error"
+ def disconnect(self, name_first, name_second):
+ self.client.disconnect(name_first, name_second)
+
+class JACKClientData():
+ def __init__(self, name, type, flags):
+ (self.name, self.type, self.flags) = (name, type, flags)
+
+class App:
+ def __init__(self):
+ self.parser = JACKGraphParser()
+ self.cgraph = conndiagram.ConnectionGraphEditor(self, self.parser)
+
+ def canvas_popup_menu_handler(self, widget):
+ self.canvas_popup_menu(0, 0, 0)
+ return True
+
+ def canvas_button_press_handler(self, widget, event):
+ if event.button == 3:
+ self.canvas_popup_menu(event.x, event.y, event.time)
+ return True
+
+ def canvas_popup_menu(self, x, y, time):
+ menu = gtk.Menu()
+ items = self.cgraph.get_data_items_at(x, y)
+ types = set([di[0] for di in items])
+ if 'wire' in types:
+ for i in items:
+ if i[0] == "wire":
+ wire = i[1]
+ add_option(menu, "Disconnect", self.disconnect, wire)
+ else:
+ return
+ menu.show_all()
+ menu.popup(None, None, None, 3, time)
+
+ def disconnect(self, wire):
+ self.parser.disconnect(wire.src.get_id(), wire.dest.get_id())
+ wire.delete()
+
+ def create(self):
+ self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.window.connect("delete_event", self.delete_event)
+ self.window.connect("destroy", self.destroy)
+ self.main_vbox = gtk.VBox()
+ self.create_main_menu()
+ self.scroll = gtk.ScrolledWindow()
+ self.scroll.add(self.cgraph.create())
+ self.main_vbox.pack_start(self.menu_bar, expand = False, fill = False)
+ self.main_vbox.add(self.scroll)
+ self.window.add(self.main_vbox)
+ self.window.show_all()
+ self.main_vbox.connect("popup-menu", self.canvas_popup_menu_handler)
+ self.cgraph.canvas.connect("button-press-event", self.canvas_button_press_handler)
+ self.cgraph.canvas.update()
+ self.add_clients(0.0, 0.0, calfpytools.JackPortIsOutput)
+ self.add_clients(200, 0.0, calfpytools.JackPortIsInput)
+ self.cgraph.canvas.update()
+ self.add_wires()
+
+ def add_clients(self, x, y, flags):
+ ports = self.parser.client.get_ports("", "", flags)
+ clients = set([p.split(":")[0] for p in ports])
+ for cl in clients:
+ self.cgraph.add_module(JACKClientData(cl, "", flags), x, y)
+
+ def add_wires(self):
+ ports = self.parser.client.get_ports("", "", calfpytools.JackPortIsInput)
+ pmap = self.cgraph.get_port_map()
+ for p in ports:
+ conns = self.parser.client.get_port(p).get_connections()
+ for c in conns:
+ if p in pmap and c in pmap:
+ print "Connect %s to %s" % (c, p)
+ self.cgraph.connect(pmap[c], pmap[p])
+ else:
+ print "Connect %s to %s - not found" % (c, p)
+
+ def create_main_menu(self):
+ self.menu_bar = gtk.MenuBar()
+ self.file_menu = add_submenu(self.menu_bar, "_File")
+ add_option(self.file_menu, "_Exit", self.exit)
+
+ def exit(self, data):
+ self.window.destroy()
+
+ def delete_event(self, widget, data = None):
+ gtk.main_quit()
+ def destroy(self, widget, data = None):
+ gtk.main_quit()
+
+app = App()
+app.create()
+gtk.main()
diff --git a/bigbull/mainwin.py b/bigbull/mainwin.py
index 7082817..d31ff81 100755
--- a/bigbull/mainwin.py
+++ b/bigbull/mainwin.py
@@ -5,32 +5,10 @@ import gtk
import lv2
import fakeserv
import client
-import cairo
-import goocanvas
-import random
import calfpytools
-
-def add_option(menu, option, handler, data = None):
- item = gtk.MenuItem(option)
- item.connect_object("activate", handler, data)
- menu.add(item)
-
-def add_submenu(menu, option):
- submenu = gtk.Menu()
- item = gtk.MenuItem(option)
- menu.append(item)
- item.set_submenu(submenu)
- return submenu
-
-class Colors:
- frame = 0xC0C0C0FF
- text = 0xFFFFFFFF
- box = 0x202020FF
- defPort = 0x404040FF
- audioPort = 0x000080FF
- controlPort = 0x008000FF
- eventPort = 0x800000FF
- activePort = 0x808080FF
+import conndiagram
+from calfgtkutils import *
+Colors = conndiagram.Colors
class LV2GraphParser():
def get_port_color(self, portData):
@@ -54,268 +32,16 @@ class LV2GraphParser():
return [(port.uri, port) for port in moduleData.ports if lv2.epi + "notAutomatic" not in port.properties]
def can_connect(self, first, second):
return first.connectableTo(second)
-
-class VisibleWire():
- def __init__(self, src, dest, wire):
- """src is source ModulePort, dst is destination ModulePort, wire is a goocanvas.Path"""
- self.src = src
- self.dest = dest
- self.wire = wire
-
-class ModulePort():
- fontName = "DejaVu Sans Mono Book 10"
- type = "port"
- def __init__(self, module, portData):
- self.module = module
- self.portData = portData
- self.isInput = self.get_parser().is_port_input(portData)
- self.box = self.title = None
-
- def get_parser(self):
- return self.module.get_parser()
-
- def get_id(self):
- return self.get_parser().get_port_id(self.portData)
-
- def render(self, ctx, parent, y):
- module = self.module
- (width, margin, spacing) = (module.width, module.margin, module.spacing)
- if self.isInput:
- al = "left"
- else:
- al = "right"
- portName = self.get_parser().get_port_name(self.portData)
- title = goocanvas.Text(parent = parent, text = portName, font = self.fontName, width = width - 2 * margin, x = margin, y = y, alignment = al, fill_color_rgba = Colors.text)
- height = 1 + int(title.get_requested_height(ctx, width - 2 * margin))
- title.ensure_updated()
- bnds = title.get_bounds()
- bw = bnds.x2 - bnds.x1 + 2 * margin
- color = self.get_parser().get_port_color(self.portData)
- if self.isInput:
- box = goocanvas.Rect(parent = parent, x = 0, y = y - 1, width = bw, height = height + 2, line_width = 1, fill_color_rgba = color, stroke_color_rgba = Colors.frame)
- else:
- box = goocanvas.Rect(parent = parent, x = bnds.x2 - margin, y = y - 1, width = width - bnds.x2 + margin, height = height + 2, line_width = 1, fill_color_rgba = color, stroke_color_rgba = Colors.frame)
- box.lower(title)
- y += height + spacing
- box.type = "port"
- self.orig_color = color
- box.object = box.module = self
- box.portData = self.portData
- title.portData = self.portData
- self.box = box
- self.title = title
- return y
-
-class ModuleBox():
- width = 100
- margin = 2
- spacing = 6
- fontName = "DejaVu Sans Mono Book 10"
-
- def __init__(self, parser, parent, moduleData, graph):
- self.parser = parser
- self.graph = graph
- self.group = None
- self.connect_candidate = None
- self.parent = parent
- self.moduleData = moduleData
- self.group = goocanvas.Group(parent = self.parent)
- self.wires = []
- self.create_items()
-
- def get_parser(self):
- return self.parser
-
- def create_items(self):
- self.group.module = self
- while self.group.get_n_children() > 0:
- self.group.remove_child(0)
- ctx = self.group.get_canvas().create_cairo_context()
- self.portDict = {}
- moduleName = self.get_parser().get_module_name(self.moduleData)
- self.title = goocanvas.Text(parent = self.group, font = self.fontName, text = "<b>" + moduleName + "</b>", width = self.width, x = 0, y = 0, alignment = "center", use_markup = True, fill_color_rgba = Colors.text)
- y = self.title.get_requested_height(ctx, self.width) + self.spacing
- for (id, portData) in self.get_parser().get_module_port_list(self.moduleData):
- y = self.create_port(ctx, id, portData, y)
- self.rect = goocanvas.Rect(parent = self.group, width = self.width, height = y, line_width = 1, stroke_color_rgba = Colors.frame, fill_color_rgba = Colors.box)
- self.rect.lower(self.title)
- self.rect.type = "module"
- self.rect.object = self.rect.module = self
- self.group.ensure_updated()
- self.wire = None
-
- def create_port(self, ctx, portId, portData, y):
- mport = ModulePort(self, portData)
- y = mport.render(ctx, self.group, y)
- self.portDict[portId] = mport
- mport.box.connect_object("button-press-event", self.port_button_press, mport)
- mport.title.connect_object("button-press-event", self.port_button_press, mport)
- return y
-
- def delete_items(self):
- self.group.remove()
-
- def port_endpoint(self, port):
- bounds = port.box.get_bounds()
- port = port.portData
- if self.get_parser().is_port_input(port):
- x = bounds.x1
- else:
- x = bounds.x2
- y = (bounds.y1 + bounds.y2) / 2
- return (x, y)
-
- def port_button_press(self, mport, box, event):
- if event.button == 1:
- port_id = mport.get_id()
- mport.box.props.fill_color_rgba = Colors.activePort
- (x, y) = self.port_endpoint(mport)
- self.drag_wire = goocanvas.Path(parent = self.parent, stroke_color_rgba = Colors.frame)
- self.drag_wire.raise_(None)
- self.graph.dragging = (self, port_id, self.drag_wire, x, y)
- self.set_connect_candidate(None)
- self.update_drag_wire(self.graph.dragging, x, y)
- print "Port URI is " + port_id
- return True
-
- def dragging(self, tuple, x2, y2):
- boundsGrp = self.group.get_bounds()
- self.update_drag_wire(tuple, x2 + boundsGrp.x1, y2 + boundsGrp.y1)
-
- def dragged(self, tuple, x2, y2):
- # self.update_drag_wire(tuple, x2, y2)
- port = self.portDict[tuple[1]]
- self.graph.dragging = None
- port.box.props.fill_color_rgba = port.orig_color
- if self.connect_candidate != None:
- print "Connect: " + tuple[1] + " with " + self.connect_candidate.get_id()
- if port.isInput:
- (src, dest) = (port, self.connect_candidate)
- else:
- (dest, src) = (port, self.connect_candidate)
- wire = VisibleWire(src, dest, tuple[2])
- self.wires.append(wire)
- self.update_wire(wire)
- self.connect_candidate.module.wires.append(VisibleWire(src, dest, tuple[2]))
- self.set_connect_candidate(None)
- else:
- tuple[2].remove()
-
- def set_connect_candidate(self, item):
- if self.connect_candidate != item:
- if self.connect_candidate != None:
- self.connect_candidate.box.props.fill_color_rgba = self.connect_candidate.orig_color
- self.connect_candidate = item
- if item != None:
- item.box.props.fill_color_rgba = Colors.activePort
-
- def update_drag_wire(self, tuple, x2, y2):
- (uri, x, y, dx, dy) = (tuple[1], tuple[3], tuple[4], x2 - tuple[3], y2 - tuple[4])
- tuple[2].props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x, y, x+dx/2, y, x+dx/2, y+dy, x+dx, y+dy)
- items = self.graph.get_data_items_at(x+dx, y+dy)
- found = False
- for type, obj, item in items:
- if type == 'port':
- if item.module != self and self.get_parser().can_connect(self.portDict[uri].portData, obj.portData):
- found = True
- self.set_connect_candidate(obj)
- if not found and self.connect_candidate != None:
- self.set_connect_candidate(None)
-
- def update_wires(self):
- for wire in self.wires:
- self.update_wire(wire)
-
- def update_wire(self, wire):
- (x1, y1) = self.port_endpoint(wire.src)
- (x2, y2) = self.port_endpoint(wire.dest)
- xm = (x1 + x2) / 2
- wire.wire.props.data = "M %0.0f,%0.0f C %0.0f,%0.0f %0.0f,%0.0f %0.0f,%0.0f" % (x1, y1, xm, y1, xm, y2, x2, y2)
-
-class ConnectionGraphEditor:
- def __init__(self, app, parser):
- self.app = app
- self.parser = parser
- self.moving = None
- self.dragging = None
+ def connect(self, first, second):
+ print "Connection not implemented yet"
pass
-
- def create(self):
- self.create_canvas()
- return self.canvas
-
- def create_canvas(self):
- self.canvas = goocanvas.Canvas()
- self.canvas.props.automatic_bounds = True
- self.canvas.set_size_request(640, 480)
- self.canvas.set_scale(1)
- #self.canvas.connect("size-allocate", self.update_canvas_bounds)
- self.canvas.props.background_color_rgb = 0
- #self.canvas.props.integer_layout = True
- self.canvas.update()
- self.canvas.get_root_item().connect("motion-notify-event", self.canvas_motion_notify)
- self.canvas.get_root_item().connect("button-release-event", self.canvas_button_release)
-
- def get_items_at(self, x, y):
- cr = self.canvas.create_cairo_context()
- items = self.canvas.get_root_item().get_items_at(x, y, cr, True, True)
- return items
-
- def get_data_items_at(self, x, y):
- items = self.get_items_at(x, y)
- if items == None:
- return []
- data_items = []
- for i in items:
- if hasattr(i, 'type'):
- data_items.append((i.type, i.object, i))
- return data_items
-
- def add_plugin(self, params):
- (plugin, x, y) = params
- mbox = ModuleBox(self.parser, self.canvas.get_root_item(), plugin, self)
- bounds = self.canvas.get_bounds()
- if x == None:
- (x, y) = (int(random.uniform(bounds[0], bounds[2] - 100)), int(random.uniform(bounds[1], bounds[3] - 50)))
- mbox.group.translate(x, y)
- mbox.group.connect("button-press-event", self.box_button_press)
- mbox.group.connect("motion-notify-event", self.box_motion_notify)
- mbox.group.connect("button-release-event", self.box_button_release)
-
- def delete_plugin(self, data):
- data.delete_items()
-
- def canvas_motion_notify(self, group, widget, event):
- if self.dragging != None:
- self.dragging[0].dragging(self.dragging, event.x, event.y)
-
- def canvas_button_release(self, group, widget, event):
- if self.dragging != None and event.button == 1:
- self.dragging[0].dragged(self.dragging, event.x, event.y)
-
- def box_button_press(self, group, widget, event):
- if event.button == 1:
- group.raise_(None)
- self.moving = group
- self.motion_x = event.x
- self.motion_y = event.y
- return True
-
- def box_button_release(self, group, widget, event):
- if event.button == 1:
- self.moving = None
-
- def box_motion_notify(self, group, widget, event):
- if self.moving == group:
- self.moving.translate(event.x - self.motion_x, event.y - self.motion_y)
- group.module.update_wires()
-
+
class App:
def __init__(self):
fakeserv.start()
self.lv2db = lv2.LV2DB()
self.parser = LV2GraphParser()
- self.cgraph = ConnectionGraphEditor(self, self.parser)
+ self.cgraph = conndiagram.ConnectionGraphEditor(self, self.parser)
def canvas_popup_menu_handler(self, widget):
self.canvas_popup_menu(0, 0, 0)
@@ -332,14 +58,14 @@ class App:
types = set([di[0] for di in items])
if 'port' in types:
pass
- #add_option(menu, "-Port-", self.cgraph.delete_plugin, (None, x, y))
+ #add_option(menu, "-Port-", self.cgraph.delete_module_cb, (None, x, y))
elif 'module' in types:
for mod in [di for di in items if di[0] == "module"]:
- add_option(menu, "Delete "+mod[1].plugin.name, self.cgraph.delete_plugin, mod[1])
+ add_option(menu, "Delete "+mod[1].plugin.name, self.cgraph.delete_module, mod[1])
else:
for uri in self.lv2db.getPluginList():
plugin = self.lv2db.getPluginInfo(uri)
- add_option(menu, plugin.name, self.cgraph.add_plugin, (plugin, x, y))
+ add_option(menu, plugin.name, self.cgraph.add_module_cb, (plugin, x, y))
menu.show_all()
menu.popup(None, None, None, 3, time)
@@ -366,7 +92,7 @@ class App:
self.plugin_menu = add_submenu(self.menu_bar, "_Plugins")
for uri in self.lv2db.getPluginList():
plugin = self.lv2db.getPluginInfo(uri)
- add_option(self.plugin_menu, plugin.name, self.cgraph.add_plugin, (plugin, None, None))
+ add_option(self.plugin_menu, plugin.name, self.cgraph.add_module_cb, (plugin, None, None))
def exit(self, data):
self.window.destroy()
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list