import ch.psi.pshell.device.Startable as Startable import traceback class StreamListener (DeviceListener): def __init__(self, merger): self.merger = merger def onCacheChanged(self, device, value, former, timestamp, valueChange): self.merger.update() class StreamMerger(DeviceBase, Readable): def __init__(self, name, st1, st2): DeviceBase.__init__(self, name) self.st1=st1 self.st2=st2 self.pulseId = -1 self.v1= None self.v2= None self.initialize() self.running=False self.listener = StreamListener(self) self.setComponents([st1,st2]) def doUpdate(self): try: while True: has_more_1 = has_more_2 = False if (self.v1 is None) or ((self.v1 is not None) and (self.v2 is not None) and (self.v1.pulseId < self.v2.pulseId)): if self.st1.bufferCapacity>0: tm_value = self.st1.popBuffer() self.v1 = None if tm_value is None else tm_value.value has_more_1 = (v1 is not None) else: self.v1 = self.st1.take() if (self.v2 is None) or ((self.v1 is not None) and (self.v2 is not None) and (self.v1.pulseId > self.v2.pulseId)): if self.st2.bufferCapacity>0: tm_value = self.st2.popBuffer() self.v2 = None if tm_value is None else tm_value.value has_more_2 = (v2 is not None) else: self.v2 = self.st2.take() if ((self.v1 is not None) and (self.v2 is not None) and (self.v1.pulseId == self.v2.pulseId)): if self.v1.pulseId > self.pulseId: keys=self.v1.keys() keys.addAll(self.v2.keys()) values=self.v1.values() values.addAll(self.v2.values()) self.pulseId = self.v1.pulseId self.values, self.keys = values, keys self.setCache(values, None) self.v1=self.v2=None else: if (not has_more_1) and (not has_more_2): break except Exception, ex: print >> sys.stderr, traceback.format_exc() def doSetMonitored(self,value): if (value): self.st1.addListener(self.listener) self.st2.addListener(self.listener) else: self.st1.removeListener(self.listener) self.st2.removeListener(self.listener) def doClose(self): self.doSetMonitored(False) def getReadables(self): ret = list(self.st1.children + self.st2.children) ret = [item for item in ret if type(item)!=Stream.PidReader] return [self.st1.getPidReader(),] + ret def read(self): return self.pulseId def start(self): if not self.st1.isStarted(): self.st1.start() if not self.st2.isStarted(): self.st2.start() def stop(self): if self.st1.isStarted(): self.st1.stop() if self.st2.isStarted(): self.st2.stop() def isStarted(self): return self.st1.isStarted() and self.st2.isStarted() #TODO: Readable children devices