Changeset - 3c523c71da29
[Not reviewed]
default
! ! !
Drew Perttula - 6 years ago 2019-05-25 12:10:51
drewp@bigasterisk.com
pyflakes cleanups and some refactors
Ignore-this: f7372e678699175feb4e628eee3d768c
61 files changed with 293 insertions and 298 deletions:
0 comments (0 inline, 0 general)
bin/ascoltami2
Show inline comments
 
#!bin/python
 
from run_local import log
 
from twisted.internet import reactor
 
import web, _thread, sys, optparse, logging
 
import sys, optparse, logging
 
from rdflib import URIRef
 
import gi
 
gi.require_version('Gst', '1.0')
 
@@ -12,7 +12,7 @@ from light9.ascoltami.playlist import Pl
 
from light9.ascoltami.webapp import makeWebApp, songUri, songLocation
 
from light9 import networking, showconfig
 

	
 
from gi.repository import GObject, Gst, Gtk
 
from gi.repository import GObject, Gst
 

	
 

	
 
class App(object):
bin/captureDevice
Show inline comments
 
@@ -23,6 +23,7 @@ from light9.greplin_cyclone import Stats
 
from light9.effect.settings import DeviceSettings
 
from light9.collector.collector_client import sendToCollector
 
from rdfdb.patch import Patch
 
from light9.zmqtransport import parseJsonMessage
 

	
 
stats = scales.collection('/webServer', scales.PmfStat('setAttr'))
 

	
 
@@ -174,7 +175,8 @@ def launch(graph):
 
                          }),
 
                          (r'/stats', StatsForCyclone),
 
                      ]),
 
                      interface='::')
 
                      interface='::',
 
                      cap=cap)
 
    log.info('serving http on %s', networking.captureDevice.port)
 

	
 

	
bin/collector
Show inline comments
 
@@ -9,127 +9,25 @@ Input can be over http or zmq.
 

	
 
from run_local import log
 

	
 
from rdflib import URIRef, Literal
 
from twisted.internet import reactor, utils
 
from txzmq import ZmqEndpoint, ZmqFactory, ZmqPullConnection
 
import json
 
import logging
 
import optparse
 
import time
 
import traceback
 
import cyclone.web, cyclone.websocket
 
from greplin import scales
 

	
 
from cycloneerr import PrettyErrorHandler
 
from light9.collector.output import EnttecDmx, Udmx, DummyOutput
 
from light9 import networking
 
from light9.collector.collector import Collector
 
from light9.namespaces import L9
 
from light9 import networking
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9.collector.weblisteners import WebListeners
 
from light9.greplin_cyclone import StatsForCyclone
 

	
 

	
 
def parseJsonMessage(msg):
 
    body = json.loads(msg)
 
    settings = []
 
    for device, attr, value in body['settings']:
 
        if isinstance(value, str) and value.startswith('http'):
 
            value = URIRef(value)
 
        else:
 
            value = Literal(value)
 
        settings.append((URIRef(device), URIRef(attr), value))
 
    return body['client'], body['clientSession'], settings, body['sendTime']
 

	
 

	
 
def startZmq(port, collector):
 
    stats = scales.collection('/zmqServer', scales.PmfStat('setAttr'))
 

	
 
    zf = ZmqFactory()
 
    addr = 'tcp://*:%s' % port
 
    log.info('creating zmq endpoint at %r', addr)
 
    e = ZmqEndpoint('bind', addr)
 

	
 
    class Pull(ZmqPullConnection):
 
        #highWaterMark = 3
 
        def onPull(self, message):
 
            with stats.setAttr.time():
 
                # todo: new compressed protocol where you send all URIs up
 
                # front and then use small ints to refer to devices and
 
                # attributes in subsequent requests.
 
                client, clientSession, settings, sendTime = parseJsonMessage(
 
                    message[0])
 
                collector.setAttrs(client, clientSession, settings, sendTime)
 

	
 
    s = Pull(zf, e)
 

	
 

	
 
class WebListeners(object):
 

	
 
    def __init__(self):
 
        self.clients = []
 
        self.pendingMessageForDev = {}  # dev: (attrs, outputmap)
 
        self.lastFlush = 0
 

	
 
    def addClient(self, client):
 
        self.clients.append([client, {}])  # seen = {dev: attrs}
 
        log.info('added client %s %s', len(self.clients), client)
 
from light9.namespaces import L9
 
from light9.zmqtransport import parseJsonMessage, startZmq
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
    def delClient(self, client):
 
        self.clients = [[c, t] for c, t in self.clients if c != client]
 
        log.info('delClient %s, %s left', client, len(self.clients))
 

	
 
    def outputAttrsSet(self, dev, attrs, outputMap):
 
        """called often- don't be slow"""
 

	
 
        self.pendingMessageForDev[dev] = (attrs, outputMap)
 
        try:
 
            self._flush()
 
        except Exception:
 
            traceback.print_exc()
 
            raise
 

	
 
    def _flush(self):
 
        now = time.time()
 
        if now < self.lastFlush + .05 or not self.clients:
 
            return
 
        self.lastFlush = now
 

	
 
        while self.pendingMessageForDev:
 
            dev, (attrs, outputMap) = self.pendingMessageForDev.popitem()
 

	
 
            msg = None  # lazy, since makeMsg is slow
 
from light9.collector.output import EnttecDmx, Udmx, DummyOutput  # noqa
 

	
 
            # this omits repeats, but can still send many
 
            # messages/sec. Not sure if piling up messages for the browser
 
            # could lead to slowdowns in the real dmx output.
 
            for client, seen in self.clients:
 
                if seen.get(dev) == attrs:
 
                    continue
 
                if msg is None:
 
                    msg = self.makeMsg(dev, attrs, outputMap)
 

	
 
                seen[dev] = attrs
 
                client.sendMessage(msg)
 

	
 
    def makeMsg(self, dev, attrs, outputMap):
 
        attrRows = []
 
        for attr, val in list(attrs.items()):
 
            output, index = outputMap[(dev, attr)]
 
            attrRows.append({
 
                'attr': attr.rsplit('/')[-1],
 
                'val': val,
 
                'chan': (output.shortId(), index + 1)
 
            })
 
        attrRows.sort(key=lambda r: r['chan'])
 
        for row in attrRows:
 
            row['chan'] = '%s %s' % (row['chan'][0], row['chan'][1])
 

	
 
        msg = json.dumps({'outputAttrsSet': {
 
            'dev': dev,
 
            'attrs': attrRows
 
        }},
 
                         sort_keys=True)
 
        return msg
 

	
 

	
 
class Updates(cyclone.websocket.WebSocketHandler):
 
@@ -163,10 +61,8 @@ def launch(graph, doLoadTest=False):
 
    try:
 
        # todo: drive outputs with config files
 
        outputs = [
 
            # EnttecDmx(L9['output/dmxA/'], '/dev/dmx3', 80),
 
            Udmx(L9['output/dmxA/'], bus=5, numChannels=80),
 
            #DummyOutput(L9['output/dmxA/'], 80),
 
            Udmx(L9['output/dmxB/'], bus=7, numChannels=500),
 
            DummyOutput(L9['output/dmxA/'], 80),
 
            DummyOutput(L9['output/dmxB/'], 510),
 
        ]
 
    except Exception:
 
        log.error("setting up outputs:")
bin/collector_loadtest.py
Show inline comments
 
import sys
 
sys.path.append('bin')
 
from run_local import log
 
from light9.collector.collector_client import sendToCollector, sendToCollectorZmq
 
from light9.collector.collector_client import sendToCollector
 
from light9.namespaces import L9, DEV
 
from twisted.internet import reactor
 
import time
bin/effecteval
Show inline comments
 
@@ -4,7 +4,7 @@ from run_local import log
 
from twisted.internet import reactor
 
from twisted.internet.defer import inlineCallbacks, returnValue
 
import cyclone.web, cyclone.websocket, cyclone.httpclient
 
import sys, optparse, logging, subprocess, json, itertools
 
import sys, optparse, logging, json, itertools
 
from rdflib import URIRef, Literal
 

	
 
sys.path.append('/usr/lib/pymodules/python2.7/')  # for numpy, on rpi
 
@@ -20,6 +20,7 @@ from rdfdb.syncedgraph import SyncedGrap
 
from greplin import scales
 

	
 
from cycloneerr import PrettyErrorHandler
 
from light9.coffee import StaticCoffee
 

	
 

	
 
class EffectEdit(PrettyErrorHandler, cyclone.web.RequestHandler):
 
@@ -201,9 +202,9 @@ class SongEffectsEval(PrettyErrorHandler
 

	
 
    def get(self):
 
        song = URIRef(self.get_argument('song'))
 
        effects = effectsForSong(self.settings.graph, song)
 
        effects = effectsForSong(self.settings.graph, song) # noqa
 
        raise NotImplementedError
 
        self.write(maxDict(effectDmxDict(e) for e in effects))
 
        self.write(maxDict(effectDmxDict(e) for e in effects)) # noqa
 
        # return dmx dict for all effects in the song, already combined
 

	
 

	
 
@@ -259,19 +260,6 @@ class App(object):
 
        log.info("listening on %s" % networking.effectEval.port)
 

	
 

	
 
class StaticCoffee(PrettyErrorHandler, cyclone.web.RequestHandler):
 

	
 
    def initialize(self, src):
 
        super(StaticCoffee, self).initialize()
 
        self.src = src
 

	
 
    def get(self):
 
        self.set_header('Content-Type', 'application/javascript')
 
        self.write(
 
            subprocess.check_output(
 
                ['/usr/bin/coffee', '--compile', '--print', self.src]))
 

	
 

	
 
if __name__ == "__main__":
 
    parser = optparse.OptionParser()
 
    parser.add_option(
bin/homepageConfig
Show inline comments
 
#!bin/python
 
from run_local import log
 
from rdflib import RDF, URIRef
 
from light9 import networking, showconfig
 
from light9 import showconfig
 
from light9.namespaces import L9
 
from urllib.parse import urlparse
 
from urllib.parse import splitport
 

	
 
from rdfdb.syncedgraph import SyncedGraph
 
from twisted.internet import reactor
 

	
 
log.info('generating config')
 
graph = showconfig.getGraph()
 

	
 
netHome = graph.value(showconfig.showUri(), L9['networking'])
bin/inputdemo
Show inline comments
 
@@ -5,13 +5,12 @@ from twisted.internet import gtk3reactor
 
gtk3reactor.install()
 
from twisted.internet import reactor
 
from rdflib import URIRef
 
import optparse, logging, urllib.request, urllib.parse, urllib.error, time
 
import optparse, logging, time
 
from gi.repository import Gtk
 
from run_local import log
 
from light9 import showconfig, networking
 
from light9 import networking
 
from light9 import clientsession
 
from rdfdb.syncedgraph import SyncedGraph
 
import cyclone.httpclient
 
from light9.curvecalc.client import sendLiveInputPoint
 

	
 

	
bin/inputquneo
Show inline comments
 
@@ -9,7 +9,7 @@ import cyclone.web, cyclone.httpclient
 
from rdflib import URIRef
 
from twisted.internet import reactor, task
 
from light9.curvecalc.client import sendLiveInputPoint
 
from light9.namespaces import L9, RDF, RDFS
 
from light9.namespaces import L9, RDF
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9 import networking
 

	
 
@@ -109,6 +109,7 @@ def main():
 
    graph = SyncedGraph(networking.rdfdb.url, "inputQuneo")
 
    wm = WatchMidi(graph)
 
    reactor.run()
 
    del wm
 

	
 

	
 
main()
bin/keyboardcomposer
Show inline comments
 
@@ -342,16 +342,16 @@ class KeyboardComposer(tk.Frame, SubClie
 
            for key in keys:
 
                # lowercase makes full=0
 
                keysym = "<KeyPress-%s>" % key
 
                tkobject.bind(keysym, \
 
                    lambda evt, num=keys.index(key), d=d: \
 
                        self.got_nudger(num, d))
 
                tkobject.bind(keysym,
 
                              lambda evt, num=keys.index(key), d=d: self.
 
                              got_nudger(num, d))
 

	
 
                # uppercase makes full=1
 
                keysym = "<KeyPress-%s>" % key.upper()
 
                keysym = keysym.replace('SEMICOLON', 'colon')
 
                tkobject.bind(keysym, \
 
                    lambda evt, num=keys.index(key), d=d: \
 
                        self.got_nudger(num, d, full=1))
 
                tkobject.bind(keysym,
 
                              lambda evt, num=keys.index(key), d=d: self.
 
                              got_nudger(num, d, full=1))
 

	
 
        # Row changing:
 
        # Page dn, C-n, and ] do down
bin/listsongs
Show inline comments
 
@@ -7,7 +7,7 @@ function _songs { local expl;  _descript
 
compdef _songs curvecalc
 
"""
 

	
 
from run_local import log
 
from run_local import log  # noqa
 
from twisted.internet import reactor
 
from rdflib import RDF
 
from light9 import networking
bin/musicPad
Show inline comments
 
@@ -5,7 +5,6 @@ rewrite all the songs with silence at th
 
import sys, wave, logging, os
 
sys.path.append(".")
 
from light9 import showconfig
 
from light9.namespaces import L9
 
from light9.ascoltami.playlist import Playlist
 
logging.basicConfig(level=logging.INFO)
 
log = logging.getLogger()
bin/musictime
Show inline comments
 
#!/usr/bin/env python
 
import run_local
 
import run_local  # noqa
 
import light9.networking
 

	
 
import tkinter as tk
bin/paintserver
Show inline comments
 
@@ -13,7 +13,7 @@ from rdflib import URIRef
 
from light9 import clientsession
 
import light9.paint.solve
 
from cycloneerr import PrettyErrorHandler
 
from light9.namespaces import RDF, L9, DEV
 
from light9.namespaces import L9, DEV
 
import imp
 

	
 

	
bin/picamserve
Show inline comments
 
@@ -162,7 +162,6 @@ class Pics(cyclone.web.RequestHandler):
 
                if not self.running:
 
                    raise StopIteration
 

	
 
                now = time.time()
 
                self.write("%s %s\n" % (len(frame), frameTime))
 
                self.write(frame)
 
                self.flush()
bin/rdfdb
Show inline comments
 
#!bin/python
 
import run_local
 
import run_local  # noqa
 
import os
 
from light9 import networking, showconfig
 
import rdfdb.service
bin/subserver
Show inline comments
 
@@ -4,11 +4,11 @@ live web display of all existing subs wi
 
dragging them into CC or Timeline
 
"""
 
from run_local import log
 
import sys, optparse, logging, json, subprocess, datetime
 
import optparse, logging, json, subprocess, datetime
 
from dateutil.tz import tzlocal
 
from twisted.internet import reactor, defer
 
import cyclone.web, cyclone.httpclient, cyclone.websocket
 
from rdflib import RDF, URIRef, Literal
 
from rdflib import URIRef, Literal
 
import pyjade.utils
 
from rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
bin/vidref
Show inline comments
 
@@ -7,10 +7,9 @@ gtk2reactor.install()
 
from twisted.internet import reactor, defer
 
import gobject
 
gobject.threads_init()
 
import gtk
 
import sys, logging, optparse, json
 
import cyclone.web, cyclone.httpclient, cyclone.websocket
 
from light9 import networking, showconfig
 
from light9 import networking
 
from light9.vidref.main import Gui
 
from light9.vidref.replay import snapshotDir
 
from rdfdb.syncedgraph import SyncedGraph
 
@@ -42,7 +41,7 @@ class Snapshot(cyclone.web.RequestHandle
 
            self.write(json.dumps({'snapshot': out}))
 
            self.set_header("Location", out)
 
            self.set_status(303)
 
        except Exception as e:
 
        except Exception:
 
            import traceback
 
            traceback.print_exc()
 
            raise
bin/vidrefsetup
Show inline comments
 
@@ -3,15 +3,12 @@
 
camera captures with a continuous camera capture yet """
 

	
 
from run_local import log
 
import sys, optparse, logging, json, subprocess, datetime
 
from dateutil.tz import tzlocal
 
from twisted.internet import reactor, defer
 
import optparse, logging
 
from twisted.internet import reactor
 
import cyclone.web, cyclone.httpclient, cyclone.websocket
 
from rdflib import RDF, URIRef, Literal
 
import pyjade.utils
 
from rdflib import URIRef
 
from rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9, DCTERMS
 
from light9.namespaces import L9
 
from light9 import networking, showconfig
 

	
 
from cycloneerr import PrettyErrorHandler
bin/wavecurve
Show inline comments
 
#!bin/python
 
import optparse
 
import run_local
 
from run_local import log
 
from light9.wavepoints import simp
 

	
 

	
 
@@ -8,9 +8,10 @@ def createCurve(inpath, outpath, t):
 
    print("reading %s, writing %s" % (inpath, outpath))
 
    points = simp(inpath.replace('.ogg', '.wav'), seconds_per_average=t)
 

	
 
    f = file(outpath, 'w')
 
    f = open(outpath, 'w')
 
    for time_val in points:
 
        print("%s %s" % time_val, file=f)
 
    log.info(r'Wrote {outpath}')
 

	
 

	
 
parser = optparse.OptionParser(usage="""%prog inputSong.wav outputCurve
 
@@ -30,8 +31,6 @@ options, args = parser.parse_args()
 

	
 
if options.all:
 
    from light9 import showconfig
 
    from light9.namespaces import L9
 
    from rdflib import RDF
 
    from light9.ascoltami.playlist import Playlist
 
    graph = showconfig.getGraph()
 

	
lib/ipython_view.py
Show inline comments
 
@@ -21,11 +21,12 @@ import re
 
import sys
 
import os
 
from gi.repository import Pango
 
from StringIO import StringIO
 
from io import StringIO
 
from functools import reduce
 
 
 
try:
 
	import IPython
 
except Exception,e:
 
        import IPython
 
except Exception as e:
 
	raise "Error importing IPython (%s)" % str(e)
 
 
 
ansi_colors =  {'0;30': 'Black',
 
@@ -148,11 +149,11 @@ class IterableIPShell:
 
 
 
  def shell(self, cmd,verbose=0,debug=0,header=''):
 
    stat = 0
 
    if verbose or debug: print header+cmd
 
    if verbose or debug: print(header+cmd)
 
    # flush stdout so we don't mangle python's buffering
 
    if not debug:
 
      input, output = os.popen4(cmd)
 
      print output.read()
 
      print(output.read())
 
      output.close()
 
      input.close()
 
 
light9/Fadable.py
Show inline comments
 
# taken from SnackMix -- now that's reusable code
 
from tkinter.tix import *
 
import time
 

	
 

	
light9/FlyingFader.py
Show inline comments
 
from tkinter.tix import *
 
from time import time, sleep
 

	
 
from tkinter import tix
 
from time import time
 

	
 
class Mass:
 

	
 
@@ -65,7 +64,7 @@ class Mass:
 
        return not self._stopped
 

	
 

	
 
class FlyingFader(Frame):
 
class FlyingFader(tix.Frame):
 

	
 
    def __init__(self,
 
                 master,
 
@@ -75,7 +74,7 @@ class FlyingFader(Frame):
 
                 font=('Arial', 8),
 
                 labelwidth=12,
 
                 **kw):
 
        Frame.__init__(self, master)
 
        tix.Frame.__init__(self, master)
 
        self.name = label
 
        self.variable = variable
 

	
 
@@ -94,25 +93,23 @@ class FlyingFader(Frame):
 
        }
 
        scaleopts.update(kw)
 
        if scaleopts['orient'] == 'vert':
 
            side1 = TOP
 
            side2 = BOTTOM
 
            side2 = tix.BOTTOM
 
        else:
 
            side1 = RIGHT
 
            side2 = LEFT
 
            side2 = tix.LEFT
 

	
 
        self.scale = Scale(self, **scaleopts)
 
        self.vlabel = Label(self, text="0.0", width=6, font=font)
 
        self.label = Label(self,
 
                           text=label,
 
                           font=font,
 
                           anchor='w',
 
                           width=labelwidth)  #wraplength=40, )
 
        self.scale = tix.Scale(self, **scaleopts)
 
        self.vlabel = tix.Label(self, text="0.0", width=6, font=font)
 
        self.label = tix.Label(self,
 
                               text=label,
 
                               font=font,
 
                               anchor='w',
 
                               width=labelwidth)  #wraplength=40, )
 

	
 
        self.oldtrough = self.scale['troughcolor']
 

	
 
        self.scale.pack(side=side2, expand=1, fill=BOTH, anchor='c')
 
        self.vlabel.pack(side=side2, expand=0, fill=X)
 
        self.label.pack(side=side2, expand=0, fill=X)
 
        self.scale.pack(side=side2, expand=1, fill=tix.BOTH, anchor='c')
 
        self.vlabel.pack(side=side2, expand=0, fill=tix.X)
 
        self.label.pack(side=side2, expand=0, fill=tix.X)
 

	
 
        for k in range(1, 10):
 
            self.scale.bind(
 
@@ -150,7 +147,7 @@ class FlyingFader(Frame):
 
        mult = 1
 
        if evt.state & 8 and evt.state & 4: mult = 0.25  # both
 
        elif evt.state & 8: mult = 0.5  # alt
 
        elif evt.state & 4: mult = 2  # control
 
        elif evt.state & 4: mult = 2  # control # noqa
 

	
 
        self.mass.x = self.variable.get()
 
        self.mass.goto(newlevel)
 
@@ -204,22 +201,19 @@ def colorfade(scale, lev):
 

	
 

	
 
if __name__ == '__main__':
 
    root = Tk()
 
    root = tix.Tk()
 
    root.tk_focusFollowsMouse()
 

	
 
    FlyingFader(root, variable=DoubleVar(), label="suck").pack(side=LEFT,
 
                                                               expand=1,
 
                                                               fill=BOTH)
 
    FlyingFader(root, variable=DoubleVar(), label="moof").pack(side=LEFT,
 
                                                               expand=1,
 
                                                               fill=BOTH)
 
    FlyingFader(root, variable=DoubleVar(), label="zarf").pack(side=LEFT,
 
                                                               expand=1,
 
                                                               fill=BOTH)
 
    FlyingFader(root, variable=tix.DoubleVar(),
 
                label="suck").pack(side=tix.LEFT, expand=1, fill=tix.BOTH)
 
    FlyingFader(root, variable=tix.DoubleVar(),
 
                label="moof").pack(side=tix.LEFT, expand=1, fill=tix.BOTH)
 
    FlyingFader(root, variable=tix.DoubleVar(),
 
                label="zarf").pack(side=tix.LEFT, expand=1, fill=tix.BOTH)
 
    FlyingFader(root,
 
                variable=DoubleVar(),
 
                label="long name goes here.  got it?").pack(side=LEFT,
 
                variable=tix.DoubleVar(),
 
                label="long name goes here.  got it?").pack(side=tix.LEFT,
 
                                                            expand=1,
 
                                                            fill=BOTH)
 
                                                            fill=tix.BOTH)
 

	
 
    root.mainloop()
light9/Patch.py
Show inline comments
 
import os
 
from rdflib import RDF
 
from light9.namespaces import L9
 
from light9 import showconfig
light9/Submaster.py
Show inline comments
 
import os, logging, time
 
import logging
 
from rdflib import Graph, RDF
 
from rdflib import RDFS, Literal, BNode
 
from light9.namespaces import L9, XSD
 
from light9.TLUtility import dict_scale, dict_max
 
from light9 import showconfig
 
from light9.Patch import resolve_name, get_dmx_channel, get_channel_uri, reload_data
 
from light9.Patch import resolve_name, get_dmx_channel, get_channel_uri
 
from louie import dispatcher
 
from .rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
log = logging.getLogger('submaster')
 

	
 

	
 
@@ -73,7 +73,7 @@ class Submaster(object):
 
        # not sure how useful this is
 
        if not isinstance(other, Submaster):
 
            return -1
 
        return cmp(self.ident(), other.ident())
 
        return cmp(self.ident(), other.ident()) # noqa
 

	
 
    def __hash__(self):
 
        return hash(self.ident())
 
@@ -189,7 +189,7 @@ class PersistentSubmaster(Submaster):
 
                continue
 
            try:
 
                self.levels[name] = float(val)
 
            except:
 
            except Exception:
 
                log.error("name %r val %r" % (name, val))
 
                raise
 

	
 
@@ -326,11 +326,11 @@ class Submasters(object):
 

	
 
    def get_all_subs(self):
 
        "All Submaster objects"
 
        l = sorted(list(self.submasters.items()))
 
        l = [x[1] for x in l]
 
        v = sorted(list(self.submasters.items()))
 
        v = [x[1] for x in v]
 
        songs = []
 
        notsongs = []
 
        for s in l:
 
        for s in v:
 
            if s.name and s.name.startswith('song'):
 
                songs.append(s)
 
            else:
light9/TLUtility.py
Show inline comments
 
@@ -56,7 +56,7 @@ def dumpobj(o):
 
    for a in [x for x in dir(o) if not callable(getattr(o, x))]:
 
        try:
 
            print("  %20s: %s " % (a, getattr(o, a)))
 
        except:
 
        except Exception:
 
            pass
 
    print("")
 

	
 
@@ -190,7 +190,7 @@ def dict_max(*dicts):
 

	
 
def dict_scale(d, scl):
 
    """scales all values in dict and returns a new dict"""
 
    return dict([(k, v * scl) for k, v in list(d.items())])
 
    return dict([(k, v * scl) for k, v in d.items()])
 

	
 

	
 
def dict_subset(d, dkeys, default=0):
light9/ascoltami/player.py
Show inline comments
 
@@ -4,8 +4,8 @@ alternate to the mpd music player, for a
 
"""
 

	
 
import time, logging, traceback
 
from gi.repository import GObject, Gst
 
from twisted.internet import reactor, task
 
from gi.repository import Gst
 
from twisted.internet import task
 

	
 
log = logging.getLogger()
 

	
 
@@ -30,7 +30,7 @@ class Player(object):
 

	
 
        task.LoopingCall(self.watchTime).start(.050)
 

	
 
        bus = self.pipeline.get_bus()
 
        #bus = self.pipeline.get_bus()
 
        # not working- see notes in pollForMessages
 
        #self.watchForMessages(bus)
 

	
 
@@ -46,7 +46,7 @@ class Player(object):
 
                self.pause()
 

	
 
            self.lastWatchTime = t
 
        except:
 
        except Exception:
 
            traceback.print_exc()
 

	
 
    def watchForMessages(self, bus):
light9/ascoltami/playlist.py
Show inline comments
 
@@ -19,13 +19,13 @@ class Playlist(object):
 
        try:
 
            currentIndex = self.songs.index(currentSong)
 
        except IndexError:
 
            raise ValueError("%r is not in the current playlist (%r)." % \
 
                (currentSong, self.playlistUri))
 
            raise ValueError("%r is not in the current playlist (%r)." %
 
                             (currentSong, self.playlistUri))
 

	
 
        try:
 
            nextSong = self.songs[currentIndex + 1]
 
        except IndexError:
 
            raise NoSuchSong("%r is the last item in the playlist." % \
 
            raise NoSuchSong("%r is the last item in the playlist." %
 
                             currentSong)
 

	
 
        return nextSong
light9/ascoltami/webapp.py
Show inline comments
 
import json, socket, subprocess, cyclone.web, os
 
import json, socket, subprocess, cyclone.web
 
from twisted.python.util import sibpath
 
from twisted.python.filepath import FilePath
 
from light9.namespaces import L9
 
from light9.showconfig import getSongsFromShow, songOnDisk
 
from rdflib import URIRef
 
@@ -140,7 +139,7 @@ class goButton(PrettyErrorHandler, cyclo
 
        """
 
        if music is playing, this silently does nothing.
 
        """
 
        graph, player = self.settings.app.graph, self.settings.app.player
 
        player = self.settings.app.player
 

	
 
        if player.isAutostopped():
 
            player.resume()
light9/coffee.py
Show inline comments
 
new file 100644
 
from cycloneerr import PrettyErrorHandler
 
import cyclone.web
 
import subprocess
 

	
 

	
 
class StaticCoffee(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    """
 
    e.g.
 

	
 
            (r'/effect\.js', StaticCoffee, {
 
                'src': 'light9/effecteval/effect.coffee'
 
            }),
 
    """ # noqa
 

	
 
    def initialize(self, src):
 
        super(StaticCoffee, self).initialize()
 
        self.src = src
 

	
 
    def get(self):
 
        self.set_header('Content-Type', 'application/javascript')
 
        self.write(
 
            subprocess.check_output(
 
                ['/usr/bin/coffee', '--compile', '--print', self.src]))
light9/collector/collector.py
Show inline comments
 
@@ -7,8 +7,9 @@ from light9.collector.device import toOu
 

	
 
# types only
 
from rdflib import Graph, URIRef
 
from typing import List, Dict, Tuple, Any, TypeVar, Generic
 
from typing import List, Dict, Tuple, TypeVar, Generic, Optional
 
from light9.collector.output import Output
 
from light9.collector.weblisteners import WebListeners
 

	
 
ClientType = TypeVar('ClientType')
 
ClientSessionType = TypeVar('ClientSessionType')
 
@@ -24,7 +25,7 @@ def outputMap(graph, outputs):
 
    """
 
    ret = {}
 

	
 
    outputByUri = {}  # universeUri : output
 
    outputByUri: Dict[URIRef, Output] = {}  # universeUri : output
 
    for out in outputs:
 
        outputByUri[out.uri] = out
 

	
 
@@ -50,8 +51,11 @@ def outputMap(graph, outputs):
 

	
 
class Collector(Generic[ClientType, ClientSessionType]):
 

	
 
    def __init__(self, graph, outputs, listeners=None, clientTimeoutSec=10):
 
        # type: (Graph, List[Output], List[Listener], float) -> None
 
    def __init__(self,
 
                 graph: Graph,
 
                 outputs: List[Output],
 
                 listeners: Optional[WebListeners] = None,
 
                 clientTimeoutSec: float = 10):
 
        self.graph = graph
 
        self.outputs = outputs
 
        self.listeners = listeners
light9/collector/collector_test.py
Show inline comments
 
import unittest
 
import datetime, time
 
from freezegun import freeze_time
 
from rdflib import Namespace, URIRef
 
from rdflib import Namespace
 

	
 
from light9.namespaces import L9, DEV
 
from light9.collector.collector import Collector, outputMap
light9/collector/device.py
Show inline comments
 
import logging
 
import math
 
from light9.namespaces import L9, RDF, DEV
 
from light9.namespaces import L9
 
from rdflib import Literal
 
from webcolors import hex_to_rgb, rgb_to_hex
 
from colormath.color_objects import sRGBColor, CMYColor
light9/collector/output.py
Show inline comments
 
@@ -3,7 +3,7 @@ import sys
 
import time
 
import usb.core
 
import logging
 
from twisted.internet import task, threads, reactor
 
from twisted.internet import threads, reactor
 
from greplin import scales
 
log = logging.getLogger('output')
 

	
light9/collector/weblisteners.py
Show inline comments
 
new file 100644
 
import logging, traceback, time, json
 
log = logging.getLogger('weblisteners')
 

	
 
class WebListeners(object):
 

	
 
    def __init__(self):
 
        self.clients = []
 
        self.pendingMessageForDev = {}  # dev: (attrs, outputmap)
 
        self.lastFlush = 0
 

	
 
    def addClient(self, client):
 
        self.clients.append([client, {}])  # seen = {dev: attrs}
 
        log.info('added client %s %s', len(self.clients), client)
 

	
 
    def delClient(self, client):
 
        self.clients = [[c, t] for c, t in self.clients if c != client]
 
        log.info('delClient %s, %s left', client, len(self.clients))
 

	
 
    def outputAttrsSet(self, dev, attrs, outputMap):
 
        """called often- don't be slow"""
 

	
 
        self.pendingMessageForDev[dev] = (attrs, outputMap)
 
        try:
 
            self._flush()
 
        except Exception:
 
            traceback.print_exc()
 
            raise
 

	
 
    def _flush(self):
 
        now = time.time()
 
        if now < self.lastFlush + .05 or not self.clients:
 
            return
 
        self.lastFlush = now
 

	
 
        while self.pendingMessageForDev:
 
            dev, (attrs, outputMap) = self.pendingMessageForDev.popitem()
 

	
 
            msg = None  # lazy, since makeMsg is slow
 

	
 
            # this omits repeats, but can still send many
 
            # messages/sec. Not sure if piling up messages for the browser
 
            # could lead to slowdowns in the real dmx output.
 
            for client, seen in self.clients:
 
                if seen.get(dev) == attrs:
 
                    continue
 
                if msg is None:
 
                    msg = self.makeMsg(dev, attrs, outputMap)
 

	
 
                seen[dev] = attrs
 
                client.sendMessage(msg)
 

	
 
    def makeMsg(self, dev, attrs, outputMap):
 
        attrRows = []
 
        for attr, val in attrs.items():
 
            output, index = outputMap[(dev, attr)]
 
            attrRows.append({
 
                'attr': attr.rsplit('/')[-1],
 
                'val': val,
 
                'chan': (output.shortId(), index + 1)
 
            })
 
        attrRows.sort(key=lambda r: r['chan'])
 
        for row in attrRows:
 
            row['chan'] = '%s %s' % (row['chan'][0], row['chan'][1])
 

	
 
        msg = json.dumps({'outputAttrsSet': {
 
            'dev': dev,
 
            'attrs': attrRows
 
        }},
 
                         sort_keys=True)
 
        return msg
light9/curvecalc/client.py
Show inline comments
 
@@ -4,7 +4,6 @@ client code for talking to curvecalc
 
import cyclone.httpclient
 
from light9 import networking
 
import urllib.request, urllib.parse, urllib.error
 
from run_local import log
 

	
 

	
 
def sendLiveInputPoint(curve, value):
light9/curvecalc/curve.py
Show inline comments
 
import glob, time, logging, ast, os
 
import logging, ast, os
 
from bisect import bisect_left, bisect
 
import louie as dispatcher
 
from twisted.internet import reactor
 
@@ -45,7 +45,7 @@ class Curve(object):
 

	
 
    def load(self, filename):
 
        self.points[:] = []
 
        for line in file(filename):
 
        for line in open(filename):
 
            x, y = line.split()
 
            self.points.append((float(x), ast.literal_eval(y)))
 
        self.points.sort()
 
@@ -75,7 +75,7 @@ class Curve(object):
 
        if filename.endswith('-music') or filename.endswith('_music'):
 
            print("not saving music track")
 
            return
 
        f = file(filename, 'w')
 
        f = open(filename, 'w')
 
        for p in self.points:
 
            f.write("%s %r\n" % p)
 
        f.close()
light9/curvecalc/curveedit.py
Show inline comments
 
"""
 
this may be split out from curvecalc someday, since it doesn't
 
need to be tied to a gui """
 
import cgi, time
 
import cgi
 
from twisted.internet import reactor
 
import cyclone.web, cyclone.httpclient, cyclone.websocket
 
from rdflib import URIRef
 
from cycloneerr import PrettyErrorHandler
 
from run_local import log
 
from louie import dispatcher
 

	
 

	
light9/curvecalc/curveview.py
Show inline comments
 
import math, logging, traceback
 
import math, logging
 
from gi.repository import Gtk
 
from gi.repository import Gdk
 
from gi.repository import GooCanvas
 
@@ -6,7 +6,6 @@ import louie as dispatcher
 
from rdflib import Literal
 
from twisted.internet import reactor
 
from light9.curvecalc.zoomcontrol import RegionZoom
 
from light9.curvecalc import cursors
 
from light9.curvecalc.curve import introPad, postPad
 
from lib.goocanvas_compat import Points, polyline_new_line
 
import imp
 
@@ -1276,8 +1275,8 @@ class Curvesetview(object):
 
        if not self.live:  # workaround for old instances living past reload()
 
            return
 

	
 
        r = self.row_under_mouse()
 
        key = event.string
 
        #r = self.row_under_mouse()
 
        #key = event.string
 
        pass  # no handlers right now
 

	
 
    def row_under_mouse(self):
light9/curvecalc/output.py
Show inline comments
 
import time, logging
 
from twisted.internet import reactor
 
from light9 import Submaster, dmxclient
 
from light9.namespaces import L9
 
from light9.curvecalc.subterm import Subterm
 

	
 
from louie import dispatcher
 
log = logging.getLogger("output")
light9/curvecalc/subterm.py
Show inline comments
 
import math, os, random, logging
 
from rdflib import Graph, URIRef, RDF, RDFS, Literal
 
import logging
 
from rdflib import Literal
 
from louie import dispatcher
 
import light9.Effects
 
from light9 import Submaster, showconfig, prof
 
from light9 import Submaster
 
from light9.Patch import get_dmx_channel
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9
light9/curvecalc/zoomcontrol.py
Show inline comments
 
from gi.repository import Gtk
 
from gi.repository import GObject
 
from gi.repository import GooCanvas
 
import louie as dispatcher
 
from light9.curvecalc import cursors
light9/dmxchanedit.py
Show inline comments
 
@@ -18,7 +18,7 @@ proposal for new attribute system:
 
"""
 

	
 
import tkinter as tk
 
from rdflib import RDF, Literal
 
from rdflib import RDF
 
import math, logging
 
from decimal import Decimal
 
from light9.namespaces import L9
light9/dmxclient.py
Show inline comments
 
@@ -72,5 +72,5 @@ dummy = os.getenv('DMXDUMMY')
 
if dummy:
 
    print("dmxclient: DMX is in dummy mode.")
 

	
 
    def outputlevels(*args, **kw):
 
    def outputlevels(*args, **kw): # noqa
 
        pass
light9/effect/effecteval.py
Show inline comments
 
from rdflib import URIRef, Literal
 
from light9.namespaces import L9, RDF, DEV
 
from rdflib import Literal
 
from light9.namespaces import L9, DEV
 
from webcolors import rgb_to_hex, hex_to_rgb
 
from colorsys import hsv_to_rgb
 
from decimal import Decimal
 
import math
 
import traceback
 
from noise import pnoise1
 
import logging
 
import time
 
from light9.effect.settings import DeviceSettings
 
from light9.effect.scale import scale
 
import random
 
@@ -135,7 +132,6 @@ def effect_animRainbow(effectSettings, s
 
def effect_auraSparkles(effectSettings, strength, songTime, noteTime):
 
    out = {}
 
    tint = effectSettings.get(L9['tint'], '#ffffff')
 
    tintStrength = float(effectSettings.get(L9['tintStrength'], 0))
 
    print(effectSettings)
 
    tr, tg, tb = hex_to_rgb(tint)
 
    for n in range(1, 5 + 1):
light9/effect/sequencer.py
Show inline comments
 
@@ -44,7 +44,9 @@ class Note(object):
 
            ea = settingValues[L9['effectAttr']]
 
            self.baseEffectSettings[ea] = settingValues[L9['value']]
 

	
 
        floatVal = lambda s, p: float(g.value(s, p).toPython())
 
        def floatVal(s, p):
 
            return float(g.value(s, p).toPython())
 

	
 
        originTime = floatVal(uri, L9['originTime'])
 
        self.points = []
 
        for curve in g.objects(uri, L9['curve']):
light9/effect/settings.py
Show inline comments
 
@@ -6,8 +6,7 @@ or output attrs (dmx channel).
 
import decimal
 
import numpy
 
from rdflib import URIRef, Literal
 
from light9.namespaces import RDF, L9, DEV
 
from rdfdb.patch import Patch
 
from light9.namespaces import RDF, L9
 
import logging
 
log = logging.getLogger('settings')
 
from light9.collector.device import resolve
light9/effect/settings_test.py
Show inline comments
 
@@ -2,7 +2,7 @@ import unittest
 
from rdflib import Literal
 
from rdfdb.patch import Patch
 
from rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.namespaces import RDF, L9, DEV
 
from light9.namespaces import L9, DEV
 
from light9.effect.settings import DeviceSettings
 

	
 

	
light9/effecteval/effectloop.py
Show inline comments
 
import time, json, logging, traceback
 
import numpy
 
import serial
 
from twisted.internet import reactor, threads
 
from twisted.internet import reactor
 
from twisted.internet.defer import inlineCallbacks, returnValue, succeed
 
from twisted.internet.error import TimeoutError
 
from rdflib import URIRef, Literal
 
from rdflib import URIRef
 
import cyclone.httpclient
 
from light9.namespaces import L9, RDF, RDFS
 
from light9.namespaces import L9, RDF
 
from light9.effecteval.effect import EffectNode
 
from light9 import Effects
 
from light9 import networking
 
from light9 import Submaster
 
from light9 import dmxclient
 
from light9 import prof
 
log = logging.getLogger('effectloop')
 

	
 

	
light9/gtkpyconsole.py
Show inline comments
 
from lib.ipython_view import IPythonView
 
import gi
 
import gi # noqa
 
from gi.repository import Gtk
 
from gi.repository import Pango
 

	
light9/namespaces.py
Show inline comments
 
from rdflib import Namespace, RDF, RDFS
 
from rdflib import Namespace, RDF, RDFS  # noqa
 

	
 

	
 
# Namespace was showing up in profiles
light9/paint/solve.py
Show inline comments
 
from light9.namespaces import RDF, L9, DEV
 
from light9.namespaces import L9, DEV
 
from PIL import Image
 
import numpy
 
import scipy.misc, scipy.ndimage, scipy.optimize
 
import cairo
 
import logging
 

	
 
from light9.effect.settings import DeviceSettings, parseHex, toHex
 
from light9.effect.settings import DeviceSettings, parseHex
 

	
 
log = logging.getLogger('solve')
 

	
 
@@ -151,7 +151,7 @@ class Solver(object):
 
        results = []
 
        dist = ImageDist(img)
 
        if device is None:
 
            items = list(self.samples.items())
 
            items = self.samples.items()
 
        else:
 
            items = self.samplesForDevice[device]
 
        for uri, img2 in sorted(items):
 
@@ -220,18 +220,18 @@ class Solver(object):
 
            #saveNumpy('/tmp/sample_%s.png' % sample.split('/')[-1],
 
            #          f(picSample))
 
            sampleDist[sample] = dist.distanceTo(picSample)
 
        results = sorted([(d, uri) for uri, d in list(sampleDist.items())])
 
        results = sorted([(d, uri) for uri, d in sampleDist.items()])
 

	
 
        sample = results[0][1]
 

	
 
        # this is wrong; some wrong-alignments ought to be dimmer than full
 
        brightest0 = brightest(pic0)
 
        brightestSample = brightest(self.samples[sample])
 
        #brightestSample = brightest(self.samples[sample])
 

	
 
        if max(brightest0) < 1 / 255:
 
            return DeviceSettings(self.graph, [])
 

	
 
        scale = brightest0 / brightestSample
 
        #scale = brightest0 / brightestSample
 

	
 
        s = DeviceSettings.fromResource(self.graph, sample)
 
        # missing color scale, but it was wrong to operate on all devs at once
 
@@ -300,7 +300,7 @@ class Solver(object):
 
        for dev, devSettings in settings.byDevice():
 
            requestedColor = devSettings.getValue(dev, L9['color'])
 
            candidatePics = []  # (distance, path, picColor)
 
            for sample, s in list(self.sampleSettings.items()):
 
            for sample, s in self.sampleSettings.items():
 
                path = self.path[sample]
 
                otherDevSettings = s.ofDevice(dev)
 
                if not otherDevSettings:
light9/paint/solve_test.py
Show inline comments
 
@@ -2,7 +2,7 @@ import unittest
 
import numpy.testing
 
from . import solve
 
from rdflib import Namespace
 
from light9.namespaces import RDF, L9, DEV
 
from light9.namespaces import L9, DEV
 
from rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.effect.settings import DeviceSettings
 

	
light9/showconfig.py
Show inline comments
 
@@ -3,7 +3,7 @@ from twisted.python.filepath import File
 
from os import path, getenv
 
from rdflib import Graph
 
from rdflib import URIRef
 
from .namespaces import MUS, L9
 
from .namespaces import L9
 
log = logging.getLogger('showconfig')
 

	
 
_config = None  # graph
light9/subclient.py
Show inline comments
 
from light9.collector.collector_client import sendToCollector
 
from twisted.internet import reactor, task
 
from twisted.internet import reactor
 
import traceback
 
import time
 
import logging
 
@@ -38,7 +38,7 @@ class SubClient:
 
        try:
 
            with self.graph.currentState() as g:
 
                outputSettings = self.get_output_settings(_graph=g)
 
        except:
 
        except Exception:
 
            traceback.print_exc()
 
            return
 
        return sendToCollector('subclient', self.session, outputSettings)
light9/uihelpers.py
Show inline comments
 
@@ -33,7 +33,7 @@ def toplevel_savegeometry(tl, name):
 
            f = open(".light9-window-geometry-%s" % name.replace(' ', '_'), 'w')
 
            f.write(tl.geometry())
 
        # else the window never got mapped
 
    except Exception as e:
 
    except Exception:
 
        # it's ok if there's no saved geometry
 
        pass
 

	
light9/vidref/main.py
Show inline comments
 
@@ -79,7 +79,7 @@ class Gui(object):
 
        try:
 
            with gtk.gdk.lock:
 
                self.replayViews.update(position)
 
        except:
 
        except Exception:
 
            traceback.print_exc()
 
        return True
 

	
light9/vidref/musictime.py
Show inline comments
 
import restkit, time, json, logging
 
import time, json, logging
 
from light9 import networking
 
from twisted.internet import reactor
 
from cyclone.httpclient import fetch
 
from restkit.errors import ResourceNotFound
 
import http_parser.http
 
log = logging.getLogger()
 

	
 

	
 
@@ -29,7 +27,6 @@ class MusicTime(object):
 
        self.period = period
 
        self.hoverPeriod = .05
 
        self.onChange = onChange
 
        self.musicResource = restkit.Resource(networking.musicPlayer.url)
 

	
 
        self.position = {}
 
        # driven by our pollCurvecalcTime and also by Gui.incomingTime
 
@@ -125,6 +122,9 @@ class MusicTime(object):
 

	
 
    def sendTime(self, t):
 
        """request that the player go to this time"""
 
        self.musicResource.post("time",
 
                                payload=json.dumps({"t": t}),
 
                                headers={"content-type": "application/json"})
 
        fetch(
 
            method=b'POST',
 
            url=networking.musicPlayer.path('time'),
 
            body=json.dumps({"t": t}),
 
            headers={b"content-type": [b"application/json"]},
 
        )
light9/vidref/remotepivideo.py
Show inline comments
 
@@ -6,8 +6,8 @@ import gtk
 
import numpy
 
import treq
 
from twisted.internet import defer
 
from light9.vidref.replay import framerate, songDir, takeDir, snapshotDir
 
from light9 import prof, showconfig
 
from light9.vidref.replay import songDir, takeDir, snapshotDir
 
from light9 import showconfig
 
from light9.namespaces import L9
 
from PIL import Image
 
from io import StringIO
light9/vidref/videorecorder.py
Show inline comments
 
@@ -158,7 +158,7 @@ class VideoRecordSink(gst.Element):
 
            img = Image.fromstring('RGB', (cap['width'], cap['height']),
 
                                   buffer.data)
 
            self.imagesToSave.put((position, img, buffer.timestamp))
 
        except:
 
        except Exception:
 
            traceback.print_exc()
 

	
 
        return gst.FLOW_OK
light9/wavepoints.py
Show inline comments
 
@@ -4,13 +4,14 @@ import wave, audioop
 
def simp(filename, seconds_per_average=0.001):
 
    """smaller seconds_per_average means fewer data points"""
 
    wavefile = wave.open(filename, 'rb')
 
    print("# gnuplot data for %s, seconds_per_average=%s" % \
 
        (filename, seconds_per_average))
 
    print("# gnuplot data for %s, seconds_per_average=%s" %
 
          (filename, seconds_per_average))
 
    print(
 
        "# %d channels, samplewidth: %d, framerate: %s, frames: %d\n# Compression type: %s (%s)"
 
        % wavefile.getparams())
 

	
 
    framerate = wavefile.getframerate()  # frames / second
 

	
 
    frames_to_read = int(framerate * seconds_per_average)
 
    print("# frames_to_read=%s" % frames_to_read)
 

	
 
@@ -31,7 +32,7 @@ def simp(filename, seconds_per_average=0
 
        values.append(m)
 
        count += frames_to_read
 
        # if count>1000000:
 
        # break
 
        #     break
 

	
 
    # find the min and max
 
    min_value, max_value = min(values), max(values)
light9/zmqtransport.py
Show inline comments
 
new file 100644
 
import json
 
from rdflib import URIRef, Literal
 
from greplin import scales
 
from txzmq import ZmqEndpoint, ZmqFactory, ZmqPullConnection
 
import logging
 

	
 
log = logging.getLogger('zmq')
 

	
 

	
 
def parseJsonMessage(msg):
 
    body = json.loads(msg)
 
    settings = []
 
    for device, attr, value in body['settings']:
 
        if isinstance(value, str) and value.startswith('http'):
 
            value = URIRef(value)
 
        else:
 
            value = Literal(value)
 
        settings.append((URIRef(device), URIRef(attr), value))
 
    return body['client'], body['clientSession'], settings, body['sendTime']
 

	
 

	
 
def startZmq(port, collector):
 
    stats = scales.collection('/zmqServer', scales.PmfStat('setAttr'))
 

	
 
    zf = ZmqFactory()
 
    addr = 'tcp://*:%s' % port
 
    log.info('creating zmq endpoint at %r', addr)
 
    e = ZmqEndpoint('bind', addr)
 

	
 
    class Pull(ZmqPullConnection):
 
        #highWaterMark = 3
 
        def onPull(self, message):
 
            with stats.setAttr.time():
 
                # todo: new compressed protocol where you send all URIs up
 
                # front and then use small ints to refer to devices and
 
                # attributes in subsequent requests.
 
                client, clientSession, settings, sendTime = parseJsonMessage(
 
                    message[0])
 
                collector.setAttrs(client, clientSession, settings, sendTime)
 

	
 
    Pull(zf, e)
0 comments (0 inline, 0 general)