generated from itdominator/Python-With-Gtk-Template
689 lines
22 KiB
Python
689 lines
22 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import print_function
|
|
|
|
|
|
# C Bindings
|
|
|
|
import os, sys, ctypes.util, functools as ft
|
|
from ctypes import *
|
|
|
|
|
|
force_str = lambda s, errors='strict': s.decode('utf-8', errors) if isinstance(s, bytes) else s
|
|
force_bytes = lambda s, errors='strict': s.encode('utf-8', errors) if isinstance(s, unicode) else s
|
|
|
|
if sys.version_info.major >= 3:
|
|
class c_str_p_type(object):
|
|
c_type = c_char_p
|
|
def __call__(self, val): return force_str(val)
|
|
def from_param(self, val):
|
|
# int will be interpreted as pointer and segfault in py3
|
|
if isinstance(val, int): raise ArgumentError(type(val))
|
|
return force_bytes(val)
|
|
unicode, c_str_p = str, c_str_p_type()
|
|
|
|
import time
|
|
mono_time = time.monotonic
|
|
|
|
else:
|
|
c_str_p = c_char_p
|
|
|
|
def mono_time():
|
|
if not hasattr(mono_time, 'ts'):
|
|
class timespec(Structure):
|
|
_fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]
|
|
librt = CDLL('librt.so.1', use_errno=True)
|
|
mono_time.get = librt.clock_gettime
|
|
mono_time.get.argtypes = [c_int, POINTER(timespec)]
|
|
mono_time.ts = timespec
|
|
ts = mono_time.ts()
|
|
if mono_time.get(4, pointer(ts)) != 0:
|
|
err = get_errno()
|
|
raise OSError(err, os.strerror(err))
|
|
return ts.tv_sec + ts.tv_nsec * 1e-9
|
|
|
|
|
|
PA_INVALID = 2**32-1
|
|
|
|
PA_VOLUME_NORM = 0x10000
|
|
PA_VOLUME_MAX = (2**32-1) // 2 # was different before pulseaudio-1.0, see 179b291b there
|
|
PA_VOLUME_INVALID = 2**32-1
|
|
|
|
pa_sw_volume_from_dB = lambda db:\
|
|
min(PA_VOLUME_MAX, int(round(((10.0 ** (db / 20.0)) ** (1/3)) * PA_VOLUME_NORM)))
|
|
PA_VOLUME_UI_MAX = 99957 # pa_sw_volume_from_dB(+11.0)
|
|
|
|
PA_CHANNELS_MAX = 32
|
|
PA_USEC_T = c_uint64
|
|
|
|
PA_CONTEXT_NOAUTOSPAWN = 0x0001
|
|
PA_CONTEXT_NOFAIL = 0x0002
|
|
|
|
PA_CONTEXT_UNCONNECTED = 0
|
|
PA_CONTEXT_CONNECTING = 1
|
|
PA_CONTEXT_AUTHORIZING = 2
|
|
PA_CONTEXT_SETTING_NAME = 3
|
|
PA_CONTEXT_READY = 4
|
|
PA_CONTEXT_FAILED = 5
|
|
PA_CONTEXT_TERMINATED = 6
|
|
|
|
PA_SUBSCRIPTION_MASK_NULL = 0x0000
|
|
PA_SUBSCRIPTION_MASK_SINK = 0x0001
|
|
PA_SUBSCRIPTION_MASK_SOURCE = 0x0002
|
|
PA_SUBSCRIPTION_MASK_SINK_INPUT = 0x0004
|
|
PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 0x0008
|
|
PA_SUBSCRIPTION_MASK_MODULE = 0x0010
|
|
PA_SUBSCRIPTION_MASK_CLIENT = 0x0020
|
|
PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 0x0040
|
|
PA_SUBSCRIPTION_MASK_SERVER = 0x0080
|
|
PA_SUBSCRIPTION_MASK_AUTOLOAD = 0x0100
|
|
PA_SUBSCRIPTION_MASK_CARD = 0x0200
|
|
PA_SUBSCRIPTION_MASK_ALL = 0x02ff
|
|
|
|
PA_SUBSCRIPTION_EVENT_SINK = 0x0000
|
|
PA_SUBSCRIPTION_EVENT_SOURCE = 0x0001
|
|
PA_SUBSCRIPTION_EVENT_SINK_INPUT = 0x0002
|
|
PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 0x0003
|
|
PA_SUBSCRIPTION_EVENT_MODULE = 0x0004
|
|
PA_SUBSCRIPTION_EVENT_CLIENT = 0x0005
|
|
PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 0x0006
|
|
PA_SUBSCRIPTION_EVENT_SERVER = 0x0007
|
|
PA_SUBSCRIPTION_EVENT_AUTOLOAD = 0x0008
|
|
PA_SUBSCRIPTION_EVENT_CARD = 0x0009
|
|
PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 0x000F
|
|
PA_SUBSCRIPTION_EVENT_NEW = 0x0000
|
|
PA_SUBSCRIPTION_EVENT_CHANGE = 0x0010
|
|
PA_SUBSCRIPTION_EVENT_REMOVE = 0x0020
|
|
PA_SUBSCRIPTION_EVENT_TYPE_MASK = 0x0030
|
|
|
|
PA_SAMPLE_FLOAT32LE = 5
|
|
PA_SAMPLE_FLOAT32BE = 6
|
|
PA_SAMPLE_FLOAT32NE = dict(
|
|
little=PA_SAMPLE_FLOAT32LE,
|
|
big=PA_SAMPLE_FLOAT32BE )[sys.byteorder]
|
|
|
|
PA_STREAM_DONT_MOVE = 0x0200
|
|
PA_STREAM_PEAK_DETECT = 0x0800
|
|
PA_STREAM_ADJUST_LATENCY = 0x2000
|
|
PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND = 0x8000
|
|
|
|
def c_enum_map(**values):
|
|
return dict((v, force_str(k)) for k,v in values.items())
|
|
|
|
_globals = globals().copy()
|
|
_pa_ev_type = dict(
|
|
(force_str(k), _globals['PA_SUBSCRIPTION_EVENT_{}'.format(k.upper())])
|
|
for k in 'new change remove'.split() )
|
|
_pa_ev_fac, _pa_ev_mask = dict(), dict()
|
|
for k, n in _globals.items():
|
|
if k.startswith('PA_SUBSCRIPTION_EVENT_'):
|
|
if k.endswith('_MASK'): continue
|
|
k = force_str(k[22:].lower())
|
|
if k in _pa_ev_type: continue
|
|
assert n & PA_SUBSCRIPTION_EVENT_FACILITY_MASK == n, [k, n]
|
|
_pa_ev_fac[k] = n
|
|
elif k.startswith('PA_SUBSCRIPTION_MASK_'):
|
|
_pa_ev_mask[force_str(k[21:].lower())] = n
|
|
|
|
PA_EVENT_TYPE_MAP = c_enum_map(**_pa_ev_type)
|
|
PA_EVENT_FACILITY_MAP = c_enum_map(**_pa_ev_fac)
|
|
PA_EVENT_MASK_MAP = c_enum_map(**_pa_ev_mask)
|
|
del _globals, _pa_ev_type, _pa_ev_fac, _pa_ev_mask
|
|
|
|
PA_UPDATE_MAP = c_enum_map(set=0, merge=1, replace=2)
|
|
PA_PORT_AVAILABLE_MAP = c_enum_map(unknown=0, no=1, yes=2)
|
|
PA_DIRECTION_MAP = c_enum_map(unknown=0, output=1, input=2)
|
|
|
|
# These are defined separately as
|
|
# pa_sink_state / pa_source_state, but seem to match.
|
|
PA_OBJ_STATE_MAP = c_enum_map(invalid=-1, running=0, idle=1, suspended=2)
|
|
|
|
|
|
class PA_MAINLOOP(Structure): pass
|
|
class PA_STREAM(Structure): pass
|
|
class PA_MAINLOOP_API(Structure): pass
|
|
class PA_CONTEXT(Structure): pass
|
|
class PA_PROPLIST(Structure): pass
|
|
class PA_OPERATION(Structure): pass
|
|
class PA_SIGNAL_EVENT(Structure): pass
|
|
class PA_IO_EVENT(Structure): pass
|
|
|
|
|
|
class PA_SAMPLE_SPEC(Structure):
|
|
_fields_ = [
|
|
('format', c_int),
|
|
('rate', c_uint32),
|
|
('channels', c_uint32)
|
|
]
|
|
|
|
class PA_CHANNEL_MAP(Structure):
|
|
_fields_ = [
|
|
('channels', c_uint8),
|
|
('map', c_int * PA_CHANNELS_MAX)
|
|
]
|
|
|
|
class PA_CVOLUME(Structure):
|
|
_fields_ = [
|
|
('channels', c_uint8),
|
|
('values', c_uint32 * PA_CHANNELS_MAX)
|
|
]
|
|
|
|
class PA_PORT_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('description', c_char_p),
|
|
('priority', c_uint32),
|
|
('available', c_int),
|
|
]
|
|
|
|
class PA_SINK_INPUT_INFO(Structure):
|
|
_fields_ = [
|
|
('index', c_uint32),
|
|
('name', c_char_p),
|
|
('owner_module', c_uint32),
|
|
('client', c_uint32),
|
|
('sink', c_uint32),
|
|
('sample_spec', PA_SAMPLE_SPEC),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
('volume', PA_CVOLUME),
|
|
('buffer_usec', PA_USEC_T),
|
|
('sink_usec', PA_USEC_T),
|
|
('resample_method', c_char_p),
|
|
('driver', c_char_p),
|
|
('mute', c_int),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('corked', c_int),
|
|
('has_volume', c_int),
|
|
('volume_writable', c_int),
|
|
]
|
|
|
|
class PA_SINK_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('index', c_uint32),
|
|
('description', c_char_p),
|
|
('sample_spec', PA_SAMPLE_SPEC),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
('owner_module', c_uint32),
|
|
('volume', PA_CVOLUME),
|
|
('mute', c_int),
|
|
('monitor_source', c_uint32),
|
|
('monitor_source_name', c_char_p),
|
|
('latency', PA_USEC_T),
|
|
('driver', c_char_p),
|
|
('flags', c_int),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('configured_latency', PA_USEC_T),
|
|
('base_volume', c_uint32),
|
|
('state', c_int),
|
|
('n_volume_steps', c_int),
|
|
('card', c_uint32),
|
|
('n_ports', c_uint32),
|
|
('ports', POINTER(POINTER(PA_PORT_INFO))),
|
|
('active_port', POINTER(PA_PORT_INFO)),
|
|
]
|
|
|
|
class PA_SOURCE_OUTPUT_INFO(Structure):
|
|
_fields_ = [
|
|
('index', c_uint32),
|
|
('name', c_char_p),
|
|
('owner_module', c_uint32),
|
|
('client', c_uint32),
|
|
('source', c_uint32),
|
|
('sample_spec', PA_SAMPLE_SPEC),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
('buffer_usec', PA_USEC_T),
|
|
('source_usec', PA_USEC_T),
|
|
('resample_method', c_char_p),
|
|
('driver', c_char_p),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('corked', c_int),
|
|
('volume', PA_CVOLUME),
|
|
('mute', c_int),
|
|
('has_volume', c_int),
|
|
('volume_writable', c_int),
|
|
]
|
|
|
|
class PA_SOURCE_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('index', c_uint32),
|
|
('description', c_char_p),
|
|
('sample_spec', PA_SAMPLE_SPEC),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
('owner_module', c_uint32),
|
|
('volume', PA_CVOLUME),
|
|
('mute', c_int),
|
|
('monitor_of_sink', c_uint32),
|
|
('monitor_of_sink_name', c_char_p),
|
|
('latency', PA_USEC_T),
|
|
('driver', c_char_p),
|
|
('flags', c_int),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('configured_latency', PA_USEC_T),
|
|
('base_volume', c_uint32),
|
|
('state', c_int),
|
|
('n_volume_steps', c_int),
|
|
('card', c_uint32),
|
|
('n_ports', c_uint32),
|
|
('ports', POINTER(POINTER(PA_PORT_INFO))),
|
|
('active_port', POINTER(PA_PORT_INFO)),
|
|
]
|
|
|
|
class PA_CLIENT_INFO(Structure):
|
|
_fields_ = [
|
|
('index', c_uint32),
|
|
('name', c_char_p),
|
|
('owner_module', c_uint32),
|
|
('driver', c_char_p),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
]
|
|
|
|
class PA_SERVER_INFO(Structure):
|
|
_fields_ = [
|
|
('user_name', c_char_p),
|
|
('host_name', c_char_p),
|
|
('server_version', c_char_p),
|
|
('server_name', c_char_p),
|
|
('sample_spec', PA_SAMPLE_SPEC),
|
|
('default_sink_name', c_char_p),
|
|
('default_source_name', c_char_p),
|
|
('cookie', c_uint32),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
]
|
|
|
|
class PA_CARD_PROFILE_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('description', c_char_p),
|
|
('n_sinks', c_uint32),
|
|
('n_sources', c_uint32),
|
|
('priority', c_uint32),
|
|
('available', c_int),
|
|
]
|
|
|
|
# Extends PA_PORT_INFO with a few card-specific things
|
|
class PA_CARD_PORT_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('description', c_char_p),
|
|
('priority', c_uint32),
|
|
('available', c_int),
|
|
('direction', c_int),
|
|
('n_profiles', c_uint32),
|
|
('profiles', c_void_p), # use profiles2
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('latency_offset', c_int64),
|
|
('profiles2', POINTER(POINTER(PA_CARD_PROFILE_INFO))),
|
|
]
|
|
|
|
class PA_CARD_INFO(Structure):
|
|
_fields_ = [
|
|
('index', c_uint32),
|
|
('name', c_char_p),
|
|
('owner_module', c_uint32),
|
|
('driver', c_char_p),
|
|
('n_profiles', c_uint32),
|
|
('profiles', c_void_p), # use profiles2 / active_profile2
|
|
('active_profile', c_void_p),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
('n_ports', c_uint32),
|
|
('ports', POINTER(POINTER(PA_CARD_PORT_INFO))),
|
|
('profiles2', POINTER(POINTER(PA_CARD_PROFILE_INFO))),
|
|
('active_profile2', POINTER(PA_CARD_PROFILE_INFO)),
|
|
]
|
|
|
|
class PA_MODULE_INFO(Structure):
|
|
_fields_ = [
|
|
('index', c_uint32),
|
|
('name', c_char_p),
|
|
('argument', c_char_p),
|
|
('n_used', c_uint32),
|
|
('auto_unload', c_int),
|
|
('proplist', POINTER(PA_PROPLIST)),
|
|
]
|
|
|
|
class PA_EXT_STREAM_RESTORE_INFO(Structure):
|
|
_fields_ = [
|
|
('name', c_char_p),
|
|
('channel_map', PA_CHANNEL_MAP),
|
|
('volume', PA_CVOLUME),
|
|
('device', c_char_p),
|
|
('mute', c_int),
|
|
]
|
|
|
|
class PA_BUFFER_ATTR(Structure):
|
|
_fields_ = [
|
|
('maxlength', c_uint32),
|
|
('tlength', c_uint32),
|
|
('prebuf', c_uint32),
|
|
('minreq', c_uint32),
|
|
('fragsize', c_uint32),
|
|
]
|
|
|
|
|
|
class POLLFD(Structure):
|
|
_fields_ = [
|
|
('fd', c_int),
|
|
('events', c_short),
|
|
('revents', c_short),
|
|
]
|
|
|
|
|
|
PA_POLL_FUNC_T = CFUNCTYPE(c_int,
|
|
POINTER(POLLFD),
|
|
c_ulong,
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SIGNAL_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_MAINLOOP_API),
|
|
POINTER(c_int),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_STATE_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_void_p)
|
|
|
|
PA_CLIENT_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_CLIENT_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SERVER_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_SERVER_INFO),
|
|
c_void_p)
|
|
|
|
PA_SINK_INPUT_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_SINK_INPUT_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SINK_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_SINK_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SOURCE_OUTPUT_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_SOURCE_OUTPUT_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SOURCE_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_SOURCE_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_CONTEXT_DRAIN_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_void_p)
|
|
|
|
PA_CONTEXT_INDEX_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_uint32,
|
|
c_void_p)
|
|
|
|
PA_CONTEXT_SUCCESS_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_EXT_STREAM_RESTORE_TEST_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_uint32,
|
|
c_void_p)
|
|
|
|
PA_EXT_STREAM_RESTORE_READ_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_EXT_STREAM_RESTORE_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_CARD_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_CARD_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_MODULE_INFO_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
POINTER(PA_MODULE_INFO),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_SUBSCRIBE_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_CONTEXT),
|
|
c_int,
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_STREAM_REQUEST_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_STREAM),
|
|
c_int,
|
|
c_void_p)
|
|
|
|
PA_STREAM_NOTIFY_CB_T = CFUNCTYPE(c_void_p,
|
|
POINTER(PA_STREAM),
|
|
c_void_p)
|
|
|
|
|
|
class LibPulse(object):
|
|
|
|
# func_def ::= arg_types_list | (arg_types_list, res_spec) | (res_spec, arg_types_list)
|
|
# res_spec ::= ctypes_restype
|
|
# | res_proc_func | (ctypes_restype, res_proc_func)
|
|
# | res_spec_name_str | (ctypes_restype, res_spec_name_str)
|
|
# res_spec_name_str ::= 'int_check_ge0' | 'pa_op' | ...
|
|
func_defs = dict(
|
|
pa_strerror=([c_int], c_str_p),
|
|
pa_runtime_path=([c_str_p], (c_char_p, 'not_null')),
|
|
pa_operation_unref=[POINTER(PA_OPERATION)],
|
|
|
|
pa_mainloop_new=(POINTER(PA_MAINLOOP)),
|
|
pa_mainloop_get_api=([POINTER(PA_MAINLOOP)], POINTER(PA_MAINLOOP_API)),
|
|
pa_mainloop_run=([POINTER(PA_MAINLOOP), POINTER(c_int)], c_int),
|
|
pa_mainloop_prepare=([POINTER(PA_MAINLOOP), c_int], 'int_check_ge0'),
|
|
pa_mainloop_poll=([POINTER(PA_MAINLOOP)], 'int_check_ge0'),
|
|
pa_mainloop_dispatch=([POINTER(PA_MAINLOOP)], 'int_check_ge0'),
|
|
pa_mainloop_iterate=([POINTER(PA_MAINLOOP), c_int, POINTER(c_int)], 'int_check_ge0'),
|
|
pa_mainloop_wakeup=[POINTER(PA_MAINLOOP)],
|
|
pa_mainloop_set_poll_func=[POINTER(PA_MAINLOOP), PA_POLL_FUNC_T, c_void_p],
|
|
pa_mainloop_quit=([POINTER(PA_MAINLOOP), c_int]),
|
|
pa_mainloop_free=[POINTER(PA_MAINLOOP)],
|
|
|
|
pa_signal_init=([POINTER(PA_MAINLOOP_API)], 'int_check_ge0'),
|
|
pa_signal_new=([c_int, PA_SIGNAL_CB_T, POINTER(PA_SIGNAL_EVENT)]),
|
|
pa_signal_done=None,
|
|
|
|
pa_context_errno=([POINTER(PA_CONTEXT)], c_int),
|
|
pa_context_new=([POINTER(PA_MAINLOOP_API), c_str_p], POINTER(PA_CONTEXT)),
|
|
pa_context_set_state_callback=([POINTER(PA_CONTEXT), PA_STATE_CB_T, c_void_p]),
|
|
pa_context_connect=([POINTER(PA_CONTEXT), c_str_p, c_int, POINTER(c_int)], 'int_check_ge0'),
|
|
pa_context_get_state=([POINTER(PA_CONTEXT)], c_int),
|
|
pa_context_disconnect=[POINTER(PA_CONTEXT)],
|
|
pa_context_unref=[POINTER(PA_CONTEXT)],
|
|
pa_context_drain=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_CONTEXT_DRAIN_CB_T, c_void_p] ),
|
|
pa_context_set_default_sink=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_default_source=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_get_sink_input_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_SINK_INPUT_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_sink_input_info=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_SINK_INPUT_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_sink_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_SINK_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_sink_info_by_name=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, PA_SINK_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_sink_info_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_SINK_INFO_CB_T, c_void_p] ),
|
|
pa_context_set_sink_mute_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_suspend_sink_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_sink_port_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_str_p, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_sink_input_mute=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_sink_volume_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, POINTER(PA_CVOLUME), PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_sink_input_volume=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, POINTER(PA_CVOLUME), PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_move_sink_input_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_uint32, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_get_source_output_info=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_SOURCE_OUTPUT_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_source_output_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_SOURCE_OUTPUT_INFO_CB_T, c_void_p] ),
|
|
pa_context_move_source_output_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_uint32, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_source_output_volume=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, POINTER(PA_CVOLUME), PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_source_output_mute=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_kill_source_output=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_get_source_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_SOURCE_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_source_info_by_name=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, PA_SOURCE_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_source_info_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_SOURCE_INFO_CB_T, c_void_p] ),
|
|
pa_context_set_source_volume_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, POINTER(PA_CVOLUME), PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_source_mute_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_suspend_source_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_source_port_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_str_p, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_get_client_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_CLIENT_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_client_info=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_CLIENT_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_server_info=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_SERVER_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_card_info_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_CARD_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_card_info_by_name=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, PA_CARD_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_card_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_CARD_INFO_CB_T, c_void_p] ),
|
|
pa_context_set_card_profile_by_index=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, c_str_p, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_get_module_info=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_MODULE_INFO_CB_T, c_void_p] ),
|
|
pa_context_get_module_info_list=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_MODULE_INFO_CB_T, c_void_p] ),
|
|
pa_context_load_module=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_char_p, c_char_p, PA_CONTEXT_INDEX_CB_T, c_void_p] ),
|
|
pa_context_unload_module=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_uint32, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_subscribe=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_set_subscribe_callback=[POINTER(PA_CONTEXT), PA_SUBSCRIBE_CB_T, c_void_p],
|
|
pa_context_play_sample=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), c_str_p, c_str_p, c_uint32, PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
pa_context_play_sample_with_proplist=( 'pa_op',
|
|
[ POINTER(PA_CONTEXT), c_str_p, c_str_p, c_uint32,
|
|
POINTER(PA_PROPLIST), PA_CONTEXT_SUCCESS_CB_T, c_void_p ] ),
|
|
|
|
pa_ext_stream_restore_test=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_EXT_STREAM_RESTORE_TEST_CB_T, c_void_p] ),
|
|
pa_ext_stream_restore_read=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), PA_EXT_STREAM_RESTORE_READ_CB_T, c_void_p] ),
|
|
pa_ext_stream_restore_write=( 'pa_op', [
|
|
POINTER(PA_CONTEXT), c_int, POINTER(PA_EXT_STREAM_RESTORE_INFO),
|
|
c_uint, c_int, PA_CONTEXT_SUCCESS_CB_T, c_void_p ] ),
|
|
pa_ext_stream_restore_delete=( 'pa_op',
|
|
[POINTER(PA_CONTEXT), POINTER(c_char_p), PA_CONTEXT_SUCCESS_CB_T, c_void_p] ),
|
|
|
|
pa_proplist_from_string=([c_str_p], POINTER(PA_PROPLIST)),
|
|
pa_proplist_iterate=([POINTER(PA_PROPLIST), POINTER(c_void_p)], c_str_p),
|
|
pa_proplist_gets=([POINTER(PA_PROPLIST), c_str_p], c_str_p),
|
|
pa_proplist_free=[POINTER(PA_PROPLIST)],
|
|
|
|
pa_channel_map_init_mono=(
|
|
[POINTER(PA_CHANNEL_MAP)], (POINTER(PA_CHANNEL_MAP), 'not_null') ),
|
|
pa_channel_map_init_stereo=(
|
|
[POINTER(PA_CHANNEL_MAP)], (POINTER(PA_CHANNEL_MAP), 'not_null') ),
|
|
pa_channel_map_snprint=([c_str_p, c_int, POINTER(PA_CHANNEL_MAP)], c_str_p),
|
|
pa_channel_map_parse=(
|
|
[POINTER(PA_CHANNEL_MAP), c_str_p], (POINTER(PA_CHANNEL_MAP), 'not_null') ),
|
|
pa_channel_position_to_string=([c_int], c_str_p),
|
|
|
|
pa_stream_new_with_proplist=(
|
|
[ POINTER(PA_CONTEXT), c_str_p,
|
|
POINTER(PA_SAMPLE_SPEC), POINTER(PA_CHANNEL_MAP), POINTER(PA_PROPLIST) ],
|
|
POINTER(PA_STREAM) ),
|
|
pa_stream_set_monitor_stream=([POINTER(PA_STREAM), c_uint32], 'int_check_ge0'),
|
|
pa_stream_set_read_callback=[POINTER(PA_STREAM), PA_STREAM_REQUEST_CB_T, c_void_p],
|
|
pa_stream_connect_record=(
|
|
[POINTER(PA_STREAM), c_str_p, POINTER(PA_BUFFER_ATTR), c_int], 'int_check_ge0' ),
|
|
pa_stream_unref=[POINTER(PA_STREAM)],
|
|
pa_stream_peek=(
|
|
[POINTER(PA_STREAM), POINTER(c_void_p), POINTER(c_int)], 'int_check_ge0' ),
|
|
pa_stream_drop=([POINTER(PA_STREAM)], 'int_check_ge0'),
|
|
pa_stream_disconnect=([POINTER(PA_STREAM)], 'int_check_ge0') )
|
|
|
|
class CallError(Exception): pass
|
|
|
|
|
|
def __init__(self):
|
|
p = CDLL(ctypes.util.find_library('libpulse') or 'libpulse.so.0')
|
|
|
|
self.funcs = dict()
|
|
for k, spec in self.func_defs.items():
|
|
func, args, res_proc = getattr(p, k), None, None
|
|
if spec:
|
|
if not isinstance(spec, tuple): spec = (spec,)
|
|
for v in spec:
|
|
assert v, [k, spec, v]
|
|
if isinstance(v, list): args = v
|
|
else: res_proc = v
|
|
func_k = k if not k.startswith('pa_') else k[3:]
|
|
self.funcs[func_k] = self._func_wrapper(k, func, args, res_proc)
|
|
|
|
def _func_wrapper(self, func_name, func, args=list(), res_proc=None):
|
|
func.restype, func.argtypes = None, args
|
|
if isinstance(res_proc, tuple): func.restype, res_proc = res_proc
|
|
if isinstance(res_proc, str):
|
|
if res_proc.startswith('int_check_'): func.restype = c_int
|
|
elif res_proc == 'pa_op': func.restype = POINTER(PA_OPERATION)
|
|
elif not func.restype and hasattr(res_proc, 'c_type'): func.restype = res_proc.c_type
|
|
elif not func.restype: func.restype, res_proc = res_proc, None
|
|
|
|
def _wrapper(*args):
|
|
# print('libpulse call:', func_name, args, file=sys.stderr)
|
|
# sys.stderr.flush()
|
|
res = func(*args)
|
|
if isinstance(res_proc, str):
|
|
assert res_proc in ['int_check_ge0', 'pa_op', 'not_null']
|
|
if (res_proc == 'int_check_ge0' and res < 0)\
|
|
or (res_proc == 'pa_op' and not res)\
|
|
or (res_proc == 'not_null' and not res):
|
|
err = [func_name, args, res]
|
|
if args and isinstance(getattr(args[0], 'contents', None), PA_CONTEXT):
|
|
errno_ = self.context_errno(args[0])
|
|
err.append('{} [pulse errno {}]'.format(self.strerror(errno_), errno_))
|
|
else: err.append('Return value check failed: {}'.format(res_proc))
|
|
raise self.CallError(*err)
|
|
elif res_proc: res = res_proc(res)
|
|
return res
|
|
|
|
_wrapper.__name__ = 'libpulse.{}'.format(func_name)
|
|
return _wrapper
|
|
|
|
def __getattr__(self, k): return self.funcs[k]
|
|
|
|
def return_value(self): return pointer(c_int())
|
|
|
|
pa = LibPulse()
|