pulseaudio

package module
v0.0.0-...-ac1b41f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2018 License: ISC Imports: 6 Imported by: 1

README

pulseaudio: native pulseaudio client for go through dbus.

License Go Report Card GoDoc

pulseaudio is a simple library that controls a pulseaudio server through its Dbus interface.

Features
  • Control your audio cards and streams in pure go
  • Complete native implementation of the pulseaudio D-Bus protocol
  • Splitted interface to allow clients to implement only what they need
Installation

This packages requires Go 1.1. If you installed it and set up your GOPATH, just run:

go get github.com/sqp/pulseaudio
Usage

The complete package documentation is available at godoc.org. See also:

Note

You will have to enable the dbus module of your pulseaudio server. This can now be done with pulseaudio.LoadModule() function.

or by adding this line in /etc/pulse/default.pa

    load-module module-dbus-protocol

if system-wide daemon mode is used, edit the file /etc/pulse/system.pa

Evolutions
  • The base API has been stable for years and there's no plan to improve it for now.
  • A higher level API could be designed to cover simple frequent needs. Open a issue to discuss it if you want.
License

pulseaudio is available under the ISC License; see LICENSE for the full text.

Documentation

Overview

Package pulseaudio controls a pulseaudio server through its Dbus interface.

This is a pure go binding for the pulseaudio Dbus interface.

Note that you will have to enable the dbus module of your pulseaudio server. This can be done by adding this line in /etc/pulse/default.pa (or /etc/pulse/system.pa, if system-wide daemon is used):

load-module module-dbus-protocol

Registering methods to listen to signals

Create a type that declares any methods matching the pulseaudio interface.

Methods will be detected when you declares the object:         Register(myobject)
Methods will start to receive events when you start the loop:  Listen()

Instead of declaring a big interface and forcing clients to provide every method they don't need, this API use a flexible interface system. The callback interface is provided by a list of single method interfaces and only those needed will have to be implemented.

You can register multiple clients at any time on the same pulseaudio session. This allow you to split the callback logic of your program and have some parts (un)loadable like a client GUI.

See types Define... for the list of callback methods that can be used.

Create a client object with some callback methods to register:

type Client struct {
	// The reference to the object isn't needed for the callbacks to work,
	// but it will certainly be useful at some point in your code.
	*pulseaudio.Client
}

func (cl *Client) NewPlaybackStream(path dbus.ObjectPath) {
	log.Println("NewPlaybackStream", path)
}

func (cl *Client) PlaybackStreamRemoved(path dbus.ObjectPath) {
	log.Println("PlaybackStreamRemoved", path)
}

func (cl *Client) DeviceVolumeUpdated(path dbus.ObjectPath, values []uint32) {
	log.Println("device volume", path, values)
}

func (cl *Client) StreamVolumeUpdated(path dbus.ObjectPath, values []uint32) {
	log.Println("stream volume", path, values)
}

Register your object and start the listening loop:

pulse, e := pulseaudio.New()
if e != nil {
	log.Panicln("connect", e)
}

client := &Client{pulse}
pulse.Register(client)

pulse.Listen()

Get properties

There are way too many properties to have a dedicated method for each of them.

Object  Object implementing the property you need.
  Core
  Device
  Stream
Name    Name of the property
Type    Type of the property.
  bool          Bool
  uint32        Uint32
  uint64        Uint64
  string        String
  ObjectPath    Path
  []uint32      ListUint32
  []string      ListString
  []ObjectPath  ListPath

First you need to get the object implementing the property you need. Then you will have to call the method matching the type of returned data for the property you want to get.

// Get the list of sinks from the Core and show some informations about them.
// You better handle errors that were not checked here for code clarity.

sinks, _ := client.Core().ListPath("Sinks") // []ObjectPath
for _, sink := range sinks {

	// Get the device to query properties for the stream referenced by his path.
	dev := client.Device(sink)

	// Get some informations about this stream.
	name, _ := dev.String("Name")          // string
	mute, _ := dev.Bool("Mute")            // bool
	vols, _ := dev.ListUint32("Volume")    // []uint32
	fmt.Println("sink  ", mute, vols, name)
}

Set properties

Methods with the tag RW can also be set.

// Mute all playback streams.
streams, _ := client.Core().ListPath("PlaybackStreams")
for _, stream := range streams {
	dev := client.Stream(stream)
	e = dev.Set("Mute", true)
	if e != nil {
		fmt.Println("mute volume:", e)
	}
}

Pulseaudio Dbus documentation

http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/Clients/DBus/

Dbus documentation was copied and up to date in may 2014 to provide some useful informations here. Feel free to check the upstream source.

Index

Constants

View Source
const (
	DbusInterface = "org.PulseAudio.Core1"
	DbusPath      = "/org/pulseaudio/core1"
)

Dbus objects paths.

Variables

View Source
var PulseCalls = Calls{
	"FallbackSinkUpdated":      func(m Msg) { m.O.(OnFallbackSinkUpdated).FallbackSinkUpdated(m.P) },
	"FallbackSinkUnset":        func(m Msg) { m.O.(OnFallbackSinkUnset).FallbackSinkUnset() },
	"NewSink":                  func(m Msg) { m.O.(OnNewSink).NewSink(m.P) },
	"SinkRemoved":              func(m Msg) { m.O.(OnSinkRemoved).SinkRemoved(m.P) },
	"NewPlaybackStream":        func(m Msg) { m.O.(OnNewPlaybackStream).NewPlaybackStream(m.D[0].(dbus.ObjectPath)) },
	"PlaybackStreamRemoved":    func(m Msg) { m.O.(OnPlaybackStreamRemoved).PlaybackStreamRemoved(m.D[0].(dbus.ObjectPath)) },
	"Device.VolumeUpdated":     func(m Msg) { m.O.(OnDeviceVolumeUpdated).DeviceVolumeUpdated(m.P, m.D[0].([]uint32)) },
	"Device.MuteUpdated":       func(m Msg) { m.O.(OnDeviceMuteUpdated).DeviceMuteUpdated(m.P, m.D[0].(bool)) },
	"Device.ActivePortUpdated": func(m Msg) { m.O.(OnDeviceActivePortUpdated).DeviceActivePortUpdated(m.P, m.D[0].(dbus.ObjectPath)) },
	"Stream.VolumeUpdated":     func(m Msg) { m.O.(OnStreamVolumeUpdated).StreamVolumeUpdated(m.P, m.D[0].([]uint32)) },
	"Stream.MuteUpdated":       func(m Msg) { m.O.(OnStreamMuteUpdated).StreamMuteUpdated(m.P, m.D[0].(bool)) },
}

PulseCalls defines callbacks methods to call the matching object method with type-asserted arguments. Public so it can be hacked before the first Register.

View Source
var PulseTypes = map[string]reflect.Type{
	"FallbackSinkUpdated":      reflect.TypeOf((*OnFallbackSinkUpdated)(nil)).Elem(),
	"FallbackSinkUnset":        reflect.TypeOf((*OnFallbackSinkUnset)(nil)).Elem(),
	"NewSink":                  reflect.TypeOf((*OnNewSink)(nil)).Elem(),
	"SinkRemoved":              reflect.TypeOf((*OnSinkRemoved)(nil)).Elem(),
	"NewPlaybackStream":        reflect.TypeOf((*OnNewPlaybackStream)(nil)).Elem(),
	"PlaybackStreamRemoved":    reflect.TypeOf((*OnPlaybackStreamRemoved)(nil)).Elem(),
	"Device.VolumeUpdated":     reflect.TypeOf((*OnDeviceVolumeUpdated)(nil)).Elem(),
	"Device.MuteUpdated":       reflect.TypeOf((*OnDeviceMuteUpdated)(nil)).Elem(),
	"Device.ActivePortUpdated": reflect.TypeOf((*OnDeviceActivePortUpdated)(nil)).Elem(),
	"Stream.VolumeUpdated":     reflect.TypeOf((*OnStreamVolumeUpdated)(nil)).Elem(),
	"Stream.MuteUpdated":       reflect.TypeOf((*OnStreamMuteUpdated)(nil)).Elem(),
}

PulseTypes defines interface types for events to register. Public so it can be hacked before the first Register.

Functions

func LoadModule

func LoadModule() error

LoadModule loads the PulseAudio DBus module.

func ModuleIsLoaded

func ModuleIsLoaded() (bool, error)

ModuleIsLoaded tests if the PulseAudio DBus module is loaded.

func UnloadModule

func UnloadModule() error

UnloadModule unloads the PulseAudio DBus module.

Types

type Calls

type Calls map[string]func(Msg)

Calls defines a list of event callback methods indexed by dbus method name.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client manages a pulseaudio Dbus client session.

func New

func New() (*Client, error)

New creates a new pulseaudio Dbus client session.

func (*Client) Client

func (pulse *Client) Client(sink dbus.ObjectPath) *Object

Client controls a pulseaudio client.

func (*Client) Core

func (pulse *Client) Core() *Object

Core controls the pulseaudio core.

Properties list:

Boolean
  !IsLocal   This per-client property can be used to find out whether the client is connected to a local server.

Uint32
  !InterfaceRevision        The "major" version of the main D-Bus interface is
                            embedded in the interface name: org.PulseAudio.Core1.
                            When changes are made that break compatibility between
                            old clients and new servers the major version is
                            incremented. This property tells the "minor" version,
                            that is, when new features are added to the interface,
                            this version number is incremented so that new clients
                            can check if the server they talk to supports the new
                            features. This documentation defines revision 0.
                            Extensions are versioned separately (i.e. they have
                            their own major and minor version numbers).
  !DefaultSampleFormat  RW  The default sample format that is used when
                            initializing a device and the configuration information
                            doesn't specify the desired sample format.
  !DefaultSampleRate    RW  The default sample rate that is used when initializing
                            a device and the configuration information doesn't
                            specify the desired sample rate.

String
  Name        The server name. At the time of writing no competing implementations
              have appeared, so the expected name is "pulseaudio".
  Version     The server version string, for example "0.9.17".
  Username    The username that the server is running under.
  Hostname    The hostname of the machine the server is running on.

ObjectPath
  !FallbackSink    RW  When a new playback stream is created and there is no other
                       policy about to which sink the stream should be connected,
                       the fallback sink is selected. This property doesn't exist
                       if there's no sink selected as the fallback sink.
  !FallbackSource  RW  When a new record stream is created and there is no other
                       policy about to which source the stream should be connected,
                       the fallback source is selected. This property doesn't
                       exist if there's no source selected as the fallback source.
  !MyClient            This property has a different value for each client: it
                       tells the reading client the client object that is
                       assigned to its connection.

[]Uint32
  !DefaultChannels  RW  The default channel map that is used when initializing a
                        device and the configuration information doesn't specify
                        the desired channel map. The default channel count can be
                        inferred from this. The channel map is expressed as a
                        list of channel positions,

[]String
  Extensions    All available server extension interfaces. Each extension interface
                defines an unique string that clients can search from this array.
                The string should contain a version part so that if backward
                compatibility breaking changes are made to the interface,
                old clients don't detect the new interface at all,
                or both old and new interfaces can be provided.
                The string is specific to the D-Bus interface of the extension,
                so if an extension module offers access through both the C API
                and D-Bus, the interfaces can be updated independently.
                The strings are intended to follow the structure and restrictions
                of D-Bus interface names, but that is not enforced.
                The clients should treat the strings as opaque identifiers.

[]ObjectPath
  Cards              All currently available cards.
  Sinks              All currently available sinks.
  Sources            All currently available sources.
  !PlaybackStreams   All current playback streams.
  !RecordStreams     All current record streams.
  Samples            All currently loaded samples.
  Modules            All currently loaded modules.
  Clients            All currently connected clients.

func (*Client) Device

func (pulse *Client) Device(sink dbus.ObjectPath) *Object

Device controls a pulseaudio device.

Methods list:

Suspend          Suspends or unsuspends the device.
  bool:            True to suspend, false to unsuspend.
!GetPortByName   Find the device port with the given name.
  string:          Port name
  out: ObjectPath: Device port object

Properties list:

Boolean
  !HasFlatVolume                  Whether or not the device is configured to use the
                                 "flat volume" logic, that is, the device volume follows
                                 the maximum volume of all connected streams.
                                 Currently this is not implemented for sources, so for
                                 them this property is always false.
  !HasConvertibleToDecibelVolume  If this is true, the volume values of the Volume property
                                  can be converted to decibels with pa_sw_volume_to_dB().
                                  If you want to avoid the C API, the function does
                                  the conversion as follows:
                                    If input = 0, then output = -200.0
                                    Otherwise output = 20 * log10((input / 65536)3)
  Mute     RW                     Whether or not the device is currently muted.
  !HasHardwareVolume              Whether or not the device volume controls the hardware volume.
  !HasHardwareMute                Whether or not muting the device controls the hardware mute state.
  !HasDynamicLatency              Whether or not the device latency can be adjusted
                                  according to the needs of the connected streams.
  !IsHardwareDevice               Whether or not this device is a hardware device.
  !IsNetworkDevice                Whether or not this device is a network device.

Uint32
  Index          The device index. Sink and source indices are separate, so it's perfectly
                 normal to have two devices with the same index: the other device is a
                 sink and the other is a source.
  !SampleFormat  The sample format of the device.
  !SampleRate    The sample rate of the device.
  !BaseVolume    The volume level at which the device doesn't perform any
                 amplification or attenuation.
  !VolumeSteps   If the device doesn't support arbitrary volume values, this property
                 tells the number of possible volume values.
                 Otherwise this property has value 65537.
  State          The current state of the device.

Uint64
  !ConfiguredLatency  The latency in microseconds that device has been configured to.
  Latency             The length of queued audio in the device buffer. Not all devices
                      support latency querying; in those cases this property does not exist.

String
  Name    The device name.
  Driver  The driver that implements the device object.
         This is usually expressed as a source code file name, for example "module-alsa-card.c".

ObjectPath
  !OwnerModule      The module that owns this device. It's not guaranteed that any module
                    claims ownership; in such case this property does not exist.
  Card              The card that this device belongs to. Not all devices are part of cards;
                    in those cases this property does not exist.
  !ActivePort  RW   The currently active device port.
                    This property doesn't exist if the device does not have any ports.

[]Uint32
  Channels    The channel map of the device. The channel count can be inferred from this.
              The channel map is expressed as a list of channel positions.
  Volume  RW  The volume of the device. The array is matched against the Channels property:
              the first array element is the volume of the first channel in the Channels
              property, and so on. There are two ways to adjust the volume:
                You can either adjust the overall volume by giving a single-value array,
                or you can precisely control the individual channels by passing an array
                containing a value for each channel.

[]ObjectPath
  Ports     All available device ports. May be empty.

{String -> [Byte]}  == map[string]string ??
  !PropertyList       The device's property list.

func (*Client) DispatchSignal

func (pulse *Client) DispatchSignal(s *dbus.Signal)

DispatchSignal forwards a signal event to the registered clients.

func (*Client) Listen

func (pulse *Client) Listen()

Listen awaits for pulseaudio messages and dispatch events to registered clients.

func (*Client) ListenForSignal

func (pulse *Client) ListenForSignal(name string, paths []dbus.ObjectPath) error

ListenForSignal registers a new event to listen.

func (*Client) Register

func (pulse *Client) Register(obj interface{}) (errs []error)

Register connects an object to the pulseaudio events hooks it implements. If the object declares any of the method in the On... interfaces list, it will be registered to receive those events.

func (*Client) StopListening

func (pulse *Client) StopListening()

StopListening unregisters an listened event.

func (*Client) StopListeningForSignal

func (pulse *Client) StopListeningForSignal(name string) error

StopListeningForSignal unregisters an listened event.

func (*Client) Stream

func (pulse *Client) Stream(sink dbus.ObjectPath) *Object

Stream controls a pulseaudio stream.

Methods list:

Kill    Kills the stream.
Move    Moves the stream to another device.
  ObjectPath: The device to move to.

Properties list:

Boolean
  !VolumeWritable   Whether or not the Volume property can be set. Note that read-only volumes can still change, clients just can't control them.
  Mute  RW        Whether or not the stream is currently muted. Record streams don't currently support muting, so this property exists for playback streams only for now.

Uint32
  Index     The stream index. Playback and record stream indices are separate, so it's perfectly normal to have two streams with the same index: the other stream is a playback stream and the other is a record stream.
  !SampleFormat   The sample format of the stream. See [[Software/PulseAudio/Documentation/Developer/Clients/DBus/Enumerations]] for the list of possible values.
  !SampleRate     The sample rate of the stream.

Uint64
  !BufferLatency      The length of buffered audio in microseconds that is not at the device yet/anymore.
  !DeviceLatency      The length of buffered audio in microseconds at the device.

String
  Driver   The driver that implements the stream object. This is usually expressed as a source code file name, for example "protocol-native.c".
  !ResampleMethod     The resampling algorithm that is used to convert the stream audio data to/from the device's sample rate.

ObjectPath
  !OwnerModule   The module that owns this stream. It's not guaranteed that any module claims ownership; in such case this property does not exist.
  Client    The client whose stream this is. Not all streams are created by clients, in those cases this property does not exist.
  Device   The device this stream is connected to.

[]Uint32
  Channels   The channel map of the stream. The channel count can be inferred from this. The channel map is expressed as a list of channel positions, see [[Software/PulseAudio/Documentation/Developer/Clients/DBus/Enumerations]] for the list of possible channel position values.
  Volume  RW   The volume of the stream. The array is matched against the Channels property: the first array element is the volume of the first channel in the Channels property, and so on.
               There are two ways to adjust the volume. You can either adjust the overall volume by giving a single-value array, or you can precisely control the individual channels by passing an array containing a value for each channel.
               The volume can only be written if VolumeWritable is true.

Type: {String -> [Byte]}
  !PropertyList   The stream's property list.

func (*Client) Unregister

func (pulse *Client) Unregister(obj interface{}) (errs []error)

Unregister disconnects an object from the pulseaudio events hooks.

type Hooker

type Hooker struct {
	Hooks map[string][]interface{}
	Calls Calls
	Types Types
}

Hooker defines a list of objects indexed by the methods they implement. An object can be referenced multiple times. If an object declares all methods, he will be referenced in every field.

hooker:= NewHooker()
hooker.AddCalls(myCalls)
hooker.AddTypes(myTypes)

// create a type with some of your callback methods and register it.
tolisten := hooker.Register(obj) // tolisten is the list of events you may have to listen.

// add the signal forwarder in your events listening loop.
matched := Call(signalName, dbusSignal)

func NewHooker

func NewHooker() *Hooker

NewHooker handles a loosely coupled hook interface to forward dbus signals to registered clients.

func (Hooker) AddCalls

func (hook Hooker) AddCalls(calls Calls)

AddCalls registers a list of callback methods.

func (Hooker) AddTypes

func (hook Hooker) AddTypes(tests Types)

AddTypes registers a list of interfaces types.

func (Hooker) Call

func (hook Hooker) Call(name string, s *dbus.Signal) bool

Call forwards a Dbus event to registered clients for this event.

func (Hooker) Register

func (hook Hooker) Register(obj interface{}) (tolisten []string)

Register connects an object to the events hooks it implements. If the object implements any of the interfaces types declared, it will be registered to receive the matching events. //

func (Hooker) Unregister

func (hook Hooker) Unregister(obj interface{}) (tounlisten []string)

Unregister disconnects an object from the events hooks.

type Msg

type Msg struct {
	O interface{}     // client object.
	P dbus.ObjectPath // signal path.
	D []interface{}   // signal data.
}

Msg defines an dbus signal event message.

type Object

type Object struct {
	dbus.BusObject
	// contains filtered or unexported fields
}

Object extends the dbus Object with properties access methods.

func NewObject

func NewObject(conn *dbus.Conn, interf string, path dbus.ObjectPath) *Object

NewObject creates a dbus Object with properties access methods.

func (*Object) Bool

func (dev *Object) Bool(name string) (val bool, e error)

Bool queries an object property and return it as bool.

func (*Object) Get

func (dev *Object) Get(property string) (dbus.Variant, error)

Get queries an object property and return it as a raw dbus.Variant.

func (*Object) GetValue

func (dev *Object) GetValue(name string, dest interface{}) (e error)

GetValue queries an object property and set it to dest. dest must be of the same type as returned data for the method.

func (*Object) ListPath

func (dev *Object) ListPath(name string) (val []dbus.ObjectPath, e error)

ListPath queries an object property and return it as []dbus.ObjectPath.

func (*Object) ListString

func (dev *Object) ListString(name string) (val []string, e error)

ListString queries an object property and return it as []string.

func (*Object) ListUint32

func (dev *Object) ListUint32(name string) (val []uint32, e error)

ListUint32 queries an object property and return it as []uint32.

func (*Object) MapString

func (dev *Object) MapString(name string) (map[string]string, error)

MapString queries an object property and return it as map[string]string.

func (*Object) ObjectPath

func (dev *Object) ObjectPath(name string) (val dbus.ObjectPath, e error)

ObjectPath queries an object property and return it as string.

func (*Object) Set

func (dev *Object) Set(property string, value interface{}) error

Set updates the given object property with value.

func (*Object) SetProperty

func (dev *Object) SetProperty(p string, v dbus.Variant) error

SetProperty calls org.freedesktop.DBus.Properties.Set on the given object. The property name must be given in interface.member notation.

TODO: Should be moved to the dbus api.

func (*Object) String

func (dev *Object) String(name string) (val string, e error)

String queries an object property and return it as string.

func (*Object) Uint32

func (dev *Object) Uint32(name string) (val uint32, e error)

Uint32 queries an object property and return it as uint32.

func (*Object) Uint64

func (dev *Object) Uint64(name string) (val uint64, e error)

Uint64 queries an object property and return it as uint64.

type OnDeviceActivePortUpdated

type OnDeviceActivePortUpdated interface {
	DeviceActivePortUpdated(dbus.ObjectPath, dbus.ObjectPath)
}

OnDeviceActivePortUpdated is an interface to the DeviceActivePortUpdated method.

type OnDeviceMuteUpdated

type OnDeviceMuteUpdated interface {
	DeviceMuteUpdated(dbus.ObjectPath, bool)
}

OnDeviceMuteUpdated is an interface to the DeviceMuteUpdated method.

type OnDeviceVolumeUpdated

type OnDeviceVolumeUpdated interface {
	DeviceVolumeUpdated(dbus.ObjectPath, []uint32)
}

OnDeviceVolumeUpdated is an interface to the DeviceVolumeUpdated method.

type OnFallbackSinkUnset

type OnFallbackSinkUnset interface {
	FallbackSinkUnset()
}

OnFallbackSinkUnset is an interface to the FallbackSinkUnset method.

type OnFallbackSinkUpdated

type OnFallbackSinkUpdated interface {
	FallbackSinkUpdated(dbus.ObjectPath)
}

OnFallbackSinkUpdated is an interface to the FallbackSinkUpdated method.

type OnNewPlaybackStream

type OnNewPlaybackStream interface {
	NewPlaybackStream(dbus.ObjectPath)
}

OnNewPlaybackStream is an interface to the NewPlaybackStream method.

type OnNewSink

type OnNewSink interface {
	NewSink(dbus.ObjectPath)
}

OnNewSink is an interface to the NewSink method.

type OnPlaybackStreamRemoved

type OnPlaybackStreamRemoved interface {
	PlaybackStreamRemoved(dbus.ObjectPath)
}

OnPlaybackStreamRemoved is an interface to the PlaybackStreamRemoved method.

type OnSinkRemoved

type OnSinkRemoved interface {
	SinkRemoved(dbus.ObjectPath)
}

OnSinkRemoved is an interface to the SinkRemoved method.

type OnStreamMuteUpdated

type OnStreamMuteUpdated interface {
	StreamMuteUpdated(dbus.ObjectPath, bool)
}

OnStreamMuteUpdated is an interface to the StreamMuteUpdated method.

type OnStreamVolumeUpdated

type OnStreamVolumeUpdated interface {
	StreamVolumeUpdated(dbus.ObjectPath, []uint32)
}

OnStreamVolumeUpdated is an interface to the StreamVolumeUpdated method.

type Types

type Types map[string]reflect.Type

Types defines a list of interfaces types indexed by dbus method name.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL