[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