initial commit
This commit is contained in:
commit
84534fdd73
4 changed files with 1046 additions and 0 deletions
399
alsa.pyx
Normal file
399
alsa.pyx
Normal file
|
@ -0,0 +1,399 @@
|
||||||
|
# do some opaque struct typedefs to make const typedefs possible
|
||||||
|
cdef extern from "alsa/asoundlib.h":
|
||||||
|
ctypedef struct snd_mixer_t
|
||||||
|
ctypedef struct snd_mixer_class_t
|
||||||
|
ctypedef struct snd_pcm_t
|
||||||
|
ctypedef struct snd_mixer_elem_t
|
||||||
|
ctypedef struct snd_mixer_selem_id_t
|
||||||
|
|
||||||
|
# define const ptr types as cython doesnt know const
|
||||||
|
cdef extern from *:
|
||||||
|
ctypedef char* const_char_ptr "const char*"
|
||||||
|
ctypedef snd_mixer_selem_id_t* const_snd_mixer_selem_id_t_ptr "const snd_mixer_selem_id_t *"
|
||||||
|
ctypedef snd_mixer_elem_t* const_snd_mixer_elem_t_ptr "const snd_mixer_elem_t *"
|
||||||
|
ctypedef snd_mixer_t* const_snd_mixer_t_ptr "const snd_mixer_t *"
|
||||||
|
|
||||||
|
cdef extern from "stdlib.h":
|
||||||
|
ctypedef unsigned long size_t
|
||||||
|
void *calloc(size_t count, size_t size)
|
||||||
|
void *malloc(size_t size)
|
||||||
|
void free(void *ptr)
|
||||||
|
void *realloc(void *ptr, size_t size)
|
||||||
|
|
||||||
|
cdef extern from "alloca.h":
|
||||||
|
void *alloca(size_t size)
|
||||||
|
|
||||||
|
cdef extern from "string.h":
|
||||||
|
void *memset (void *s, int c, size_t n)
|
||||||
|
|
||||||
|
cdef extern from "sys/poll.h":
|
||||||
|
struct pollfd:
|
||||||
|
int fd
|
||||||
|
short int events
|
||||||
|
|
||||||
|
cdef extern from "alsa/asoundlib.h":
|
||||||
|
ctypedef enum snd_mixer_selem_regopt_abstract:
|
||||||
|
pass
|
||||||
|
ctypedef enum snd_mixer_elem_type_t:
|
||||||
|
pass
|
||||||
|
ctypedef enum snd_mixer_selem_channel_id_t:
|
||||||
|
pass
|
||||||
|
struct snd_mixer_selem_regopt:
|
||||||
|
pass
|
||||||
|
ctypedef int (*snd_mixer_compare_t)(const_snd_mixer_elem_t_ptr e1, const_snd_mixer_elem_t_ptr e2)
|
||||||
|
ctypedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl, unsigned int mask, snd_mixer_elem_t *elem)
|
||||||
|
ctypedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem, unsigned int mask)
|
||||||
|
|
||||||
|
int snd_mixer_open(snd_mixer_t **mixer, int mode)
|
||||||
|
int snd_mixer_close(snd_mixer_t *mixer)
|
||||||
|
snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer)
|
||||||
|
snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_handle_events(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_attach(snd_mixer_t *mixer, const_char_ptr name)
|
||||||
|
int snd_mixer_detach(snd_mixer_t *mixer, const_char_ptr name)
|
||||||
|
int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_poll_descriptors(snd_mixer_t *mixer, pollfd *pfds, unsigned int space)
|
||||||
|
int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
||||||
|
int snd_mixer_load(snd_mixer_t *mixer)
|
||||||
|
void snd_mixer_free(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_wait(snd_mixer_t *mixer, int timeout)
|
||||||
|
int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort)
|
||||||
|
void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
|
||||||
|
void * snd_mixer_get_callback_private(const_snd_mixer_t_ptr obj)
|
||||||
|
void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val)
|
||||||
|
unsigned int snd_mixer_get_count(const_snd_mixer_t_ptr obj)
|
||||||
|
int snd_mixer_class_unregister(snd_mixer_class_t *clss)
|
||||||
|
|
||||||
|
snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem)
|
||||||
|
snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem)
|
||||||
|
void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val)
|
||||||
|
void * snd_mixer_elem_get_callback_private(const_snd_mixer_elem_t_ptr obj)
|
||||||
|
void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val)
|
||||||
|
snd_mixer_elem_type_t snd_mixer_elem_get_type(const_snd_mixer_elem_t_ptr obj)
|
||||||
|
|
||||||
|
int snd_mixer_selem_register(snd_mixer_t *mixer, snd_mixer_selem_regopt *options, snd_mixer_class_t **classp)
|
||||||
|
void snd_mixer_selem_get_id(snd_mixer_elem_t *element, snd_mixer_selem_id_t *id)
|
||||||
|
const_char_ptr snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
|
||||||
|
unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem)
|
||||||
|
snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer, const_snd_mixer_selem_id_t_ptr id)
|
||||||
|
|
||||||
|
int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel)
|
||||||
|
int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel)
|
||||||
|
int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem)
|
||||||
|
|
||||||
|
int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
|
||||||
|
int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
|
||||||
|
int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
|
||||||
|
int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
|
||||||
|
int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
|
||||||
|
int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
|
||||||
|
int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
|
||||||
|
int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value)
|
||||||
|
int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value)
|
||||||
|
int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
|
||||||
|
int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
|
||||||
|
int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value)
|
||||||
|
int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value)
|
||||||
|
int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem, long min, long max)
|
||||||
|
int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem, long min, long max)
|
||||||
|
|
||||||
|
int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str)
|
||||||
|
int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *idxp)
|
||||||
|
int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int idx)
|
||||||
|
|
||||||
|
size_t snd_mixer_selem_id_sizeof()
|
||||||
|
int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
|
||||||
|
void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
|
||||||
|
void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const_snd_mixer_selem_id_t_ptr src)
|
||||||
|
const_char_ptr snd_mixer_selem_id_get_name(const_snd_mixer_selem_id_t_ptr obj)
|
||||||
|
unsigned int snd_mixer_selem_id_get_index(const_snd_mixer_selem_id_t_ptr obj)
|
||||||
|
void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const_char_ptr val)
|
||||||
|
void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
|
||||||
|
|
||||||
|
cdef struct selem:
|
||||||
|
snd_mixer_elem_t *elem
|
||||||
|
selem *next
|
||||||
|
|
||||||
|
SANE_CONTROL_COUNT = 16 # assuming a sane value of 16 controls
|
||||||
|
|
||||||
|
def rel_to_abs(min, max, value):
|
||||||
|
return int(value*(max-min)+min)
|
||||||
|
|
||||||
|
def abs_to_rel(min, max, value):
|
||||||
|
return float((value-min))/(max-min)
|
||||||
|
|
||||||
|
cdef class Mixer:
|
||||||
|
cdef snd_mixer_t *handle
|
||||||
|
cdef snd_mixer_elem_t **selems
|
||||||
|
_elements = dict()
|
||||||
|
def __init__(self, card="hw:0"):
|
||||||
|
cdef int selem_count = 0, selems_size = SANE_CONTROL_COUNT
|
||||||
|
cdef snd_mixer_elem_t *temp_elem
|
||||||
|
cdef snd_mixer_elem_t **temp_elems
|
||||||
|
cdef char name[32]
|
||||||
|
cdef int enum_items_count, value
|
||||||
|
cdef int err
|
||||||
|
cdef long pmin, pmax, cmin, cmax
|
||||||
|
|
||||||
|
err = snd_mixer_open(&self.handle, 0)
|
||||||
|
if err < 0: return
|
||||||
|
err = snd_mixer_attach(self.handle, card)
|
||||||
|
if err < 0: return
|
||||||
|
err = snd_mixer_selem_register(self.handle, NULL, NULL)
|
||||||
|
if err < 0: return
|
||||||
|
err = snd_mixer_load(self.handle)
|
||||||
|
if err < 0: return
|
||||||
|
|
||||||
|
self.selems = <snd_mixer_elem_t **>malloc(selems_size*sizeof(snd_mixer_elem_t *))
|
||||||
|
|
||||||
|
temp_elem = snd_mixer_first_elem(self.handle)
|
||||||
|
while temp_elem:
|
||||||
|
selem_count += 1
|
||||||
|
if selem_count > selems_size:
|
||||||
|
# running out of space - realloc double the size
|
||||||
|
selems_size *= 2
|
||||||
|
temp_elems = <snd_mixer_elem_t **>realloc(self.selems, selems_size*sizeof(snd_mixer_elem_t *))
|
||||||
|
if not temp_elems:
|
||||||
|
raise MemoryError
|
||||||
|
return
|
||||||
|
self.selems = temp_elems
|
||||||
|
self.selems[selem_count-1] = temp_elem
|
||||||
|
|
||||||
|
enumeration = None
|
||||||
|
if snd_mixer_selem_is_enumerated(temp_elem):
|
||||||
|
enumeration = list()
|
||||||
|
enum_items_count = snd_mixer_selem_get_enum_items(temp_elem)
|
||||||
|
for i from 0 <= i < enum_items_count:
|
||||||
|
snd_mixer_selem_get_enum_item_name(temp_elem, i, sizeof(name)-1, name)
|
||||||
|
enumeration.append(name)
|
||||||
|
|
||||||
|
playback_volume = None
|
||||||
|
if snd_mixer_selem_has_playback_volume(temp_elem):
|
||||||
|
snd_mixer_selem_get_playback_volume_range(temp_elem, &pmin, &pmax)
|
||||||
|
playback_volume = (pmin, pmax)
|
||||||
|
playback_switch = None
|
||||||
|
if snd_mixer_selem_has_playback_switch(temp_elem):
|
||||||
|
playback_switch = True
|
||||||
|
capture_volume = None
|
||||||
|
if snd_mixer_selem_has_capture_volume(temp_elem):
|
||||||
|
snd_mixer_selem_get_capture_volume_range(temp_elem, &cmin, &cmax)
|
||||||
|
capture_volume = (cmin, cmax)
|
||||||
|
capture_switch = None
|
||||||
|
if snd_mixer_selem_has_capture_switch(temp_elem):
|
||||||
|
capture_switch = True
|
||||||
|
|
||||||
|
self._elements[snd_mixer_selem_get_name(temp_elem)] = {
|
||||||
|
"index": selem_count-1,
|
||||||
|
"enumeration": enumeration,
|
||||||
|
"playback_volume": playback_volume,
|
||||||
|
"playback_switch": playback_switch,
|
||||||
|
"capture_volume": capture_volume,
|
||||||
|
"capture_switch": capture_switch
|
||||||
|
}
|
||||||
|
temp_elem = snd_mixer_elem_next(temp_elem)
|
||||||
|
# shrink allocated memory to exact needed size
|
||||||
|
self.selems = <snd_mixer_elem_t **>realloc(self.selems, selem_count*sizeof(snd_mixer_elem_t *))
|
||||||
|
|
||||||
|
def get_enum_items(self, elem):
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
return self._elements[elem]["enumeration"]
|
||||||
|
|
||||||
|
def get_enum_item(self, elem):
|
||||||
|
cdef unsigned int idx
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["enumeration"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_get_enum_item(selem, <snd_mixer_selem_channel_id_t>0, &idx)
|
||||||
|
return elem["enumeration"][idx]
|
||||||
|
|
||||||
|
def set_enum_item(self, elem, value):
|
||||||
|
cdef unsigned int idx
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["enumeration"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if value not in elem["enumeration"]:
|
||||||
|
if value < len(elem["enumeration"]):
|
||||||
|
idx = value
|
||||||
|
else:
|
||||||
|
raise KeyError("not a valid enumeration item", value)
|
||||||
|
else:
|
||||||
|
idx = elem["enumeration"].index(value)
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_set_enum_item(selem, <snd_mixer_selem_channel_id_t>0, idx)
|
||||||
|
|
||||||
|
def get_playback_volume(self, elem):
|
||||||
|
cdef long ival
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["playback_volume"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
min, max = elem["playback_volume"]
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_get_playback_volume(selem, <snd_mixer_selem_channel_id_t>0, &ival)
|
||||||
|
return abs_to_rel(min, max, ival)
|
||||||
|
|
||||||
|
def set_playback_volume(self, elem, value):
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
if value < 0 or value > 1:
|
||||||
|
raise ValueError("value out of range [0..1]", value)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["playback_volume"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
min, max = elem["playback_volume"]
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
ival = rel_to_abs(min, max, value)
|
||||||
|
snd_mixer_selem_set_playback_volume_all(selem, ival)
|
||||||
|
|
||||||
|
def get_capture_volume(self, elem):
|
||||||
|
cdef long ival
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["capture_volume"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
min, max = elem["capture_volume"]
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_get_capture_volume(selem, <snd_mixer_selem_channel_id_t>0, &ival)
|
||||||
|
return abs_to_rel(min, max, ival)
|
||||||
|
|
||||||
|
def set_capture_volume(self, elem, value):
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
if value < 0 or value > 1:
|
||||||
|
raise ValueError("value out of range [0..1]", value)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["capture_volume"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
min, max = elem["capture_volume"]
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
ival = rel_to_abs(min, max, value)
|
||||||
|
snd_mixer_selem_set_capture_volume_all(selem, ival)
|
||||||
|
|
||||||
|
def get_playback_switch(self, elem):
|
||||||
|
cdef int value
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["playback_switch"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_get_playback_switch(selem, <snd_mixer_selem_channel_id_t>0, &value)
|
||||||
|
return bool(value)
|
||||||
|
|
||||||
|
def set_playback_switch(self, elem, value):
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["playback_switch"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
value = int(bool(value))
|
||||||
|
snd_mixer_selem_set_playback_switch_all(selem, value)
|
||||||
|
|
||||||
|
def get_capture_switeh(self, elem):
|
||||||
|
cdef int value
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["capture_switch"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
snd_mixer_selem_get_capture_switch(selem, <snd_mixer_selem_channel_id_t>0, &value)
|
||||||
|
return bool(value)
|
||||||
|
|
||||||
|
def set_capture_switch(self, elem, value):
|
||||||
|
cdef snd_mixer_elem_t * selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if elem["capture_switch"] is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
selem = self.selems[elem["index"]]
|
||||||
|
value = int(bool(value))
|
||||||
|
snd_mixer_selem_set_capture_switch_all(selem, value)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
#never called
|
||||||
|
snd_mixer_close(self.handle)
|
502
alsa.pyx.old
Normal file
502
alsa.pyx.old
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
# do some opaque struct typedefs to make const typedefs possible
|
||||||
|
cdef extern from "alsa/asoundlib.h":
|
||||||
|
ctypedef struct snd_mixer_t
|
||||||
|
ctypedef struct snd_mixer_class_t
|
||||||
|
ctypedef struct snd_pcm_t
|
||||||
|
ctypedef struct snd_mixer_elem_t
|
||||||
|
ctypedef struct snd_mixer_selem_id_t
|
||||||
|
|
||||||
|
# define const ptr types as cython doesnt know const
|
||||||
|
cdef extern from *:
|
||||||
|
ctypedef char* const_char_ptr "const char*"
|
||||||
|
ctypedef snd_mixer_selem_id_t* const_snd_mixer_selem_id_t_ptr "const snd_mixer_selem_id_t *"
|
||||||
|
ctypedef snd_mixer_elem_t* const_snd_mixer_elem_t_ptr "const snd_mixer_elem_t *"
|
||||||
|
ctypedef snd_mixer_t* const_snd_mixer_t_ptr "const snd_mixer_t *"
|
||||||
|
|
||||||
|
cdef extern from "stdlib.h":
|
||||||
|
ctypedef unsigned long size_t
|
||||||
|
void *calloc(size_t count, size_t size)
|
||||||
|
void *malloc(size_t size)
|
||||||
|
void free(void *ptr)
|
||||||
|
void *realloc(void *ptr, size_t size)
|
||||||
|
|
||||||
|
cdef extern from "alloca.h":
|
||||||
|
void *alloca(size_t size)
|
||||||
|
|
||||||
|
cdef extern from "string.h":
|
||||||
|
void *memset (void *s, int c, size_t n)
|
||||||
|
|
||||||
|
cdef extern from "sys/poll.h":
|
||||||
|
struct pollfd:
|
||||||
|
int fd
|
||||||
|
short int events
|
||||||
|
|
||||||
|
cdef extern from "alsa/asoundlib.h":
|
||||||
|
ctypedef enum snd_mixer_selem_regopt_abstract:
|
||||||
|
pass
|
||||||
|
ctypedef enum snd_mixer_elem_type_t:
|
||||||
|
pass
|
||||||
|
ctypedef enum snd_mixer_selem_channel_id_t:
|
||||||
|
pass
|
||||||
|
struct snd_mixer_selem_regopt:
|
||||||
|
pass
|
||||||
|
ctypedef int (*snd_mixer_compare_t)(const_snd_mixer_elem_t_ptr e1, const_snd_mixer_elem_t_ptr e2)
|
||||||
|
ctypedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl, unsigned int mask, snd_mixer_elem_t *elem)
|
||||||
|
ctypedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem, unsigned int mask)
|
||||||
|
|
||||||
|
int snd_mixer_open(snd_mixer_t **mixer, int mode)
|
||||||
|
int snd_mixer_close(snd_mixer_t *mixer)
|
||||||
|
snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer)
|
||||||
|
snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_handle_events(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_attach(snd_mixer_t *mixer, const_char_ptr name)
|
||||||
|
int snd_mixer_detach(snd_mixer_t *mixer, const_char_ptr name)
|
||||||
|
int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_poll_descriptors(snd_mixer_t *mixer, pollfd *pfds, unsigned int space)
|
||||||
|
int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, pollfd *pfds, unsigned int nfds, unsigned short *revents)
|
||||||
|
int snd_mixer_load(snd_mixer_t *mixer)
|
||||||
|
void snd_mixer_free(snd_mixer_t *mixer)
|
||||||
|
int snd_mixer_wait(snd_mixer_t *mixer, int timeout)
|
||||||
|
int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort)
|
||||||
|
void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
|
||||||
|
void * snd_mixer_get_callback_private(const_snd_mixer_t_ptr obj)
|
||||||
|
void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val)
|
||||||
|
unsigned int snd_mixer_get_count(const_snd_mixer_t_ptr obj)
|
||||||
|
int snd_mixer_class_unregister(snd_mixer_class_t *clss)
|
||||||
|
|
||||||
|
snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem)
|
||||||
|
snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem)
|
||||||
|
void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val)
|
||||||
|
void * snd_mixer_elem_get_callback_private(const_snd_mixer_elem_t_ptr obj)
|
||||||
|
void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val)
|
||||||
|
snd_mixer_elem_type_t snd_mixer_elem_get_type(const_snd_mixer_elem_t_ptr obj)
|
||||||
|
|
||||||
|
int snd_mixer_selem_register(snd_mixer_t *mixer, snd_mixer_selem_regopt *options, snd_mixer_class_t **classp)
|
||||||
|
void snd_mixer_selem_get_id(snd_mixer_elem_t *element, snd_mixer_selem_id_t *id)
|
||||||
|
const_char_ptr snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
|
||||||
|
unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem)
|
||||||
|
snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer, const_snd_mixer_selem_id_t_ptr id)
|
||||||
|
|
||||||
|
int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel)
|
||||||
|
int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel)
|
||||||
|
int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem)
|
||||||
|
|
||||||
|
int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
|
||||||
|
int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
|
||||||
|
int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
|
||||||
|
int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
|
||||||
|
int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
|
||||||
|
int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
|
||||||
|
int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
|
||||||
|
int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
|
||||||
|
int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value)
|
||||||
|
int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value)
|
||||||
|
int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
|
||||||
|
int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
|
||||||
|
int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
|
||||||
|
int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value)
|
||||||
|
int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value)
|
||||||
|
int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem, long min, long max)
|
||||||
|
int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem, long *min, long *max)
|
||||||
|
int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem, long min, long max)
|
||||||
|
|
||||||
|
int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
|
||||||
|
int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str)
|
||||||
|
int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *idxp)
|
||||||
|
int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int idx)
|
||||||
|
|
||||||
|
size_t snd_mixer_selem_id_sizeof()
|
||||||
|
int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
|
||||||
|
void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
|
||||||
|
void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const_snd_mixer_selem_id_t_ptr src)
|
||||||
|
const_char_ptr snd_mixer_selem_id_get_name(const_snd_mixer_selem_id_t_ptr obj)
|
||||||
|
unsigned int snd_mixer_selem_id_get_index(const_snd_mixer_selem_id_t_ptr obj)
|
||||||
|
void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const_char_ptr val)
|
||||||
|
void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
|
||||||
|
|
||||||
|
cdef int get_handle(snd_mixer_t **handle):
|
||||||
|
cdef int err
|
||||||
|
err = snd_mixer_open(handle, 0)
|
||||||
|
if err < 0: return err
|
||||||
|
err = snd_mixer_attach(handle[0], "hw:0")
|
||||||
|
if err < 0: return err
|
||||||
|
err = snd_mixer_selem_register(handle[0], NULL, NULL)
|
||||||
|
if err < 0: return err
|
||||||
|
err = snd_mixer_load(handle[0])
|
||||||
|
if err < 0: return err
|
||||||
|
return 0
|
||||||
|
|
||||||
|
cdef struct selem:
|
||||||
|
snd_mixer_elem_t *elem
|
||||||
|
selem *next
|
||||||
|
|
||||||
|
SANE_CONTROL_COUNT = 16 # assuming a sane value of 16 controls
|
||||||
|
|
||||||
|
cdef class Mixer:
|
||||||
|
cdef snd_mixer_t *handle
|
||||||
|
cdef snd_mixer_elem_t **selems
|
||||||
|
_elements = dict()
|
||||||
|
def __init__(self):
|
||||||
|
cdef int selem_count = 0, selems_size = SANE_CONTROL_COUNT
|
||||||
|
cdef snd_mixer_elem_t *temp_elem
|
||||||
|
cdef snd_mixer_elem_t **temp_elems
|
||||||
|
|
||||||
|
get_handle(&self.handle)
|
||||||
|
|
||||||
|
temp_elem = snd_mixer_first_elem(self.handle)
|
||||||
|
if not temp_elem:
|
||||||
|
return
|
||||||
|
selem_count = 1
|
||||||
|
self.selems = <snd_mixer_elem_t **>malloc(selems_size*sizeof(snd_mixer_elem_t *))
|
||||||
|
self.selems[0] = temp_elem
|
||||||
|
|
||||||
|
while True:
|
||||||
|
temp_elem = snd_mixer_elem_next(temp_elem)
|
||||||
|
if not temp_elem:
|
||||||
|
break
|
||||||
|
selem_count += 1
|
||||||
|
if selem_count > selems_size:
|
||||||
|
# running out of space - realloc double the size
|
||||||
|
selems_size *= 2
|
||||||
|
temp_elems = <snd_mixer_elem_t **>realloc(self.selems, selems_size*sizeof(snd_mixer_elem_t *))
|
||||||
|
if not temp_elems:
|
||||||
|
raise MemoryError
|
||||||
|
return
|
||||||
|
self.selems = temp_elems
|
||||||
|
self.selems[selem_count-1] = temp_elem
|
||||||
|
self._elements[snd_mixer_selem_get_name(self.selems[i])] = {
|
||||||
|
"index": selem_count-1,
|
||||||
|
"enumeration": None,
|
||||||
|
"playback_volume": None,
|
||||||
|
"playback_switch": None,
|
||||||
|
"capture_volume": None,
|
||||||
|
"capture_switch": None
|
||||||
|
}
|
||||||
|
# shrink allocated memory to exact needed size
|
||||||
|
self.selems = <snd_mixer_elem_t **>realloc(self.selems, selem_count*sizeof(snd_mixer_elem_t *))
|
||||||
|
|
||||||
|
def get_enum_items(self, elem):
|
||||||
|
cdef snd_mixer_elem_t *selem
|
||||||
|
|
||||||
|
if elem not in self._elements:
|
||||||
|
raise KeyError("not a valid control", elem)
|
||||||
|
|
||||||
|
elem = self._elements[elem]
|
||||||
|
if not elem["is_enumerated"]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
index = elem["index"]
|
||||||
|
selem = self.selems[index]
|
||||||
|
|
||||||
|
|
||||||
|
def get_enum_item(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_enum_item(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_playback_volume(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_playback_volume(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_capture_volume(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_capture_volume(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_playback_switch(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_playback_switch(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_capture_switeh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_capture_switch(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
print "Destructor"
|
||||||
|
snd_mixer_close(self.handle)
|
||||||
|
|
||||||
|
m = Mixer()
|
||||||
|
print m.get_enum_items("IEC958 Playback Source")
|
||||||
|
|
||||||
|
def list_elems3():
|
||||||
|
cdef snd_mixer_t *handle
|
||||||
|
cdef snd_mixer_elem_t *elem
|
||||||
|
cdef snd_mixer_selem_id_t *sid
|
||||||
|
cdef long pmin, pmax, cmin, cmax, lvalue
|
||||||
|
cdef int enum_items_count, ivalue
|
||||||
|
cdef char name[32]
|
||||||
|
cdef unsigned int idx
|
||||||
|
|
||||||
|
sid = <snd_mixer_selem_id_t *>alloca(snd_mixer_selem_id_sizeof())
|
||||||
|
memset(sid, 0, snd_mixer_selem_id_sizeof())
|
||||||
|
|
||||||
|
get_handle(&handle)
|
||||||
|
elem = snd_mixer_first_elem(handle)
|
||||||
|
|
||||||
|
print "\tpvol\tcvol\tpsw\tcsw\tenum"
|
||||||
|
while elem:
|
||||||
|
print snd_mixer_selem_get_name(elem),
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_playback_volume(elem):
|
||||||
|
snd_mixer_selem_get_playback_volume(elem, <snd_mixer_selem_channel_id_t>0, &lvalue)
|
||||||
|
print "%d\t"%lvalue,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_playback_switch(elem):
|
||||||
|
snd_mixer_selem_get_playback_switch(elem, <snd_mixer_selem_channel_id_t>0, &ivalue)
|
||||||
|
print "%d\t"%ivalue,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_capture_volume(elem):
|
||||||
|
snd_mixer_selem_get_capture_volume(elem, <snd_mixer_selem_channel_id_t>0, &lvalue)
|
||||||
|
print "%d\t"%lvalue,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_capture_switch(elem):
|
||||||
|
snd_mixer_selem_get_capture_switch(elem, <snd_mixer_selem_channel_id_t>0, &ivalue)
|
||||||
|
print "%d\t"%ivalue,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_is_enumerated(elem):
|
||||||
|
snd_mixer_selem_get_enum_item(elem, <snd_mixer_selem_channel_id_t>0, &idx)
|
||||||
|
print "%d\t"%idx,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
print
|
||||||
|
elem = snd_mixer_elem_next(elem)
|
||||||
|
|
||||||
|
snd_mixer_close(handle)
|
||||||
|
|
||||||
|
def list_elems2():
|
||||||
|
cdef snd_mixer_t *handle
|
||||||
|
cdef snd_mixer_elem_t *elem
|
||||||
|
cdef snd_mixer_selem_id_t *sid
|
||||||
|
cdef long pmin, pmax, cmin, cmax
|
||||||
|
cdef int enum_items_count
|
||||||
|
cdef char name[32]
|
||||||
|
|
||||||
|
sid = <snd_mixer_selem_id_t *>alloca(snd_mixer_selem_id_sizeof())
|
||||||
|
memset(sid, 0, snd_mixer_selem_id_sizeof())
|
||||||
|
|
||||||
|
get_handle(&handle)
|
||||||
|
elem = snd_mixer_first_elem(handle)
|
||||||
|
|
||||||
|
print "\tpvol\tcvol\tpsw\tcsw\tenum"
|
||||||
|
while elem:
|
||||||
|
print snd_mixer_selem_get_name(elem),
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_playback_volume(elem):
|
||||||
|
snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax)
|
||||||
|
print "%d-%d\t"%(pmin, pmax),
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_playback_switch(elem):
|
||||||
|
print "yes\t",
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_capture_volume(elem):
|
||||||
|
snd_mixer_selem_get_capture_volume_range(elem, &cmin, &cmax)
|
||||||
|
print "%d-%d\t"%(cmin, cmax),
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_has_capture_switch(elem):
|
||||||
|
print "yes\t",
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
if snd_mixer_selem_is_enumerated(elem):
|
||||||
|
enum_items_count = snd_mixer_selem_get_enum_items(elem)
|
||||||
|
for i from 0 <= i < enum_items_count:
|
||||||
|
snd_mixer_selem_get_enum_item_name(elem, i, sizeof(name)-1, name)
|
||||||
|
print "%s,"%name,
|
||||||
|
else:
|
||||||
|
print "\t",
|
||||||
|
print
|
||||||
|
elem = snd_mixer_elem_next(elem)
|
||||||
|
|
||||||
|
snd_mixer_close(handle)
|
||||||
|
|
||||||
|
def list_elems():
|
||||||
|
cdef long pmin, pmax, cmin, cmax, ival
|
||||||
|
cdef int enum_items_count, value
|
||||||
|
cdef unsigned int idx
|
||||||
|
cdef char name[32]
|
||||||
|
|
||||||
|
cdef snd_mixer_t *handle
|
||||||
|
get_handle(&handle)
|
||||||
|
|
||||||
|
# poll fd
|
||||||
|
count = snd_mixer_poll_descriptors_count(handle)
|
||||||
|
print "poll count:", count
|
||||||
|
cdef pollfd* fds = <pollfd*>calloc(count, sizeof(pollfd))
|
||||||
|
snd_mixer_poll_descriptors(handle, fds, count)
|
||||||
|
cdef pollfd fd
|
||||||
|
for i in xrange(count):
|
||||||
|
fd = fds[i]
|
||||||
|
print "poll fd: ", fd.fd
|
||||||
|
print "poll events: ", fd.events
|
||||||
|
|
||||||
|
cdef snd_mixer_elem_t *elem
|
||||||
|
cdef snd_mixer_selem_id_t *sid = <snd_mixer_selem_id_t *>alloca(snd_mixer_selem_id_sizeof())
|
||||||
|
memset(sid, 0, snd_mixer_selem_id_sizeof())
|
||||||
|
elem = snd_mixer_first_elem(handle)
|
||||||
|
while elem:
|
||||||
|
print
|
||||||
|
snd_mixer_selem_get_id(elem, sid)
|
||||||
|
print "name:", snd_mixer_selem_id_get_name(sid)
|
||||||
|
print "index:", snd_mixer_selem_id_get_index(sid)
|
||||||
|
|
||||||
|
playback_volume_or_switch = False
|
||||||
|
capture_volume_or_switch = False
|
||||||
|
|
||||||
|
if snd_mixer_selem_has_common_volume(elem):
|
||||||
|
print "Common Volume"
|
||||||
|
if snd_mixer_selem_has_playback_volume(elem):
|
||||||
|
playback_volume_or_switch = True
|
||||||
|
print "Playback Volume"
|
||||||
|
if snd_mixer_selem_has_playback_volume_joined(elem):
|
||||||
|
print "Playback Volume Joined"
|
||||||
|
if snd_mixer_selem_has_capture_volume(elem):
|
||||||
|
capture_volume_or_switch = True
|
||||||
|
print "Capture Volume"
|
||||||
|
if snd_mixer_selem_has_capture_volume_joined(elem):
|
||||||
|
print "Capture Volume Joined"
|
||||||
|
|
||||||
|
if snd_mixer_selem_has_common_switch(elem):
|
||||||
|
print "Common Switch"
|
||||||
|
if snd_mixer_selem_has_playback_switch(elem):
|
||||||
|
playback_volume_or_switch = True
|
||||||
|
print "Playback Switch"
|
||||||
|
if snd_mixer_selem_has_playback_switch_joined(elem):
|
||||||
|
print "Playback Switch Joined"
|
||||||
|
if snd_mixer_selem_has_capture_switch(elem):
|
||||||
|
capture_volume_or_switch = True
|
||||||
|
print "Capture Switch"
|
||||||
|
if snd_mixer_selem_has_capture_switch_joined(elem):
|
||||||
|
print "Capture Switch Joined"
|
||||||
|
if snd_mixer_selem_has_capture_switch_exclusive(elem):
|
||||||
|
print "Capture Switch Exclusive"
|
||||||
|
|
||||||
|
playback_channel_count = 0
|
||||||
|
if playback_volume_or_switch:
|
||||||
|
if snd_mixer_selem_is_playback_mono(elem):
|
||||||
|
snd_mixer_selem_get_playback_volume(elem, <snd_mixer_selem_channel_id_t>0, &ival)
|
||||||
|
print "Playback Volume Channel Mono:", ival
|
||||||
|
snd_mixer_selem_get_playback_switch(elem, <snd_mixer_selem_channel_id_t>0, &value)
|
||||||
|
print "Playback Switch Mono:", value
|
||||||
|
playback_channel_count = 1
|
||||||
|
else:
|
||||||
|
for i in xrange(32):
|
||||||
|
if snd_mixer_selem_has_playback_channel(elem, i):
|
||||||
|
snd_mixer_selem_get_playback_volume(elem, i, &ival)
|
||||||
|
print "Playback Volume Channel %d:"%i, ival
|
||||||
|
snd_mixer_selem_get_playback_switch(elem, i, &value)
|
||||||
|
print "Playback Switch Channel %d:"%i, value
|
||||||
|
playback_channel_count += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
print "Playback Channel Count:", playback_channel_count
|
||||||
|
|
||||||
|
capture_channel_count = 0
|
||||||
|
if capture_volume_or_switch:
|
||||||
|
if snd_mixer_selem_is_capture_mono(elem):
|
||||||
|
snd_mixer_selem_get_capture_volume(elem, <snd_mixer_selem_channel_id_t>0, &ival)
|
||||||
|
print "Capture Volume Channel Mono:", ival
|
||||||
|
snd_mixer_selem_get_capture_switch(elem, <snd_mixer_selem_channel_id_t>0, &value)
|
||||||
|
print "Capture Switch Mono:", value
|
||||||
|
capture_channel_count = 1
|
||||||
|
else:
|
||||||
|
for i in xrange(32):
|
||||||
|
if snd_mixer_selem_has_capture_channel(elem, i):
|
||||||
|
snd_mixer_selem_get_capture_volume(elem, i, &ival)
|
||||||
|
print "Capture Volume Channel %d:"%i, ival
|
||||||
|
snd_mixer_selem_get_capture_switch(elem, i, &value)
|
||||||
|
print "Capture Switch Channel %d:"%i, value
|
||||||
|
capture_channel_count += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
print "Capture Channel Count:", capture_channel_count
|
||||||
|
|
||||||
|
snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax)
|
||||||
|
snd_mixer_selem_get_capture_volume_range(elem, &cmin, &cmax)
|
||||||
|
|
||||||
|
print "Playback Volume Range:", pmin, pmax
|
||||||
|
print "Capture Volume Range:", cmin, cmax
|
||||||
|
|
||||||
|
if snd_mixer_selem_is_enumerated(elem):
|
||||||
|
snd_mixer_selem_get_enum_item(elem, <snd_mixer_selem_channel_id_t>0, &idx)
|
||||||
|
print "Selected enum item:", idx
|
||||||
|
|
||||||
|
enum_items_count = snd_mixer_selem_get_enum_items(elem)
|
||||||
|
print "Enumerates over %d Items: "%enum_items_count,
|
||||||
|
|
||||||
|
for i from 0 <= i < enum_items_count:
|
||||||
|
snd_mixer_selem_get_enum_item_name(elem, i, sizeof(name)-1, name)
|
||||||
|
print "%s,"%name,
|
||||||
|
print
|
||||||
|
|
||||||
|
elem = snd_mixer_elem_next(elem)
|
||||||
|
snd_mixer_close(handle)
|
||||||
|
|
||||||
|
#list_elems3()
|
||||||
|
|
||||||
|
|
||||||
|
#cdef snd_mixer_t *handle
|
||||||
|
#
|
||||||
|
#get_handle(&handle)
|
||||||
|
#
|
||||||
|
#cdef snd_mixer_elem_t *elem
|
||||||
|
#cdef snd_mixer_selem_id_t *sid = <snd_mixer_selem_id_t *>alloca(snd_mixer_selem_id_sizeof())
|
||||||
|
#memset(sid, 0, snd_mixer_selem_id_sizeof())
|
||||||
|
#
|
||||||
|
#snd_mixer_selem_id_set_index(sid, 0)
|
||||||
|
#snd_mixer_selem_id_set_name(sid, "Master")
|
||||||
|
#elem = snd_mixer_find_selem(handle, sid)
|
||||||
|
#
|
||||||
|
#snd_mixer_selem_set_playback_volume(elem, <snd_mixer_selem_channel_id_t>0, 32)
|
||||||
|
#
|
||||||
|
#snd_mixer_selem_id_set_index(sid, 0)
|
||||||
|
#snd_mixer_selem_id_set_name(sid, "IEC958 Playback Source")
|
||||||
|
#elem = snd_mixer_find_selem(handle, sid)
|
||||||
|
#
|
||||||
|
#print snd_mixer_selem_set_enum_item(elem, <snd_mixer_selem_channel_id_t>0, 0)
|
||||||
|
|
||||||
|
#snd_mixer_selem_id_set_index(sid, 0)
|
||||||
|
#snd_mixer_selem_id_set_name(sid, "Mono Mixer Bypass Playback Swit")
|
||||||
|
#elem = snd_mixer_find_selem(handle, sid)
|
||||||
|
|
||||||
|
#snd_mixer_selem_set_playback_switch(elem, <snd_mixer_selem_channel_id_t>0, 1)
|
123
mixer.py
Normal file
123
mixer.py
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
from alsa import Mixer
|
||||||
|
|
||||||
|
m = Mixer()
|
||||||
|
|
||||||
|
PVOL, PSW, CVOL, CSW, ENUM = m.set_playback_volume, m.set_playback_switch, m.set_capture_volume, m.set_capture_switch, m.set_enum_item
|
||||||
|
|
||||||
|
controls = [
|
||||||
|
(PVOL, "Headphone"),
|
||||||
|
(PSW, "Headphone Playback ZC"),
|
||||||
|
(PVOL, "Speaker"),
|
||||||
|
(PSW, "Speaker Playback ZC"),
|
||||||
|
(PVOL, "Bass"), (CVOL, "Bass"),
|
||||||
|
(ENUM, "Bass Boost"),
|
||||||
|
(ENUM, "Bass Filter"),
|
||||||
|
(PVOL, "Treble"), (CVOL, "Treble"),
|
||||||
|
(ENUM, "Treble Cut-off"),
|
||||||
|
(PVOL, "PCM"), (CVOL, "PCM"),
|
||||||
|
(PVOL, "Sidetone"), (CVOL, "Sidetone"),
|
||||||
|
(ENUM, "Line Left Mux"),
|
||||||
|
(ENUM, "Line Mixer"),
|
||||||
|
(ENUM, "Line Mono Mux"),
|
||||||
|
(ENUM, "Line Right Mux"),
|
||||||
|
(ENUM, "Mic Selection Mux"),
|
||||||
|
(ENUM, "Mic Sidetone Mux"),
|
||||||
|
(CVOL, "Mic1"),
|
||||||
|
(CVOL, "Mic2"),
|
||||||
|
(PVOL, "Mono"),
|
||||||
|
(ENUM, "Mono 2 Mux"),
|
||||||
|
(PVOL, "Mono Bypass"),
|
||||||
|
(PSW, "Mono Mixer Bypass"),
|
||||||
|
(PSW, "Mono Mixer Left"),
|
||||||
|
(PSW, "Mono Mixer Right"),
|
||||||
|
(PSW, "Mono Mixer Sidetone"),
|
||||||
|
(PSW, "Mono Mixer Voice"),
|
||||||
|
(PSW, "Mono Playback ZC"),
|
||||||
|
(PVOL, "Mono Sidetone"),
|
||||||
|
(PVOL, "Mono Voice"),
|
||||||
|
(PSW, "Playback 6dB Attenuate"),
|
||||||
|
(CSW, "Playback Mixer Left"),
|
||||||
|
(PSW, "Playback Mixer Right"),
|
||||||
|
(PSW, "Playback Mixer Voice"),
|
||||||
|
(ENUM, "Playback Mono Mix"),
|
||||||
|
(ENUM, "Playback Phase"),
|
||||||
|
(CVOL, "Capture"), (CSW, "Capture"),
|
||||||
|
(PSW, "Capture 6dB Attenuate"),
|
||||||
|
(PSW, "Capture Filter"),
|
||||||
|
(ENUM, "Capture Filter Cut-off"),
|
||||||
|
(ENUM, "Capture Filter Select"),
|
||||||
|
(ENUM, "Capture Left Mixer"),
|
||||||
|
(ENUM, "Capture Left Mux"),
|
||||||
|
(ENUM, "Capture Right Mixer"),
|
||||||
|
(ENUM, "Capture Right Mux"),
|
||||||
|
(PSW, "Capture ZC"),
|
||||||
|
(PVOL, "3D"), (PSW, "3D"), (CVOL, "3D"),
|
||||||
|
(ENUM, "3D Function"),
|
||||||
|
(ENUM, "3D Lower Cut-off"),
|
||||||
|
(ENUM, "3D Upper Cut-off"),
|
||||||
|
(CVOL, "ADC"),
|
||||||
|
(ENUM, "ADC Data Select"),
|
||||||
|
(PVOL, "ALC Capture Attack Time"), (CVOL, "ALC Capture Attack Time"),
|
||||||
|
(PVOL, "ALC Capture Decay Time"), (CVOL, "ALC Capture Decay Time"),
|
||||||
|
(ENUM, "ALC Capture Function"),
|
||||||
|
(PVOL, "ALC Capture Hold Time"), (CVOL, "ALC Capture Hold Time"),
|
||||||
|
(PVOL, "ALC Capture Max"), (CVOL, "ALC Capture Max"),
|
||||||
|
(PSW, "ALC Capture NG"),
|
||||||
|
(PVOL, "ALC Capture NG Threshold"), (CVOL, "ALC Capture NG Threshold"),
|
||||||
|
(ENUM, "ALC Capture NG Type"),
|
||||||
|
(PVOL, "ALC Capture Target"), (CVOL, "ALC Capture Target"),
|
||||||
|
(PSW, "ALC Capture ZC"),
|
||||||
|
(CSW, "ALC Mixer Line"),
|
||||||
|
(CSW, "ALC Mixer Mic1"),
|
||||||
|
(CSW, "ALC Mixer Mic2"),
|
||||||
|
(CSW, "ALC Mixer Rx"),
|
||||||
|
(PSW, "Amp Spk"),
|
||||||
|
(PVOL, "Bypass"),
|
||||||
|
(ENUM, "DAI Mode"),
|
||||||
|
(ENUM, "De-emphasis"),
|
||||||
|
(PSW, "GSM Line In"),
|
||||||
|
(PSW, "GSM Line Out"),
|
||||||
|
(PSW, "Handset Mic"),
|
||||||
|
(PSW, "Handset Spk"),
|
||||||
|
(PSW, "Headset Mic"),
|
||||||
|
(PSW, "Left Mixer Bypass"),
|
||||||
|
(PSW, "Left Mixer Left"),
|
||||||
|
(PSW, "Left Mixer Sidetone"),
|
||||||
|
(PSW, "Left Mixer Voice"),
|
||||||
|
(ENUM, "Out3 Mux"),
|
||||||
|
(ENUM, "Out4 Mux"),
|
||||||
|
(ENUM, "ROUT2 Phase"),
|
||||||
|
(PSW, "Right Mixer Bypass"),
|
||||||
|
(PSW, "Right Mixer Right"),
|
||||||
|
(PSW, "Right Mixer Sidetone"),
|
||||||
|
(PSW, "Right Mixer Voice"),
|
||||||
|
(PVOL, "Voice"),
|
||||||
|
(CVOL, "Voice Sidetone")
|
||||||
|
]
|
||||||
|
|
||||||
|
def restore_defaults():
|
||||||
|
for control in controls:
|
||||||
|
func, elem = control
|
||||||
|
func(elem, 0)
|
||||||
|
|
||||||
|
restore_defaults()
|
||||||
|
|
||||||
|
def load_stereoout():
|
||||||
|
PVOL("Headphone", 0.9)
|
||||||
|
PVOL("PCM", 1.0)
|
||||||
|
PSW("Amp Spk", True)
|
||||||
|
PSW("Left Mixer Left", True)
|
||||||
|
PSW("Right Mixer Right", True)
|
||||||
|
PSW("Stereo Out", True)
|
||||||
|
|
||||||
|
#load_stereoout()
|
||||||
|
|
||||||
|
def load_handsetout():
|
||||||
|
PVOL("Headphone", 0.9)
|
||||||
|
PVOL("PCM", 1.0)
|
||||||
|
PSW("Left Mixer Left", True)
|
||||||
|
PSW("Right Mixer Right", True)
|
||||||
|
PSW("Stereo Out", True)
|
||||||
|
|
||||||
|
load_stereoout()
|
||||||
|
|
22
setup.py
Normal file
22
setup.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from distutils.core import setup
|
||||||
|
from distutils.extension import Extension
|
||||||
|
from Cython.Distutils import build_ext
|
||||||
|
|
||||||
|
ext_modules = [Extension('alsa', ['alsa.pyx'],
|
||||||
|
libraries=['asound'],
|
||||||
|
# include_dirs=['/usr/include/alsa/'],
|
||||||
|
# extra_compile_args=["-Wno-cast-qual", "-Wno-strict-prototypes"],
|
||||||
|
)]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name = 'alsa',
|
||||||
|
# version='1.12',
|
||||||
|
# description='pyneod daemon suite',
|
||||||
|
cmdclass = {'build_ext': build_ext},
|
||||||
|
ext_modules = ext_modules,
|
||||||
|
author='Johannes Schauer',
|
||||||
|
author_email='josch@pyneo.org',
|
||||||
|
)
|
||||||
|
# vim:tw=0:nowrap
|
Loading…
Reference in a new issue