diff options
author | Paul W. Frields <stickster@gmail.com> | 2009-09-01 11:59:47 -0400 |
---|---|---|
committer | Paul W. Frields <stickster@gmail.com> | 2009-09-01 11:59:47 -0400 |
commit | 204ab2cd298d1f8c1c5e3c05307f8fa30d201843 (patch) | |
tree | 4913dcb35b1776e18b1853305903de4389c1d6aa /pulsecaster/pulseaudio | |
parent | 43dda3349580f28f06686577052f8f83465dd17e (diff) | |
download | pulsecaster-204ab2cd298d1f8c1c5e3c05307f8fa30d201843.tar.gz pulsecaster-204ab2cd298d1f8c1c5e3c05307f8fa30d201843.tar.xz pulsecaster-204ab2cd298d1f8c1c5e3c05307f8fa30d201843.zip |
Move folders to a more standard location
Diffstat (limited to 'pulsecaster/pulseaudio')
-rw-r--r-- | pulsecaster/pulseaudio/PulseClient.py | 66 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/PulseObj.py | 623 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/PulseSink.py | 213 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/PulseSource.py | 189 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/PulseVolume.py | 114 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/__init__.py | 29 | ||||
-rw-r--r-- | pulsecaster/pulseaudio/lib_pulseaudio.py | 733 |
7 files changed, 1967 insertions, 0 deletions
diff --git a/pulsecaster/pulseaudio/PulseClient.py b/pulsecaster/pulseaudio/PulseClient.py new file mode 100644 index 0000000..6705080 --- /dev/null +++ b/pulsecaster/pulseaudio/PulseClient.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# PulseClient.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + +from lib_pulseaudio import * + +# This class contains all basic client features +class PulseClient: + def __init__(self, name, index = 0): + self.index = index + self.name = name + return + + ### + + def printDebug(self): + print "self.index:", self.index + print "self.name:", self.name + return + + ### + + def __str__(self): + return "Client-ID: " + str(self.index) + ", Name: \"" + self.name + "\"" + +################################################################################ + +# This class is used with Ctypes +class PulseClientCtypes(PulseClient): + def __init__(self, pa_client): + PulseClient.__init__(self, pa_client.name, pa_client.index) + + self.owner_module = pa_client.owner_module + self.driver = pa_client.driver + #self.proplist = pa_sink_input_info.proplist + return + + ### + + def printDebug(self): + print "PulseClientCtypes" + PulseClient.printDebug(self) + print "self.owner_module:", self.owner_module + print "self.driver:", self.driver + #print "self.proplist:", self.proplist + return + diff --git a/pulsecaster/pulseaudio/PulseObj.py b/pulsecaster/pulseaudio/PulseObj.py new file mode 100644 index 0000000..98c4105 --- /dev/null +++ b/pulsecaster/pulseaudio/PulseObj.py @@ -0,0 +1,623 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# PulseObj.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + +from lib_pulseaudio import * +from PulseSink import PulseSinkInputInfo, PulseSinkInfo +from PulseSource import PulseSourceOutputInfo, PulseSourceInfo +from PulseClient import PulseClientCtypes + +################################################################################ +# +# Classes +# +################################################################################ + +class PulseObj: + "Basic PulseAudio object" + + ############################################################################## + # + # Init + # + ############################################################################## + + def __init__(self, server = None, retry = False, clientName = 'Unknown (Python)'): + "Initialise pulseaudio connection" + + # Variables + self.server = server + self.mainloop = None + self.mainloop_api = None + self.context = None + self.ret = None + self.retry = retry + self.operation = None + self.connected = False + self.action_done = False + self.data = None + + # Init + + # + # Callbacks + # + self.PA_SIGNAL_CB = PA_SIGNAL_CB_T(self.py_signal_cb) + + self.PA_STATE_CB = PA_STATE_CB_T(self.py_state_cb) + # + # Mainloop init + # + self.mainloop = pa_mainloop_new() + + self.mainloop_api = pa_mainloop_get_api(self.mainloop) + + # + # Signal binding + # + r = pa_signal_init(self.mainloop_api) + + if r != 0: + # FIXME + print "FIXME Do something. Something is wrong" + + # SIGINT + pa_signal_new(2, self.PA_SIGNAL_CB, None) + + # SIGTERM + pa_signal_new(15, self.PA_SIGNAL_CB, None) + + # + # Context creating + # + self.context = pa_context_new(self.mainloop_api, clientName) + + pa_context_set_state_callback(self.context, self.PA_STATE_CB, None) + + self.start_action() + + # + # Connect + # + if 0 > pa_context_connect(self.context, + self.server, + 0, + None): + if self.retry: + pa_context_disconnect(self.context) + return + self.pulse_context_error() + + self.pulse_iterate() + + return + + ############################################################################## + # + # Callback methods + # + # FIXME: rename methods better + # + ############################################################################## + + def py_signal_cb(self, api, e, sig, userdata): + #print "py_signal_cb:", api, e, sig, userdata + + if sig == 2: + self.pulse_disconnect() + elif sig == 15: + self.pulse_disconnect() + + return 0 + + ### + + def py_state_cb(self, c, b): + #print "py_state_cb:", c[0]._opaque_struct, b + state = pa_context_get_state(c); + + + if state == 0: + None + #print "py_state_cb: Unconnected" + + elif state == 1: + None + #print "py_state_cb: Connecting" + + elif state == 2: + None + #print "py_state_cb: Authorizing" + + elif state == 3: + None + #print "py_state_cb: Setting name" + + elif state == 4: + #print "py_state_cb: Ready" + self.complete_action() + self.connected = True + + elif state == 5: + None + #print "py_state_cb: Failed" + + elif state == 6: + None + #print "py_state_cb: Terminated" + if not self.retry: + import sys + sys.exit(pa_context_errno(c)) + + self.complete_action() + + else: + None + #print "py_state_cb: Unknown state", state + + + #print "py_state_cb:", pa_strerror(pa_context_errno(c)) + return 0 + + ### + + def py_client_cb(self, c, client_info, endofdata, userdata): + "Sink callback" + #print "py_client_cb:", c, client_info, endofdata, userdata + + if (endofdata): + self.complete_action() + return 0 + + if self.data == None: + self.data = [ PulseClientCtypes(client_info[0]) ] + else: + self.data.append(PulseClientCtypes(client_info[0])) + + return 0 + + ### + + def py_sink_input_cb(self, c, sink_input_info, endofdata, userdata): + "Sink input callback" + #print "py_sink_input_cb:", c, sink_input_info, endofdata, userdata + + if (endofdata): + self.complete_action() + return 0 + + if self.data == None: + self.data = [ PulseSinkInputInfo(sink_input_info[0]) ] + else: + self.data.append(PulseSinkInputInfo(sink_input_info[0])) + + return 0 + + ### + + def py_sink_cb(self, c, sink_info, endofdata, userdata): + "Sink callback" + #print "py_sink_cb:", c, sink_info, endofdata, userdata + + if (endofdata): + self.complete_action() + return 0 + + if self.data == None: + self.data = [ PulseSinkInfo(sink_info[0]) ] + else: + self.data.append(PulseSinkInfo(sink_info[0])) + + return 0 + ### + + def py_source_output_cb(self, c, source_output_info, endofdata, userdata): + "Source output callback" + #print "py_source_output_cb:", c, source_output_info, endofdata, userdata + + if (endofdata): + self.complete_action() + return 0 + + if self.data == None: + self.data = [ PulseSourceOutputInfo(source_output_info[0]) ] + else: + self.data.append(PulseSourceOutputInfo(source_output_info[0])) + + return 0 + + ### + + def py_source_cb(self, c, source_info, endofdata, userdata): + "Source callback" + #print "py_source_cb:", c, source_info, endofdata, userdata + + if (endofdata): + self.complete_action() + return 0 + + if self.data == None: + self.data = [ PulseSourceInfo(source_info[0]) ] + else: + self.data.append(PulseSourceInfo(source_info[0])) + + return 0 + ### + + def py_drain_cb(self, c, userdata): + #print "py_drain_cb: called" + return + + ### + + def py_subscribe_cb(self, c, event, index, userdata): + print 'py_subscribe_cb: called' + print 'py_subscribe_cb:', c, event, index, userdata + self.complete_action() + return 0 + + def py_context_success(self, c, success, userdata): + if success == 0: + None + #print "py_context_success: Failed" + else: + None + #print "py_context_success: Success" + + self.complete_action() + return 0 + + ############################################################################## + # + ############################################################################## + + def complete_action(self): + "Completed action" + #print "complete_action: Called" + self.action_done = True + return + + ### + + def start_action(self): + "Call every time when starting action" + #print "start_action: Called" + self.action_done = False + return + + ### + + def pulse_disconnect(self): + "Call when disconnect object" + + #print "pulse_disconnect: Disconnecting" + pa_context_disconnect(self.context) + pa_mainloop_free(self.mainloop) + return + + ### + + def pulse_context_error(self): + "Print context error msg" + + #print "pulse_context_error:", pa_strerror(pa_context_errno(self.context)) + self.pulse_disconnect() + return + + ### + + def pulse_sink_input_list(self): + "List all sink input" + #print "pulse_sink_input_list: Called"; + + return_data = None + + self.start_action() + + # Callback function + SINK_INPUT_LIST_CB = PA_SINK_INPUT_INFO_CB_T(self.py_sink_input_cb) + + self.operation = pa_context_get_sink_input_info_list(self.context, + SINK_INPUT_LIST_CB, + None) + self.pulse_iterate() + + #print "pulse_sink_input_list:", self.data + return_data = self.data + self.data = None + + return return_data + + ### + + def pulse_sink_list(self): + "List all sinks" + #print "pulse_sink_list: Called"; + + return_data = None + + self.start_action() + + # Callback function + SINK_LIST_CB = PA_SINK_INFO_CB_T(self.py_sink_cb) + + self.operation = pa_context_get_sink_info_list(self.context, + SINK_LIST_CB, + None) + self.pulse_iterate() + + #print "pulse_sink_list:", self.data + return_data = self.data + self.data = None + + return return_data + + ### + + def pulse_source_output_list(self): + "List all source outputs" + #print "pulse_source_output_list: Called"; + + return_data = None + + self.start_action() + + # Callback function + SOURCE_OUTPUT_LIST_CB = PA_SOURCE_OUTPUT_INFO_CB_T(self.py_source_output_cb) + + self.operation = pa_context_get_source_output_info_list(self.context, + SOURCE_OUTPUT_LIST_CB, + None) + self.pulse_iterate() + + #print "pulse_source_output_list:", self.data + return_data = self.data + self.data = None + + return return_data + + ### + + def pulse_source_list(self): + "List all sources" + #print "pulse_source_list: Called"; + + return_data = None + + self.start_action() + + # Callback function + SOURCE_LIST_CB = PA_SOURCE_INFO_CB_T(self.py_source_cb) + + self.operation = pa_context_get_source_info_list(self.context, + SOURCE_LIST_CB, + None) + self.pulse_iterate() + + #print "pulse_source_list:", self.data + return_data = self.data + self.data = None + + return return_data + + ### + def pulse_client_list(self): + "Fetch all clients" + + self.start_action() + + CLIENT_INFO_CB = PA_CLIENT_INFO_CB_T(self.py_client_cb) + + self.operation = pa_context_get_client_info_list(self.context, + CLIENT_INFO_CB, + None) + + self.pulse_iterate() + + #print "pulse_client_list:", self.data + return_data = self.data + self.data = None + + return return_data + + ### + + def pulse_sink_input_mute(self, index, mute): + "Mute one stream by index" + + self.start_action() + + CONTEXT_SUCCESS = PA_CONTEXT_SUCCESS_CB_T(self.py_context_success) + + self.operation = pa_context_set_sink_input_mute(self.context, + index, + mute, # Mute = 1 + CONTEXT_SUCCESS, + None) + + self.pulse_iterate() + + return + + ### + + def pulse_sink_mute(self, index, mute): + "Mute sink by index" + + self.start_action() + + CONTEXT_SUCCESS = PA_CONTEXT_SUCCESS_CB_T(self.py_context_success) + + self.operation = pa_context_set_sink_mute_by_index(self.context, + index, + mute, # Mute = 1 + CONTEXT_SUCCESS, + None) + + self.pulse_iterate() + + return + + ### + + def pulse_mute_stream(self, index): + self.pulse_sink_input_mute(index, 1) + return + + ### + + def pulse_unmute_stream(self, index): + self.pulse_sink_input_mute(index, 0) + return + + ### + + def pulse_mute_sink(self, index): + self.pulse_sink_mute(index, 1) + return + + ### + + def pulse_unmute_sink(self, index): + self.pulse_sink_mute(index, 0) + return + + ### + + def pulse_set_sink_input_volume(self, index, vol): + "Set volume by index" + self.start_action() + + #print "pulse_set_sink_input_volume:", index, "Vol:", vol + + #print vol.values + #for a in vol.toCtypes().values: + # print a + #return + + PA_CONTEXT_SUCCESS_CB = PA_CONTEXT_SUCCESS_CB_T(self.py_context_success) + + self.operation = pa_context_set_sink_input_volume(self.context, + index, + vol.toCtypes(), + PA_CONTEXT_SUCCESS_CB, + None) + + self.pulse_iterate() + + return + + ### + + def pulse_set_sink_volume(self, index, vol): + "Set volume by index" + self.start_action() + + #print "pulse_set_sink_volume:", index, "Vol:", vol + + PA_CONTEXT_SUCCESS_CB = PA_CONTEXT_SUCCESS_CB_T(self.py_context_success) + + self.operation = pa_context_set_sink_volume_by_index(self.context, + index, + vol.toCtypes(), + PA_CONTEXT_SUCCESS_CB, + None) + + self.pulse_iterate() + + return + + ### + + def pulse_context_subscribe(self, mask): + "Subscribe to event" + self.start_action() + print "pulse_context_subscribe:", mask + CONTEXT_SUCCESS = PA_CONTEXT_SUCCESS_CB_T(self.py_context_success) + + self.operation = pa_context_subscribe(self.context, + mask, + CONTEXT_SUCCESS, + None) + self.pulse_iterate() + return + + ### + + def pulse_context_set_subscribe_callback(self, callback): + "Set subscribe callback" + print "py_context_set_subscribe_callback:", callback + PA_CONTEXT_SUBSCRIBE_CB = PA_CONTEXT_SUBSCRIBE_CB_T(callback) + + # This returns a void, not a PA_OPERATION + pa_context_set_subscribe_callback(self.context, + PA_CONTEXT_SUBSCRIBE_CB, + None) + return + + ### + + def reconnect(self): + self.context = pa_context_new(self.mainloop_api, clientName) + + pa_context_set_state_callback(self.context, self.PA_STATE_CB, None) + + self.start_action() + + + if 0 > pa_context_connect(self.context, + self.server, + 0, + None): + if self.retry: + pa_context_disconnect(self.context) + #print "bar" + return + self.pulse_context_error() + #print "foo" + + self.pulse_iterate() + + return + + ### + + def pulse_iterate(self, times = 1): + "Runs queries" + #print "pulse_iterate: Called" + self.ret = pointer(c_int()) + + pa_mainloop_iterate(self.mainloop, times, self.ret) + + while not self.action_done: + pa_mainloop_iterate(self.mainloop, times, self.ret) + + return + + ### + + def pulse_run(self): + self.ret = pointer(c_int(0)) + + #pa_mainloop_iterate(self.mainloop, 11, self.ret) + pa_mainloop_run(self.mainloop, self.ret) + return diff --git a/pulsecaster/pulseaudio/PulseSink.py b/pulsecaster/pulseaudio/PulseSink.py new file mode 100644 index 0000000..15a6517 --- /dev/null +++ b/pulsecaster/pulseaudio/PulseSink.py @@ -0,0 +1,213 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# PulseSink.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + +from lib_pulseaudio import * + +from PulseClient import PulseClient +from PulseVolume import PulseVolumeCtypes + +# This class contains all commons features from PulseSinkInputInfo and +# PulseSinkInfo +class PulseSink: + def __init__(self, index, name, mute, volume, client): + self.index = index + self.name = name + self.mute = mute + self.volume = volume + self.client = client + return + + # PROTOTYPE + def unmuteStream(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + # PROTOTYPE + def muteStream(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + # PROTOTYPE + def setVolume(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + def printDebug(self): + print "self.index:", self.index + print "self.name:", self.name + print "self.mute:", self.mute + print "self.volume:", self.volume + print "self.client:", self.client + return + +################################################################################ + +class PulseSinkInfo(PulseSink): + def __init__(self, pa_sink_info): + PulseSink.__init__(self, pa_sink_info.index, + pa_sink_info.name, + pa_sink_info.mute, + PulseVolumeCtypes(pa_sink_info.volume), + PulseClient("Selected Sink")) + + self.description = pa_sink_info.description + self.sample_spec = pa_sink_info.sample_spec + self.channel_map = pa_sink_info.channel_map + self.owner_module = pa_sink_info.owner_module + self.monitor_source = pa_sink_info.monitor_source + self.monitor_source_name = pa_sink_info.monitor_source_name + self.latency = pa_sink_info.latency + self.driver = pa_sink_info.driver + self.flags = pa_sink_info.flags + self.proplist = pa_sink_info.proplist + self.configured_latency = pa_sink_info.configured_latency + + return + + ### + # + # Define PROTOTYPE functions + + def unmuteStream(self, pulseInterface): + pulseInterface.pulse_unmute_sink(self.index) + + self.mute = 0 + return + + ### + + def muteStream(self, pulseInterface): + pulseInterface.pulse_mute_sink(self.index) + + self.mute = 1 + return + + ### + + def setVolume(self, pulseInterface, volume): + pulseInterface.pulse_set_sink_volume(self.index, volume) + + self.volume = volume + return + + ### + + def printDebug(self): + print "PulseSinkInfo" + PulseSink.printDebug(self) + print "self.description", self.description + print "self.sample_spec", self.sample_spec + print "self.channel_map", self.channel_map + print "self.owner_module", self.owner_module + print "self.monitor_source", self.monitor_source + print "self.monitor_source_name", self.monitor_source_name + print "self.latency", self.latency + print "self.driver", self.driver + print "self.flags", self.flags + print "self.proplist", self.proplist + print "self.configured_latency", self.configured_latency + return + + ### + + def __str__(self): + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\"" + +################################################################################ + +class PulseSinkInputInfo(PulseSink): + def __init__(self, pa_sink_input_info): + PulseSink.__init__(self, pa_sink_input_info.index, + pa_sink_input_info.name, + pa_sink_input_info.mute, + PulseVolumeCtypes(pa_sink_input_info.volume), + PulseClient("Unknown client")) + self.owner_module = pa_sink_input_info.owner_module + self.client_id = pa_sink_input_info.client + self.sink = pa_sink_input_info.sink + self.sample_spec = pa_sink_input_info.sample_spec + self.channel_map = pa_sink_input_info.channel_map + self.buffer_usec = pa_sink_input_info.buffer_usec + self.sink_usec = pa_sink_input_info.sink_usec + self.resample_method = pa_sink_input_info.resample_method + self.driver = pa_sink_input_info.driver + #self.proplist = pa_sink_input_info.proplist + + return + + ### + + def setClient(self, c): + self.client = c + + ### + # + # Define PROTOTYPE functions + + def unmuteStream(self, pulseInterface): + pulseInterface.pulse_unmute_stream(self.index) + + self.mute = 0 + return + + ### + + def muteStream(self, pulseInterface): + pulseInterface.pulse_mute_stream(self.index) + + self.mute = 1 + return + + ### + + def setVolume(self, pulseInterface, volume): + pulseInterface.pulse_set_sink_input_volume(self.index, volume) + + self.volume = volume + return + + ### + + def printDebug(self): + print "PulseSinkInputInfo" + PulseSink.printDebug(self) + + print "self.owner_module:", self.owner_module + print "self.client_id:", self.client_id + print "self.sink:", self.sink + print "self.sample_spec:", self.sample_spec + print "self.channel_map:", self.channel_map + print "self.buffer_usec:", self.buffer_usec + print "self.sink_usec:", self.sink_usec + print "self.resample_method:", self.resample_method + print "self.driver:", self.driver + + ### + + def __str__(self): + if self.client: + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\", mute: " + str(self.mute) + ", " + str(self.client) + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\", mute: " + str(self.mute) diff --git a/pulsecaster/pulseaudio/PulseSource.py b/pulsecaster/pulseaudio/PulseSource.py new file mode 100644 index 0000000..e99eaaf --- /dev/null +++ b/pulsecaster/pulseaudio/PulseSource.py @@ -0,0 +1,189 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# PulseSource.py +# Copyright (C) 2009 Harry Karvonen, Paul W. Frields +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# Paul W. Frields <stickster@gmail.com> +# + +from lib_pulseaudio import * + +from PulseClient import PulseClient +from PulseVolume import PulseVolumeCtypes + +# This class contains all commons features from PulseSourceInputInfo and +# PulseSourceInfo +class PulseSource: + def __init__(self, index, name, mute, volume, client): + self.index = index + self.name = name + self.mute = mute + self.volume = volume + self.client = client + return + + # PROTOTYPE + def unmuteStream(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + # PROTOTYPE + def muteStream(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + # PROTOTYPE + def setVolume(self): + raise Exception("ABSTRACT METHOD CALLED") + return + + def printDebug(self): + print "self.index:", self.index + print "self.name:", self.name + print "self.mute:", self.mute + print "self.volume:", self.volume + print "self.client:", self.client + return + +################################################################################ + +class PulseSourceInfo(PulseSource): + def __init__(self, pa_source_info): + PulseSource.__init__(self, pa_source_info.index, + pa_source_info.name, + pa_source_info.mute, + PulseVolumeCtypes(pa_source_info.volume), + PulseClient("Selected Source")) + + self.description = pa_source_info.description + self.sample_spec = pa_source_info.sample_spec + self.channel_map = pa_source_info.channel_map + self.owner_module = pa_source_info.owner_module + self.monitor_of_sink = pa_source_info.monitor_of_sink + self.monitor_of_sink_name = pa_source_info.monitor_of_sink_name + self.latency = pa_source_info.latency + self.driver = pa_source_info.driver + self.flags = pa_source_info.flags + self.proplist = pa_source_info.proplist + self.configured_latency = pa_source_info.configured_latency + + return + + ### + # + # Define PROTOTYPE functions + + def unmuteStream(self, pulseInterface): + pulseInterface.pulse_unmute_source(self.index) + + self.mute = 0 + return + + ### + + def muteStream(self, pulseInterface): + pulseInterface.pulse_mute_source(self.index) + + self.mute = 1 + return + + ### + + def setVolume(self, pulseInterface, volume): + pulseInterface.pulse_set_source_volume(self.index, volume) + + self.volume = volume + return + + ### + + def printDebug(self): + print "PulseSourceInfo" + PulseSource.printDebug(self) + print "self.description", self.description + print "self.sample_spec", self.sample_spec + print "self.channel_map", self.channel_map + print "self.owner_module", self.owner_module + print "self.monitor_of_sink", self.monitor_of_sink + print "self.monitor_of_sink_name", self.monitor_of_sink_name + print "self.latency", self.latency + print "self.driver", self.driver + print "self.flags", self.flags + print "self.proplist", self.proplist + print "self.configured_latency", self.configured_latency + return + + ### + + def __str__(self): + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\"" + +################################################################################ + +class PulseSourceOutputInfo(PulseSource): + def __init__(self, pa_source_output_info): + PulseSource.__init__(self, pa_source_output_info.index, + pa_source_output_info.name, + pa_source_output_info.mute, + PulseVolumeCtypes(pa_source_output_info.volume), + PulseClient("Unknown client")) + self.owner_module = pa_source_output_info.owner_module + self.client_id = pa_source_output_info.client + self.source = pa_source_output_info.source + self.sample_spec = pa_source_output_info.sample_spec + self.channel_map = pa_source_output_info.channel_map + self.buffer_usec = pa_source_output_info.buffer_usec + self.source_usec = pa_source_output_info.source_usec + self.resample_method = pa_source_output_info.resample_method + self.driver = pa_source_output_info.driver + #self.proplist = pa_source_output_info.proplist + + return + + ### + + def setClient(self, c): + self.client = c + + ### + + def printDebug(self): + print "PulseSourceInputInfo" + PulseSource.printDebug(self) + + print "self.owner_module:", self.owner_module + print "self.client_id:", self.client_id + print "self.source:", self.source + print "self.sample_spec:", self.sample_spec + print "self.channel_map:", self.channel_map + print "self.buffer_usec:", self.buffer_usec + print "self.source_usec:", self.source_usec + print "self.resample_method:", self.resample_method + print "self.driver:", self.driver + + ### + + def __str__(self): + if self.client: + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\", mute: " + str(self.mute) + ", " + str(self.client) + return "ID: " + str(self.index) + ", Name: \"" + \ + self.name + "\", mute: " + str(self.mute) + diff --git a/pulsecaster/pulseaudio/PulseVolume.py b/pulsecaster/pulseaudio/PulseVolume.py new file mode 100644 index 0000000..1ff6b7a --- /dev/null +++ b/pulsecaster/pulseaudio/PulseVolume.py @@ -0,0 +1,114 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# PulseVolume.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + +from lib_pulseaudio import * +import math + +# This contains all basic volume features +class PulseVolume: + def __init__(self, vol = 0, channels = 2): + self.channels = channels + + if vol > 100 or vol < 0: + print "WARNING: Volume is invalid!" + vol = 0 + + self.values = [vol] * self.channels + + return + + ############################## + # + # Type conversions + # + #def fromCtypes(self, pa_cvolume): + # self.channels = pa_cvolume.channels + # self.values = map(lambda x: (math.ceil(float(x) * 100 / PA_VOLUME_NORM)), + # pa_cvolume.values[0:self.channels]) + # return self + + def toCtypes(self): + ct = PA_CVOLUME() + ct.channels = self.channels + + for x in range(0, self.channels): + ct.values[x] = (self.values[x] * PA_VOLUME_NORM) / 100 + + return ct + + ### + + def printDebug(self): + print "PulseVolume" + print "self.channels:", self.channels + print "self.values:", self.values + #print "self.proplist:", self.proplist + + ### + + def incVolume(self, vol): + "Increment volume level (mono only)" + vol += sum(self.values) / len(self.values) + + vol = int(vol) + + if vol > 100: + vol = 100 + elif vol < 0: + vol = 0 + + self.setVolume(vol) + + return + + ### + + def setVolume(self, vol, balance = None): + if not balance: + self.values = [vol] * self.channels + else: + self.values[balance] = vol + + return + + ### + + def getVolume(self): + "Return mono volume" + return int(sum(self.values) / len(self.values)) + + ### + + def __str__(self): + return "Channels: " + str(self.channels) + \ + ", values: \"" + str(map(lambda x: str(x) + "%", self.values)) + "\"" + +################################################################################ + +class PulseVolumeCtypes(PulseVolume): + def __init__(self, pa_cvolume): + self.channels = pa_cvolume.channels + self.values = map(lambda x: (math.ceil(float(x) * 100 / PA_VOLUME_NORM)), + pa_cvolume.values[0:self.channels]) + return + diff --git a/pulsecaster/pulseaudio/__init__.py b/pulsecaster/pulseaudio/__init__.py new file mode 100644 index 0000000..8fa7217 --- /dev/null +++ b/pulsecaster/pulseaudio/__init__.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# __init__.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + + + +from PulseObj import * +from PulseVolume import * +from PulseClient import * +from PulseSink import * diff --git a/pulsecaster/pulseaudio/lib_pulseaudio.py b/pulsecaster/pulseaudio/lib_pulseaudio.py new file mode 100644 index 0000000..95a26d7 --- /dev/null +++ b/pulsecaster/pulseaudio/lib_pulseaudio.py @@ -0,0 +1,733 @@ +#!/usr/bin/python +# vi: et sw=2 +# +# lib_pulseaudio.py +# Copyright (C) 2009 Harry Karvonen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# +# Provides pulseaudio interface for python +# +# Author: Harry Karvonen <harry.karvonen@gmail.com> +# + +from ctypes import * + +pulse = CDLL("libpulse.so.0"); + +################################################################################ +# +# Constrants +# +################################################################################ + +PA_CHANNELS_MAX = 32 +PA_VOLUME_NORM = 0x10000 + +# sample types +( + PA_SAMPLE_U8, + PA_SAMPLE_ALAW, + PA_SAMPLE_ULAW, + PA_SAMPLE_S16LE, + PA_SAMPLE_S16BE, + PA_SAMPLE_FLOAT32LE, + PA_SAMPLE_FLOAT32BE, + PA_SAMPLE_S32LE, + PA_SAMPLE_S32BE, + PA_SAMPLE_S24LE, + PA_SAMPLE_S24BE, + PA_SAMPLE_S24_32LE, + PA_SAMPLE_S24_32BE, + PA_SAMPLE_MAX, + PA_SAMPLE_INVALID +) = map(c_int, xrange(15)) + +# channel positions +( + PA_CHANNEL_POSITION_INVALID, + PA_CHANNEL_POSITION_MONO, + PA_CHANNEL_POSITION_LEFT, + PA_CHANNEL_POSITION_RIGHT, + PA_CHANNEL_POSITION_CENTER, + PA_CHANNEL_POSITION_FRONT_LEFT, + PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, + PA_CHANNEL_POSITION_REAR_CENTER, + PA_CHANNEL_POSITION_REAR_LEFT, + PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SUBWOOFER, + PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + PA_CHANNEL_POSITION_SIDE_LEFT, + PA_CHANNEL_POSITION_SIDE_RIGHT, + PA_CHANNEL_POSITION_AUX0, + PA_CHANNEL_POSITION_AUX1, + PA_CHANNEL_POSITION_AUX2, + PA_CHANNEL_POSITION_AUX3, + PA_CHANNEL_POSITION_AUX4, + PA_CHANNEL_POSITION_AUX5, + PA_CHANNEL_POSITION_AUX6, + PA_CHANNEL_POSITION_AUX7, + PA_CHANNEL_POSITION_AUX8, + PA_CHANNEL_POSITION_AUX9, + PA_CHANNEL_POSITION_AUX10, + PA_CHANNEL_POSITION_AUX11, + PA_CHANNEL_POSITION_AUX12, + PA_CHANNEL_POSITION_AUX13, + PA_CHANNEL_POSITION_AUX14, + PA_CHANNEL_POSITION_AUX15, + PA_CHANNEL_POSITION_AUX16, + PA_CHANNEL_POSITION_AUX17, + PA_CHANNEL_POSITION_AUX18, + PA_CHANNEL_POSITION_AUX19, + PA_CHANNEL_POSITION_AUX20, + PA_CHANNEL_POSITION_AUX21, + PA_CHANNEL_POSITION_AUX22, + PA_CHANNEL_POSITION_AUX23, + PA_CHANNEL_POSITION_AUX24, + PA_CHANNEL_POSITION_AUX25, + PA_CHANNEL_POSITION_AUX26, + PA_CHANNEL_POSITION_AUX27, + PA_CHANNEL_POSITION_AUX28, + PA_CHANNEL_POSITION_AUX29, + PA_CHANNEL_POSITION_AUX30, + PA_CHANNEL_POSITION_AUX31, + PA_CHANNEL_POSITION_TOP_CENTER, + PA_CHANNEL_POSITION_TOP_FRONT_LEFT, + PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, + PA_CHANNEL_POSITION_TOP_FRONT_CENTER, + PA_CHANNEL_POSITION_TOP_REAR_LEFT, + PA_CHANNEL_POSITION_TOP_REAR_RIGHT, + PA_CHANNEL_POSITION_TOP_REAR_CENTER, + PA_CHANNEL_POSITION_MAX +) = map(c_int, xrange(57)) + +# stream states +( + PA_STREAM_UNCONNECTED, + PA_STREAM_CREATING, + PA_STREAM_READY, + PA_STREAM_FAILED, + PA_STREAM_TERMINATED +) = map(c_int, xrange(5)) + +# stream directions +( + PA_STREAM_NODIRECTION, + PA_STREAM_PLAYBACK, + PA_STREAM_RECORD, + PA_STREAM_UPLOAD +) = map(c_int, xrange(4)) + +# stream flags +( + PA_STREAM_START_CORKED, + PA_STREAM_INTERPOLATE_TIMING, + PA_STREAM_NOT_MONOTONIC, + PA_STREAM_AUTO_TIMING_UPDATE, + PA_STREAM_NO_REMAP_CHANNELS, + PA_STREAM_NO_REMIX_CHANNELS, + PA_STREAM_FIX_FORMAT, + PA_STREAM_FIX_RATE, + PA_STREAM_FIX_CHANNELS, + PA_STREAM_DONT_MOVE, + PA_STREAM_VARIABLE_RATE, + PA_STREAM_PEAK_DETECT, + PA_STREAM_START_MUTED, + PA_STREAM_ADJUST_LATENCY, + PA_STREAM_EARLY_REQUESTS, + PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND, + PA_STREAM_START_UNMUTED, + PA_STREAM_FAIL_ON_SUSPEND +) = map(c_int, xrange(18)) + +# subscription event masks +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_CARD = 0x0200 +PA_SUBSCRIPTION_MASK_ALL = 0x02ff + +# subscription event types +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_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 + +################################################################################ +# +# Structs +# +################################################################################ + +class PA_IO_EVENT(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_MAINLOOP(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_MAINLOOP_API(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_SIGNAL_EVENT(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_CONTEXT(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_OPERATION(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_STREAM(Structure): + _fields_ = [("_opaque_struct", c_int)] + +class PA_SAMPLE_SPEC(Structure): + _fields_ = [ + ("format", c_int), # FIXME check this + ("rate", c_uint32), + ("channels", c_uint8) + ] + +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_BUFFER_ATTR(Structure): + _fields_ = [ + ("maxlength", c_uint32), + ("tlength", c_uint32), + ("prebuf", c_uint32), + ("minreq", c_uint32), + ("fragsize", c_uint32) + ] + +PA_USEC_T = c_uint64 + +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_SINK_INPUT_INFO(Structure): + __slots__ = [ + 'index', + 'name', + 'owner_module', + 'client', + 'sink', + 'sample_spec', + 'channel_map', + 'volume', + 'buffer_usec', + 'sink_usec', + 'resample_method', + 'driver', + 'mute', + ] + _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(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(c_int)), + ("configured_latency", PA_USEC_T) + ] + +class PA_SOURCE_OUTPUT_INFO(Structure): + __slots__ = [ + 'index', + 'name', + 'owner_module', + 'client', + 'source', + 'sample_spec', + 'channel_map', + 'volume', + 'buffer_usec', + 'sink_usec', + 'resample_method', + 'driver', + 'mute', + ] + _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), + ("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(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(c_int)), + ("configured_latency", PA_USEC_T) + ] + +class PA_CLIENT_INFO(Structure): + _fields_ = [ + ("index", c_uint32), + ("name", c_char_p), + ("owner_module", c_uint32), + ("driver", c_char_p) + #("proplist", POINTER(c_int)) + ] + +################################################################################ +# +# Callback types +# +################################################################################ + +#PA_IO_EVENT_CB_T = CFUNCTYPE(c_void_p, +# POINTER(PA_MAINLOOP_API), +# POINTER(PA_IO_EVENT), +# c_int, +# c_int, +# c_void_p) + +# SIGNAL +PA_SIGNAL_CB_T = CFUNCTYPE(c_void_p, + POINTER(PA_MAINLOOP_API), + POINTER(PA_SIGNAL_EVENT), + c_int, + c_void_p) + +# STATE +PA_STATE_CB_T = CFUNCTYPE(c_int, + POINTER(PA_CONTEXT), + c_void_p) + +# CLIENT +PA_CLIENT_INFO_CB_T = CFUNCTYPE(c_void_p, + POINTER(PA_CONTEXT), + POINTER(PA_CLIENT_INFO), + c_int, + c_void_p) +# SINK INPUT +PA_SINK_INPUT_INFO_CB_T = CFUNCTYPE(c_int, #FIXME wrong type + POINTER(PA_CONTEXT), + POINTER(PA_SINK_INPUT_INFO), + c_int, + c_void_p) + +# SINK +PA_SINK_INFO_CB_T = CFUNCTYPE(c_int, #FIXME wrong type + POINTER(PA_CONTEXT), + POINTER(PA_SINK_INFO), + c_int, + c_void_p) +# SOURCE OUTPUT +PA_SOURCE_OUTPUT_INFO_CB_T = CFUNCTYPE(c_int, #FIXME wrong type + POINTER(PA_CONTEXT), + POINTER(PA_SOURCE_OUTPUT_INFO), + c_int, + c_void_p) + +# SOURCE +PA_SOURCE_INFO_CB_T = CFUNCTYPE(c_int, #FIXME wrong type + POINTER(PA_CONTEXT), + POINTER(PA_SOURCE_INFO), + c_int, + c_void_p) +# CONTEXT +PA_CONTEXT_DRAIN_CB_T = CFUNCTYPE(c_void_p, + POINTER(PA_CONTEXT), + c_void_p) + +PA_CONTEXT_SUCCESS_CB_T = CFUNCTYPE(c_void_p, + POINTER(PA_CONTEXT), + c_int, + c_void_p) + +PA_CONTEXT_SUBSCRIBE_CB_T = CFUNCTYPE(c_void_p, + POINTER(PA_CONTEXT), + c_int, + c_uint32, + c_void_p) + +################################################################################ +# +# Functions +# +################################################################################ + +# +# pa_strerror +pa_strerror = pulse.pa_strerror +pa_strerror.restype = c_char_p +pa_strerror.argtypes = [ + c_int +] + +# +# pa_mainloop_* +pa_mainloop_new = pulse.pa_mainloop_new +pa_mainloop_new.restype = POINTER(PA_MAINLOOP) +pa_mainloop_new.argtypes = [ +] + +pa_mainloop_get_api = pulse.pa_mainloop_get_api +pa_mainloop_get_api.restype = POINTER(PA_MAINLOOP_API) +pa_mainloop_get_api.argtypes = [ + POINTER(PA_MAINLOOP) +] + +pa_mainloop_run = pulse.pa_mainloop_run +pa_mainloop_run.restype = c_int +pa_mainloop_run.argtypes = [ + POINTER(PA_MAINLOOP), + POINTER(c_int) +] + +pa_mainloop_iterate = pulse.pa_mainloop_iterate +pa_mainloop_iterate.restype = c_int +pa_mainloop_iterate.argtypes = [ + POINTER(PA_MAINLOOP), + c_int, + POINTER(c_int) +] + +pa_mainloop_quit = pulse.pa_mainloop_quit +pa_mainloop_quit.restype = c_int +pa_mainloop_quit.argtypes = [ + POINTER(PA_MAINLOOP), + c_int +] + +pa_mainloop_dispatch = pulse.pa_mainloop_dispatch +pa_mainloop_dispatch.restype = c_int +pa_mainloop_dispatch.argtypes = [ + POINTER(PA_MAINLOOP) +] + +pa_mainloop_free = pulse.pa_mainloop_run +pa_mainloop_free.restype = c_int +pa_mainloop_free.argtypes = [ + POINTER(PA_MAINLOOP) +] + +# +# pa_signal_* +pa_signal_init = pulse.pa_signal_init +pa_signal_init.restype = c_int +pa_signal_init.argtypes = [ + POINTER(PA_MAINLOOP_API) +] + +pa_signal_new = pulse.pa_signal_new +pa_signal_new.restype = POINTER(PA_SIGNAL_EVENT) +pa_signal_new.argtypes = [ + c_int, + PA_SIGNAL_CB_T, + c_void_p +] + +# +# pa_context_* +pa_context_errno = pulse.pa_context_errno +pa_context_errno.restype = c_int +pa_context_errno.argtypes = [ + POINTER(PA_CONTEXT) +] + +pa_context_new = pulse.pa_context_new +pa_context_new.restype = POINTER(PA_CONTEXT) +pa_context_new.argtypes = [ + POINTER(PA_MAINLOOP_API), + c_char_p +] + + +pa_context_set_state_callback = pulse.pa_context_set_state_callback +pa_context_set_state_callback.restype = None +pa_context_set_state_callback.argtypes = [ + POINTER(PA_CONTEXT), + PA_STATE_CB_T, + c_void_p +] + +pa_context_connect = pulse.pa_context_connect +pa_context_connect.restype = c_int +pa_context_connect.argtypes = [ + POINTER(PA_CONTEXT), + c_char_p, + c_int, #FIXME | isn't correct + POINTER(c_int) +] + +pa_context_get_state = pulse.pa_context_get_state +pa_context_get_state.restype = c_int; +pa_context_get_state.argtypes = [ + POINTER(PA_CONTEXT) +] + +pa_context_drain = pulse.pa_context_drain +pa_context_drain.restype = POINTER(PA_OPERATION) +pa_context_drain.argtypes = [ + POINTER(PA_CONTEXT), + PA_CONTEXT_DRAIN_CB_T, + c_void_p +] + +pa_context_disconnect = pulse.pa_context_disconnect +pa_context_disconnect.restype = c_int; +pa_context_disconnect.argtypes = [ + POINTER(PA_CONTEXT) +] + +# +# pa_context_*_sink_* +pa_context_get_sink_input_info_list = pulse.pa_context_get_sink_input_info_list +pa_context_get_sink_input_info_list.restype = POINTER(c_int) +pa_context_get_sink_input_info_list.argtypes = [ + POINTER(PA_CONTEXT), + PA_SINK_INPUT_INFO_CB_T, + c_void_p +] + +pa_context_get_sink_info_list = pulse.pa_context_get_sink_info_list +pa_context_get_sink_info_list.restype = POINTER(c_int) +pa_context_get_sink_info_list.argtypes = [ + POINTER(PA_CONTEXT), + PA_SINK_INFO_CB_T, + c_void_p +] + +pa_context_set_sink_mute_by_index = pulse.pa_context_set_sink_mute_by_index +pa_context_set_sink_mute_by_index.restype = POINTER(c_int) +pa_context_set_sink_mute_by_index.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + c_int, + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +pa_context_set_sink_input_mute = pulse.pa_context_set_sink_input_mute +pa_context_set_sink_input_mute.restype = POINTER(c_int) +pa_context_set_sink_input_mute.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + c_int, + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +pa_context_set_sink_volume_by_index = pulse.pa_context_set_sink_volume_by_index +pa_context_set_sink_volume_by_index.restype = POINTER(c_int) +pa_context_set_sink_volume_by_index.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + POINTER(PA_CVOLUME), + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +pa_context_set_sink_input_volume = pulse.pa_context_set_sink_input_volume +pa_context_set_sink_input_volume.restype = POINTER(c_int) +pa_context_set_sink_input_volume.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + POINTER(PA_CVOLUME), + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +# +# pa_context_*_source_* +pa_context_get_source_output_info_list = pulse.pa_context_get_source_output_info_list +pa_context_get_source_output_info_list.restype = POINTER(c_int) +pa_context_get_source_output_info_list.argtypes = [ + POINTER(PA_CONTEXT), + PA_SOURCE_OUTPUT_INFO_CB_T, + c_void_p +] + +pa_context_get_source_info_list = pulse.pa_context_get_source_info_list +pa_context_get_source_info_list.restype = POINTER(c_int) +pa_context_get_source_info_list.argtypes = [ + POINTER(PA_CONTEXT), + PA_SOURCE_INFO_CB_T, + c_void_p +] + +pa_context_set_source_mute_by_index = pulse.pa_context_set_source_mute_by_index +pa_context_set_source_mute_by_index.restype = POINTER(c_int) +pa_context_set_source_mute_by_index.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + c_int, + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +pa_context_set_source_volume_by_index = pulse.pa_context_set_source_volume_by_index +pa_context_set_source_volume_by_index.restype = POINTER(c_int) +pa_context_set_source_volume_by_index.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + POINTER(PA_CVOLUME), + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +# +# pa_context_*_client_* + +pa_context_get_client_info_list = pulse.pa_context_get_client_info_list +pa_context_get_client_info_list.restype = POINTER(c_int) +pa_context_get_client_info_list.argtypes = [ + POINTER(PA_CONTEXT), + PA_CLIENT_INFO_CB_T, + c_void_p +] +pa_context_get_client_info = pulse.pa_context_get_client_info +pa_context_get_client_info.restype = POINTER(c_int) +pa_context_get_client_info.argtypes = [ + POINTER(PA_CONTEXT), + c_uint32, + PA_CLIENT_INFO_CB_T, + c_void_p +] + +# +# pa_context_*_subscribe* +pa_context_set_subscribe_callback = pulse.pa_context_set_subscribe_callback +pa_context_set_subscribe_callback.restype = c_int +pa_context_set_subscribe_callback.argtypes = [ + POINTER(PA_CONTEXT), + PA_CONTEXT_SUBSCRIBE_CB_T, + c_void_p +] + +pa_context_subscribe = pulse.pa_context_subscribe +pa_context_subscribe.restype = POINTER(PA_OPERATION) +pa_context_subscribe.argtypes = [ + POINTER(PA_CONTEXT), + c_int, + PA_CONTEXT_SUCCESS_CB_T, + c_void_p +] + +# +# pa_operation_* +pa_operation_unref = pulse.pa_operation_unref +pa_operation_unref.restype = c_int +pa_operation_unref.argtypes = [ + POINTER(PA_OPERATION) +] + +# +# pa_stream_* +pa_stream_connect_record = pulse.pa_stream_connect_record +pa_stream_connect_record.restype = c_int +pa_stream_connect_record.argtypes = [ + POINTER(PA_STREAM), + c_char_p, + POINTER(PA_BUFFER_ATTR), + c_int # original pa_stream_flags_t +] + +pa_stream_peek = pulse.pa_stream_peek +pa_stream_peek.restype = c_int +pa_stream_peek.argtypes = [ + POINTER(PA_STREAM), + POINTER(c_void_p), # original is void **data, no idea if this works + POINTER(c_size_t) +] + |