def _parse_signal_sources(self): srcs = [] candidates = [] # This is internal clock source. for subunit_id, subunit_id_plugs in self.subunit_plugs['music'].items( ): for i, plug in subunit_id_plugs['output'].items(): if plug['type'] == 'Sync': addr = AvcCcm.get_subunit_signal_addr('music', 0, i) candidates.append((addr, plug)) # External source is available. for i, plug in self.unit_plugs['external']['input'].items(): if plug['type'] in ('Sync', 'Digital', 'Clock'): addr = AvcCcm.get_unit_signal_addr('external', i) candidates.append((addr, plug)) # SYT-match is available, but not practical. for i, plug in self.unit_plugs['isoc']['input'].items(): if plug['type'] == 'Sync': addr = AvcCcm.get_unit_signal_addr('isoc', i) candidates.append((addr, plug)) # BeBoBv3 has. # Inquire these are able to connect to destination. for params in candidates: addr = params[0] plug = params[1] try: AvcCcm.ask_signal_source(self.fcp, addr, self.signal_destination) except: continue srcs.append(params) return srcs
def get_avail_connections(cls, fcp, unit_plug_list, subunit_plug_list): src_candidates = {} dst_candidates = {} avail = {} for seqid, info in unit_plug_list.items(): data = info['data'] addr = AvcCcm.get_unit_signal_addr(data['unit-type'], data['plug']) if info['dir'] == 'output': target = dst_candidates else: target = src_candidates target[seqid] = addr for seqid, info in subunit_plug_list.items(): data = info['data'] addr = AvcCcm.get_subunit_signal_addr(data['subunit-type'], data['subunit-id'], data['plug']) # Inverse direction against plugs of unit. if info['dir'] == 'output': target = src_candidates else: target = dst_candidates target[seqid] = addr for dst_seqid, dst_addr in dst_candidates.items(): try: curr_src_info = AvcCcm.get_signal_source(fcp, dst_addr) except Exception: curr_src_info = None for src_seqid, src_addr in src_candidates.items(): try: AvcCcm.ask_signal_source(fcp, src_addr, dst_addr) except Exception: continue if dst_seqid not in avail: avail[dst_seqid] = [] src_info = AvcCcm.parse_signal_addr(src_addr) avail[dst_seqid].append((src_seqid, src_info == curr_src_info)) return avail
class ApogeeEnsembleUnit(BebobUnit): __CLOCK_SRCS = { 'Coaxial': AvcCcm.get_unit_signal_addr('external', 4), 'Optical': AvcCcm.get_unit_signal_addr('external', 5), 'Word-clock': AvcCcm.get_unit_signal_addr('external', 6), } def __init__(self, path): super().__init__(path) if (self.vendor_id, self.model_id) != (0x0003db, 0x01eeee): raise OSError('Not supported.') guid = self.get_property('guid') self.__path = Path('/tmp/hinawa-{0:08x}'.format(guid)) if self.__path.exists() and self.__path.is_file(): self.__load_cache() else: self.__create_cache() self.__set_from_cache() self.__save_cache() def __load_cache(self): with self.__path.open(mode='r') as f: self.__cache = load(f) def __save_cache(self): with self.__path.open(mode='w+') as f: dump(self.__cache, f) def __create_cache(self): cache = {} HwCmd.create_cache(cache) DisplayCmd.create_cache(cache) OptIfaceCmd.create_cache(cache) MicCmd.create_cache(cache) InputCmd.create_cache(cache) OutputCmd.create_cache(cache) MixerCmd.create_cache(cache) RouteCmd.create_cache(cache) SpdifResampleCmd.create_cache(cache) self.__cache = cache def __set_from_cache(self): val = HwCmd.get_cd_mode(self.__cache) HwCmd.set_cd_mode(self.__cache, self.fcp, val) val = HwCmd.get_16bit_mode(self.__cache) HwCmd.set_16bit_mode(self.__cache, self.fcp, val) val = DisplayCmd.get_illuminate(self.__cache) DisplayCmd.set_illuminate(self.__cache, self.fcp, val) val = DisplayCmd.get_mode(self.__cache) DisplayCmd.set_mode(self.__cache, self.fcp, val) val = DisplayCmd.get_target(self.__cache) DisplayCmd.set_target(self.__cache, self.fcp, val) val = DisplayCmd.get_overhold(self.__cache) DisplayCmd.set_overhold(self.__cache, self.fcp, val) for target in OptIfaceCmd.get_target_labels(): val = OptIfaceCmd.get_mode(self.__cache, target) OptIfaceCmd.set_mode(self.__cache, self.fcp, target, val) for target in MicCmd.get_mic_labels(): val = MicCmd.get_power(self.__cache, target) MicCmd.set_power(self.__cache, self.fcp, target, val) val = MicCmd.get_polarity(self.__cache, target) MicCmd.set_polarity(self.__cache, self.fcp, target, val) for target in InputCmd.get_in_labels(): val = InputCmd.get_soft_limit(self.__cache, target) InputCmd.set_soft_limit(self.__cache, self.fcp, target, val) val = InputCmd.get_attr(self.__cache, target) InputCmd.set_attr(self.__cache, self.fcp, target, val) for target in OutputCmd.get_target_labels(): val = OutputCmd.get_attr(self.__cache, target) OutputCmd.set_attr(self.__cache, self.fcp, target, val) for target in MixerCmd.get_target_labels(): for src in MixerCmd.get_src_labels(): vals = MixerCmd.get_src_gain(self.__cache, target, src) MixerCmd.set_src_gain(self.__cache, self.fcp, target, src, *vals) for target in RouteCmd.get_out_labels(): src = RouteCmd.get_out_src(self.__cache, target) RouteCmd.set_out_src(self.__cache, self.fcp, target, src) for target in RouteCmd.get_cap_labels(): src = RouteCmd.get_cap_src(self.__cache, target) RouteCmd.set_cap_src(self.__cache, self.fcp, target, src) for target in RouteCmd.get_hp_labels(): src = RouteCmd.get_hp_src(self.__cache, target) RouteCmd.set_hp_src(self.__cache, self.fcp, target, src) params = SpdifResampleCmd.get_params(self.__cache) SpdifResampleCmd.set_params(self.__cache, self.fcp, *params) def __get_clock_plugs(self): plugs = {} info = AvcConnection.get_subunit_plug_info(self.fcp, 'music', 0) for direction in ('input', 'output'): for i in range(info[direction]): addr = BcoPlugInfo.get_subunit_addr(direction, 'music', 0, i) plug_type = BcoPlugInfo.get_plug_type(self.fcp, addr) if plug_type == 'Sync': plugs[direction] = \ AvcCcm.get_subunit_signal_addr('music', 0, i) break else: raise OSError('Unexpected state of device for clock source.') return plugs def get_clock_src_labels(self): labels = list(self.__CLOCK_SRCS.keys()) labels.append('Internal') return labels def set_clock_src(self, src): if self.get_property('streaming'): raise OSError('Packet streaming started.') if src not in self.__CLOCK_SRCS and src != 'Internal': raise ValueError('Invalid argument for source of clock.') plugs = self.__get_clock_plugs() dst = plugs['input'] if src == 'Internal': src = plugs['output'] else: src = self.__CLOCK_SRCS[src] AvcCcm.set_signal_source(self.fcp, src, dst) def get_clock_src(self): plugs = self.__get_clock_plugs() dst = plugs['input'] src = AvcCcm.get_signal_source(self.fcp, dst) addr = AvcCcm.parse_signal_addr(plugs['output']) if AvcCcm.compare_addrs(src, addr): return 'Internal' for name, addr in self.__CLOCK_SRCS.items(): if AvcCcm.compare_addrs(src, AvcCcm.parse_signal_addr(addr)): return name raise OSError('Unexpected state of device.') def get_stream_mode_labels(self): return HwCmd.get_stream_mode_labels() def set_stream_mode(self, mode): HwCmd.set_stream_mode(mode) def get_stream_mode(self): sync_plug_ids = { 5: '8x8', 6: '10x10', 7: '16x16', } plugs = self.__get_clock_plugs() addr = AvcCcm.parse_signal_addr(plugs['output']) plug_id = addr['data']['plug'] if plug_id not in sync_plug_ids: raise OSError('Unexpected state of device.') return sync_plug_ids[plug_id] def reset_meters(self): DisplayCmd.reset_meter(self.fcp) def set_cd_mode(self, enable): if enable: if self.__cache['hw']['16bit'] != 'spdif-coax-out-1/2': raise ValueError('16bit-mode should be spdif-coax-out-1/2.') rate = AvcConnection.get_plug_signal_format(self.fcp, 'output', 0) if rate != 44100: raise ValueError('Sampling rate should be 44100.') HwCmd.set_cd_mode(self.__cache, self.fcp, enable) self.__save_cache() def get_cd_mode(self): return HwCmd.get_cd_mode(self.__cache) def get_16bit_mode_labels(self): return HwCmd.get_16bit_mode_labels() def set_16bit_mode(self, target): if target != 'none': rate = AvcConnection.get_plug_signal_format(self.fcp, 'output', 0) if rate not in (44100, 48000): raise ValueError('Sampling rate should be 44100 or 48000.') HwCmd.set_16bit_mode(self.__cache, self.fcp, target) self.__save_cache() def get_16bit_mode(self): return HwCmd.get_16bit_mode(self.__cache) # Hardware configurations. def set_display_mode(self, enable): DisplayCmd.set_mode(self.__cache, self.fcp, enable) self.__save_cache() def get_display_mode(self): return DisplayCmd.get_mode(self.__cache) def get_display_target_labels(self): return DisplayCmd.get_target_labels() def set_display_target(self, target): DisplayCmd.set_target(self.__cache, self.fcp, target) self.__save_cache() def get_display_target(self): return DisplayCmd.get_target(self.__cache) def set_display_illuminate(self, enable): DisplayCmd.set_illuminate(self.__cache, self.fcp, enable) self.__save_cache() def get_display_illuminate(self): return DisplayCmd.get_illuminate(self.__cache) def set_display_overhold(self, enable): DisplayCmd.set_overhold(self.__cache, self.fcp, enable) self.__save_cache() def get_display_overhold(self): return DisplayCmd.get_overhold(self.__cache) def get_opt_iface_target_labels(self): return OptIfaceCmd.get_target_labels() def get_opt_iface_mode_labels(self): return OptIfaceCmd.get_mode_labels() def set_opt_iface_mode(self, target, mode): OptIfaceCmd.set_mode(self.__cache, self.fcp, target, mode) self.__save_cache() def get_opt_iface_mode(self, target): return OptIfaceCmd.get_mode(self.__cache, target) # Knob configurations. def get_knob_out_labels(self): return KnobCmd.get_knob_out_labels() def set_knob_out_volume(self, target, db): KnobCmd.set_out_vol(self.fcp, target, db) def get_knob_states(self): return KnobCmd.get_states(self.fcp) # Microphone configurations. def get_mic_labels(self): return MicCmd.get_mic_labels() def set_polarity(self, target, invert): MicCmd.set_polarity(self.__cache, self.fcp, target, invert) self.__save_cache() def get_polarity(self, target): return MicCmd.get_polarity(self.__cache, target) def set_phantom_power(self, target, enable): MicCmd.set_power(self.__cache, self.fcp, target, enable) self.__save_cache() def get_phantom_power(self, target): return MicCmd.get_power(self.__cache, target) # Line input/output configurations. def get_line_in_labels(self): return InputCmd.get_in_labels() def set_soft_limit(self, target, enable): InputCmd.set_soft_limit(self.__cache, self.fcp, target, enable) self.__save_cache() def get_soft_limit(self, target): return InputCmd.get_soft_limit(self.__cache, target) def get_in_attr_labels(self): return InputCmd.get_attr_labels() def set_in_attr(self, target, attr): InputCmd.set_attr(self.__cache, self.fcp, target, attr) self.__save_cache() def get_in_attr(self, target): return InputCmd.get_attr(self.__cache, target) def get_line_out_labels(self): return OutputCmd.get_target_labels() def get_out_attr_labels(self): return OutputCmd.get_attr_labels() def set_out_attr(self, target, attr): OutputCmd.set_attr(self.__cache, self.fcp, target, attr) self.__save_cache() def get_out_attr(self, target): return OutputCmd.get_attr(self.__cache, target) # Route configurations. def get_out_labels(self): return RouteCmd.get_out_labels() def get_out_src_labels(self): return RouteCmd.get_out_src_labels() def set_out_src(self, target, src): RouteCmd.set_out_src(self.__cache, self.fcp, target, src) self.__save_cache() def get_out_src(self, target): return RouteCmd.get_out_src(self.__cache, target) def get_cap_labels(self): return RouteCmd.get_cap_labels() def get_cap_src_labels(self): return RouteCmd.get_cap_src_labels() def set_cap_src(self, target, src): RouteCmd.set_cap_src(self.__cache, self.fcp, target, src) self.__save_cache() def get_cap_src(self, target): return RouteCmd.get_cap_src(self.__cache, target) def get_hp_labels(self): return RouteCmd.get_hp_labels() def get_hp_src_labels(self): return RouteCmd.get_hp_src_labels() def set_hp_src(self, target, src): RouteCmd.set_hp_src(self.__cache, self.fcp, target, src) self.__save_cache() def get_hp_src(self, target): return RouteCmd.get_hp_src(self.__cache, target) # Internal multiplexer configuration. def get_mixer_labels(self): return MixerCmd.get_target_labels() def get_mixer_src_labels(self): return MixerCmd.get_src_labels() def set_mixer_src(self, target, src, db, balance): MixerCmd.set_src_gain(self.__cache, self.fcp, target, src, db, balance) self.__save_cache() def get_mixer_src(self, target, src): return MixerCmd.get_src_gain(self.__cache, target, src) # S/PDIF resampler configuration. def get_spdif_resample_iface_labels(self): return SpdifResampleCmd.get_iface_labels() def get_spdif_resample_direction_labels(self): return SpdifResampleCmd.get_direction_labels() def get_spdif_resample_rate_labels(self): return SpdifResampleCmd.get_rate_labels() def set_spdif_resample(self, enable, iface, direction, rate): SpdifResampleCmd.set_params(self.__cache, self.fcp, enable, iface, direction, rate) self.__save_cache() def get_spdif_resample(self): return SpdifResampleCmd.get_params(self.__cache)
class MaudioProtocolNormal(MaudioProtocolAbstract): __IDS = ( 0x00000a, # Ozonic 0x010062, # Firewire Solo 0x010060, # Firewire Audiophile 0x010046, # Firewire 410 # Need information. # NRV10 # ProFire Lightbridge ) __LABELS = ( { 'inputs': ('analog-1/2', 'analog-3/4', 'stream-1/2', 'stream-3/4'), 'outputs': ('analog-1/2', 'analog-3/4'), 'mixers': ('mixer-1/2', 'mixer-3/4'), 'meters': ('analog-in-1', 'analog-in-2', 'analog-in-3', 'analog-in-4', 'stream-in-1', 'stream-in-2', 'stream-in-3', 'stream-in-4', 'analog-out-1', 'analog-out-2', 'analog-out-3', 'analog-out-4') }, { 'inputs': ('analog-1/2', 'digital-1/2', 'stream-1/2', 'stream-3/4'), 'outputs': ('analog-1/2', 'digital-1/2'), 'mixers': ('mixer-1/2', 'mixer-3/4'), 'meters': ('analog-in-1', 'analog-in-2', 'digital-in-1', 'digital-in-2', 'stream-in-1', 'stream-in-2', 'stream-in-3', 'stream-in-4', 'analog-out-1', 'analog-out-2', 'digital-out-1', 'digital-out-2') }, { 'inputs': ('analog-1/2', 'digital-1/2', 'stream-1/2', 'stream-3/4', 'stream-5/6'), 'outputs': ('analog-1/2', 'analog-3/4', 'digital-1/2'), 'mixers': ('mixer-1/2', 'mixer-3/4', 'mixer-5/6'), 'meters': ('analog-in-1', 'analog-in-2', 'digital-in-1', 'digital-in-2', 'analog-out-1', 'analog-out-2', 'analog-out-3', 'analog-out-4', 'digital-out-1', 'digital-out-2', 'headphone-out-1', 'headphone-out-2', 'aux-out-1', 'aux-out-2') }, { 'inputs': ('analog-1/2', 'digital-1/2', 'stream-1/2', 'stream-3/4', 'stream-5/6', 'stream-7/8', 'stream-9/10'), 'outputs': ('analog-1/2', 'analog-3/4', 'analog-5/6', 'analog-7/8', 'digital-1/2'), 'mixers': ('mixer-1/2', 'mixer-3/4', 'mixer-5/6', 'mixer-7/8', 'mixer-9/10'), 'meters': ('analog-in-1', 'analog-in-2', 'digital-in-1', 'digital-in-2', 'analog-out-1', 'analog-out-2', 'analog-out-3', 'analog-out-4', 'analog-out-5', 'analog-out-6', 'analog-out-7', 'analog-out-8', 'digital-out-1', 'digital-out-2', 'headphone-out-1', 'headphone-out-2', 'aux-out-1', 'aux-out-2') }, ) # = __LABELS['inputs'] __INPUTS = ( ((3, (1, 2)), (4, (1, 2)), (1, (1, 2)), (2, (1, 2))), ((1, (1, 2)), (2, (1, 2)), (4, (1, 2)), (3, (1, 2))), ((4, (1, 2)), (5, (1, 2)), (1, (1, 2)), (2, (1, 2)), (3, (1, 2))), ((3, (1, 2)), (4, (1, 2)), (2, (1, 2)), (1, (1, 2)), (1, (3, 4)), (1, (5, 6)), (1, (7, 8))), ) # = __LABELS['inputs'] __AUX__INPUTS = ( (), (), ((9, (1, 2)), (10, (1, 2)), (6, (1, 2)), (7, (1, 2)), (8, (1, 2))), ((7, (1, 2)), (8, (1, 2)), (9, (1, 2)), (6, (1, 2)), (5, (1, 2)), (5, (3, 4)), (5, (5, 6)), (5, (7, 8))), ) __AUX_OUTPUT = ( None, None, 11, 9, ) # = __LABELS['inputs'] __MIXER_SOURCES = ( ((2, (1, 2)), (3, (1, 2)), (0, (1, 2)), (1, (1, 2))), ((0, (1, 2)), (1, (1, 2)), (3, (1, 2)), (2, (1, 2))), ((3, (1, 2)), (4, (1, 2)), (0, (1, 2)), (1, (1, 2)), (2, (1, 2))), ((2, (1, 2)), (3, (1, 2)), (1, (1, 2)), (0, (1, 2)), (0, (3, 4)), (0, (5, 6)), (0, (7, 8))), ) # = __LABELS['mixers'] __MIXERS = ( ((1, (1, 2)), (1, (1, 2))), ((1, (1, 2)), (1, (3, 4))), ((1, (1, 2)), (2, (1, 2)), (3, (1, 2))), ((1, (1, 2)), (1, (3, 4)), (1, (5, 6)), (1, (7, 8)), (1, (9, 10))), ) # = __LABELS['outputs'] __OUTPUT_SOURCES = ( (), (), (1, 2, 3), (2, 3, 4, 5, 6), ) # = __LABELS['outputs'] __OUTPUTS = ( (), (), ((12, (1, 2)), (13, (1, 2)), (14, (1, 2))), ((10, (1, 2)), (11, (1, 2)), (12, (1, 2)), (13, (1, 2)), (14, (1, 2))), ) __HP_SOURCES = ( (), (), ((4, (0, 1, 2, 3)), ), ((7, (2, 3, 4, 5, 6, 7)), ), ) __HP_OUTS = ( (), (), ((15, (1, 2)), ), ((15, (1, 2)), ), ) __METERS = ( 48, 52, 60, 76, ) __CLOCKS = ( {}, { 'Internal': AvcCcm.get_subunit_signal_addr('music', 0, 1), 'S/PDIF': AvcCcm.get_unit_signal_addr('external', 1) }, { 'Internal': AvcCcm.get_subunit_signal_addr('music', 0, 1), 'S/PDIF': AvcCcm.get_unit_signal_addr('external', 2) }, { 'Internal': AvcCcm.get_subunit_signal_addr('music', 0, 1), 'S/PDIF': AvcCcm.get_unit_signal_addr('external', 2), 'ADAT': AvcCcm.get_unit_signal_addr('external', 3) }, ) def __init__(self, unit, debug): if unit.model_id not in self.__IDS: raise OSError('Not supported') super().__init__(unit, debug) index = self.__IDS.index(unit.model_id) self.labels = self.__LABELS[index] self.mixers = self.__MIXERS[index] self.__inputs = self.__INPUTS[index] self.__aux_inputs = self.__AUX__INPUTS[index] self.__aux_output = self.__AUX_OUTPUT[index] self.__mixer_sources = self.__MIXER_SOURCES[index] self.__output_sources = self.__OUTPUT_SOURCES[index] self.__outputs = self.__OUTPUTS[index] self.__hp_sources = self.__HP_SOURCES[index] self.__hp_outs = self.__HP_OUTS[index] self.__meters = self.__METERS[index] self.__clocks = self.__CLOCKS[index] def _refer_fb_data(self, targets, index, ch): if index >= len(targets): raise ValueError('Invalid argument for function block index') if ch >= len(targets[index][1]): raise ValueError('Invalid argument for channel number') fb = targets[index][0] ch = targets[index][1][ch] return (fb, ch) def _set_volume(self, targets, index, ch, db): fb, ch = self._refer_fb_data(targets, index, ch) data = AvcAudio.build_data_from_db(db) AvcAudio.set_feature_volume_state(self.unit.fcp, 0, 'current', fb, ch, data) def _get_volume(self, targets, index, ch): fb, ch = self._refer_fb_data(targets, index, ch) data = AvcAudio.get_feature_volume_state(self.unit.fcp, 0, 'current', fb, ch) return AvcAudio.parse_data_to_db(data) def get_input_labels(self): return self.labels['inputs'] def _refer_input_data(self, target): if target not in self.labels['inputs']: raise ValueError('Invalid argument for input') return self.labels['inputs'].index(target) def set_input_gain(self, target, ch, db): index = self._refer_input_data(target) self._set_volume(self.__inputs, index, ch, db) def get_input_gain(self, target, ch): index = self._refer_input_data(target) return self._get_volume(self.__inputs, index, ch) def get_input_balance_labels(self): labels = [] for label in self.labels['inputs']: if label.find('stream-') == 0: continue labels.append(label) return labels def set_input_balance(self, target, ch, balance): index = self._refer_input_data(target) fb, ch = self._refer_fb_data(self.__inputs, index, ch) data = AvcAudio.build_data_from_db(balance) AvcAudio.set_feature_lr_state(self.unit.fcp, 0, 'current', fb, ch, data) def get_input_balance(self, target, ch): index = self._refer_input_data(target) fb, ch = self._refer_fb_data(self.__inputs, index, ch) data = AvcAudio.get_feature_lr_state(self.unit.fcp, 0, 'current', fb, ch) return AvcAudio.parse_data_to_db(data) def get_output_labels(self): if len(self.__outputs) == 0: return () return self.labels['outputs'] def _refer_out_data(self, target): if target not in self.labels['outputs']: raise ValueError('Invalid argument for output') return self.labels['outputs'].index(target) def set_output_volume(self, target, ch, db): index = self._refer_out_data(target) self._set_volume(self.__outputs, index, ch, db) def get_output_volume(self, target, ch): index = self._refer_out_data(target) return self._get_volume(self.__outputs, index, ch) def set_aux_volume(self, ch, db): if ch > 2: raise ValueError('Invalid argument for master channel') fb = self.__aux_output data = AvcAudio.build_data_from_db(db) AvcAudio.set_feature_volume_state(self.unit.fcp, 0, 'current', fb, ch, data) def get_aux_volume(self, ch): if ch > 2: raise ValueError('Invalid argument for master channel') fb = self.__aux_output data = AvcAudio.get_feature_volume_state(self.unit.fcp, 0, 'current', fb, ch) return AvcAudio.parse_data_to_db(data) def set_aux_balance(self, ch, balance): if ch > 2: raise ValueError('Invalid argument for master channel') fb = self.__aux_output data = AvcAudio.build_data_from_db(balance) ch += 1 AvcAudio.set_feature_lr_state(self.unit.fcp, 0, 'current', fb, ch, data) def get_aux_balance(self, ch): if ch > 2: raise ValueError('Invalid argument for master channel') fb = self.__aux_output ch += 1 data = AvcAudio.get_feature_lr_state(self.unit.fcp, 0, 'current', fb, ch) return AvcAudio.parse_data_to_db(data) def get_headphone_labels(self): labels = [] for i in range(len(self.__hp_outs)): labels.append('headphone-{0}/{1}'.format(i * 2 + 1, i * 2 + 2)) return labels def _refer_hp_data(self, target): matches = match('^headphone-([0-9]*)/([0-9]*)$', target) if not matches: raise ValueError('Invalid argument for headphone') left = int(matches.group(1)) // 2 right = int(matches.group(2)) // 2 if right != left + 1: raise ValueError('Invalid argument for headphone') return left def set_headphone_volume(self, target, ch, db): index = self._refer_hp_data(target) self._set_volume(self.__hp_outs, index, ch, db) def get_headphone_volume(self, target, ch): index = self._refer_hp_data(target) return self._get_volume(self.__hp_outs, index, ch) def get_aux_input_labels(self): if not self.__aux_output: return () return self.labels['inputs'] def set_aux_input(self, target, ch, db): index = self._refer_input_data(target) self._set_volume(self.__aux_inputs, index, ch, db) def get_aux_input(self, target, ch): index = self._refer_input_data(target) return self._get_volume(self.__aux_inputs, index, ch) def get_mixer_labels(self): return self.labels['mixers'] def get_mixer_source_labels(self): return self.labels['inputs'] def _refer_mixer_data(self, target, source): if source not in self.labels['inputs']: raise ValueError('Invalid argument for mixer input') if target not in self.labels['mixers']: raise ValueError('Invalid argument for mixer output') input = self.labels['inputs'].index(source) in_fb = self.__mixer_sources[input][0] in_ch = self.__mixer_sources[input][1][0] # Use left channel. mixer = self.labels['mixers'].index(target) out_fb = self.mixers[mixer][0] out_ch = self.mixers[mixer][1][0] # Use left channel. return (in_fb, in_ch, out_fb, out_ch) def set_mixer_routing(self, target, source, enable): in_fb, in_ch, out_fb, out_ch = self._refer_mixer_data(target, source) if enable: data = (0x00, 0x00) else: data = (0x80, 0x00) AvcAudio.set_processing_mixer_state(self.unit.fcp, 0, 'current', out_fb, in_fb, in_ch, out_ch, data) def get_mixer_routing(self, target, source): in_fb, in_ch, out_fb, out_ch = self._refer_mixer_data(target, source) data = AvcAudio.get_processing_mixer_state(self.unit.fcp, 0, 'current', out_fb, in_fb, in_ch, out_ch) return data[0] == 0x00 and data[1] == 0x00 def get_headphone_source_labels(self, target): labels = [] if len(self.__hp_sources) > 0: for mixer in self.labels['mixers']: labels.append(mixer) if self.__aux_output: labels.append("aux-1/2") return labels def set_headphone_source(self, target, source): index = self._refer_hp_data(target) if source in self.labels['mixers']: ch = self.labels['mixers'].index(source) elif source.find('aux') == 0: ch = len(self.labels['mixers']) else: raise ValueError('Invalid argument for output target') fb = self.__hp_sources[index][0] value = self.__hp_sources[index][1][ch] AvcAudio.set_selector_state(self.unit.fcp, 0, 'current', fb, value) def get_headphone_source(self, target): index = self._refer_hp_data(target) fb = self.__hp_sources[index][0] value = AvcAudio.get_selector_state(self.unit.fcp, 0, 'current', fb) ch = self.__hp_sources[index][1][value] if ch < len(self.labels['mixers']): return self.labels['mixers'][ch] return 'aux-1/2' def get_output_source_labels(self, target): index = self._refer_out_data(target) labels = [] labels.append(self.labels['mixers'][index]) if self.__aux_output: labels.append("aux-1/2") return labels def set_output_source(self, target, source): index = self._refer_out_data(target) if source in self.labels['mixers'][index]: value = 0 elif source.find('aux') == 0: value = 1 else: raise ValueError('Invalid argument for output target') fb = self.__output_sources[index] AvcAudio.set_selector_state(self.unit.fcp, 0, 'current', fb, value) def get_output_source(self, target): index = self._refer_out_data(target) fb = self.__output_sources[index] value = AvcAudio.get_selector_state(self.unit.fcp, 0, 'current', fb) if value == 1 and self.__aux_output: return 'aux-1/2' return self.labels['mixers'][index] # 0x0000ffff - 0x7fffffff # db = 20 * log10(vol / 0x80000000) # vol = 0, then db = -144.0 # may differs analog-in and the others. def get_meters(self): labels = self.labels['meters'] meters = {} req = Hinawa.FwReq() frames = [0] * 256 data = req.transaction(self.unit.get_node(), Hinawa.FwTcode.READ_BLOCK_REQUEST, self._ADDR_FOR_METERING, self.__meters, frames) for i, name in enumerate(labels): meters[name] = unpack('>I', data[i * 4:(i + 1) * 4])[0] if len(data) > len(labels) * 4: meters['rotery-0'] = data[-3] & 0x0f meters['rotery-1'] = (data[-3] & 0xf0) >> 4 meters['rotery-2'] = 0 meters['switch-0'] = (data[-4] & 0xf0) >> 4 meters['switch-1'] = data[-4] & 0x0f meters['rate'] = AvcConnection.SAMPLING_RATES[data[-2]] meters['sync'] = data[-1] & 0x0f return meters def get_clock_source_labels(self): return self.__clocks.keys() def set_clock_source(self, src): if self.unit.get_property('streaming'): raise ValueError('Packet streaming already runs.') dst = AvcCcm.get_subunit_signal_addr('music', 0, 1) addr = self.__clocks[src] AvcCcm.set_signal_source(self.unit.fcp, addr, dst) def get_clock_source(self): dst = AvcCcm.get_subunit_signal_addr('music', 0, 1) curr = AvcCcm.get_signal_source(self.unit.fcp, dst) for name, addr in self.__clocks.items(): if AvcCcm.compare_addrs(curr, AvcCcm.parse_signal_addr(addr)): return name def get_sampling_rate(self): in_rate = AvcConnection.get_plug_signal_format(self.unit.fcp, 'input', 0) out_rate = AvcConnection.get_plug_signal_format( self.unit.fcp, 'output', 0) if in_rate != out_rate: raise OSError('Unexpected state of the unit: {0}!={1}'.format( in_rate, out_rate)) return in_rate