#ifndef foosydneyhfoo #define foosydneyhfoo /* Requirements: - 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) */ #include #include #include /* Detect byte order, based on sys/param.h */ #if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || defined(WIN32) # define SA_LITTLE_ENDIAN # undef SA_BIG_ENDIAN #elif (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) # undef SA_LITTLE_ENDIAN # define SA_BIG_ENDIAN #else # error "Cannot determine byte order!" #endif typedef struct sa_device sa_device_t; /** Volume that corresponds to muted in/out */ #define SA_VOLUME_MUTED 0x80000000 /** Ways to express seek offsets for pread/pwrite */ typedef enum { SA_SEEK_RELATIVE, SA_SEEK_ABSOLUTE, SA_SEEK_RELATIVE_END, } sa_seek_t; /** Supported formats */ typedef enum { SA_PCM_FORMAT_U8, SA_PCM_FORMAT_ULAW, SA_PCM_FORMAT_ALAW, SA_PCM_FORMAT_S16_LE, SA_PCM_FORMAT_S16_BE, SA_PCM_FORMAT_S24_LE, SA_PCM_FORMAT_S24_BE, SA_PCM_FORMAT_S32_LE, SA_PCM_FORMAT_S32_BE, SA_PCM_FORMAT_FLOAT32_LE, SA_PCM_FORMAT_FLOAT32_BE, SA_PCM_FORMAT_MAX } sa_pcm_format_t; /* Native endianness definitions for PCM */ #ifdef SA_LITTLE_ENDIAN #define SA_PCM_FORMAT_S16_NE SA_PCM_FORMAT_S16_LE #define SA_PCM_FORMAT_S24_NE SA_PCM_FORMAT_S24_LE #define SA_PCM_FORMAT_S32_NE SA_PCM_FORMAT_S32_LE #define SA_PCM_FORMAT_FLOAT32_NE SA_PCM_FORMAT_FLOAT32_LE #else #define SA_PCM_FORMAT_S16_NE SA_PCM_FORMAT_S16_BE #define SA_PCM_FORMAT_S24_NE SA_PCM_FORMAT_S24_BE #define SA_PCM_FORMAT_S32_NE SA_PCM_FORMAT_S32_BE #define SA_PCM_FORMAT_FLOAT32_NE SA_PCM_FORMAT_FLOAT32_BE #endif #define SA_CODEC_MPEG "mpeg" #define SA_CODEC_AC3 "ac3" #define SA_CODEC_GSM "gsm" #define SA_CODEC_VORBIS "vorbis" #define SA_CODEC_SPEEX "speex" /** Device opening modes */ typedef enum { SA_MODE_RDONLY = 1, SA_MODE_WRONLY = 2, SA_MODE_RDWR = 3 } sa_mode_t; /** Error codes */ typedef enum { SA_SUCCESS = 0, SA_ERROR_NOT_SUPPORTED = -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_t; /** Possible events for notifications */ typedef enum { SA_NOTIFY_REQUEST_STOP, SA_NOTIFY_REQUEST_START, SA_NOTIFY_VOLUME_CHANGED_IN, SA_NOTIFY_VOLUME_CHANGED_OUT, SA_NOTIFY_DEVICE_CHANGED } sa_notify_t; /** Classes of events */ typedef enum { SA_EVENT_REQUEST_IO, SA_EVENT_INIT_THREAD, SA_EVENT_NOTIFY, SA_EVENT_ERROR } sa_event_t; /** List of sample position queries */ typedef enum { SA_POSITION_WRITE_DELAY, SA_POSITION_WRITE_HARDWARE, SA_POSITION_WRITE_SOFTWARE, SA_POSITION_READ_DELAY, SA_POSITION_READ_HARDWARE, SA_POSITION_READ_SOFTWARE, SA_POSITION_DUPLEX_DELAY, SA_POSITION_MAX } sa_position_t; /* Channel positions */ typedef enum { SA_CHANNEL_MONO, SA_CHANNEL_LEFT, SA_CHANNEL_RIGHT, SA_CHANNEL_CENTER, SA_CHANNEL_FRONT_LEFT, SA_CHANNEL_FRONT_RIGHT, SA_CHANNEL_FRONT_CENTER, SA_CHANNEL_REAR_LEFT, SA_CHANNEL_REAR_RIGHT, SA_CHANNEL_REAR_CENTER, SA_CHANNEL_LFE, SA_CHANNEL_FRONT_LEFT_OF_CENTER, SA_CHANNEL_FRONT_RIGHT_OF_CENTER, SA_CHANNEL_SIDE_LEFT, SA_CHANNEL_SIDE_RIGHT, SA_CHANNEL_TOP_CENTER, SA_CHANNEL_TOP_FRONT_LEFT, SA_CHANNEL_TOP_FRONT_RIGHT, SA_CHANNEL_TOP_FRONT_CENTER, SA_CHANNEL_TOP_REAR_LEFT, SA_CHANNEL_TOP_REAR_RIGHT, SA_CHANNEL_TOP_REAR_CENTER, SA_CHANNEL_AUX0, SA_CHANNEL_AUX1, SA_CHANNEL_AUX2, SA_CHANNEL_AUX3, SA_CHANNEL_AUX4, SA_CHANNEL_AUX5, SA_CHANNEL_AUX6, SA_CHANNEL_AUX7, SA_CHANNEL_AUX8, SA_CHANNEL_AUX9, SA_CHANNEL_AUX10, SA_CHANNEL_AUX11, SA_CHANNEL_AUX12, SA_CHANNEL_AUX13, SA_CHANNEL_AUX14, SA_CHANNEL_AUX15, SA_CHANNEL_AUX16, SA_CHANNEL_AUX17, SA_CHANNEL_AUX18, SA_CHANNEL_AUX19, SA_CHANNEL_AUX20, SA_CHANNEL_AUX21, SA_CHANNEL_AUX22, SA_CHANNEL_AUX23, SA_CHANNEL_AUX24, SA_CHANNEL_AUX25, SA_CHANNEL_AUX26, SA_CHANNEL_AUX27, SA_CHANNEL_AUX28, SA_CHANNEL_AUX29, SA_CHANNEL_AUX30, SA_CHANNEL_AUX31, SA_CHANNEL_MAX } sa_channel_t; typedef enum { SA_STATE_INIT, SA_STATE_RUNNING, SA_STATE_STOPPED, /* put more stuff */ } sa_state_t; typedef enum { SA_XRUN_MODE_STOP, SA_XRUN_MODE_SPIN } sa_xrun_mode_t; typedef enum { SA_ADJUST_UP = 1, SA_ADJUST_DOWN = -1, SA_ADJUST_NONE = 0, } sa_adjust_t; /** Main callback function */ typedef int (*sa_event_callback_t)(sa_device_t *dev, sa_event_t event); /** Create an opaque (e.g. AC3) codec stream */ int sa_device_create_opaque(sa_device_t **dev, const char *client_name, sa_mode_t mode, const char *codec); /** Normal way to open a PCM device */ int sa_device_create_pcm(sa_device_t **dev, const char *client_name, sa_mode_t mode, sa_pcm_format_t format, unsigned rate, unsigned nchannels); /** Initialise the device */ int sa_device_open(sa_device_t *dev); /** Close/destroy everything */ int sa_device_destroy(sa_device_t *dev); /* "Soft" params */ int sa_device_set_write_lower_watermark(sa_device_t *dev, size_t size); int sa_device_set_read_lower_watermark(sa_device_t *dev, size_t size); int sa_device_set_write_upper_watermark(sa_device_t *dev, size_t size); int sa_device_set_read_upper_watermark(sa_device_t *dev, size_t size); /** Set the mapping between channels and the loudspeakers */ int sa_device_set_channel_map(sa_device_t *dev, const sa_channel_t map[]); /** Whether xruns cause the card to reset */ int sa_device_set_xrun_mode(sa_device_t *dev, sa_xrun_mode_t mode); /** Set the device to non-interleaved mode */ int sa_device_set_ni(sa_device_t *dev, int enable); /** Require dynamic sample rate */ int sa_device_set_dsr(sa_device_t *dev, int enable); /** Select driver */ int sa_device_set_driver(sa_device_t *dev, const char *driver); /** Start callback */ int sa_device_start_thread(sa_device_t *dev, sa_event_callback_t *callback); /** Change the device connected to the stream */ int sa_device_change_device(sa_device_t *dev, const char *device_name); /** volume in hundreths of dB's*/ int sa_device_change_input_volume(sa_device_t *dev, int *vol); /** volume in hundreths of dB's*/ int sa_device_change_output_volume(sa_device_t *dev, int *vol); /** Change the sampling rate */ int sa_device_change_sampling_rate(sa_device_t *dev, unsigned rate); /** Change the name of the client application using the device */ int sa_device_change_client_name(sa_device_t *dev, const char *client_name); /** Change the name of the stream being sent */ int sa_device_change_stream_name(sa_device_t *dev, const char *stream_name); /** Associate opaque user data */ int sa_device_change_user_data(sa_device_t *dev, void *value); /* Hardware-related. This is implementation-specific and hardware specific. */ int sa_device_adjust_rate(sa_device_t *dev, sa_adjust_t direction); int sa_device_adjust_nchannels(sa_device_t *dev, sa_adjust_t direction); int sa_device_adjust_pcm_format(sa_device_t *dev, sa_adjust_t direction); /* Query functions */ /** Get current state of the audio device */ int sa_device_get_state(sa_device_t *dev, sa_state_t *state); /** Get current sampling rate */ int sa_device_get_sampling_rate(sa_device_t *dev, unsigned *rate); /** Get number of channels */ int sa_device_get_nchannels(sa_device_t *dev, int *nchannels); /** Get format being used */ int sa_device_get_pcm_format(sa_device_t *dev, sa_pcm_format_t *format); /** Get opaque pointer associated to the device */ int sa_device_get_user_data(sa_device_t *dev, void **value); /** Obtain the error code */ int sa_device_get_event_error(sa_device_t *dev, sa_error_t *error); /** Obtain the notification code */ int sa_device_get_event_notify(sa_device_t *dev, sa_notify_t *notify); /** sync/timing */ int sa_device_get_position(sa_device_t *dev, sa_position_t position, int64_t *pos); /* Blocking IO calls */ /** Interleaved capture function */ int sa_device_read(sa_device_t *dev, void *data, size_t nbytes); /** Interleaved playback function */ int sa_device_write(sa_device_t *dev, const void *data, size_t nbytes); /** Non-interleaved capture function */ int sa_device_read_ni(sa_device_t *dev, unsigned channel, void *data, size_t nbytes); /** Non-interleaved playback function */ int sa_device_write_ni(sa_device_t *dev, unsigned channel, const void *data, size_t nbytes); /** Interleaved capture function with seek offset */ int sa_device_pread(sa_device_t *dev, void *data, size_t nbytes, int64_t offset, sa_seek_t whence); /** Interleaved playback function with seek offset */ int sa_device_pwrite(sa_device_t *dev, const void *data, size_t nbytes, int64_t offset, sa_seek_t whence); /** Non-interleaved capture function with seek offset */ int sa_device_pread_ni(sa_device_t *dev, unsigned channel, void *data, size_t nbytes, int64_t offset, sa_seek_t whence); /** Non-interleaved playback function with seek offset */ int sa_device_pwrite_ni(sa_device_t *dev, 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_device_get_read_size(sa_device_t *dev, size_t *size); /** Query how much can be written without blocking */ int sa_device_get_write_size(sa_device_t *dev, size_t *size); /* Control/xrun */ /** Resume playing after a pause */ int sa_device_resume(sa_device_t *dev); /** Pause audio playback (do not empty the buffer) */ int sa_device_pause(sa_device_t *dev); /** Block until all audio has been played */ int sa_device_drain(sa_device_t *dev); #endif