Changeset - 6fa4288da8a6
[Not reviewed]
bin/captureDevice
Show inline comments
 
#!bin/python
 
from __future__ import division
 
from rdflib import URIRef
 
from twisted.internet import reactor
 
from twisted.internet.defer import inlineCallbacks, Deferred
 

	
 
import logging
 
import optparse
 
import os
 
import time
 
import treq
 
import cyclone.web, cyclone.websocket, cyclone.httpclient
 
from greplin import scales
 

	
 
from run_local import log
 
from lib.cycloneerr import PrettyErrorHandler
 

	
 
from light9.namespaces import L9, RDF
 
from light9 import networking, showconfig
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9.paint.capture import writeCaptureDescription
 
from light9.greplin_cyclone import StatsForCyclone
 
from light9.effect.settings import DeviceSettings
 
from light9.effect.sequencer import sendToCollector
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 

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

	
 
class Camera(object):
 
    def __init__(self, imageUrl):
 
        self.imageUrl = imageUrl
 
    
 
    def takePic(self, uri, writePath):
 
        log.info('takePic %s', uri)
 
        return treq.get(self.imageUrl).addCallbacks(
 
            lambda r: self._done(writePath, r), log.error)
 
        
 
    @inlineCallbacks
 
    def _done(self, writePath, response):
 
        jpg = yield response.content()
 
        try:
 
            os.makedirs(os.path.dirname(writePath))
 
        except OSError:
 
            pass
 
        with open(writePath, 'w') as out:
 
            out.write(jpg)
 
        log.info('wrote %s', writePath)
 

	
 
def deferSleep(sec):
bin/clientdemo
Show inline comments
 
#!bin/python
 

	
 
import os, sys
 
sys.path.append(".")
 
from twisted.internet import reactor
 
import cyclone.web, cyclone.httpclient, logging
 
from rdflib import Namespace, Literal, URIRef
 
from light9 import networking
 
from light9.rdfdb.patch import Patch
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
if __name__ == "__main__":
 
    logging.basicConfig(level=logging.DEBUG)
 
    log = logging.getLogger()
 

	
 
    g = SyncedGraph(networking.rdfdb.url, "clientdemo")
 

	
 
    from light9.Submaster import PersistentSubmaster
 
    sub = PersistentSubmaster(graph=g, uri=URIRef("http://light9.bigasterisk.com/sub/bcools"))
 

	
 
    #get sub to show its updating name, then push that all the way into KC gui so we can see just names refresh in there
 

	
 

	
 
    L9 = Namespace("http://light9.bigasterisk.com/")
 
    def updateDemoValue():
 
        v = list(g.objects(L9['demo'], L9['is']))
 
        print "demo value is %r" % v
 

	
 
    g.addHandler(updateDemoValue)
 

	
 
    def adj():
 
        g.patch(Patch(addQuads=[(L9['demo'], L9['is'], Literal(os.getpid()),
 
                                 L9['clientdemo'])],
 
                      delQuads=[]))
bin/collector
Show inline comments
 
@@ -4,49 +4,49 @@ Collector receives device attrs from mul
 
them, and sends output attrs to hardware. The combining part has
 
custom code for some attributes.
 

	
 
Input can be over http or zmq.
 
"""
 

	
 
from __future__ import division
 
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 run_local import log
 
from lib.cycloneerr import PrettyErrorHandler
 
from light9.collector.output import EnttecDmx, Udmx, DummyOutput
 
from light9.collector.collector import Collector
 
from light9.namespaces import L9
 
from light9 import networking
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9.greplin_cyclone import StatsForCyclone
 

	
 
def parseJsonMessage(msg):
 
    body = json.loads(msg)
 
    settings = []
 
    for device, attr, value in body['settings']:
 
        if isinstance(value, basestring) 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)
 
    s = ZmqPullConnection(zf, e)
 
    def onPull(message):
 
        with stats.setAttr.time():
bin/curvecalc
Show inline comments
 
@@ -20,51 +20,51 @@ from twisted.internet import reactor
 
import time, textwrap, os, optparse, linecache, signal, traceback, json
 
import gi
 
from gi.repository import Gtk
 
from gi.repository import GObject
 
from gi.repository import Gdk
 

	
 
from urlparse import parse_qsl
 
import louie as dispatcher 
 
from rdflib import URIRef, Literal, RDF, RDFS
 
import logging
 

	
 
from run_local import log
 
from light9 import showconfig, networking
 
from light9.curvecalc import curveview 
 
from light9.curvecalc.curve import Curveset
 
from light9.curvecalc.curveedit import serveCurveEdit
 
from light9.curvecalc.musicaccess import Music
 
from light9.curvecalc.output import Output
 
from light9.curvecalc.subterm import Subterm
 
from light9.curvecalc.subtermview import add_one_subterm
 
from light9.editchoicegtk import EditChoice, Local
 
from light9.gtkpyconsole import togglePyConsole
 
from light9.namespaces import L9
 
from light9.observable import Observable
 
from light9.rdfdb import clientsession
 
from light9.rdfdb.patch import Patch
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb import clientsession
 
from rdfdb.patch import Patch
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9.wavelength import wavelength
 

	
 
class SubtermExists(ValueError):
 
    pass
 

	
 
class Main(object):
 
    def __init__(self, graph, opts, session, curveset, music):
 
        self.graph, self.opts, self.session = graph, opts, session
 
        self.curveset, self.music = curveset, music
 
        self.lastSeenInputTime = 0
 
        self.currentSubterms = [] # Subterm objects that are synced to the graph
 

	
 
        self.setTheme()
 
        wtree = self.wtree = Gtk.Builder()
 
        wtree.add_from_file("light9/curvecalc/curvecalc.glade")
 
        mainwin = wtree.get_object("MainWindow")
 
        
 
        mainwin.connect("destroy", self.onQuit)
 
        wtree.connect_signals(self)
 

	
 
        mainwin.show_all()
 

	
 
        mainwin.connect("delete-event", lambda *args: reactor.crash())
 
        def updateTitle():
bin/effecteval
Show inline comments
 
#!bin/python
 

	
 
from __future__ import division
 
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
 
from rdflib import URIRef, Literal
 

	
 
sys.path.append('/usr/lib/pymodules/python2.7/') # for numpy, on rpi
 
sys.path.append('/usr/lib/python2.7/dist-packages') # For numpy
 
from light9 import networking, showconfig
 
from light9.effecteval.effect import EffectNode
 
from light9.effect.edit import getMusicStatus, songNotePatch
 
from light9.effecteval.effectloop import makeEffectLoop
 
from light9.greplin_cyclone import StatsForCyclone
 
from light9.namespaces import L9
 
from light9.rdfdb.patch import Patch
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
 
from rdfdb.syncedgraph import SyncedGraph
 
from greplin import scales
 

	
 
from lib.cycloneerr import PrettyErrorHandler
 

	
 
class EffectEdit(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def get(self):
 
        self.set_header('Content-Type', 'text/html')        
 
        self.write(open("light9/effecteval/effect.html").read())
 
    def delete(self):
 
        graph = self.settings.graph
 
        uri = URIRef(self.get_argument('uri'))
 
        with graph.currentState(tripleFilter=(None, L9['effect'], uri)) as g:
 
            song = ctx = list(g.subjects(L9['effect'], uri))[0]
 
        self.settings.graph.patch(Patch(delQuads=[
 
            (song, L9['effect'], uri, ctx),
 
            ]))
 
        
 
@inlineCallbacks
 
def currentSong():
 
    s = (yield getMusicStatus())['song']
 
    if s is None:
 
        raise ValueError("no current song")
 
    returnValue(URIRef(s))
 

	
bin/effectsequencer
Show inline comments
 
#!bin/python
 
"""
 
plays back effect notes from the timeline
 
"""
 
from __future__ import division
 
from run_local import log
 
from twisted.internet import reactor
 
from light9.greplin_cyclone import StatsForCyclone
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9 import networking, showconfig
 
from greplin import scales
 
import optparse, sys, logging
 
import cyclone.web
 
from rdflib import URIRef
 
from light9.effect.sequencer import Sequencer, sendToCollector
 
from light9.rdfdb import clientsession
 
from rdfdb import clientsession
 

	
 
class App(object):
 
    def __init__(self, show, session):
 
        self.show = show
 
        self.session = session
 

	
 
        self.graph = SyncedGraph(networking.rdfdb.url, "effectSequencer")
 
        self.graph.initiallySynced.addCallback(self.launch)
 

	
 

	
 
        self.stats = scales.collection('/',
 
                                       scales.PmfStat('sendLevels'),
 
                                       scales.PmfStat('getMusic'),
 
                                       scales.PmfStat('evals'),
 
                                       scales.PmfStat('sendOutput'),
 
                                       scales.IntStat('errors'),
 
                                       )
 
    def launch(self, *args):
 
        self.seq = Sequencer(
 
            self.graph,
 
            lambda settings: sendToCollector('effectSequencer', self.session,
 
                                             settings))
 

	
 
        self.cycloneApp = cyclone.web.Application(handlers=[
bin/gtk_dnd_demo.py
Show inline comments
 
#!bin/python
 
import run_local
 
import gtk
 
import sys
 
sys.path.append(".")
 
from rdflib import URIRef
 
from light9 import networking
 
from light9.editchoicegtk import EditChoice, Local
 
from light9.observable import Observable
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
win = gtk.Window()
 

	
 
graph = SyncedGraph(networking.rdfdb.url, "gtkdnddemo")
 

	
 
r1 = URIRef("http://example.com/interestingThing")
 
v = Observable(r1)
 
win.add(EditChoice(graph, v))
 
win.show_all()
 
gtk.main()
bin/homepageConfig
Show inline comments
 
#!bin/python
 
from run_local import log
 
from rdflib import RDF, URIRef
 
from light9 import networking, showconfig
 
from light9.namespaces import L9
 
from urlparse import urlparse
 
from urllib import splitport
 

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

	
 
graph = showconfig.getGraph()
 

	
 
netHome = graph.value(showconfig.showUri(), L9['networking'])
 
webServer = graph.value(netHome, L9['webServer'])
 
if not webServer:
 
    raise ValueError('no %r :webServer' % netHome)
 
print "listen %s;" % splitport(urlparse(webServer).netloc)[1]
 

	
 
def location(path, server):
 
    print """
 
    location /%(path)s/ {
 

	
 
      # for websocket
 
      proxy_http_version 1.1;
 
      proxy_set_header Upgrade $http_upgrade;
 
      proxy_set_header Connection "upgrade";
 
      proxy_set_header Host $host;
 

	
 
      proxy_pass %(server)s;
 
      proxy_buffering off;
 
      rewrite /[^/]+/(.*) /$1 break;
 
    }""" % vars()
bin/inputdemo
Show inline comments
 
#!bin/python
 
import sys
 
sys.path.append('/usr/lib/python2.7/dist-packages') # For gtk
 
from twisted.internet import gtk3reactor
 
gtk3reactor.install()
 
from twisted.internet import reactor
 
from rdflib import URIRef
 
import optparse, logging, urllib, time
 
from gi.repository import Gtk
 
from run_local import log
 
from light9 import showconfig, networking
 
from light9.rdfdb import clientsession
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb import clientsession
 
from rdfdb.syncedgraph import SyncedGraph
 
import cyclone.httpclient
 
from light9.curvecalc.client import sendLiveInputPoint
 

	
 
class App(object):
 
    def __init__(self):
 
        parser = optparse.OptionParser()
 
        parser.set_usage("%prog [opts] [curve uri]")
 
        parser.add_option("--debug", action="store_true",
 
                          help="log at DEBUG")
 
        clientsession.add_option(parser)
 
        opts, args = parser.parse_args()
 

	
 
        log.setLevel(logging.DEBUG if opts.debug else logging.INFO)
 

	
 
        self.session = clientsession.getUri('inputdemo', opts)
 
        self.graph = SyncedGraph(networking.rdfdb.url, "inputdemo")
 

	
 
        self.graph.initiallySynced.addCallback(lambda _: self.launch())
 

	
 
        self.curve = args[0] if args else URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-1401259747.675542')
 
        print "sending points on curve %s" % self.curve
 
        
 
        reactor.run()
 

	
bin/inputquneo
Show inline comments
 
#!bin/python
 
"""
 
read Quneo midi events, write to curvecalc and maybe to effects
 
"""
 
from __future__ import division
 
from run_local import log
 
import logging, urllib
 
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.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9 import networking
 

	
 
import sys
 
sys.path.append('/usr/lib/python2.7/dist-packages') # For pygame
 
import pygame.midi
 

	
 
curves = {
 
    23: URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-2'),
 
    24: URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-3'),
 
    25: URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-4'),
 
    6:URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-5'),
 
    18: URIRef('http://light9.bigasterisk.com/show/dance2014/song1/curve/c-6'),
 
}
 

	
 
class WatchMidi(object):
 
    def __init__(self, graph):
 
        self.graph = graph
 
        pygame.midi.init()
 

	
 
        dev = self.findQuneo()
 
        self.inp = pygame.midi.Input(dev)
 
        task.LoopingCall(self.step).start(.05)
 

	
 
        self.noteIsOn = {}
bin/keyboardcomposer
Show inline comments
 
#!bin/python
 

	
 
from __future__ import division, nested_scopes
 
from run_local import log
 
import cgi, time, logging
 
from optparse import OptionParser
 
import webcolors, colorsys
 
from louie import dispatcher
 
from twisted.internet import reactor, tksupport
 
from twisted.web import resource
 
from rdflib import URIRef, Literal
 
import Tix as tk
 

	
 
from light9.Fadable import Fadable
 
from light9.subclient import SubClient
 
from light9 import showconfig, networking, prof
 
from light9.uihelpers import toplevelat
 
from light9.namespaces import L9, RDF, RDFS
 
from light9.tkdnd import initTkdnd, dragSourceRegister, dropTargetRegister
 
from light9.rdfdb import clientsession
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb import clientsession
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9.effect.sequencer import CodeWatcher
 
import light9.effect.effecteval
 
from light9.effect.settings import DeviceSettings
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 

	
 
from bcf2000 import BCF2000
 

	
 
nudge_keys = {
 
    'up'   : list('qwertyui'),
 
    'down' : list('asdfghjk')
 
}
 

	
 
class DummySliders:
 
    def valueOut(self, name, value):
 
        pass
 
    def close(self):
 
        pass
 
    def reopen(self):
 
        pass
 

	
 
class SubScale(tk.Scale, Fadable):
 
    def __init__(self, master, *args, **kw):
 
        self.scale_var = kw.get('variable') or tk.DoubleVar()
 
        kw.update({'variable' : self.scale_var,
 
                   'from' : 1, 'to' : 0, 'showvalue' : 0,
 
                   'sliderlength' : 15, 'res' : 0.01,
 
                   'width' : 40, 'troughcolor' : 'black', 'bg' : 'grey40',
 
                   'highlightthickness' : 1, 'bd' : 1,
bin/listsongs
Show inline comments
 
#!bin/python
 

	
 
"""for completion, print the available song uris on stdout
 

	
 
in .zshrc:
 

	
 
function _songs { local expl;  _description files expl 'songs';  compadd "$expl[@]" - `${LIGHT9_SHOW}/../../bin/listsongs` }
 
compdef _songs curvecalc
 
"""
 

	
 
from run_local import log
 
from twisted.internet import reactor
 
from rdflib import RDF
 
from light9 import networking
 
from light9.namespaces import L9
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
graph = SyncedGraph(networking.rdfdb.url, "listsongs")
 

	
 
@graph.initiallySynced.addCallback
 
def printSongs(result):
 
    with graph.currentState() as current:
 
        for song in current.subjects(RDF.type, L9['Song']):
 
            print song
 
    reactor.stop()
 

	
 
reactor.run()
bin/paintserver
Show inline comments
 
#!bin/python
 

	
 
from __future__ import division
 
from run_local import log
 
import json
 
from twisted.internet import reactor
 
from light9.greplin_cyclone import StatsForCyclone
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 
from light9 import networking, showconfig
 
from greplin import scales
 
import optparse, sys, logging
 
import cyclone.web
 
from rdflib import URIRef
 
from light9.rdfdb import clientsession
 
from rdfdb import clientsession
 
import light9.paint.solve
 
from lib.cycloneerr import PrettyErrorHandler
 
from light9.namespaces import RDF, L9, DEV
 

	
 

	
 

	
 

	
 
class Solve(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def post(self):
 
        painting = json.loads(self.request.body)
 
        with self.settings.stats.solve.time():
 
            img = self.settings.solver.draw(painting)
 
            sample, sampleDist = self.settings.solver.bestMatch(img, device=DEV['aura2'])
 
            with self.settings.graph.currentState() as g:
 
                bestPath = g.value(sample, L9['imagePath']).replace(L9[''], '')
 
            #out = solver.solve(painting)
 
            #layers = solver.simulationLayers(out)
 
            
 
        self.write(json.dumps({
 
            'bestMatch': {'uri': sample, 'path': bestPath, 'dist': sampleDist},
 
        #    'layers': layers,
 
        #    'out': out,
 
        }))
 

	
bin/rdfdb
Show inline comments
 
@@ -96,54 +96,54 @@ Our web ui:
 
          <creator> changed <subj>'s <pred> from <o1> to <o2>
 
          <creator> added <o> to <s> <p>
 

	
 
    raw messages for debugging this client
 

	
 
    ctx urls take you to->
 
    files, who's dirty, have we seen external changes, notice big
 
    files that are taking a long time to save
 

	
 
    graph contents. plain rdf browser like an outliner or
 
    something. clicking any resource from the other displays takes you
 
    to this, focused on that resource
 

	
 
"""
 
from twisted.internet import reactor, defer
 
import twisted.internet.error
 
from twisted.python.filepath import FilePath
 
from twisted.python.failure import Failure
 
from twisted.internet.inotify import humanReadableMask, IN_CREATE
 
import sys, optparse, logging, json, os
 
import cyclone.web, cyclone.httpclient, cyclone.websocket
 
sys.path.append(".")
 
from light9 import networking, showconfig, prof
 
from rdflib import ConjunctiveGraph, URIRef, Graph
 
from light9.rdfdb.graphfile import GraphFile
 
from light9.rdfdb.patch import Patch, ALLSTMTS
 
from light9.rdfdb.rdflibpatch import patchQuads
 
from light9.rdfdb.file_vs_uri import correctToTopdirPrefix, fileForUri, uriFromFile
 
from light9.rdfdb.patchsender import sendPatch
 
from light9.rdfdb.patchreceiver import makePatchEndpointPutMethod
 
from rdfdb.graphfile import GraphFile
 
from rdfdb.patch import Patch, ALLSTMTS
 
from rdfdb.rdflibpatch import patchQuads
 
from rdfdb.file_vs_uri import correctToTopdirPrefix, fileForUri, uriFromFile
 
from rdfdb.patchsender import sendPatch
 
from rdfdb.patchreceiver import makePatchEndpointPutMethod
 

	
 
from twisted.internet.inotify import INotify
 
from run_local import log
 
log.setLevel(logging.DEBUG)
 

	
 
from lib.cycloneerr import PrettyErrorHandler
 

	
 
class WebsocketDisconnect(ValueError):
 
    pass
 

	
 
def sendGraphToClient(graph, client):
 
    """send the client the whole graph contents"""
 
    log.info("sending all graphs to %r" % client)
 
    client.sendPatch(Patch(
 
        addQuads=graph.quads(ALLSTMTS),
 
        delQuads=[]))
 
    
 

	
 
class Client(object):
 
    """
 
    one of our syncedgraph clients
 
    """
 
    def __init__(self, updateUri, label):
 
        self.label = label
bin/subcomposer
Show inline comments
 
@@ -11,53 +11,53 @@ subcomposer
 
      watch observable(currentSub) for a new sub, and also watch currentSub for edits to push to the OneLevel widgets
 

	
 
        OneLevel widget
 
          UI edits are caught here and go all the way back to currentSub
 

	
 

	
 
"""
 
from __future__ import division, nested_scopes
 
import time, logging
 
from optparse import OptionParser
 
import logging, urllib
 
import Tkinter as tk
 
import louie as dispatcher
 
from twisted.internet import reactor, tksupport, task
 
from rdflib import URIRef, RDF, RDFS, Literal
 

	
 
from run_local import log
 
log.setLevel(logging.DEBUG)
 

	
 
from light9.dmxchanedit import Levelbox
 
from light9 import dmxclient, Submaster, prof, showconfig, networking
 

	
 
from light9.Patch import get_channel_name
 
from light9.uihelpers import toplevelat
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.rdfdb import clientsession
 
from rdfdb.syncedgraph import SyncedGraph
 
from rdfdb import clientsession
 
from light9.tkdnd import initTkdnd
 
from light9.namespaces import L9
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
from light9.observable import Observable
 
from light9.editchoice import EditChoice, Local
 
from light9.subcomposer import subcomposerweb
 

	
 

	
 
class Subcomposer(tk.Frame):
 
    """
 
    <session> l9:currentSub ?sub is the URI of the sub we're tied to for displaying and
 
    editing. If we don't have a currentSub, then we're actually
 
    editing a session-local sub called <session> l9:currentSub <sessionLocalSub>
 

	
 
    I'm not sure that Locals should even be PersistentSubmaster with
 
    uri and graph storage, but I think that way is making fewer
 
    special cases.
 

	
 
    Contains an EditChoice widget
 

	
 
    Dependencies:
 

	
 
      graph (?session :currentSub ?s) -> self.currentSub
 
      self.currentSub -> graph
 
      self.currentSub -> self._currentChoice (which might be Local)
 
      self._currentChoice (which might be Local) -> self.currentSub
 

	
bin/subserver
Show inline comments
 
#!bin/python
 
"""
 
live web display of all existing subs with pictures, mainly for
 
dragging them into CC or Timeline
 
"""
 
from run_local import log
 
import sys, 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
 
import pyjade.utils
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.rdfdb.patch import Patch
 
from rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9, DCTERMS
 
from light9 import networking, showconfig
 

	
 
from lib.cycloneerr import PrettyErrorHandler
 
        
 
class Static(PrettyErrorHandler, cyclone.web.StaticFileHandler):
 
    def get(self, path, *args, **kw):
 
        if path in ['', 'effects']:
 
            return self.respondStaticJade("light9/subserver/%s.jade" %
 
                                          (path or 'index'))
 
            
 
        if path.endswith(".js"):
 
            return self.responseStaticCoffee(
 
                'light9/subserver/%s' %
 
                path.replace(".js", ".coffee")) # potential security hole
 

	
 
        cyclone.web.StaticFileHandler.get(self, path, *args, **kw)
 

	
 
    def respondStaticJade(self, src):
 
        html = pyjade.utils.process(open(src).read())
 
        self.write(html)
 

	
 
    def responseStaticCoffee(self, src):
 
        self.write(subprocess.check_output([
bin/vidref
Show inline comments
 
#!bin/python
 
from run_local import log
 
import sys
 
sys.path.append('/usr/lib/python2.7/dist-packages') # For gtk
 
from twisted.internet import gtk2reactor
 
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.vidref.main import Gui
 
from light9.vidref.replay import snapshotDir
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
 # find replay dirs correctly. show multiple
 
 # replays. trash. reorder/pin. dump takes that are too short; they're
 
 # just from seeking
 

	
 
parser = optparse.OptionParser()
 
parser.add_option("-v", "--verbose", action="store_true",
 
                  help="logging.DEBUG")
 
(options, args) = parser.parse_args()
 

	
 

	
 
log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
 

	
 
class Snapshot(cyclone.web.RequestHandler):
 
    @defer.inlineCallbacks
 
    def post(self):
 
        # save next pic
 
        # return /snapshot/path
 
        try:
 
            outputFilename = yield self.settings.gui.snapshot()
 

	
 
            assert outputFilename.startswith(snapshotDir())
 
            out = networking.vidref.path(
 
                "snapshot/%s" % outputFilename[len(snapshotDir()):].lstrip('/'))
bin/vidrefsetup
Show inline comments
 
#!bin/python
 
""" this should be part of vidref, but I haven't worked out sharing
 
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 cyclone.web, cyclone.httpclient, cyclone.websocket
 
from rdflib import RDF, URIRef, Literal
 
import pyjade.utils
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.rdfdb.patch import Patch
 
from rdfdb.syncedgraph import SyncedGraph
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9, DCTERMS
 
from light9 import networking, showconfig
 

	
 
from lib.cycloneerr import PrettyErrorHandler
 

	
 
class RedirToCamera(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def get(self):
 
        return self.redirect(networking.picamserve.path(
 
            'pic?' + self.request.query))
 
        
 
class UrlToCamera(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def get(self):
 
        self.set_header('Content-Type', 'text/plain')
 
        self.write(networking.picamserve.path('pic'))
 
                   
 
class VidrefCamRequest(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def get(self):
 
        graph = self.settings.graph
 
        show = showconfig.showUri()
 
        with graph.currentState(tripleFilter=(show, None, None)) as g:
 
            ret = g.value(show, L9['vidrefCamRequest'])
 
            if ret is None:
 
                self.send_error(404)
 
            self.redirect(ret)
light9/Submaster.py
Show inline comments
 
from __future__ import division
 
import os, logging, time
 
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 louie import dispatcher
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
log = logging.getLogger('submaster')
 

	
 
class Submaster(object):
 
    """mapping of channels to levels"""
 
    def __init__(self, name, levels):
 
        """this sub has a name just for debugging. It doesn't get persisted.
 
        See PersistentSubmaster.
 

	
 
        levels is a dict
 
        """
 
        self.name = name
 
        self.levels = levels
 

	
 
        self.temporary = True
 

	
 
        if not self.temporary:
 
            # obsolete
 
            dispatcher.connect(log.error, 'reload all subs')
 

	
 
        #log.debug("%s initial levels %s", self.name, self.levels)
 

	
 
    def _editedLevels(self):
 
        pass
 

	
light9/collector/collector_test.py
Show inline comments
 
import unittest
 
import datetime, time
 
from freezegun import freeze_time
 
from rdflib import Namespace, URIRef
 

	
 
from light9.namespaces import L9, DEV
 
from light9.collector.collector import Collector, outputMap
 
from light9.rdfdb.mock_syncedgraph import MockSyncedGraph
 
from rdfdb.mock_syncedgraph import MockSyncedGraph
 

	
 
UDMX = Namespace('http://light9.bigasterisk.com/output/udmx/')
 
DMX0 = Namespace('http://light9.bigasterisk.com/output/dmx0/')
 

	
 
PREFIX = '''
 
   @prefix : <http://light9.bigasterisk.com/> .
 
        @prefix dev: <http://light9.bigasterisk.com/device/> .
 
        @prefix udmx: <http://light9.bigasterisk.com/output/udmx/> .
 
        @prefix dmx0: <http://light9.bigasterisk.com/output/dmx0/> .
 
'''
 

	
 
THEATER = '''
 
        :brightness         a :DeviceAttr; :dataType :scalar .
 

	
 
        :SimpleDimmer a :DeviceClass;
 
          :deviceAttr :brightness;
 
          :attr
 
            [ :outputAttr :level; :dmxOffset 0 ] .
 
                
 
        :ChauvetColorStrip a :DeviceClass;
 
          :deviceAttr :color;
 
          :attr
 
            [ :outputAttr :mode;  :dmxOffset 0 ],
 
            [ :outputAttr :red;   :dmxOffset 1 ],
light9/curvecalc/curve.py
Show inline comments
 
from __future__ import division
 
import glob, time, logging, ast, os
 
from bisect import bisect_left,bisect
 
import louie as dispatcher
 
from twisted.internet import reactor
 
from rdflib import Literal
 
from light9 import showconfig
 
from light9.namespaces import L9, RDF, RDFS
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 

	
 
log = logging.getLogger()
 
# todo: move to config, consolidate with ascoltami, musicPad, etc
 
introPad = 4
 
postPad = 4
 

	
 
class Curve(object):
 
    """curve does not know its name. see Curveset"""
 
    def __init__(self, uri, pointsStorage='graph'):
 
        self.uri = uri
 
        self.pointsStorage = pointsStorage
 
        self.points = [] # x-sorted list of (x,y)
 
        self._muted = False
 

	
 
    def __repr__(self):
 
        return "<%s %s (%s points)>" % (self.__class__.__name__, self.uri,
 
                                        len(self.points))
 

	
 
    def muted():
 
        doc = "Whether to currently send levels (boolean, obviously)"
 
        def fget(self):
 
            return self._muted
 
        def fset(self, val):
 
            self._muted = val
light9/curvecalc/subterm.py
Show inline comments
 
import math, os, random, logging
 
from rdflib import Graph, URIRef, RDF, RDFS, Literal
 
from louie import dispatcher
 
import light9.Effects
 
from light9 import Submaster, showconfig, prof
 
from light9.Patch import get_dmx_channel
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9
 
log = logging.getLogger()
 

	
 
class Expr(object):
 
    """singleton, provides functions for use in subterm expressions,
 
    e.g. chases"""
 
    def __init__(self):
 
        self.effectGlobals = light9.Effects.configExprGlobals()
 
    
 
    def exprGlobals(self, startDict, t):
 
        """globals dict for use by expressions"""
 

	
 
        glo = startDict.copy()
 
        
 
        # add in functions from Effects
 
        glo.update(self.effectGlobals)
 

	
 
        def chan(name):
 
            return Submaster.Submaster(
 
                name=name,
 
                levels={get_dmx_channel(name) : 1.0})
 
        glo['chan'] = chan
 
        glo['within'] = lambda a, b: a < t < b
 
        glo['bef'] = lambda x: t < x
light9/effect/edit.py
Show inline comments
 
import json
 
import cyclone.httpclient
 
from twisted.internet.defer import inlineCallbacks, returnValue
 
from rdflib import URIRef, Literal
 

	
 
from light9 import networking
 
from light9.namespaces import L9, RDF, RDFS
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
from light9.curvecalc.curve import CurveResource
 

	
 
def clamp(x, lo, hi):
 
    return max(lo, min(hi, x))
 

	
 

	
 
@inlineCallbacks
 
def getMusicStatus():
 
    returnValue(json.loads((yield cyclone.httpclient.fetch(
 
        networking.musicPlayer.path('time'), timeout=.5)).body))
 

	
 
@inlineCallbacks
 
def songEffectPatch(graph, dropped, song, event, ctx):
 
    """
 
    some uri was 'dropped' in the curvecalc timeline. event is 'default' or 'start' or 'end'.
 
    """
 
    with graph.currentState(
 
            tripleFilter=(dropped, None, None)) as g:
 
        droppedTypes = list(g.objects(dropped, RDF.type))
 
        droppedLabel = g.label(dropped)
 
        droppedCodes = list(g.objects(dropped, L9['code']))
 

	
 
    quads = []
 
    fade = 2 if event == 'default' else 0
light9/effect/settings.py
Show inline comments
 
from __future__ import division
 
"""
 
Data structure and convertors for a table of (device,attr,value)
 
rows. These might be effect attrs ('strength'), device attrs ('rx'),
 
or output attrs (dmx channel).
 
"""
 
import decimal
 
import numpy
 
from rdflib import URIRef, Literal
 
from light9.namespaces import RDF, L9, DEV
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
import logging
 
log = logging.getLogger('settings')
 
from light9.collector.device import resolve
 

	
 
def parseHex(h):
 
    if h[0] != '#': raise ValueError(h)
 
    return [int(h[i:i+2], 16) for i in 1, 3, 5]
 

	
 
def parseHexNorm(h):
 
    return [x / 255 for x in parseHex(h)]
 
    
 
def toHex(rgbFloat):
 
    return '#%02x%02x%02x' % tuple(max(0, min(255, int(v * 255))) for v in rgbFloat)
 

	
 
def getVal(graph, subj):
 
    lit = graph.value(subj, L9['value']) or graph.value(subj, L9['scaledValue'])
 
    ret = lit.toPython()
 
    if isinstance(ret, decimal.Decimal):
 
        ret = float(ret)
 
    return ret
 

	
 
class _Settings(object):
 
    """
 
    default values are 0 or '#000000'. Internal rep must not store zeros or some
light9/effect/settings_test.py
Show inline comments
 
import unittest
 
from rdflib import Literal
 
from light9.rdfdb.patch import Patch
 
from light9.rdfdb.localsyncedgraph import LocalSyncedGraph
 
from rdfdb.patch import Patch
 
from rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.namespaces import RDF, L9, DEV
 
from light9.effect.settings import DeviceSettings
 
             
 
        
 
class TestDeviceSettings(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                             'test/cam/bg.n3'])
 

	
 
    def testToVectorZero(self):
 
        ds = DeviceSettings(self.graph, [])
 
        self.assertEqual([0] * 30, ds.toVector())
 

	
 
    def testEq(self):
 
        s1 = DeviceSettings(self.graph, [
 
            (L9['light1'], L9['attr1'], 0.5),
 
            (L9['light1'], L9['attr2'], 0.3),
 
        ])
 
        s2 = DeviceSettings(self.graph, [
 
            (L9['light1'], L9['attr2'], 0.3),
 
            (L9['light1'], L9['attr1'], 0.5),
 
        ])
 
        self.assertTrue(s1 == s2)
 
        self.assertFalse(s1 != s2)
light9/paint/capture.py
Show inline comments
 
import os
 
from rdflib import URIRef
 
from light9 import showconfig
 
from light9.rdfdb.patch import Patch
 
from rdfdb.patch import Patch
 
from light9.namespaces import L9, RDF
 
from light9.paint.solve import loadNumpy
 

	
 
def writeCaptureDescription(graph, ctx, session, uri, dev, outPath,
 
                            settingsSubgraphCache, settings):
 
    graph.patch(Patch(addQuads=settings.statements(
 
        uri, ctx=ctx,
 
        settingRoot=URIRef('/'.join([
 
            showconfig.showUri(), 'capture', dev.rsplit('/')[1]])),
 
        settingsSubgraphCache=settingsSubgraphCache)))
 
    graph.patch(Patch(addQuads=[
 
        (dev, L9['capture'], uri, ctx),
 
        (session, L9['capture'], uri, ctx),
 
        (uri, RDF.type, L9['LightSample'], ctx),
 
        (uri, L9['imagePath'], URIRef('/'.join([
 
            showconfig.showUri(), outPath])), ctx),
 
        ]))
 
    graph.suggestPrefixes(ctx, {'cap': uri.rsplit('/', 1)[0] + '/',
 
                                'showcap': showconfig.showUri() + '/capture/'})
 
    
 
class CaptureLoader(object):
 
    def __init__(self, graph):
 
        self.graph = graph
 
        
light9/paint/solve_test.py
Show inline comments
 
import unittest
 
import numpy.testing
 
import solve
 
from rdflib import Namespace
 
from light9.namespaces import RDF, L9, DEV
 
from light9.rdfdb.localsyncedgraph import LocalSyncedGraph
 
from rdfdb.localsyncedgraph import LocalSyncedGraph
 
from light9.effect.settings import DeviceSettings
 

	
 
class TestSolve(unittest.TestCase):
 
    def setUp(self):
 
        self.graph = LocalSyncedGraph(files=['test/cam/lightConfig.n3',
 
                                             'test/cam/bg.n3'])
 
        self.solver = solve.Solver(self.graph, imgSize=(100, 48), sessions=[L9['session0']])
 
        self.solver.loadSamples()
 
        self.solveMethod = self.solver.solve
 

	
 
    @unittest.skip('solveBrute unfinished')
 
    def testBlack(self):
 
        devAttrs = self.solveMethod({'strokes': []})
 
        self.assertEqual(DeviceSettings(self.graph, []), devAttrs)
 

	
 
    @unittest.skip("unfinished")
 
    def testSingleLightCloseMatch(self):
 
        devAttrs = self.solveMethod({'strokes': [{'pts': [[224, 141],
 
                                                 [223, 159]],
 
                                         'color': '#ffffff'}]})
 
        self.assertEqual(DeviceSettings(self.graph, [
 
            (DEV['aura1'], L9['color'], u"#ffffff"),
 
            (DEV['aura1'], L9['rx'], 0.5 ),
 
            (DEV['aura1'], L9['ry'], 0.573),
requirements.txt
Show inline comments
 
@@ -12,24 +12,25 @@ klein==17.2.0
 
Louie==1.1
 
mock==2.0.0
 
noise==1.2.2
 
nose-watcher==0.1.3
 
nose==1.3.7
 
Pillow==4.0.0
 
pyjade==4.0.0
 
pyserial==3.3
 
python-dateutil==2.6.0
 
pyusb==1.0.0
 
rdflib==4.2.2
 
restkit==4.2.2
 
scipy==0.19.0
 
service_identity==16.0.0
 
statprof==0.1.2
 
toposort==1.5
 
treq==17.3.1
 
Twisted==17.1.0
 
txosc==0.2.0
 
txzmq==0.8.0
 
typing==3.6.1
 
watchdog==0.8.3
 
web.py==0.38
 
webcolors==1.7
 
https://projects.bigasterisk.com/rdfdb/rdfdb-0.3.0.tar.gz
0 comments (0 inline, 0 general)