summaryrefslogtreecommitdiffstats
path: root/src/sydney.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sydney.h')
-rw-r--r--src/sydney.h541
1 files changed, 403 insertions, 138 deletions
diff --git a/src/sydney.h b/src/sydney.h
index 58324ca..cdc006c 100644
--- a/src/sydney.h
+++ b/src/sydney.h
@@ -1,33 +1,39 @@
#ifndef foosydneyhfoo
#define foosydneyhfoo
-#ifdef __cplusplus
-extern "C" {
-#endif
+/***
+ This file is part of libsydney.
+
+ Copyright 2007-2008 Lennart Poettering
+
+ libsydney is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 2.1 of the
+ License, or (at your option) any later version.
+
+ libsydney 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
+ Lesser General Public License for more details.
-/*
- Requirements & General observations
-
- - In sync mode, the device will automatically write data so that an
- initial read causes writes of zeros to be issued to that one can
- do "while (1); {read(); write()}
- - All functions are thread-safe and can be called in any thread
- context. None of the functions is async-signal safe.
- - It is assumed that duplex streams have a single clock (synchronised)
- - Property set extensible. To be kept in sync with PulseAudio and libsydney.
- - Property keys need to be valid UTF-8, text values, too.
- - Will warn if application.name or application.id not set.
- - Error codes are returned immediately, as negative integers
- - application.process.* will be filled in automatically but may be overwritten by the client.
- They thus should not be used for authentication purposes.
- - It is recommended to set most properties before the _open() call.
-
-*/
+ You should have received a copy of the GNU Lesser General Public
+ License along with libsydney. If not, see
+ <http://www.gnu.org/licenses/>.
+***/
#include <sys/types.h>
#include <sys/param.h>
#include <inttypes.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __GNUC__
+/* Make sure __attribute__ works on non-gcc systems. Yes, might be a bit ugly */
+#define __attribute__(x)
+#endif
+
/* Detect byte order, based on sys/param.h */
#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || defined(WIN32)
#define SA_LITTLE_ENDIAN 1
@@ -39,8 +45,269 @@ extern "C" {
#error "Cannot determine byte order!"
#endif
+/**
+ * SA_PROP_MEDIA_NAME:
+ *
+ * A name describing the media being played. Localized if possible and applicable.
+ */
+#define SA_PROP_MEDIA_NAME "media.name"
+
+/**
+ * SA_PROP_MEDIA_TITLE:
+ *
+ * A (song) title describing the media being played. Localized if possible and applicable.
+ */
+#define SA_PROP_MEDIA_TITLE "media.title"
+
+/**
+ * SA_PROP_MEDIA_ARTIST:
+ *
+ * The artist of this media. Localized if possible and applicable.
+ */
+#define SA_PROP_MEDIA_ARTIST "media.artist"
+
+/**
+ * SA_PROP_MEDIA_LANGUAGE:
+ *
+ * The language this media is in, in some standard POSIX locale string, such as "de_DE".
+ */
+#define SA_PROP_MEDIA_LANGUAGE "media.language"
+
+/**
+ * SA_PROP_MEDIA_FILENAME:
+ *
+ * The file name this media was or can be loaded from.
+ */
+#define SA_PROP_MEDIA_FILENAME "media.filename"
+
+/**
+ * SA_PROP_MEDIA_ICON:
+ *
+ * An icon for this media in binary PNG format.
+ */
+#define SA_PROP_MEDIA_ICON "media.icon"
+
+/**
+ * SA_PROP_MEDIA_ICON_NAME:
+ *
+ * An icon name as defined in the XDG icon naming specifcation.
+ */
+#define SA_PROP_MEDIA_ICON_NAME "media.icon_name"
+
+/**
+ * SA_PROP_MEDIA_ROLE:
+ *
+ * The "role" this media is played in. For event sounds the string
+ * "event". For other cases strings like "music", "video", "game", ...
+ */
+#define SA_PROP_MEDIA_ROLE "media.role"
+
+/**
+ * SA_PROP_EVENT_ID:
+ *
+ * A textual id for an event sound, as mandated by the XDG sound naming specification.
+ */
+#define SA_PROP_EVENT_ID "event.id"
+
+/**
+ * SA_PROP_EVENT_DESCRIPTION:
+ *
+ * A descriptive string for the sound event. Localized if possible and applicable.
+ */
+#define SA_PROP_EVENT_DESCRIPTION "event.description"
+
+/**
+ * SA_PROP_EVENT_MOUSE_X:
+ *
+ * If this sound event was triggered by a mouse input event, the X
+ * position of the mouse cursor on the screen, formatted as string.
+ */
+#define SA_PROP_EVENT_MOUSE_X "event.mouse.x"
+
+/**
+ * SA_PROP_EVENT_MOUSE_Y:
+ *
+ * If this sound event was triggered by a mouse input event, the Y
+ * position of the mouse cursor on the screen, formatted as string.
+ */
+#define SA_PROP_EVENT_MOUSE_Y "event.mouse.y"
+
+/**
+ * SA_PROP_EVENT_MOUSE_HPOS:
+ *
+ * If this sound event was triggered by a mouse input event, the X
+ * position of the mouse cursor as fractional value between 0 and 1,
+ * formatted as string, 0 reflecting the left side of the screen, 1
+ * the right side.
+ */
+#define SA_PROP_EVENT_MOUSE_HPOS "event.mouse.hpos"
+
+/**
+ * SA_PROP_EVENT_MOUSE_VPOS:
+ *
+ * If this sound event was triggered by a mouse input event, the Y
+ * position of the mouse cursor as fractional value between 0 and 1,
+ * formatted as string, 0 reflecting the top end of the screen, 1
+ * the bottom end.
+ */
+#define SA_PROP_EVENT_MOUSE_VPOS "event.mouse.vpos"
+
+/**
+ * SA_PROP_EVENT_MOUSE_BUTTON:
+ *
+ * If this sound event was triggered by a mouse input event, the
+ * number of the mouse button that triggered it, formatted as string. 1
+ * for left mouse button, 3 for right, 2 for middle.
+ */
+#define SA_PROP_EVENT_MOUSE_BUTTON "event.mouse.button"
+
+/**
+ * SA_PROP_WINDOW_NAME:
+ *
+ * If this sound event was triggered by a window on the screen, the
+ * name of this window as human readable string.
+ */
+#define SA_PROP_WINDOW_NAME "window.name"
+
+/**
+ * SA_PROP_WINDOW_ID:
+ *
+ * If this sound event was triggered by a window on the screen, some
+ * identification string for this window, so that the sound system can
+ * recognize specific windows.
+ */
+#define SA_PROP_WINDOW_ID "window.id"
+
+/**
+ * SA_PROP_WINDOW_ICON:
+ *
+ * If this sound event was triggered by a window on the screen, binary
+ * icon data in PNG format for this window.
+ */
+#define SA_PROP_WINDOW_ICON "window.icon"
+
+/**
+ * SA_PROP_WINDOW_ICON_NAME:
+ *
+ * If this sound event was triggered by a window on the screen, an
+ * icon name for this window, as defined in the XDG icon naming
+ * specification.
+ */
+#define SA_PROP_WINDOW_ICON_NAME "window.icon_name"
+
+/**
+ * SA_PROP_WINDOW_X11_DISPLAY:
+ *
+ * If this sound event was triggered by a window on the screen and the
+ * windowing system is X11, the X display name of the window (e.g. ":0").
+ */
+#define SA_PROP_WINDOW_X11_DISPLAY "window.x11.display"
+
+/**
+ * SA_PROP_WINDOW_X11_SCREEN:
+ *
+ * If this sound event was triggered by a window on the screen and the
+ * windowing system is X11, the X screen id of the window formatted as
+ * string (e.g. "0").
+ */
+#define SA_PROP_WINDOW_X11_SCREEN "window.x11.screen"
+
+/**
+ * SA_PROP_WINDOW_X11_MONITOR:
+ *
+ * If this sound event was triggered by a window on the screen and the
+ * windowing system is X11, the X monitor id of the window formatted as
+ * string (e.g. "0").
+ */
+#define SA_PROP_WINDOW_X11_MONITOR "window.x11.monitor"
+
+/**
+ * SA_PROP_WINDOW_X11_XID:
+ *
+ * If this sound event was triggered by a window on the screen and the
+ * windowing system is X11, the XID of the window formatted as string.
+ */
+#define SA_PROP_WINDOW_X11_XID "window.x11.xid"
+
+/**
+ * SA_PROP_APPLICATION_NAME:
+ *
+ * The name of the application this sound event was triggered by as
+ * human readable string. (e.g. "GNU Emacs") Localized if possible and
+ * applicable.
+ */
+#define SA_PROP_APPLICATION_NAME "application.name"
+
+/**
+ * SA_PROP_APPLICATION_ID:
+ *
+ * An identifier for the program this sound event was triggered
+ * by. (e.g. "org.gnu.emacs").
+ */
+#define SA_PROP_APPLICATION_ID "application.id"
+
+/**
+ * SA_PROP_APPLICATION_VERSION:
+ *
+ * A version number for the program this sound event was triggered
+ * by. (e.g. "22.2")
+ */
+#define SA_PROP_APPLICATION_VERSION "application.version"
+
+/**
+ * SA_PROP_APPLICATION_ICON:
+ *
+ * Binary icon data in PNG format for the application this sound event
+ * is triggered by.
+ */
+#define SA_PROP_APPLICATION_ICON "application.icon"
+
+/**
+ * SA_PROP_APPLICATION_ICON_NAME:
+ *
+ * An icon name for the application this sound event is triggered by,
+ * as defined in the XDG icon naming specification.
+ */
+#define SA_PROP_APPLICATION_ICON_NAME "application.icon_name"
+
+/**
+ * SA_PROP_APPLICATION_LANGUAGE:
+ *
+ * The locale string the application that is triggering this sound
+ * event is running in. A POSIX locale string such as de_DE@euro.
+ */
+#define SA_PROP_APPLICATION_LANGUAGE "application.language"
+
+/**
+ * SA_PROP_APPLICATION_PROCESS_ID:
+ *
+ * The unix PID of the process that is triggering this sound event, formatted as string.
+ */
+#define SA_PROP_APPLICATION_PROCESS_ID "application.process.id"
+
+/**
+ * SA_PROP_APPLICATION_PROCESS_BINARY:
+ *
+ * The path to the process binary of the process that is triggering this sound event.
+ */
+#define SA_PROP_APPLICATION_PROCESS_BINARY "application.process.binary"
+
+/**
+ * SA_PROP_APPLICATION_PROCESS_USER:
+ *
+ * The user that owns the process that is triggering this sound event.
+ */
+#define SA_PROP_APPLICATION_PROCESS_USER "application.process.user"
+
+/**
+ * SA_PROP_APPLICATION_PROCESS_HOST:
+ *
+ * The host name of the host the process that is triggering this sound event runs on.
+ */
+#define SA_PROP_APPLICATION_PROCESS_HOST "application.process.host"
+
/** Stream object */
-typedef struct sa_stream sa_stream_t;
+typedef struct sa_stream sa_stream;
/** Volume that corresponds to muted in/out */
#define SA_VOLUME_MUTED ((int32_t) (-0x80000000))
@@ -104,23 +371,34 @@ typedef enum {
_SA_MODE_MAX = 4
} sa_mode_t;
-/** Error codes */
+/**
+ * Error codes:
+ * SCA_SUCCESS: Success
+ *
+ * Error codes
+ */
enum {
SA_SUCCESS = 0,
- SA_ERROR_NOT_SUPPORTED = -1,
+ SA_ERROR_NOTSUPPORTED = -1,
SA_ERROR_INVALID = -2,
SA_ERROR_STATE = -3,
SA_ERROR_OOM = -4,
- SA_ERROR_NO_DEVICE = -5,
- SA_ERROR_NO_DRIVER = -6,
- SA_ERROR_NO_CODEC = -7,
- SA_ERROR_NO_PCM_FORMAT = -7,
- SA_ERROR_SYSTEM = -8,
- SA_ERROR_NO_INIT = -9,
- SA_ERROR_NO_META = -10,
- SA_ERROR_NO_DATA = -11,
- SA_ERROR_NO_SPACE = -12,
- _SA_ERROR_MAX = -13
+ SA_ERROR_NODRIVER = -5,
+ SA_ERROR_SYSTEM = -6,
+ SA_ERROR_CORRUPT = -7,
+ SA_ERROR_TOOBIG = -8,
+ SA_ERROR_NOTFOUND = -9,
+ SA_ERROR_DESTROYED = -10,
+ SA_ERROR_CANCELED = -11,
+ SA_ERROR_NOTAVAILABLE = -12,
+ SA_ERROR_ACCESS = -13,
+ SA_ERROR_IO = -14,
+ SA_ERROR_INTERNAL = -15,
+ SA_ERROR_DISABLED = -16,
+ SA_ERROR_NODEVICE = -17,
+ SA_ERROR_NOCODEC = -18,
+ SA_ERROR_NOPCMFORMAT = -19,
+ _SA_ERROR_MAX = -20
};
/** Possible events for notifications */
@@ -219,6 +497,7 @@ typedef enum {
SA_STATE_RUNNING,
SA_STATE_STOPPED,
SA_STATE_DRAINING,
+ SA_STATE_DEAD,
/* put more stuff */
_SA_STATE_MAX
} sa_state_t;
@@ -236,185 +515,171 @@ typedef enum {
SA_ADJUST_NONE = 0
} sa_adjust_t;
-/** Stream properties */
-#define SA_PROP_MEDIA_NAME "media.name"
-#define SA_PROP_MEDIA_TITLE "media.title"
-#define SA_PROP_MEDIA_ARTIST "media.artist"
-#define SA_PROP_MEDIA_LANGUAGE "media.language"
-#define SA_PROP_MEDIA_FILENAME "media.filename"
-#define SA_PROP_MEDIA_ICON "media.icon"
-#define SA_PROP_MEDIA_ICON_NAME "media.icon_name"
-#define SA_PROP_MEDIA_ROLE "media.role"
-#define SA_PROP_EVENT_ID "event.id"
-#define SA_PROP_EVENT_X11_DISPLAY "event.x11.display"
-#define SA_PROP_EVENT_X11_XID "event.x11.xid"
-#define SA_PROP_EVENT_MOUSE_X "event.mouse.x"
-#define SA_PROP_EVENT_MOUSE_Y "event.mouse.y"
-#define SA_PROP_EVENT_MOUSE_BUTTON "event.mouse.button"
-#define SA_PROP_APPLICATION_NAME "application.name"
-#define SA_PROP_APPLICATION_ID "application.id"
-#define SA_PROP_APPLICATION_VERSION "application.version"
-#define SA_PROP_APPLICATION_ICON "application.icon"
-#define SA_PROP_APPLICATION_ICON_NAME "application.icon_name"
-#define SA_PROP_APPLICATION_LANGUAGE "application.language"
-#define SA_PROP_APPLICATION_PROCESS_ID "application.process.id"
-#define SA_PROP_APPLICATION_PROCESS_BINARY "application.process.binary"
-#define SA_PROP_APPLICATION_PROCESS_USER "application.process.user"
-#define SA_PROP_APPLICATION_PROCESS_HOST "application.process.host"
-
/** Main callback function */
-typedef int (*sa_event_callback_t)(sa_stream_t *s, sa_event_t event);
+typedef int (*sa_event_callback_t)(sa_stream *s, sa_event_t event);
+
+/**
+ * sa_proplist:
+ *
+ * A sydney property list object. Basically a hashtable.
+ */
+typedef struct sa_proplist sa_proplist;
+
+int sa_proplist_create(sa_proplist **p);
+int sa_proplist_destroy(sa_proplist *p);
+int sa_proplist_sets(sa_proplist *p, const char *key, const char *value);
+int sa_proplist_setf(sa_proplist *p, const char *key, const char *format, ...) __attribute__((format(printf, 3, 4)));
+int sa_proplist_set(sa_proplist *p, const char *key, const void *data, size_t nbytes);
/** Create an opaque (e.g. AC3) codec stream */
-int sa_stream_create_opaque(sa_stream_t **s, const char *client_name, sa_mode_t mode, const char *codec);
+int sa_stream_create_opaque(sa_stream **s, sa_mode_t mode, const char *codec);
/** Normal way to open a PCM device */
-int sa_stream_create_pcm(sa_stream_t **s, const char *client_name, sa_mode_t mode, sa_pcm_format_t format, unsigned rate, unsigned nchannels);
+int sa_stream_create_pcm(sa_stream **s, sa_mode_t mode, sa_pcm_format_t format, unsigned rate, unsigned nchannels);
/** Initialise the device */
-int sa_stream_open(sa_stream_t *s);
+int sa_stream_open(sa_stream *s);
/** Close/destroy everything */
-int sa_stream_destroy(sa_stream_t *s);
+int sa_stream_destroy(sa_stream *s);
/* Buffer params */
-int sa_stream_set_write_latency(sa_stream_t *s, size_t nbytes);
-int sa_stream_set_write_wakeup(sa_stream_t *s, size_t nbytes);
-int sa_stream_set_read_latency(sa_stream_t *s, size_t nbytes);
-int sa_stream_set_read_wakeup(sa_stream_t *s, size_t nbytes);
+int sa_stream_change_write_latency(sa_stream *s, size_t latency_nbytes, size_t process_time_nbytes);
+int sa_stream_change_read_latency(sa_stream *s, size_t latency_nbytes, size_t process_time_nbytes);
/** Set the mapping between channels and the loudspeakers */
-int sa_stream_set_channel_map(sa_stream_t *s, const sa_channel_t map[], unsigned n);
+int sa_stream_set_channel_map(sa_stream *s, const sa_channel_t map[], unsigned n);
/** Whether xruns cause the card to reset */
-int sa_stream_set_xrun_mode(sa_stream_t *s, sa_xrun_mode_t mode);
+int sa_stream_set_xrun_mode(sa_stream *s, sa_xrun_mode_t mode);
/** Set the device to non-interleaved mode */
-int sa_stream_set_non_interleaved(sa_stream_t *s, int enable);
+int sa_stream_set_non_interleaved(sa_stream *s, int enable);
/** Allow that the sample rate may be changed during runtime */
-int sa_stream_set_dynamic_rate(sa_stream_t *s, int enabled);
-
-/** Set the number of PCM channels for input */
-int sa_stream_set_read_pcm_nchannels(sa_stream *s, unsigned nchannels);
-
-/** Set the number of PCM channels for output */
-int sa_stream_set_write_pcm_nchannels(sa_stream *s, unsigned nchannels);
+int sa_stream_set_dynamic_pcm_rate(sa_stream *s, int enabled);
/** Select driver */
-int sa_stream_set_driver(sa_stream_t *s, const char *driver);
-
-/** Start callback thread */
-int sa_stream_start_thread(sa_stream_t *s, sa_event_callback_t callback);
+int sa_stream_set_driver(sa_stream *s, const char *driver);
-/** Start callback thread */
-int sa_stream_stop_thread(sa_stream_t *s);
+/** Enable asynchronous mode and set event callback*/
+int sa_stream_set_event_callback(sa_stream *s, sa_event_callback_t callback);
/** Change the device connected to the stream */
-int sa_stream_change_device(sa_stream_t *s, const char *device_name);
+int sa_stream_change_device(sa_stream *s, const char *device_name);
/** volume in hundreths of dB*/
-int sa_stream_change_read_volume(sa_stream_t *s, const int32_t vol[], unsigned n);
+int sa_stream_change_read_volume(sa_stream *s, const int32_t vol[], unsigned n);
/** volume in hundreths of dB*/
-int sa_stream_change_write_volume(sa_stream_t *s, const int32_t vol[], unsigned n);
+int sa_stream_change_write_volume(sa_stream *s, const int32_t vol[], unsigned n);
/** Change the sampling rate */
-int sa_stream_change_rate(sa_stream_t *s, unsigned rate);
+int sa_stream_change_pcm_rate(sa_stream *s, unsigned rate);
+
+int sa_stream_change_props(sa_stream *c, ...) __attribute__((sentinel));
+int sa_stream_change_props_full(sa_stream *c, sa_proplist *p);
/** Associate opaque user data */
-int sa_stream_change_user_data(sa_stream_t *s, const void *value);
+int sa_stream_change_user_data(sa_stream *s, const void *value);
/* Hardware-related. This is implementation-specific and hardware specific. */
-int sa_stream_set_adjust_rate(sa_stream_t *s, sa_adjust_t direction);
-int sa_stream_set_adjust_nchannels(sa_stream_t *s, sa_adjust_t direction);
-int sa_stream_set_adjust_pcm_format(sa_stream_t *s, sa_adjust_t direction);
+int sa_stream_set_adjust_rate(sa_stream *s, sa_adjust_t direction);
+int sa_stream_set_adjust_nchannels(sa_stream *s, sa_adjust_t direction);
+int sa_stream_set_adjust_pcm_format(sa_stream *s, sa_adjust_t direction);
/* Query functions */
-int sa_stream_get_mode(sa_stream_t *s, sa_mode_t *access_mode);
-int sa_stream_get_codec(sa_stream_t *s, char *codec, size_t *size);
-int sa_stream_get_pcm_format(sa_stream_t *s, sa_pcm_format_t *format);
-int sa_stream_get_pcm_rate(sa_stream_t *s, unsigned *rate);
-int sa_stream_get_pcm_nchannels(sa_stream_t *s, int *nchannels);
-int sa_stream_get_user_data(sa_stream_t *s, void **value);
-int sa_stream_get_write_latency(sa_stream_t *s, size_t *nbytes);
-int sa_stream_get_write_wakeup(sa_stream_t *s, size_t *nbytes);
-int sa_stream_get_read_latency(sa_stream_t *s, size_t *nbytes);
-int sa_stream_get_read_wakeup(sa_stream_t *s, size_t *nbytes);
-int sa_stream_get_pcm_channel_map(sa_stream_t *s, sa_channel_t map[], unsigned *n);
-int sa_stream_get_xrun_mode(sa_stream_t *s, sa_xrun_mode_t *mode);
-int sa_stream_get_non_interleaved(sa_stream_t *s, int *enabled);
-int sa_stream_get_pcm_dynamic_rate(sa_stream_t *s, int *enabled);
-int sa_stream_get_driver(sa_stream_t *s, char *driver_name, size_t *size);
-int sa_stream_get_device(sa_stream_t *s, char *device_name, size_t *size);
-int sa_stream_get_read_volume(sa_stream_t *s, int32_t vol[], unsigned *n);
-int sa_stream_get_write_volume(sa_stream_t *s, int32_t vol[], unsigned *n);
-int sa_stream_get_meta_data(sa_stream_t *s, const char *name, void*data, size_t *size);
-int sa_stream_get_adjust_pcm_rate(sa_stream_t *s, sa_adjust_t *direction);
-int sa_stream_get_adjust_pcm_nchannels(sa_stream_t *s, sa_adjust_t *direction);
-int sa_stream_get_adjust_pcm_format(sa_stream_t *s, sa_adjust_t *direction);
+int sa_stream_get_mode(sa_stream *s, sa_mode_t *access_mode);
+int sa_stream_get_codec(sa_stream *s, char **codec);
+int sa_stream_get_pcm_format(sa_stream *s, sa_pcm_format_t *format);
+int sa_stream_get_pcm_rate(sa_stream *s, unsigned *rate);
+int sa_stream_get_pcm_nchannels(sa_stream *s, unsigned *nchannels);
+int sa_stream_get_user_data(sa_stream *s, void **value);
+int sa_stream_get_write_latency(sa_stream *s, size_t *nbytes);
+int sa_stream_get_write_process_time(sa_stream *s, size_t *nbytes);
+int sa_stream_get_read_latency(sa_stream *s, size_t *nbytes);
+int sa_stream_get_read_process_time(sa_stream *s, size_t *nbytes);
+int sa_stream_get_pcm_channel_map(sa_stream *s, sa_channel_t **map, unsigned *n);
+int sa_stream_get_xrun_mode(sa_stream *s, sa_xrun_mode_t *mode);
+int sa_stream_get_non_interleaved(sa_stream *s, int *enabled);
+int sa_stream_get_dynamic_pcm_rate(sa_stream *s, int *enabled);
+int sa_stream_get_driver(sa_stream *s, char **driver_name);
+int sa_stream_get_device(sa_stream *s, char **device_name);
+int sa_stream_get_read_volume(sa_stream *s, int32_t **vol, unsigned *n);
+int sa_stream_get_write_volume(sa_stream *s, int32_t **vol, unsigned *n);
+int sa_stream_get_adjust_pcm_rate(sa_stream *s, sa_adjust_t *direction);
+int sa_stream_get_adjust_pcm_nchannels(sa_stream *s, sa_adjust_t *direction);
+int sa_stream_get_adjust_pcm_format(sa_stream *s, sa_adjust_t *direction);
/** Get current state of the audio device */
-int sa_stream_get_state(sa_stream_t *s, sa_state_t *state);
+int sa_stream_get_state(sa_stream *s, sa_state_t *state);
/** Obtain the error code */
-int sa_stream_get_event_error(sa_stream_t *s, int *error);
+int sa_stream_get_event_error(sa_stream *s, int *error);
/** Obtain the notification code */
-int sa_stream_get_event_notify(sa_stream_t *s, sa_notify_t *notify);
+int sa_stream_get_event_notify(sa_stream *s, sa_notify_t *notify, void **data, size_t *data_nbytes);
/** sync/timing */
-int sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos);
+int sa_stream_get_position(sa_stream *s, sa_position_t position, int64_t *pos);
-/* Blocking IO calls */
+/* IO calls */
+int sa_stream_wait(sa_stream *s, sa_event_t *event);
/** Interleaved capture function */
-int sa_stream_read(sa_stream_t *s, void *data, size_t nbytes);
+int sa_stream_read(sa_stream *s, void *data, size_t nbytes);
/** Non-interleaved capture function */
-int sa_stream_read_ni(sa_stream_t *s, unsigned channel, void *data, size_t nbytes);
+int sa_stream_read_ni(sa_stream *s, unsigned channel, void *data, size_t nbytes);
/** Interleaved playback function */
-int sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes);
+int sa_stream_write(sa_stream *s, const void *data, size_t nbytes);
/** Non-interleaved playback function */
-int sa_stream_write_ni(sa_stream_t *s, unsigned channel, const void *data, size_t nbytes);
+int sa_stream_write_ni(sa_stream *s, unsigned channel, const void *data, size_t nbytes);
/** Interleaved playback function with seek offset */
-int sa_stream_pwrite(sa_stream_t *s, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence);
+int sa_stream_pwrite(sa_stream *s, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence);
/** Non-interleaved playback function with seek offset */
-int sa_stream_pwrite_ni(sa_stream_t *s, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence);
+int sa_stream_pwrite_ni(sa_stream *s, unsigned channel, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence);
/** Query how much can be read without blocking */
-int sa_stream_get_read_size(sa_stream_t *s, size_t *nbytes);
+int sa_stream_get_read_size(sa_stream *s, size_t *nbytes);
/** Query how much can be written without blocking */
-int sa_stream_get_write_size(sa_stream_t *s, size_t *nbytes);
+int sa_stream_get_write_size(sa_stream *s, size_t *nbytes);
/* Control/xrun */
/** Resume playing after a pause */
-int sa_stream_start(sa_stream_t *s);
+int sa_stream_start(sa_stream *s);
/** Pause audio playback (do not empty the buffer) */
-int sa_stream_stop(sa_stream_t *s);
+int sa_stream_stop(sa_stream *s);
/** Block until all audio has been played */
-int sa_stream_drain(sa_stream_t *s);
+int sa_stream_drain(sa_stream *s);
/** Return a human readable error */
const char *sa_strerror(int code);
-/* Stream properties */
+unsigned sa_stream_bytes_to_frames(sa_stream *s, size_t nbytes, int round_up);
+size_t sa_stream_frames_to_bytes(sa_stream *s, unsigned nframes);
+
+uint64_t sa_stream_bytes_to_usec(sa_stream *s, size_t nbytes, int round_up);
+size_t sa_stream_usec_to_bytes(sa_stream *s, uint64_t usec, int round_up);
-/** Update meta data string properties that are attached to this stream. Takes a NULL terminated list of string key/value pairs. */
-int sa_stream_change_props(sa_stream_t *s, ...) SA_GCC_SENTINEL;
+uint64_t sa_stream_frames_to_usec(sa_stream *s, unsigned nframes, int round_up);
+unsigned sa_stream_usec_to_frames(sa_stream *s, uint64_t usec, int round_up);
-/** Update abritrary meta data properties that are attached to this stream */
-int sa_stream_change_prop(sa_stream_t *s, const char *key, const void *data, size_t nbytes);
+typedef struct sa_allocator {
+ void* (*malloc)(size_t size);
+ void* (*calloc)(size_t nmemb, size_t size);
+ void (*free)(void *ptr);
+ void* (*realloc)(void *ptr, size_t size);
+} sa_allocator;
-/** Remove abritrary meta data properties that are attached to this stream */
-int sa_stream_remove_prop(sa_stream_t *s, ...) SA_GCC_SENTINEL;
+void sa_set_allocator(const sa_allocator *a);
#ifdef __cplusplus
}