Commits

Markus Tzoe committed 60cf17e

Init version of go bindings for libshout

Comments (0)

Files changed (1)

+package shout
+
+// #cgo CFLAGS: -I/opt/include
+// #cgo LDFLAGS: -L/opt/lib -lshout
+// #include <shout/shout.h>
+// #include <stdlib.h>
+import "C"
+
+import (
+	"fmt"
+	"unsafe"
+)
+
+const (
+	SHOUTERR_SUCCESS          = (0)
+	SHOUTERR_INSANE           = (-1)
+	SHOUTERR_NOCONNECT        = (-2)
+	SHOUTERR_NOLOGIN          = (-3)
+	SHOUTERR_SOCKET           = (-4)
+	SHOUTERR_MALLOC           = (-5)
+	SHOUTERR_METADATA         = (-6)
+	SHOUTERR_CONNECTED        = (-7)
+	SHOUTERR_UNCONNECTED      = (-8)
+	SHOUTERR_UNSUPPORTED      = (-9)
+	SHOUTERR_BUSY             = (-10)
+	SHOUT_FORMAT_OGG          = (0)
+	SHOUT_FORMAT_MP3          = (1)
+	SHOUT_FORMAT_VORBIS       = SHOUT_FORMAT_OGG
+	SHOUT_PROTOCOL_HTTP       = (0)
+	SHOUT_PROTOCOL_XAUDIOCAST = (1)
+	SHOUT_PROTOCOL_ICY        = (2)
+	//SHOUT_AI_BITRATE          = "bitrate"
+	//SHOUT_AI_SAMPLERATE       = "samplerate"
+	//SHOUT_AI_CHANNELS         = "channels"
+	//SHOUT_AI_QUALITY          = "quality"
+)
+
+var errors map[int]error
+
+type Shout struct {
+	handle C.shout_t
+}
+
+type ShoutMeta struct {
+	handle C.shout_metadata_t
+}
+
+func init() {
+	errors = make(map[int]error)
+	errors[SHOUTERR_SUCCESS] = nil //fmt.Errorf("No error.")
+	errors[SHOUTERR_INSANE] = fmt.Errorf("Nonsensical arguments.")
+	errors[SHOUTERR_NOCONNECT] = fmt.Errorf("Couldn't connect.")
+	errors[SHOUTERR_NOLOGIN] = fmt.Errorf("Login failed.")
+	errors[SHOUTERR_SOCKET] = fmt.Errorf("Socket error.")
+	errors[SHOUTERR_MALLOC] = fmt.Errorf("Out of memory.")
+	errors[SHOUTERR_METADATA] = fmt.Errorf("Unknown error.")
+	errors[SHOUTERR_CONNECTED] = fmt.Errorf("Cannot set parameter while connected.")
+	errors[SHOUTERR_UNCONNECTED] = fmt.Errorf("Not connected.")
+	errors[SHOUTERR_UNSUPPORTED] = fmt.Errorf("Unsupported request option")
+	errors[SHOUTERR_BUSY] = fmt.Errorf("Socket is busy")
+}
+
+/* initializes the shout library. Must be called before anything else. */
+func Init() {
+	C.shout_init()
+}
+
+/* shuts down the shout library, deallocating any global storage. Don't call anything afterwards. */
+func Shutdown() {
+	C.shout_shutdown()
+}
+
+/* returns a version string and integer of major, minor, and patch levels, respectively. */
+func Version() (string, int, int, int) {
+	var major, minor, patch _Ctype_int
+	ret, _ := C.shout_version(&major, &minor, &patch)
+	return C.GoString(ret), int(major), int(minor), int(patch)
+}
+
+/* Factory method: allocates and sets up a shout_t handle. Returns nil and error if it can't get enough memory. */
+func New() (*Shout, error) {
+	ret := new(Shout)
+	handle, err := C.shout_new()
+	if err != nil && handle == (*C.shout_t)(unsafe.Pointer(uintptr(0))) {
+		return nil, err
+	}
+	ret.handle = *handle
+	defer C.shout_free(handle)
+	return ret, nil
+}
+
+/* Returns a statically allocated string describing the last shout error to occur. */
+/*func (sh *Shout) GetError() string {
+	ret, _ := C.shout_get_error(&sh.handle)
+	return C.GoString(ret)
+}*/
+
+/* Return the error code (e.g. SHOUTERR_SOCKET) for this shout instance */
+/*func (sh *Shout) GetErrno() int {
+	ret, _ := C.shout_get_errno(&sh.handle)
+	return int(ret)
+}*/
+
+/* returns SHOUTERR_CONNECTED or SHOUTERR_UNCONNECTED */
+func (sh *Shout) GetConnected() int {
+	ret, _ := C.shout_get_connected(&sh.handle)
+	return int(ret)
+}
+
+func (sh *Shout) SetHost(host string) error {
+	h := C.CString(host)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_host(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetHost() string {
+	ret, _ := C.shout_get_host(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetPort(port uint16) error {
+	ret, _ := C.shout_set_port(&sh.handle, C.ushort(port))
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetPort() uint16 {
+	ret, _ := C.shout_get_port(&sh.handle)
+	return uint16(ret)
+}
+
+func (sh *Shout) SetPassword(password string) error {
+	passwd := C.CString(password)
+	defer C.free(unsafe.Pointer(passwd))
+	ret, _ := C.shout_set_password(&sh.handle, passwd)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetPassword() string {
+	ret, _ := C.shout_get_password(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetMount(mount string) error {
+	mnt := C.CString(mount)
+	defer C.free(unsafe.Pointer(mnt))
+	ret, _ := C.shout_set_mount(&sh.handle, mnt)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetMount() string {
+	ret, _ := C.shout_get_mount(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetName(name string) error {
+	n := C.CString(name)
+	defer C.free(unsafe.Pointer(n))
+	ret, _ := C.shout_set_name(&sh.handle, n)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetName() string {
+	ret, _ := C.shout_get_name(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetUrl(url string) error {
+	h := C.CString(url)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_url(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetUrl() string {
+	ret, _ := C.shout_get_url(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetGenre(genre string) error {
+	h := C.CString(genre)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_genre(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetGenre() string {
+	ret, _ := C.shout_get_genre(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetUser(user string) error {
+	h := C.CString(user)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_user(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetUser() string {
+	ret, _ := C.shout_get_user(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetAgent(agent string) error {
+	h := C.CString(agent)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_agent(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetAgent() string {
+	ret, _ := C.shout_get_agent(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetDescription(description string) error {
+	h := C.CString(description)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_description(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetDescription() string {
+	ret, _ := C.shout_get_description(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetDumpfile(dumpfile string) error {
+	h := C.CString(dumpfile)
+	defer C.free(unsafe.Pointer(h))
+	ret, _ := C.shout_set_dumpfile(&sh.handle, h)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetDumpfile() string {
+	ret, _ := C.shout_get_dumpfile(&sh.handle)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetAudioInfo(name, value string) error {
+	n, v := C.CString(name), C.CString(value)
+	defer C.free(unsafe.Pointer(n))
+	defer C.free(unsafe.Pointer(v))
+	ret, _ := C.shout_set_audio_info(&sh.handle, n, v)
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetAudioInfo(name string) string {
+	n := C.CString(name)
+	defer C.free(unsafe.Pointer(n))
+	ret, _ := C.shout_get_audio_info(&sh.handle, n)
+	return C.GoString(ret)
+}
+
+func (sh *Shout) SetPublic(public uint) error {
+	ret, _ := C.shout_set_public(&sh.handle, C.uint(public))
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetPublic() uint {
+	ret, _ := C.shout_get_public(&sh.handle)
+	return uint(ret)
+}
+
+/* takes a SHOUT_FORMAT_xxxx argument */
+func (sh *Shout) SetFormat(format uint) error {
+	ret, _ := C.shout_set_format(&sh.handle, C.uint(format))
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetFormat() uint {
+	ret, _ := C.shout_get_format(&sh.handle)
+	return uint(ret)
+}
+
+/* takes a SHOUT_PROTOCOL_xxxxx argument */
+func (sh *Shout) SetProtocol(protocol uint) error {
+	ret, _ := C.shout_set_protocol(&sh.handle, C.uint(protocol))
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetProtocol() uint {
+	ret, _ := C.shout_get_protocol(&sh.handle)
+	return uint(ret)
+}
+
+/* Instructs libshout to use nonblocking I/O. Must be called before
+ * shout_open (no switching back and forth midstream at the moment). */
+func (sh *Shout) SetNonblocking(nonblocking uint) error {
+	ret, _ := C.shout_set_nonblocking(&sh.handle, C.uint(nonblocking))
+	return errors[int(ret)]
+}
+
+func (sh *Shout) GetNonblocking() uint {
+	ret, _ := C.shout_get_nonblocking(&sh.handle)
+	return uint(ret)
+}
+
+/* Opens a connection to the server.  All parameters must already be set */
+func (sh *Shout) Open() error {
+	ret, _ := C.shout_open(&sh.handle)
+	return errors[int(ret)]
+}
+
+/* Closes a connection to the server */
+func (sh *Shout) Close() error {
+	ret, _ := C.shout_close(&sh.handle)
+	return errors[int(ret)]
+}
+
+/* Send data to the server, parsing it for format specific timing info */
+func (sh *Shout) Send(data string) error {
+	dt := (*_Ctype_unsignedchar)(unsafe.Pointer(C.CString(data)))
+	defer C.free(unsafe.Pointer(dt))
+	size := C.size_t(len(data))
+	ret, _ := C.shout_send(&sh.handle, dt, size)
+	return errors[int(ret)]
+}
+
+/* Send unparsed data to the server.  Do not use this unless you know what you are doing. 
+ * Returns the number of bytes written, or error.
+ */
+func (sh *Shout) SendRaw(data string) (int64, error) {
+	dt := (*_Ctype_unsignedchar)(unsafe.Pointer(C.CString(data)))
+	defer C.free(unsafe.Pointer(dt))
+	size := C.size_t(len(data))
+	ret, _ := C.shout_send_raw(&sh.handle, dt, size)
+	if int64(ret) < 0 {
+		return int64(ret), errors[int(ret)]
+	}
+	return int64(ret), nil
+}
+
+/* return the number of bytes currently on the write queue (only makes sense in nonblocking mode). */
+func (sh *Shout) QueueLen() (int64, error) {
+	ret, _ := C.shout_queuelen(&sh.handle)
+	if int64(ret) < 0 {
+		return int64(ret), errors[int(ret)]
+	}
+	return int64(ret), nil
+}
+
+/* Puts caller to sleep until it is time to send more data to the server */
+func (sh *Shout) Sync() {
+	C.shout_sync(&sh.handle)
+}
+
+/* Amount of time in ms caller should wait before sending again */
+func (sh *Shout) Delay() int {
+	ret, _ := C.shout_delay(&sh.handle)
+	return int(ret)
+}
+
+/* Sets MP3 metadata.
+ * Returns: nil or error.
+ */
+func (sh *Shout) SetMetadata(meta *ShoutMeta) error {
+	ret, _ := C.shout_set_metadata(&sh.handle, &meta.handle)
+	return errors[int(ret)]
+}
+
+/* Allocates a new metadata structure. */
+func NewMetadata() (*ShoutMeta, error) {
+	ret := new(ShoutMeta)
+	handle, err := C.shout_metadata_new()
+	if err != nil && handle == (*C.shout_metadata_t)(unsafe.Pointer(uintptr(0))) {
+		return nil, err
+	}
+	ret.handle = *handle
+	defer C.shout_metadata_free(handle)
+	return ret, nil
+}
+
+/* Add a parameter to the metadata structure.
+ * Returns: nil or error.
+ */
+func (meta *ShoutMeta) Add(name, value string) error {
+	n, v := C.CString(name), C.CString(value)
+	defer C.free(unsafe.Pointer(n))
+	defer C.free(unsafe.Pointer(v))
+	ret, _ := C.shout_metadata_add(&meta.handle, n, v)
+	return errors[int(ret)]
+}