#!/usr/bin/python # -*- coding: utf-8 -*- # -*- Python -*- from pyalsa.alsahcontrol import HControl, Element as HElement, \ Info as HInfo, Value as HValue, InterfaceId, \ EventMask, EventMaskRemove MIXER = InterfaceId['Mixer'] MIXERS = str(MIXER) class BaseElement(InternalMElement): def __init__(self, mixer, name, index, weight): InternalMElement.__init__(self, mixer, name, index, weight) self.channels = 0 self.min = [0, 0] self.max = [0, 0] def opsIsChannel(self, dir, chn): return chn >= 0 and chn < self.channels def opsGetRange(self, dir): return (0, self.min[dir], self.max[dir]) def opsSetRange(self, dir, min, max): self.min[dir] = min self.max[dir] = max def volumeToUser(self, info, dir, value): min = info.min max = info.max if min == max: return self.min[dir] n = (value - min) * (self.max[dir] - self.min[dir]) return self.min[dir] + (n + (max - min) / 2) / (max - min) def volumeFromUser(self, info, dir, value): min = info.min max = info.max if self.max[dir] == self.min[dir]: return min n = (value - self.min[dir]) * (max - min) return min + (n + (self.max[dir] - self.min[dir]) / 2) / (self.max[dir] - self.min[dir]) class StandardElement(BaseElement): def __init__(self, mixer, name, index, weight): BaseElement.__init__(self, mixer, name, index, weight) self.channels = 1 self.volume = [None, None] self.volumeinfo = [None, None] self.volumearray = [None, None] self.switch = [None, None] self.switchinfo = [None, None] self.switcharray = [None, None] def decideChannels(self): max = 0 for i in [0, 1]: if self.volume[i]: count = self.volumeinfo[i].count if count > max: max = count if self.switch[i]: count = self.switchinfo[i].count if count > max: max = count self.channels = max def attachVolume(self, helem, dir): self.volume[dir] = helem self.volumeinfo[dir] = HInfo(helem) self.min[dir] = self.volumeinfo[dir].min self.max[dir] = self.volumeinfo[dir].max self.volumearray[dir] = HValue(helem).getArray(self.volumeinfo[dir].type, self.volumeinfo[dir].count) def attachSwitch(self, helem, dir): self.switch[dir] = helem self.switchinfo[dir] = HInfo(helem) self.switcharray[dir] = HValue(helem).getArray(self.switchinfo[dir].type, self.switchinfo[dir].count) def attach(self, helem): BaseElement.attach(self, helem) if helem.name.endswith('Playback Volume'): self.attachVolume(helem, 0) self.caps |= self.CAP_PVOLUME elif helem.name.endswith('Capture Volume'): self.attachVolume(helem, 1) self.caps |= self.CAP_CVOLUME elif helem.name.endswith('Playback Switch'): self.attachSwitch(helem, 0) self.caps |= self.CAP_PSWITCH elif helem.name.endswith('Capture Switch'): self.attachSwitch(helem, 1) self.caps |= self.CAP_CSWITCH self.decideChannels() self.eventInfo() def opsGetVolume(self, dir, chn): return (0, self.volumeToUser(self.volumeinfo[dir], dir, self.volumearray[dir][chn])) def opsSetVolume(self, dir, chn, value): val = self.volumeFromUser(self.volumeinfo[dir], dir, value) if self.volumearray[dir][chn] == val: return self.volumearray[dir][chn] = val hv = HValue(self.volume[dir]) hv.setArray(self.volumeinfo[dir].type, self.volumearray[dir]) hv.write() def opsGetSwitch(self, dir, chn): return (0, self.switcharray[dir][chn]) def opsSetSwitch(self, dir, chn, value): if self.switcharray[dir][chn] and value: return if not self.switcharray[dir][chn] and not value: return self.switcharray[dir] = int(value) hv = HValue(self.switch[dir]) hv.setArray(self.switchinfo[dir].type, self.switcharray[dir]) hv.write() def update(self, helem): for i in [0, 1]: if helem == self.volume[i]: self.volumearray[i] = HValue(helem).getArray(self.volumeinfo[i].type, self.volumeinfo[i].count) elif helem == self.switch[i]: self.switcharray[i] = HValue(helem).getArray(self.switchinfo[i].type, self.switchinfo[i].count) self.eventValue() class EnumElement(BaseElement): def __init__(self, mixer, name, index, weight): BaseElement.__init__(self, mixer, name, index, weight) self.mycaps = 0 def attach(self, helem): BaseElement.attach(self, helem) self.enum = helem self.enuminfo = HInfo(helem) self.enumarray = HValue(helem).getArray(self.enuminfo.type, self.enuminfo.count) self.channels = self.enuminfo.count self.texts = self.enuminfo.itemNames self.caps |= self.mycaps def opsIsEnumerated(self, dir=-1): if dir < 0: return 1 if dir == 0 and self.mycaps & self.CAP_PENUM: return 1 if dir == 1 and self.mycaps & self.CAP_CENUM: return 1 def opsIsEnumCnt(self, dir): return self.enuminfo.items def opsGetEnumItemName(self, item): return (0, self.texts[item]) def opsGetEnumItem(self, chn): if chn >= self.channels: return -1 return (0, self.enumarray[chn]) def opsSetEnumItem(self, chn, value): if chn >= self.channels: return -1 if self.enumarray[chn] == value: return self.enumarray[chn] = int(value) hv = HValue(self.enum) hv.setArray(self.enuminfo.type, self.enumarray) hv.write() def update(self, helem): self.enumarray = HValue(helem).getArray(self.enuminfo.type, self.enuminfo.count) self.eventValue() class EnumElementPlayback(EnumElement): def __init__(self, mixer, name, index, weight): EnumElement.__init__(self, mixer, name, index, weight) self.mycaps = self.CAP_PENUM class EnumElementCapture(EnumElement): def __init__(self, mixer, name, index, weight): EnumElement.__init__(self, mixer, name, index, weight) self.mycaps = self.CAP_CENUM ELEMS = [] def element_add(helem): key = helem.name+'//'+str(helem.index)+'//'+str(helem.interface) if not CONTROLS.has_key(key): return val = CONTROLS[key] felem = None for elem in ELEMS: if elem.name == val[0] and elem.index == val[1]: felem = elem break if not felem: felem = mixer.newMElement(val[3], val[0], val[1], val[2]) mixer.addMElement(felem) ELEMS.append(felem) felem.attach(helem) def eventHandler(evmask, helem, melem): if evmask == EventMaskRemove: return if evmask & EventMask['Add']: element_add(helem) if evmask & EventMask['Value']: melem.update(helem) def init(): hctl = HControl(device, load=False) mixer.attachHCtl(hctl) mixer.register()