def __init__(self, parent, description, name='Repeat', **kwds): super(Repeat, self).__init__(parent, description, name, **kwds) self.random_delay = Expression.convert(description.get('random_delay', 0)) self.period = Expression.convert(description.get('period', 0)) self.repeat = Expression.convert(description.get('repeat', 'infinite')) assert self.random_delay > 0 or self.period > 0, ( 'You must set either a period or a random_delay')
def __init__(self, parent, desc): times = [] for e in desc.get('elements', []): times.append([Expression.convert(e.pop(a, None)) for a in Sequence.ATTRIBUTES]) self.elements = [] self.pattern_makers = PatternDesc.make_patterns_for_element( self, desc.get('patterns', {})) super(Sequence, self).__init__( parent, desc, name='Sequence', full_slave=False) self.loops = Expression.convert(desc.get('loops', 1)) self.duration = Expression.convert(desc.get('duration', Units.INFINITY)) self.sequence = [] self.paused_children = set() for element, t in zip(self.elements, times): begin, end, duration = t if duration is not None: if end is not None: begin = end - duration elif begin is not None: end = begin + duration self.sequence.append([begin or 0, element.start]) if end is not None: self.sequence.append([end, element.pause]) self.sequence.append([self.duration, self.pause]) self.sequence.sort(key=operator.itemgetter(0))
def __init__(self, parent, desc): times = [] for e in desc.get('elements', []): times.append([Expression.convert(e.pop(a, None)) for a in Sequence.ATTRIBUTES]) self.elements = [] self.output = desc.get('output', None) self.patterns = {} for k, v in desc.get('pattern', {}).items(): self.patterns[k] = make_pattern(self, v, k) super(Sequence, self).__init__( parent, desc, name='Sequence', full_slave=False) self.loops = Expression.convert(desc.get('loops', 1)) self.duration = Expression.convert(desc.get('duration', 'infinity')) self.sequence = [] self.paused_children = set() for element, t in zip(self.elements, times): begin, end, duration = t if duration is not None: if end is not None: begin = end - duration elif begin is not None: end = begin + duration self.sequence.append([begin or 0, element.start]) if end is not None: self.sequence.append([end, element.pause]) self.sequence.append([self.duration, self.pause]) self.sequence.sort(key=operator.itemgetter(0))
def settings_update(self, get): if not self.count_set: self._set_count(light_count(get)) self.brightness = Expression.convert(get('light', 'brightness')) if not self.period_set: self.period = Expression.convert( get('light', 'visualizer', 'period'))
def update_callback(self): self.period = Expression.convert(self.values.period) self.lighting_window.set_light_count( self.values.light_count or (self.values.layout[0] * self.values.layout[1])) self.lighting_window.set_shape(self.values.shape == 'rect') self.lighting_window.set_show_label(self.values.show_label) self.lighting_window.set_label_starts_at_zero( self.values.label_starts_at_zero) self.lighting_window.set_layout(self.values.layout, self.values.size, self.values.padding, self.values.instrument_padding, self.values.label_padding) self.columns = self.values.layout[0] self.transform = self.values.transform if self.transform: try: self.transform = cechomesh.Transform(self.transform) except: LOGGER.error('Don\'t understand transform %s', self.transform) self.transform = None self.brightness = Expression.convert(self.values.brightness) if self.transform: self.brightness = self.transform.apply(self.brightness)
def split(items): kwds = {} numeric = [] for k, v in six.iteritems(items): if isinstance(k, six.string_types) and k[0].isalpha(): kwds[k] = v else: from echomesh.expression import Expression numeric.append([Expression.convert(k), Expression.convert(v)]) return kwds, sorted(numeric)
def __init__(self, element, period, begin=None, end=None, count=None, skip=1, repeat=INFINITY, **kwds): parts = [ Expression.convert(x, element) for x in (count, begin, end, skip)] self.count, self.begin, self.end, self.skip = Interval.interval(*parts) self.element = element self.period = Expression.convert(period, element) self.repeat = repeat if kwds: LOGGER.error('Unknown keywords "%s" for counter', kwds)
def __init__(self, element, loops=1, position=(0, 0), rotation=(0, 0, 0), size=1, duration=None, z=DEFAULT_Z, shader=None, **kwds): super(ImageSprite, self).__init__() import pi3d self.element = element self.imagename = IMAGE_DIRECTORY.expand(kwds.pop('file', None)) del kwds['type'] if kwds: s = '' if len(kwds) == 1 else 's' LOGGER.error('Unknown keyword%s: %s', s, ', '.join(kwds)) self._loops = loops self._loop_number = 0 self._position = Expression.expression(position, element) self._rotation = Expression.expression(rotation, element) self._size = Expression.expression(size, element) self._z = Expression.expression(z, element) self.element.time = 0 # elapsed time. self._time = 0 # start time. if duration is None: for env in [self._position, self._rotation, self._size, self._z]: if env.is_constant(): duration = max(duration, env.length) if duration is None: duration = INFINITY else: self._duration = Expression.convert(duration) if not self._duration: LOGGER.warning('An image sprite had a zero duration.') if not ImageSprite.CACHE: ImageSprite.CACHE = pi3d.TextureCache() texture = ImageSprite.CACHE.create(self.imagename) x, y, z = self.coords() self.sprite = pi3d.ImageSprite(texture, w=texture.ix, h=texture.iy, shader=Shader.shader(shader), x=x, y=y, z=z) self.sprite.repaint = self.repaint
def __init__(self, parent, description, name='Repeat', delay=0, **kwds): delay = Expression.convert(description.get('delay', delay)) super(Repeat, self).__init__(parent, description, name, delay=delay, **kwds) self.random_delay = Expression.convert( description.get('random_delay', 0)) self.period = Expression.convert(description.get('period', 0)) self.repeat = Expression.convert(description.get('repeat', 'infinite')) assert self.random_delay > 0 or self.period > 0, ( 'You must set either a period or a random_delay')
def set_player(self, element, level=1, pan=0, loops=1, begin=0, end=INF, length=INF, **kwds): self._element = element self._file = kwds.pop('file') self._filename = Util.DEFAULT_AUDIO_DIRECTORY.expand(self._file) if kwds: LOGGER.error('Unused keywords %s', kwds) self._passthrough = (level == 1 and pan == 0) self._length = length self._level = Expression.expression(level, element) self._pan = Expression.expression(pan, element) self._loops = loops self._begin = begin self._end = end
def __init__( self, element, loops=1, position=(0, 0), rotation=(0, 0, 0), size=1, duration=None, z=DEFAULT_Z, shader=None, **kwds ): super(ImageSprite, self).__init__() import pi3d self.element = element self.imagename = IMAGE_DIRECTORY.expand(kwds.pop("file", None)) del kwds["type"] if kwds: s = "" if len(kwds) == 1 else "s" LOGGER.error("Unknown keyword%s: %s", s, ", ".join(kwds)) self._loops = loops self._loop_number = 0 self._position = Expression.expression(position, element) self._rotation = Expression.expression(rotation, element) self._size = Expression.expression(size, element) self._z = Expression.expression(z, element) self.element.time = 0 # elapsed time. self._time = 0 # start time. if duration is None: for env in [self._position, self._rotation, self._size, self._z]: if env.is_constant(): duration = max(duration, env.length) if duration is None: duration = INFINITY else: self._duration = Expression.convert(duration) if not self._duration: LOGGER.warning("An image sprite had a zero duration.") if not ImageSprite.CACHE: ImageSprite.CACHE = pi3d.TextureCache() texture = ImageSprite.CACHE.create(self.imagename) x, y, z = self.coords() self.sprite = pi3d.ImageSprite(texture, w=texture.ix, h=texture.iy, shader=Shader.shader(shader), x=x, y=y, z=z) self.sprite.repaint = self.repaint
def get(self, *path): with self.lock: value = self.clients.get(path) if not value: value = Expression.convert(Settings.get(*path)) self.clients[path] = value return value
def __init__(self, data, element=None): self.element = element kwds, numeric = SplitNumbers.split(data) self.times, self.data = zip(*numeric) if not self.times: raise Exception('Didn\'t understand envelope %s' % data) if len(self.times) == 1: self._set_constant(self.data[0]) return _check_times(self.times) self.loops = kwds.get('loops', 1) self.last_time = self.times[-1] length = kwds.get('length', self.last_time * self.loops) from echomesh.expression import Expression self.length = Expression.convert(length, self.element) if self.length > 0: self._is_constant = False self.slot = 0 self.reverse = kwds.get('reverse', False) else: self._set_constant(self.data[0]) if self.length < 0: LOGGER.error('Negative length "%s" is not allowed.', length) self.length = 0
def make_table_and_patterns(pattern_desc, attributes): table = {} patterns = [] desc = pattern_desc.description pd = pattern_desc try: for k, v in six.iteritems(desc): if not k.startswith('pattern'): if k in attributes: v = Expression.expression(v, pattern_desc.element) table[k] = v pats = desc.get('patterns') or desc.get('pattern') or [] if type(pats) is not list: pats = [pats] for p in pats: pd = _PatternDesc(pattern_desc.element, p, pattern_desc.name) pattern = _make_pattern(pd, False) if pattern: patterns.append(pattern) except Exception as e: if RAISE_ORIGINAL_EXCEPTION: raise else: raise Exception('%s in %s' % (e, pd)) return table, patterns
def set_player(player, element, level=1, pan=0, loops=1, begin=0, end=-1, length=-1, **kwds): kwds.pop('type', None) player._element = element player._file = kwds.pop('file') player._filename = Util.DEFAULT_AUDIO_DIRECTORY.expand(player._file) if kwds: LOGGER.error('Unused keywords %s', kwds) player._passthrough = (level == 1 and pan == 0) player._length = length player._level = Expression.expression(level, element) player._pan = Expression.expression(pan, element) player._loops = loops player._begin = begin player._end = end
def config_update(self, get): config = get('network', 'client') if self.constructed: # TODO: restart the server on the fly if its parameters change. pass else: self.constructed = True super(ClientServer, self).__init__( config['host_name'], config['port'], allow_reuse_address=config['allow_reuse_address'], debug=config['debug'], read_callback=self.read_callback, timeout=Expression.convert(get('network', 'timeout')), ) self.start() if (not self.process) and config['start']: args = {} if config['pipe_stdin']: args['stdin'] = subprocess.PIPE if config['pipe_stdout']: args['stdout'] = subprocess.PIPE command = Client.make_command() LOGGER.vdebug("About to start client process: '%s'", command) try: self.process = subprocess.Popen(command, **args) except: LOGGER.error("Couldn't start the subprocess with command '%s'", command) else: LOGGER.vdebug('Client process started!') elif self.process: LOGGER.vdebug('Not starting client: the configuration said not to.')
def _fix_config(self, get): light = copy.deepcopy(get('light')) light['brightness'] = Expression.convert(light['brightness']) light['hardware']['period'] = Expression.convert(light['hardware']['period']) light['visualizer']['period'] = Expression.convert(light['visualizer']['period']) visualizer = light['visualizer'] visualizer['background'] = ColorTable.to_color(visualizer['background']) dl = visualizer['instrument'] dl['border']['color'] = ColorTable.to_color(dl['border']['color']) dl['background'] = ColorTable.to_color(dl['background']) data = {'light': light, 'midi': get('midi')} config = {'type': 'config', 'data': data} self.closes_echomesh = visualizer['closes_echomesh'] ## ! return config
def __init__(self, desc, element, name): self.name = name self.element = element desc = ReadObservingDictionary(desc) pat = desc.pop('pattern', []) if isinstance(pat, dict): pat = [pat] elif isinstance(pat, six.string_types): pat = split_on_commas(pat) self._patterns = [make_pattern(element, p) for p in pat] if self.PATTERN_COUNT is not None: assert self.PATTERN_COUNT == len(self._patterns), ( "Pattern type %s expects %s subpatterns but got %d" % (self.__class__.__name__, self.PATTERN_COUNT, len(self._patterns))) self.dictionary = {} self.is_constant = all(p.is_constant for p in self._patterns) missing = [] self.constants = set() for k, v in self.SETTINGS.items(): const = v.get('constant', self.CONSTANT) literal = v.get('literal') if const: self.constants.add(k) value = desc.get(k, v.get('default')) if value is None and 'default' not in v: missing.append(k) else: if literal: expression = LiteralExpression(value) elif const: expression = ConstantExpression.constant_expression(value) else: expression = Expression.expression(value, element) self.dictionary[k] = expression self.is_constant = self.is_constant and expression.is_constant() if missing: raise Exception('%s is missing required arguments %s' % (self, ', '.join(missing))) unread = desc.unread() if unread: LOGGER.error( "For pattern type %s, we didn't use the following parameters: %s", self.__class__.__name__, ', '.join(unread)) self._in_precompute = True self._precompute() self._in_precompute = False if self.is_constant: self._value = self._evaluate();
def __init__(self, desc, element, name): self.name = name self.element = element desc = ReadObservingDictionary(desc) pat = desc.pop('pattern', []) if isinstance(pat, dict): pat = [pat] elif isinstance(pat, six.string_types): pat = split_on_commas(pat) self._patterns = [make_pattern(element, p) for p in pat] if self.PATTERN_COUNT is not None: assert self.PATTERN_COUNT == len(self._patterns), ( "Pattern type %s expects %s subpatterns but got %d" % (self.__class__.__name__, self.PATTERN_COUNT, len(self._patterns))) self.dictionary = {} self.is_constant = all(p.is_constant for p in self._patterns) missing = [] self.constants = set() for k, v in self.SETTINGS.items(): const = v.get('constant', self.CONSTANT) literal = v.get('literal') if const: self.constants.add(k) value = desc.get(k, v.get('default')) if value is None and 'default' not in v: missing.append(k) else: if literal: expression = LiteralExpression(value) elif const: expression = ConstantExpression.constant_expression(value) else: expression = Expression.expression(value, element) self.dictionary[k] = expression self.is_constant = self.is_constant and expression.is_constant( ) if missing: raise Exception('%s is missing required arguments %s' % (self, ', '.join(missing))) unread = desc.unread() if unread: LOGGER.error( "For pattern type %s, we didn't use the following parameters: %s", self.__class__.__name__, ', '.join(unread)) self._in_precompute = True self._precompute() self._in_precompute = False if self.is_constant: self._value = self._evaluate()
def __init__(self, element, period, begin=None, end=None, count=None, skip=1, repeat=INFINITY, **kwds): parts = [ Expression.convert(x, element) for x in (count, begin, end, skip) ] self.count, self.begin, self.end, self.skip = Interval.interval(*parts) self.element = element self.period = Expression.convert(period, element) self.repeat = repeat if kwds: LOGGER.error('Unknown keywords "%s" for counter', kwds)
def settings_update(self, get): port = get('osc', 'server', 'port') if port == self.port: return if self.server: self.server.close() self.server = None self.port = port self.server = OSC.OSCServer(('', port), None, port) self.server.socket.settimeout( Expression.convert(get('network', 'timeout')))
def make_command(): parts = [] config = Config.get('network', 'client') parts.append(config['binary'] or COMMAND) parts.append(config['host_name']) parts.append(str(config['port'])) timeout = Expression.convert(Config.get('network', 'timeout')) parts.append(str(timeout)) parts.append(str(config['buffer_size'])) parts.append(str(config['debug'])) return parts
def __init__(self, parent, desc): times = [] for e in desc.get('elements', []): times.append([ Expression.convert(e.pop(a, None)) for a in Sequence.ATTRIBUTES ]) self.elements = [] self.output = desc.get('output', None) self.patterns = {} for k, v in desc.get('pattern', {}).items(): self.patterns[k] = make_pattern(self, v, k) super(Sequence, self).__init__(parent, desc, name='Sequence', full_slave=False) self.loops = Expression.convert(desc.get('loops', 1)) self.duration = Expression.convert(desc.get('duration', 'infinity')) self.sequence = [] self.paused_children = set() for element, t in zip(self.elements, times): begin, end, duration = t if duration is not None: if end is not None: begin = end - duration elif begin is not None: end = begin + duration self.sequence.append([begin or 0, element.start]) if end is not None: self.sequence.append([end, element.pause]) self.sequence.append([self.duration, self.pause]) self.sequence.sort(key=operator.itemgetter(0))
def after_server_starts(self): if cechomesh.LOADED: run_after(self.run, Expression.convert(Settings.get('execution', 'delay_before_run'))) else: self.run() if self.display: self.display_loop() elif not USE_KEYBOARD_THREAD and self.keyboard_runnable: self.keyboard_runnable.loop() else: while self.is_running: time.sleep(self.timeout)
def config_update(self, get): new_port = get('network', self.config_name, 'port') timeout_name = 'network', 'timeout' timeout = Expression.convert(get(*timeout_name)) self.port, old_port = new_port, self.port try: self.timeout = Expression.convert(timeout) except: timeout_name = '.'.join(timeout_name) LOGGER.error( '\nCouldn\'t evaluate value "%s" in "%s=%s"', timeout, timeout_name, timeout, raw=True) LOGGER.error( 'Timeout defaults to %s=%s.', timeout_name, DEFAULT_TIMEOUT, raw=True) self.timeout = DEFAULT_TIMEOUT if self.is_running and self.socket: if self.port == old_port: self.socket.timeout = self.timeout else: self.remove_slave(self.socket) self.socket.pause() self._make_socket()
def __init__(self, data, element=None): self.element = element from echomesh.expression import SplitNumbers kwds, numeric = SplitNumbers.split(data) self.times, self.data = zip(*numeric) if not self.times: raise Exception('Didn\'t understand envelope %s' % data) if len(self.times) == 1: self._set_constant(self.data[0]) return _check_times(self.times) self.loops = kwds.get('loops', 1) if not isinstance(self.loops, six.integer_types): from echomesh.expression import Expression self.loops = Expression.convert(self.loops) self.last_time = self.times[-1] length = kwds.get('length', self.last_time * self.loops) from echomesh.expression import Expression self.length = Expression.convert(length, self.element) if self.length > 0: self._is_constant = False self.slot = 0 self.reverse = kwds.get('reverse', False) else: self._set_constant(self.data[0]) if self.length < 0: LOGGER.error('Negative length "%s" is not allowed.', length) self.length = 0
def update_callback(self): self.period = Expression.convert(self.values.period) self.lighting_window.set_light_count( self.values.light_count or ( self.values.layout[0] * self.values.layout[1])) self.lighting_window.set_shape(self.values.shape == 'rect') self.lighting_window.set_show_label(self.values.show_label) self.lighting_window.set_label_starts_at_zero( self.values.label_starts_at_zero) self.lighting_window.set_layout( self.values.layout, self.values.size, self.values.padding, self.values.instrument_padding, self.values.label_padding) self.columns = self.values.layout[0] self.transform = self.values.transform if self.transform: try: self.transform = cechomesh.Transform(self.transform) except: LOGGER.error('Don\'t understand transform %s', self.transform) self.transform = None self.brightness = Expression.convert(self.values.brightness) if self.transform: self.brightness = self.transform.apply(self.brightness)
def settings_update(self, get): new_port = get('network', self.settings_name, 'port') timeout_name = 'network', 'timeout' timeout = Expression.convert(get(*timeout_name)) self.port, old_port = new_port, self.port try: self.timeout = Expression.convert(timeout) except: timeout_name = '.'.join(timeout_name) LOGGER.error( '\nCouldn\'t evaluate value "%s" in "%s=%s"', timeout, timeout_name, timeout, raw=True) LOGGER.error( 'Timeout defaults to %s=%s.', timeout_name, DEFAULT_TIMEOUT, raw=True) self.timeout = DEFAULT_TIMEOUT if self.is_running and self.socket: if self.port == old_port: self.socket.timeout = self.timeout else: self.remove_slave(self.socket) self.socket.pause() self._make_socket()
def keyboard(instance, writer=sys.stdout, reader=sys.stdin.readline, new_thread=True): def processor(line): try: return Command.execute(instance, line) except: LOGGER.error('Error processing command line.') sleep = Expression.convert(Settings.get('execution', 'delay_before_keyboard_activates')) keyboard = Keyboard(sleep=sleep, message=MESSAGE, processor=processor, writer=writer, reader=reader) if new_thread: runnable = ThreadRunnable(target=keyboard.loop) runnable.add_mutual_pause_slave(keyboard) return keyboard, runnable else: return keyboard, keyboard
def __init__(self): super(Pi3dDisplay, self).__init__() self.timeout = Expression.convert(Settings.get('network', 'timeout')) keywords = {} background = Settings.get('pi3d', 'background') if background: keywords.update(background=background) dimensions = Settings.get('pi3d', 'dimensions') if dimensions: x, y, width, height = dimensions keywords.update(x=x, y=y, width=width, height=height) for k in ['aspect', 'depth', 'far', 'near', 'tk', 'window_title']: keywords[k] = Settings.get('pi3d', k) from pi3d import Display self.display = Display.create(**keywords) Settings.add_client(self) Shader.SHADER()
def test_semitones(self): self.assertNear(Expression.convert('10 semitones'), 1.7817974362806785)
def test_ten_khz(self): self.assertNear(Expression.convert('10 kilohertz'), 0.0001)
def test_ten_hz(self): self.assertNear(Expression.convert('10 hertz'), 0.1)
def test_hz(self): self.assertNear(Expression.convert('1Hz'), 1.0)
def test_cent(self): self.assertNear(Expression.convert('50 cent'), 1.029302236643492)
def test_fraction_and_paren(self): self.assertNear(Expression.convert('(1/2)sec'), 0.5)
def test_fraction(self): self.assertNear(Expression.convert('1/2sec'), 0.5)
def test_addition(self): self.assertNear(Expression.convert('13 + 12 ms'), 0.025)
def test_ms(self): self.assertNear(Expression.convert('10ms'), 0.01)
def test_negative_decimal(self): self.assertNear(Expression.convert('-103.4 semitones'), 0.0025475626362608667)
def test_exponential(self): self.assertNear(Expression.convert('-1.034E+2 semitones'), 0.0025475626362608667)
def test_unicode_fraction(self): self.assertNear(Expression.convert('½sec'), 0.5)
def test_unit_no_space(self): self.assertNear(Expression.convert('12dB'), 3.9810717055349722)
def test_negative(self): self.assertNear(Expression.convert('-1 semitone'), 0.9438743126816935)