1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
package simple
/*
#cgo pkg-config: libpulse-simple
#include <pulse/simple.h>
#include <pulse/error.h>
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"unsafe"
)
type Conn struct {
Ptr unsafe.Pointer
}
func wrapConn(ptr *C.pa_simple) Conn {
return Conn{Ptr: unsafe.Pointer(ptr)}
}
func (v Conn) native() *C.pa_simple {
return (*C.pa_simple)(v.Ptr)
}
type StreamDirection uint
const (
StreamDirectionPlayback = C.PA_STREAM_PLAYBACK
)
type SampleFormat uint
const (
SampleFormatU8 = C.PA_SAMPLE_U8
SampleFormatS16NE = C.PA_SAMPLE_S16NE
SampleFormatS16LE = C.PA_SAMPLE_S16LE
SampleFormatS16BE = C.PA_SAMPLE_S16BE
SampleFormatFloat32LE = C.PA_SAMPLE_FLOAT32LE
SampleFormatFloat32BE = C.PA_SAMPLE_FLOAT32BE
SampleFormatS32LE = C.PA_SAMPLE_S32LE
SampleFormatS32BE = C.PA_SAMPLE_S32BE
)
type SampleSpec struct {
Format SampleFormat
Rate uint32
Channels uint8
}
func (ss *SampleSpec) native() *C.pa_sample_spec {
if ss == nil {
return nil
}
var ss0 C.pa_sample_spec
ss0.format = C.pa_sample_format_t(ss.Format)
ss0.rate = C.uint32_t(ss.Rate)
ss0.channels = C.uint8_t(ss.Channels)
return &ss0
}
// server: server name, empty for default
// name: A descriptive name for this client, application name
// dir: Open this stream for recording or playback?
// dev: sink or source name, empty for default
// streamName: A descriptive name for this stream (application name, song title, ...)
// sampleSpec: The sample type to use
func NewConn(server, name string, dir StreamDirection, dev, streamName string,
sampleSpec *SampleSpec) (Conn, error) {
var server0 *C.char
if server != "" {
server0 = C.CString(server) // or null
defer C.free(unsafe.Pointer(server0))
}
name0 := C.CString(name)
var dev0 *C.char
if dev != "" {
dev0 = C.CString(dev)
defer C.free(unsafe.Pointer(dev0))
}
streamName0 := C.CString(streamName)
var errCode C.int
ret := C.pa_simple_new(server0, name0, C.pa_stream_direction_t(dir),
dev0, streamName0, sampleSpec.native(), nil, nil, &errCode)
// clean
C.free(unsafe.Pointer(name0))
C.free(unsafe.Pointer(streamName0))
if ret == nil {
return Conn{}, newError("pa_simple_new", errCode)
}
return wrapConn(ret), nil
}
func (c Conn) Write(data unsafe.Pointer, bytes uint) (int, error) {
var errCode C.int
ret := C.pa_simple_write(c.native(), data, C.size_t(bytes), &errCode)
return int(ret), newError("pa_simple_write", errCode)
}
func (c Conn) Drain() (int, error) {
var errCode C.int
ret := C.pa_simple_drain(c.native(), &errCode)
return int(ret), newError("pa_simple_drain", errCode)
}
// Close and free
func (c Conn) Free() {
C.pa_simple_free(c.native())
}
func (c Conn) Flush() (int, error) {
var errCode C.int
ret := C.pa_simple_flush(c.native(), &errCode)
return int(ret), newError("pa_simple_flush", errCode)
}
type Error struct {
Code int
Fn string
}
func newError(fn string, errCode C.int) error {
if errCode != 0 /*PA_OK*/ {
return Error{
Code: int(errCode),
Fn: fn,
}
}
return nil
}
func (err Error) Error() string {
errMsg := C.GoString(C.pa_strerror(C.int(err.Code)))
return fmt.Sprintf("%s: %s", err.Fn, errMsg)
}
|