def _process(self, sequence, producer): if self.wrap: products = tuple(map(quickdict, sequence)) yield (("str", json.encode(quickdict(timetag=datetime.datetime.now(), products=products))), ) else: for operands in sequence: yield (("str", json.encode(quickdict(operands))),)
def __sourcetuiostate(self, observable, src): """Return the record associated to observable.""" for ref, sources in self._tuiostate.items(): if ref() is observable: rvalue = sources.setdefault(src, quickdict()) break else: rvalue = quickdict() self._tuiostate[weakref.ref(observable)] = {src:rvalue} return rvalue
def _process(self, sequence, producer): if self.wrap: products = tuple(map(quickdict, sequence)) yield (("data", pickle.encode(quickdict(timetag=datetime.datetime.now(), products=products), self.protocol)), ) else: for operands in sequence: yield (("data", pickle.encode(quickdict(operands), self.protocol)),)
def _process(self, sequence, producer): for operands in sequence: source = timetag = add = update = remove = None for key, value in operands: if key=="source": source = value elif key=="timetag": timetag = value elif "added" in key: add = value elif "updated" in key: update = value else: remove = value if source is None: source = id(producer) if timetag is None: timetag = datetime.datetime.now() record = self._buffer.setdefault(source, {}) if add is not None: for key, value in add.items(): record[key] = [(timetag, value)] if update is not None: for key, value in update.items(): stroke = record.setdefault(key, []) stroke.append((timetag, value)) if remove is not None: results = [] for key in remove.keys(): stroke = record.pop(key) # FIXME: this should be done in a separated Node. l = lambda o: quickdict(t=o[0], x=o[1]['rel_pos'][0]*100, y=o[1]['rel_pos'][1]*100) stroke = tuple(map(l, stroke)) # --- results.append(("gestures.%s"%key, dict(stroke=stroke, cls=self.cls))) if results: yield results
def _draw(self): stream = io.StringIO() memo = set() for node in self._starters: self._grapher.draw(node, stream, maxdepth=self.maxdepth, memo=memo) graph = stream.getvalue() if graph: self.postProduct(quickdict(str=self.separator+graph))
def test_encode_decode(self): obj = quickdict(a=CustomClass(), timetag=datetime.datetime.now(), data=b"unittest") encoded = pickle.encode(obj) decoded = pickle.decode(encoded) self.assertEqual(obj, decoded)
def __produce(self): if self._update: self._update = False data = io.StringIO() intro = False for ref, record in self.__stat.items(): if record.partial>0: if not intro: delta = datetime.datetime.now() - self._inittime data.write("Statistics after %s\n"%delta) intro = True record.tot += record.partial data.write(str(ref())) data.write("\n") data.write(" tags: %s\n"%record.tags) if record.lagmax is not None: msecs = record.lagmax.seconds*1000 \ +record.lagmax.microseconds/1000 record.lagmax = None data.write(" tot=%d, hz=%g, lagmax=%f ms\n"%( record.tot, record.partial*1000/self.__timer.interval(), msecs)) else: data.write(" tot=%d, hz=%d\n"%(record.tot, record.partial)) record.partial = 0 record.tags.clear() if intro: data.write("\n") self.postProduct(quickdict(str=data.getvalue()))
def _consume(self, products, producer): for product in products: diff = product.get("diff") if isinstance(diff, collections.Mapping): source = product.get("source") record = self._sources.setdefault( source, quickdict({"state": StateMachine(), "color": (QtGui.QColor(*colors[len(self._sources)%12]), QtGui.QColor(QtCore.Qt.black))})) # Update state record.state.applyDiff(diff) # Update history history = record.history for key, event in diff.items(): if key in ("added", "updated"): for gid, value in event["contacts"].items(): track = history.setdefault(gid, []) if track or "rel_pos" in value: track.append(value) elif key=="removed": for key in event.get("contacts", tuple()): history.pop(key, None) else: raise ValueError("Unexpected key for a diff: %s", key) self.gui().update()
def _postData(self): data = self.__input.read() attr = "str" if self._textmode else "data" if attr in self._activetags and (data or self.postend): product = quickdict() product[attr] = data self.postProduct(product)
def append(self, products): """Store products as a buffer item.""" record = quickdict() record.timetag = datetime.datetime.now() record.products = products self._buffer.append(record) self._sum += len(products) if not self._checkSizeLimit(): self.changed.emit()
def __init__(self, request=QRequest("diff.*.contacts|source|timetag"), blender=Functor.RESULTONLY, rawsource=False, hz=None, parent=None): super().__init__(request, Offer(quickdict(osc=osc.Packet)), blender, hz=hz, parent=parent) # self._tuiostate[observable-ref][source][profile] = [fseq, {s_id: TuioDescriptor}] self._tuiostate = {} self.observableRemoved.connect(self.__removeRecord) self._rawsource = assertIsInstance(rawsource, bool)
def __init__(self, request=Request.ANY, fps=1, parent=None): super().__init__(request, Offer(quickdict(str=str())), Functor.RESULTONLY, parent=parent) self.__timer = QtCore.QTimer(timeout=self.__produce) self.__timer.start(1000/float(fps)) self._inittime = datetime.datetime.now() self.__stat = {} self._update = False self.observableRemoved.connect(self.__removeRecord)
def __init__(self, starters=tuple(), request=Request.ANY, maxdepth=None, hz=1, parent=None): super().__init__(Offer(quickdict(str=str())), parent=parent) self._starters = starters self._grapher = SimpleGrapher(request) self.__tid = QtCore.QTimer(timeout=self._draw) if hz: self.__tid.start(1000/hz) if hz<1: QtCore.QTimer.singleShot(100, self._draw) self.maxdepth = maxdepth self.separator = SimpleGrapherProducer._SEPARATOR
def __init__(self, rt=False, blender=Functor.MERGECOPY, parent=None): timetag = datetime.datetime.now() super().__init__( QRequest("data"), Offer(quickdict( osc=osc.Bundle(timetag, (osc.Bundle(timetag, (Offer.UNDEFINED, )), osc.Message(str(), str(), Offer.UNDEFINED), Offer.UNDEFINED)), timetag=timetag)), blender, parent=parent) self._receipttime = assertIsInstance(rt, bool)
def __init__(self, request=Request.ANY, mode="items", separator="\n", src=False, dest=False, depth=None, parent=None): super().__init__(request, Offer(quickdict(str=str())), Functor.RESULTONLY, parent=parent) self.dumpsrc = assertIsInstance(src, bool) self.dumpdest = assertIsInstance(dest, bool) self.depth = None if depth is None else int(depth) if mode not in ("items", "values", "keys"): raise ValueError( "mode must be 'items' or 'values' or 'keys', not '%s'"%mode) else: self._mode = mode self.separator = assertIsInstance(separator, str, None) if self.separator is None: self.separator = ""
def __init__(self, filename, **kwargs): timetag = datetime.datetime.now() super().__init__( filename, OscLogPlayer._Decoder(), OscLogPlayer._Sender(), offer=Offer(quickdict( osc=osc.Bundle(timetag, (osc.Bundle(timetag, (Offer.UNDEFINED, )), osc.Message(str(), str(), Offer.UNDEFINED), Offer.UNDEFINED)), timetag=timetag)), **kwargs)
def __init__(self, inputdevice, postend=True, parent=None): """:class:`Producer <boing.core.Producer>` node that anytime the device *inputdevice* send the signal :attr:`readyRead <boing.utils.fileutils.CommunicationDevice.readyRead>` it reads the device and it produces a message containing the data. The provided products is a dictionary ``{"str": data}`` if ``data`` is a string, otherwise the product will be a dictionary like ``{"data": data}``. If the argument *postend* is set to ``True``, the :class:`DataReader` will never produce an empty product, like ``{"str": ""}`` or ``{"data": b""}``. *parent* defines the parent of the node. """ self._textmode = inputdevice.isTextModeEnabled() if self._textmode: offer = Offer(quickdict(str=str())) tags = dict(str=QRequest("str")) else: offer = Offer(quickdict(data=bytearray())) tags = dict(data=QRequest("data")) super().__init__(offer, tags=tags, parent=parent) self.__input = inputdevice self.__input.readyRead.connect(self._postData) self.postend = assertIsInstance(postend, bool)
def getTemplate(): template = quickdict() contact = template.diff.added.contacts[0] contact.rel_pos = tuple() contact.rel_speed = tuple() contact.rel_accel = tuple() contact.si_angle = tuple() contact.objclass = tuple() contact.boundingbox.rel_pos = tuple() contact.boundingbox.rel_speed = tuple() contact.boundingbox.si_angle = tuple() contact.boundingbox.rel_size = tuple() template.diff.updated.contacts[0] = contact template.diff.removed.contact[0] = None template.source = str() return template
def _process(self, sequence, producer): stream = io.StringIO() if self.dumpsrc: stream.write("from: %s\n"%str(producer)) if self.dumpdest: stream.write("DumpNode(request=%s)\n"%repr(str(self.request()))) for operands in sequence: data = quickdict(operands) if self.mode()=="items": deepDump(data, stream, None if self.depth is None else self.depth+1) stream.write(self.separator) elif self.mode()=="values": values = tuple(data.values()) deepDump(values if len(values)>1 else values[0], stream, self.depth) stream.write(self.separator) elif self.mode()=="keys": deepDump(tuple(data.keys()), stream, self.depth) stream.write(self.separator) yield (("str", stream.getvalue()),)
def __handleOsc(self, packet): source = fseq = profile = None desc = {} alive = set() for msg in packet.elements: if msg.address.startswith("/tuio/"): profile = msg.address[6:] command = msg.arguments[0] if command=="source": source = msg.arguments[1] elif command=="fseq": fseq = int(msg.arguments[1]) elif command=="alive": alive = set(msg.arguments[1:]) elif command=="set": tobj = tuio.TuioDescriptor(msg.source, profile, packet.timetag, source, fseq, *msg.arguments[1:]) desc[tobj.s] = tobj if source is None and not self._rawsource: source = "Tuio#%d"%id(self) # TODO: old bundles rejection based on fseq # Update the contacts with the bundle information for s_id, tobj in desc.items(): source_ids = self.__idpairs.setdefault(source, {}) gid = source_ids.get(s_id) if gid is None: gid = self.__nextId() source_ids[s_id] = gid if profile=="2Dcur": node = quickdict() if tuio.TuioDescriptor.undef_value not in [tobj.x, tobj.y]: node.rel_pos = [tobj.x, tobj.y] if tuio.TuioDescriptor.undef_value not in [tobj.X, tobj.Y]: node.rel_speed = [tobj.X, tobj.Y, 0, 0] yield "diff.updated.contacts.%s"%gid, node elif profile in ("25Dcur", "3Dcur"): node = quickdict() node.rel_pos = [tobj.x, tobj.y, tobj.z] node.rel_speed = [tobj.X, tobj.Y, tobj.Z, 0] yield "diff.updated.contacts.%s"%gid, node elif profile=="2Dblb": node = quickdict() if tuio.TuioDescriptor.undef_value not in [tobj.x, tobj.y]: node.rel_pos = [tobj.x, tobj.y] if tuio.TuioDescriptor.undef_value not in [tobj.X, tobj.Y]: node.rel_speed = [tobj.X, tobj.Y, 0, 0] node.si_angle = [tobj.a, ] node.rel_size = [tobj.w, tobj.h] yield "diff.updated.contacts.%s.boundingbox"%gid, node elif profile=="25Dblb": node = quickdict() node.rel_pos = [tobj.x, tobj.y, tobj.z] node.rel_speed = [tobj.X, tobj.Y, tobj.Z, 0] node.si_angle = [tobj.a, ] node.rel_size = [tobj.w, tobj.h] yield "diff.updated.contacts.%s.boundingbox"%gid, node elif profile=="3Dblb": node = quickdict() node.rel_pos = [tobj.x, tobj.y, tobj.z] node.rel_speed = [tobj.X, tobj.Y, tobj.Z, 0] node.si_angle = [tobj.a, tobj.b, tobj.c] node.rel_size = [tobj.w, tobj.h, tobj.d] yield "diff.updated.contacts.%s.boundingbox"%gid, node elif profile=="2Dobj": node = quickdict() if tuio.TuioDescriptor.undef_value not in [tobj.x, tobj.y]: node.rel_pos = [tobj.x, tobj.y] if tuio.TuioDescriptor.undef_value not in [tobj.X, tobj.Y]: node.rel_speed = [tobj.X, tobj.Y, 0, 0] node.objclass = tobj.i node.si_angle = [tobj.a, ] yield "diff.updated.contacts.%s"%gid, node elif profile=="25Dobj": node = quickdict() node.rel_pos = [tobj.x, tobj.y, tobj.z] node.rel_speed = [tobj.X, tobj.Y, tobj.Z, 0] node.objclass = tobj.i node.si_angle = [tobj.a, ] yield "diff.updated.contacts.%s"%gid, node elif profile=="3Dobj": node = quickdict() node.rel_pos = [tobj.x, tobj.y, tobj.z] node.rel_speed = [tobj.X, tobj.Y, tobj.Z, 0] node.objclass = tobj.i node.si_angle = [tobj.a, tobj.b, tobj.c] yield "diff.updated.contacts.%s"%gid, node # Remove items that are not alive src_profiles = self.__alive.setdefault(source, {}) alive_old = src_profiles.get(profile, set()) toRemove = alive_old - alive for s_id in toRemove: # Check if other profiles has the same session_id still alive keep = False for p, a in src_profiles.items(): if p==profile: continue elif s_id in a: keep = True break if not keep: gid = self.__idpairs.get(source, {}).pop(s_id, None) if gid is not None: yield "diff.removed.contacts.%s"%gid, None src_profiles[profile] = alive yield "source", source
def __init__(self, wrap=False, protocol=None, request=QRequest.ANY, blender=Functor.MERGECOPY, parent=None): super().__init__(request, Offer(quickdict(data=bytes())), blender, parent=parent) self.wrap = assertIsInstance(wrap, bool) self.protocol = assertIsInstance(protocol, None, int)
def __init__(self, parent=None): # It is forced to be use a RESULTONLY blender because for each # received product, it may produce multiple products. super().__init__(QRequest("data"), Offer(quickdict(data=bytearray())), Functor.RESULTONLY, parent=parent) self._slipbuffer = None
def __init__(self, blender=Functor.MERGECOPY, parent=None): super().__init__(QRequest("data"), Offer(quickdict(data=bytearray())), blender, parent=parent)
def _encodeEvent(self, event, producer): # Set of s_id that have been updated. # setters[<profile>] = {s_id1, s_id2, ..., s_idn} setters = {} # Set of profiles for which a s_id have been removed removed = set() diff = event["diff"] source = event.get("source") if source is None and not self._rawsource: source = "Tuio#%d"%id(self) sourcetuiostate = self.__sourcetuiostate(producer, source) toupdate = None if "added" in diff: toupdate = diff.added.contacts if "updated" in diff: if toupdate is None: toupdate = diff.updated.contacts else: deepupdate(toupdate, diff.updated.contacts) if toupdate is not None: for gid, gdiff in toupdate.items(): # Determine the TUIO profiles for the gesture event profiles = set() for profile, profilestate in sourcetuiostate.items(): if gid in profilestate[1]: profiles.add(profile) if not profiles: if "rel_pos" in gdiff: if "objclass" in gdiff: if len(gdiff.rel_pos)==2: profiles.add("2Dobj") elif len(gdiff.rel_pos)==3: profiles.add("3Dobj") elif len(gdiff.rel_pos)==2: profiles.add("2Dcur") elif len(gdiff.rel_pos)==3: profiles.add("3Dcur") if "boundingbox" in gdiff: if "rel_pos" in gdiff.boundingbox: if len(gdiff.boundingbox.rel_pos)==2: profiles.add("2Dblb") elif len(gdiff.boundingbox.rel_pos)==3: profiles.add("3Dblb") elif "rel_pos" in gdiff: if len(gdiff.rel_pos)==2: profiles.add("2Dblb") elif len(gdiff.rel_pos)==3: profiles.add("3Dblb") elif len(profiles)==1 and "boundingbox" in gdiff: if "rel_pos" in gdiff.boundingbox: if len(gdiff.boundingbox.rel_pos)==2: profiles.add("2Dblb") elif len(gdiff.boundingbox.rel_pos)==3: profiles.add("3Dblb") else: for other in profiles: break if other.startswith("2D"): profiles.add("2Dblb") elif other.startswith("3D"): profiles.add("3Dblb") # Create set descriptors for each updated profile for profile in profiles: update = False profilestate = sourcetuiostate.setdefault( profile, [0, {}]) if gid in profilestate[1]: prev = profilestate[1][gid] else: len_ = len(tuio.TuioDescriptor.profiles[profile]) prev = tuio.TuioDescriptor( None, profile, None, None, None, *([tuio.TuioDescriptor.undef_value]*len_)) prev.s = int(gid) profilestate[1][gid] = prev update = True if profile=="2Dcur": if "rel_pos" in gdiff: prev.x, prev.y = gdiff.rel_pos[:2] update = True if "rel_speed" in gdiff: prev.X, prev.Y = gdiff.rel_speed[:2] update = True elif profile in ("25Dcurr", "3Dcur"): if "rel_pos" in gdiff: prev.x, prev.y, prev.z= gdiff.rel_pos[:3] update = True if "rel_speed" in gdiff: prev.X, prev.Y, prev.Z = gdiff.rel_speed[:3] update = True elif profile=="2Dobj": if "rel_pos" in gdiff: prev.x, prev.y = gdiff.rel_pos[:2] update = True if "rel_speed" in gdiff: prev.X, prev.Y = gdiff.rel_speed[:2] update = True if "si_angle" in gdiff: prev.a = gdiff.si_angle[0] update = True if "objclass" in gdiff: prev.i = gdiff.objclass update = True elif profile=="25Dobj": if "rel_pos" in gdiff: prev.x, prev.y, prev.z= gdiff.rel_pos[:3] update = True if "rel_speed" in gdiff: prev.X, prev.Y, prev.Z = gdiff.rel_speed[:3] update = True if "si_angle" in gdiff: prev.a = gdiff.si_angle[0] update = True if "objclass" in gdiff: prev.i = gdiff.objclass update = True elif profile=="3Dobj": if "rel_pos" in gdiff: prev.x, prev.y, prev.z= gdiff.rel_pos[:3] update = True if "rel_speed" in gdiff: prev.X, prev.Y, prev.Z = gdiff.rel_speed[:3] update = True if "si_angle" in gdiff: prev.a, prev.b, prev.c = gdiff.si_angle[:3] update = True if "objclass" in gdiff: prev.i = gdiff.objclass update = True elif profile=="2Dblb": if "boundingbox" in gdiff: bb = gdiff.boundingbox if "rel_pos" in bb: prev.x, prev.y = bb.rel_pos[:2] update = True if "rel_speed" in bb: prev.X, prev.Y = bb.rel_speed[:2] update = True if "si_angle" in bb: prev.a = bb.si_angle[0] update = True if "rel_size" in bb: prev.w, prev.h = bb.rel_size[:2] update = True elif profile=="25Dblb": if "boundingbox" in gdiff: bb = gdiff.boundingbox if "rel_pos" in bb: prev.x, prev.y, prev.z = bb.rel_pos[:3] update = True if "rel_speed" in bb: prev.X, prev.Y, prev.Z = bb.rel_speed[:3] update = True if "si_angle" in bb: prev.a = bb.si_angle[0] update = True if "rel_size" in bb: prev.w, prev.h = bb.rel_size[:2] update = True elif profile=="3Dblb": if "boundingbox" in gdiff: bb = gdiff.boundingbox if "rel_pos" in bb: prev.x, prev.y, prev.z = bb.rel_pos[:3] update = True if "rel_speed" in bb: prev.X, prev.Y, prev.Z = bb.rel_speed[:3] update = True if "si_angle" in bb: prev.a, prev.b, prev.c = bb.si_angle[:3] update = True if "rel_size" in bb: prev.w, prev.h, prev.d = bb.rel_size[:3] update = True if update: setters.setdefault(profile, set()).add(gid) if "removed" in diff: for gid in diff.removed.contacts.keys(): for profile, profilestate in sourcetuiostate.items(): if gid in profilestate[1]: del profilestate[1][gid] removed.add(profile) if profile in setters: setters[profile].discard(gid) # Create an OSC bundle packets = [] for profile in (set(setters.keys()) | removed): profilestate = sourcetuiostate[profile] sourcemsg = osc.Message("/tuio/%s"%profile, "ss", "source", source) alive = list(int(gid) for gid in profilestate[1].keys()) alivemsg = osc.Message("/tuio/%s"%profile, "s"+"i"*len(alive), "alive", *alive) msgs = [sourcemsg, alivemsg] profilesetters = setters.get(profile) if profilesetters is not None: setmsgs = [] for s_id in profilesetters: desc = profilestate[1][s_id] args = [] for name in tuio.TuioDescriptor.profiles[profile]: args.append(getattr(desc, name)) setmsgs.append(osc.Message("/tuio/%s"%profile, None, "set", *args)) msgs.extend(setmsgs) msgs.append(osc.Message("/tuio/%s"%profile, "si", "fseq", profilestate[0])) profilestate[0] += 1 forward = quickdict() forward.osc = osc.Bundle(event.get("timetag"), msgs) self.postProduct(forward)
def __init__(self, wrap=False, request=QRequest.ANY, blender=Functor.MERGECOPY, parent=None): super().__init__(request, Offer(quickdict(str=str())), blender, parent=parent) self.wrap = assertIsInstance(wrap, bool)
def __init__(self, wrap=False, rt=False, blender=Functor.RESULTONLY, parent=None): super().__init__(QRequest("osc"), Offer(quickdict(data=bytearray())), blender, parent=parent) self.wrap = assertIsInstance(wrap, bool) self.rt = assertIsInstance(rt, bool)
def __init__(self, encoding="utf-8", blender=Functor.MERGECOPY, parent=None): super().__init__(QRequest("data"), Offer(quickdict(str=str())), blender, parent=parent) self.encoding = assertIsInstance(encoding, str) self.errors = "replace"
def __init__(self, encoding="utf-8", blender=Functor.MERGECOPY, parent=None): super().__init__(QRequest("str"), Offer(quickdict(data=bytearray())), blender, parent=parent) self.encoding = assertIsInstance(encoding, str)
def send(self, player, obj): for packet in obj.elements: packet.timetag = player._date if player._date is not None \ else datetime.datetime.now() player.postProduct(quickdict(osc=packet, timetag=packet.timetag))
def __init__(self, blender=Functor.MERGECOPY, parent=None): super().__init__(QRequest("osc"), Offer(quickdict(str=str())), blender, parent=parent)