def __init__(self, path): super().__init__() self.open(path) if self.get_property('type') != 4: raise ValueError('The character device is not for OXFW unit') ctx = GLib.MainContext.new() self.create_source().attach(ctx) self.__unit_dispatcher = GLib.MainLoop.new(ctx, False) self.__unit_th = Thread(target=lambda d: d.run(), args=(self.__unit_dispatcher, )) self.__unit_th.start() node = self.get_node() ctx = GLib.MainContext.new() node.create_source().attach(ctx) self.__node_dispatcher = GLib.MainLoop.new(ctx, False) self.__node_th = Thread(target=lambda d: d.run(), args=(self.__node_dispatcher, )) self.__node_th.start() parser = Ta1394ConfigRomParser() info = parser.parse_rom(self.get_node().get_config_rom()) self.vendor_name = info['vendor-name'] self.model_name = info['model-name'] self.fcp = Hinawa.FwFcp() self.fcp.bind(self.get_node()) self.hw_info = self._parse_hardware_info() self.supported_sampling_rates = self._parse_supported_sampling_rates() self.supported_stream_formats = self._parse_supported_stream_formats()
def set_sampling_rate(self, rate): if self.get_property('streaming'): raise RuntimeError('Packet streaming started.') if self._on_juju: raise RuntimeError('This operation is not supported withou ALSA.') req = Hinawa.FwReq() self._protocol.write_sampling_rate(req, rate)
def __init__(self, path): super().__init__() self.open(path) if self.get_property('type') != 3: raise ValueError('The character device is not for BeBoB unit') ctx = GLib.MainContext.new() self.create_source().attach(ctx) self.__unit_dispatcher = GLib.MainLoop.new(ctx, False) self.__unit_th = Thread(target=lambda d: d.run(), args=(self.__unit_dispatcher, )) self.__unit_th.start() node = self.get_node() ctx = GLib.MainContext.new() node.create_source().attach(ctx) self.__node_dispatcher = GLib.MainLoop.new(ctx, False) self.__node_th = Thread(target=lambda d: d.run(), args=(self.__node_dispatcher, )) self.__node_th.start() parser = BebobConfigRomParser() info = parser.parse_rom(self.get_node().get_config_rom()) self.vendor_id = info['vendor-id'] self.model_id = info['model-id'] self.fcp = Hinawa.FwFcp() self.fcp.bind(self.get_node()) self.firmware_info = self._get_firmware_info()
def __init__(self, path): if match('/dev/snd/hwC[0-9]*D0', path): super().__init__() self.open(path) if self.get_property('type') != 4: raise ValueError('The character device is not for OXFW unit') self.listen() self._on_juju = False, elif match('/dev/fw[0-9]*', path): # Just using parent class. super(Hinawa.FwUnit, self).__init__() Hinawa.FwUnit.open(self, path) Hinawa.FwUnit.listen(self) self._on_juju = True else: raise ValueError('Invalid argument for character device') parser = Ta1394ConfigRomParser() info = parser.parse_rom(self.get_config_rom()) self.vendor_name = info['vendor-name'] self.model_name = info['model-name'] self.fcp = Hinawa.FwFcp() self.fcp.listen(self) self.hw_info = self._parse_hardware_info() self.supported_sampling_rates = self._parse_supported_sampling_rates() self.supported_stream_formats = self._parse_supported_stream_formats()
def __init__(self, path): if match('/dev/snd/hwC[0-9]*D0', path): super().__init__() self.open(path) if self.get_property('type') != 3: raise ValueError('The character device is not for BeBoB unit') self._on_juju = False, self.listen() elif match('/dev/fw[0-9]*', path): # Just using parent class. super(Hinawa.FwUnit, self).__init__() Hinawa.FwUnit.open(self, path) Hinawa.FwUnit.listen(self) self._on_juju = True else: raise ValueError('Invalid argument for character device') parser = BebobConfigRomParser() info = parser.parse_rom(self.get_config_rom()) self.vendor_id = info['vendor-id'] self.model_id = info['model-id'] self.fcp = Hinawa.FwFcp() self.fcp.listen(self) self.firmware_info = self._get_firmware_info()
def set_standalone_clock_source(self, source): req = Hinawa.FwReq() labels = self._protocol.get_clock_source_names() if source not in labels or source == 'Unused': raise ValueError('Invalid argument for clock source.') alias = self._protocol.CLOCK_BITS[labels.index(source)] ExtStandaloneSpace.write_clock_source(self._protocol, req, alias)
def get_metering(self): meters = {} req = Hinawa.FwReq() for peak in ExtPeakSpace.get(self._protocol, req): for src in self._srcs: if peak['src-blk'] == src[1] and peak['src-ch'] in src[2]: break else: continue for dst in self._dsts: if peak['dst-blk'] == dst[1] and peak['dst-ch'] in dst[2]: break else: continue src_index = src[2].index(peak['src-ch']) dst_index = dst[2].index(peak['dst-ch']) if src[0] not in meters: meters[src[0]] = {0: {}, 1: {}} if dst[0] not in meters[src[0]][src_index]: meters[src[0]][src_index][dst[0]] = {0: 0, 1: 0} meters[src[0]][src_index][dst[0]][dst_index] = peak['peak'] return meters
def get_router_entries(self, rate): if rate not in self._protocol.get_supported_sampling_rates(): raise ValueError('Invalid argument for sampling rate.') mode = self._get_rate_mode(rate) entries = [] req = Hinawa.FwReq() routes = ExtCurrentConfigSpace.read_router_config( self._protocol, req, mode) for route in routes: for src in self._srcs: if route['src-blk'] == src[1] and route['src-ch'] in src[2]: break else: continue for dst in self._dsts: if route['dst-blk'] == dst[1] and route['dst-ch'] in dst[2]: break else: continue entry = { 'src': '{0}:{1}'.format(src[0], src[2].index(route['src-ch'])), 'dst': '{0}:{1}'.format(dst[0], dst[2].index(route['dst-ch'])), } entries.append(entry) return entries
def __init__(self, path): super().__init__() self.open(path) if self.get_property('type') != 1: raise ValueError('The character device is not for Dice unit') ctx = GLib.MainContext.new() self.create_source().attach(ctx) self.__unit_dispatcher = GLib.MainLoop.new(ctx, False) self.__unit_th = Thread(target=lambda d: d.run(), args=(self.__unit_dispatcher, )) self.__unit_th.start() node = self.get_node() ctx = GLib.MainContext.new() node.create_source().attach(ctx) self.__node_dispatcher = GLib.MainLoop.new(ctx, False) self.__node_th = Thread(target=lambda d: d.run(), args=(self.__node_dispatcher, )) self.__node_th.start() parser = Ta1394ConfigRomParser() info = parser.parse_rom(self.get_node().get_config_rom()) self.vendor_id = info['vendor-id'] self.model_id = info['model-id'] req = Hinawa.FwReq() self._protocol = TcatProtocolGeneral(self, req)
def get_stream_params(self, rate): if rate not in self._protocol.get_supported_sampling_rates(): raise ValueError('Invalid argument for sampling rate.') mode = self._get_rate_mode(rate) req = Hinawa.FwReq() return ExtCurrentConfigSpace.read_stream_config( self._protocol, req, mode)
def _write_quads(self, offset, quads): frames = [] count = len(quads) for i in range(count): frames.extend(pack('>I', quads[0])) quads = quads[1:] req = Hinawa.FwReq() req.write(self, self._BASE_ADDR + offset, frames)
def set_clock_source(self, source): if self.get_property('streaming'): raise RuntimeError('Packet streaming started.') req = Hinawa.FwReq() labels = self._protocol.get_clock_source_names() if source not in labels or source == 'Unused': raise ValueError('Invalid argument for clock source.') alias = self._protocol.CLOCK_BITS[labels.index(source)] self._protocol.write_clock_source(req, alias)
def write(self, offset, frames): req = Hinawa.FwReq(timeout=100) addr = self.BASE_ADDR + offset if self._debug: print(' write: {0:012x}:'.format(addr)) for i, frame in enumerate(frames): print(' {0:04x}: {1:02x}'.format(offset + i, frame)) req.write(self._unit, addr, frames)
def read(self, offset, size): req = Hinawa.FwReq() addr = self.BASE_ADDR + offset frames = req.read(self._unit, addr, size) if self._debug: print(' read: {0:012x}:'.format(addr)) for i, frame in enumerate(frames): print(' {0:04x}: {1:02x}'.format(offset + i, frame)) return bytearray(frames)
def set_mixer_src(self, target, src, db): offset = FFMixerRegs.calculate_src_offset(self.__spec, target, src) val = self.__build_val_from_db(db) data = pack('<I', val) req = Hinawa.FwReq() req.transaction(self.get_node(), Hinawa.FwTcode.WRITE_BLOCK_REQUEST, self.__regs[1] + offset, len(data), data) self.__mixer_cache[offset // 4] = val self.__write_cache_to_file()
def get_sync_status(self): req = Hinawa.FwReq() frames = bytearray(8) frames = req.transaction(self.get_node(), Hinawa.FwTcode.READ_BLOCK_REQUEST, 0x0000801c0000, 8, frames) quads = unpack('<2I', frames) return FFStatusReg.parse(quads)
def _read_quads(self, offset, count): quads = [] req = Hinawa.FwReq() size = count * 4 frames = req.read(self, self._BASE_ADDR + offset, size) for i in range(count): quads.append(unpack('>I', frames[0:4])[0]) frames = frames[4:] return quads
def get_mixer_balance(self, output, input, ch): req = Hinawa.FwReq() gains = self._get_mixer_gains(req, output, input, ch) total = gains[0]['val'] + gains[1]['val'] if total == 0: balance = ch * 100.0 else: balance = float(100 * gains[1]['val'] // total) return balance
def set_mixer_balance(self, output, input, ch, balance): req = Hinawa.FwReq() gains = self._get_mixer_gains(req, output, input, ch) total = gains[0]['val'] + gains[1]['val'] gains[0]['val'] = int(total * (100 - balance) // 100) gains[1]['val'] = total - gains[0]['val'] for gain in gains: ExtMixerSpace.write_gain(self._protocol, req, gain['dst-ch'], gain['src-ch'], gain['val'])
def _write_transaction(self, offset, size): req = Hinawa.FwReq() addr = self.__BASE_ADDR + offset if size == 4: tcode = Hinawa.FwTcode.WRITE_QUADLET_REQUEST else: tcode = Hinawa.FwTcode.WRITE_BLOCK_REQUEST frames = bytearray(size) return req.transaction(self.get_node(), tcode, addr, size, frames)
def __load_option_settings(self): # Assist ALSA fireface driver to handle MIDI messages from Fireface 400. if self.__name == 'Fireface400': FFOptionReg.build_single_option(self.__option_cache, 'midi-low-addr', '0x00000000', True) req = Hinawa.FwReq() frames = pack('<3I', *self.__option_cache) req.transaction(self.get_node(), Hinawa.FwTcode.WRITE_BLOCK_REQUEST, self.__regs[0], len(frames), frames)
def set_out_volume(self, target, db): if db > self.get_db_max(): raise ValueError('Invalid argument for db.') offset = FFOutRegs.calculate_out_offset(self.__spec, target) val = self.__build_val_from_db(db) data = pack('<I', val) req = Hinawa.FwReq() req.transaction(self.get_node(), Hinawa.FwTcode.WRITE_BLOCK_REQUEST, self.__regs[2] + offset, len(data), data) self.__out_cache[offset // 4] = val
def get_mixer_balance(self, output, input, ch): req = Hinawa.FwReq() gains = self._get_mixer_gains(req, output, input) left = gains[ch]['val'] right = gains[ch + 2]['val'] total = left + right if total == 0: return float('-inf') else: return 100 * right / total
def get_meters(cls, unit: Hinawa.FwNode): req = Hinawa.FwReq() frames = bytearray(8) frames = req.transaction(unit.get_node(), Hinawa.FwTcode.READ_BLOCK_REQUEST, cls.__ADDR_IN_METERS, 8, frames) vals = unpack('>2I', frames) meters = { 'analog-1': vals[0], 'alaong-2': vals[1], } return meters
def _seek_snd_unit_from_guid(guid): for fullpath in Path('/dev/snd').glob('hw*'): fullpath = str(fullpath) try: unit = Hinawa.SndUnit() unit.open(fullpath) if unit.get_property('guid') == guid: return fullpath except Exception as e: pass finally: del unit return None
def write(self, offset, frames): req = Hinawa.FwReq(timeout=100) if len(frames) == 4: tcode = Hinawa.FwTcode.WRITE_QUADLET_REQUEST else: tcode = Hinawa.FwTcode.WRITE_BLOCK_REQUEST addr = self.BASE_ADDR + offset if self._debug: print(' write: {0:012x}:'.format(addr)) for i, frame in enumerate(frames): print(' {0:04x}: {1:02x}'.format(offset + i, frame)) req.transaction(self.get_node(), tcode, addr, len(frames), frames)
def _write_quads(self, offset, quads): frames = [] count = len(quads) for i in range(count): frames.extend(pack('>I', quads[0])) quads = quads[1:] req = Hinawa.FwReq() if len(frames) == 4: tcode = Hinawa.FwTcode.WRITE_QUADLET_REQUEST else: tcode = Hinawa.FwTcode.WRITE_BLOCK_REQUEST req.transaction(self.get_node(), tcode, self._BASE_ADDR + offset, len(frames), frames)
def set_mixer_balance(self, output, input, ch, balance): req = Hinawa.FwReq() gains = self._get_mixer_gains(req, output, input) total = gains[ch]['val'] + gainc[ch + 2]['val'] left = total * (100 - balance) // 100 right = total - left gains[ch]['val'] = left gains[ch + 2]['val'] = right for gain in gains: dst_ch = gain['dst-ch'] src_ch = gain['src-ch'] val = gain['val'] ExtMixerSpace.write_gain(self._protocol, req, dst_ch, src_ch, val)
def get_meters(cls, unit: Hinawa.FwNode): req = Hinawa.FwReq() frames = bytearray(16) frames = req.transaction(unit.get_node(), Hinawa.FwTcode.READ_BLOCK_REQUEST, cls.__ADDR_SRC_LEVELS, 16, frames) vals = unpack('>4I', frames) meters = { 'stream-1': vals[0], 'stream-2': vals[1], 'analog-1': vals[2], 'alaong-2': vals[3], } return meters
def get_meters(self): meters = {} req = Hinawa.FwReq() data = req.read(self._unit, self._ADDR_FOR_METERING, 84) meters['switch-0'] = data[0] meters['rotery-0'] = data[1] meters['rotery-1'] = data[2] meters['rotery-2'] = data[3] data = data[4:] for i, label in enumerate(self._METERING_LABELS): meters[label] = (data[i * 2] << 8) | data[i * 2 + 1] meters['rate'] = AvcConnection.sampling_rates[(data[-1] >> 8) & 0x0f] meters['sync'] = (data[-1] & 0x0f) > 0 return meters