(rsound) Cleanups

This commit is contained in:
twinaphex 2015-04-03 16:06:57 +02:00
parent 67867311d9
commit 9a989462f1
3 changed files with 200 additions and 200 deletions

View File

@ -55,6 +55,7 @@ static void err_cb(void *userdata)
static void *rs_init(const char *device, unsigned rate, unsigned latency) static void *rs_init(const char *device, unsigned rate, unsigned latency)
{ {
int channels, format;
rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t)); rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t));
if (!rsd) if (!rsd)
return NULL; return NULL;
@ -72,8 +73,8 @@ static void *rs_init(const char *device, unsigned rate, unsigned latency)
rsd->buffer = fifo_new(1024 * 4); rsd->buffer = fifo_new(1024 * 4);
int channels = 2; channels = 2;
int format = RSD_S16_NE; format = RSD_S16_NE;
rsd_set_param(rd, RSD_CHANNELS, &channels); rsd_set_param(rd, RSD_CHANNELS, &channels);
rsd_set_param(rd, RSD_SAMPLERATE, &rate); rsd_set_param(rd, RSD_SAMPLERATE, &rate);
@ -106,9 +107,13 @@ static ssize_t rs_write(void *data, const void *buf, size_t size)
if (rsd->nonblock) if (rsd->nonblock)
{ {
size_t avail, write_amt;
rsd_callback_lock(rsd->rd); rsd_callback_lock(rsd->rd);
size_t avail = fifo_write_avail(rsd->buffer);
size_t write_amt = avail > size ? size : avail; avail = fifo_write_avail(rsd->buffer);
write_amt = avail > size ? size : avail;
fifo_write(rsd->buffer, buf, write_amt); fifo_write(rsd->buffer, buf, write_amt);
rsd_callback_unlock(rsd->rd); rsd_callback_unlock(rsd->rd);
return write_amt; return write_amt;
@ -118,8 +123,10 @@ static ssize_t rs_write(void *data, const void *buf, size_t size)
size_t written = 0; size_t written = 0;
while (written < size && !rsd->has_error) while (written < size && !rsd->has_error)
{ {
size_t avail;
rsd_callback_lock(rsd->rd); rsd_callback_lock(rsd->rd);
size_t avail = fifo_write_avail(rsd->buffer);
avail = fifo_write_avail(rsd->buffer);
if (avail == 0) if (avail == 0)
{ {

View File

@ -87,247 +87,239 @@ extern "C" {
#define RSD_SET_CALLBACK RSD_SET_CALLBACK #define RSD_SET_CALLBACK RSD_SET_CALLBACK
#define RSD_CALLBACK_LOCK RSD_CALLBACK_LOCK #define RSD_CALLBACK_LOCK RSD_CALLBACK_LOCK
#define RSD_CALLBACK_UNLOCK RSD_CALLBACK_UNLOCK #define RSD_CALLBACK_UNLOCK RSD_CALLBACK_UNLOCK
/* End feature tests */ /* End feature tests */
/* Defines sample formats available. Defaults to S16_LE should it never be set. */
enum rsd_format
{
RSD_NO_FMT = 0x0000,
RSD_S16_LE = 0x0001,
RSD_S16_BE = 0x0002,
RSD_U16_LE = 0x0004,
RSD_U16_BE = 0x0008,
RSD_U8 = 0x0010,
RSD_S8 = 0x0020,
RSD_S16_NE = 0x0040,
RSD_U16_NE = 0x0080,
RSD_ALAW = 0x0100,
RSD_MULAW = 0x0200,
RSD_S32_LE = 0x0400,
RSD_S32_BE = 0x0800,
RSD_S32_NE = 0x1000,
RSD_U32_LE = 0x2000,
RSD_U32_BE = 0x4000,
RSD_U32_NE = 0x8000,
};
/* Defines operations that can be used with rsd_set_param() */
enum rsd_settings
{
RSD_SAMPLERATE = 0,
RSD_CHANNELS,
RSD_HOST,
RSD_PORT,
RSD_BUFSIZE,
RSD_LATENCY,
RSD_FORMAT,
RSD_IDENTITY
};
/* Defines sample formats available. Defaults to S16_LE should it never be set. */ /* Audio callback for rsd_set_callback. Return -1 to trigger an error in the stream. */
enum rsd_format typedef ssize_t (*rsd_audio_callback_t)(void *data, size_t bytes, void *userdata);
/* Error callback. Signals caller that stream has been stopped,
* either by audio callback returning -1 or stream was hung up. */
typedef void (*rsd_error_callback_t)(void *userdata);
/* Defines the main structure for use with the API. */
typedef struct rsound
{
struct
{ {
RSD_NO_FMT = 0x0000, volatile int socket;
RSD_S16_LE = 0x0001, volatile int ctl_socket;
RSD_S16_BE = 0x0002, } conn;
RSD_U16_LE = 0x0004,
RSD_U16_BE = 0x0008,
RSD_U8 = 0x0010,
RSD_S8 = 0x0020,
RSD_S16_NE = 0x0040,
RSD_U16_NE = 0x0080,
RSD_ALAW = 0x0100,
RSD_MULAW = 0x0200,
RSD_S32_LE = 0x0400,
RSD_S32_BE = 0x0800,
RSD_S32_NE = 0x1000,
RSD_U32_LE = 0x2000,
RSD_U32_BE = 0x4000,
RSD_U32_NE = 0x8000,
};
/* Defines operations that can be used with rsd_set_param() */ char *host;
enum rsd_settings char *port;
char *buffer; /* Obsolete, but kept for backwards header compatibility. */
int conn_type;
volatile int buffer_pointer; /* Obsolete, but kept for backwards header compatibility. */
size_t buffer_size;
fifo_buffer_t *fifo_buffer;
volatile int thread_active;
int64_t total_written;
int64_t start_time;
volatile int has_written;
int bytes_in_buffer;
int delay_offset;
int max_latency;
struct
{ {
RSD_SAMPLERATE = 0, uint32_t latency;
RSD_CHANNELS, uint32_t chunk_size;
RSD_HOST, } backend_info;
RSD_PORT,
RSD_BUFSIZE,
RSD_LATENCY,
RSD_FORMAT,
RSD_IDENTITY
};
/* Audio callback for rsd_set_callback. Return -1 to trigger an error in the stream. */ volatile int ready_for_data;
typedef ssize_t (*rsd_audio_callback_t)(void *data, size_t bytes, void *userdata);
/* Error callback. Signals caller that stream has been stopped, either by audio callback returning -1 or stream was hung up. */ uint32_t rate;
typedef void (*rsd_error_callback_t)(void *userdata); uint32_t channels;
uint16_t format;
int samplesize;
/* Defines the main structure for use with the API. */ struct
typedef struct rsound
{ {
struct { sthread_t *thread;
volatile int socket; slock_t *mutex;
volatile int ctl_socket; slock_t *cond_mutex;
} conn; scond_t *cond;
} thread;
char *host; char identity[256];
char *port;
char *buffer; /* Obsolete, but kept for backwards header compatibility. */
int conn_type;
volatile int buffer_pointer; /* Obsolete, but kept for backwards header compatibility. */ rsd_audio_callback_t audio_callback;
size_t buffer_size; rsd_error_callback_t error_callback;
fifo_buffer_t *fifo_buffer; size_t cb_max_size;
void *cb_data;
slock_t *cb_lock;
} rsound_t;
volatile int thread_active; /* -- API --
All functions (except for rsd_write() return 0 for success, and -1 for error. errno is currently not set. */
int64_t total_written; /* Initializes an rsound_t structure. To make sure no memory leaks occur, you need to rsd_free() it after use.
int64_t start_time;
volatile int has_written;
int bytes_in_buffer;
int delay_offset;
int max_latency;
struct {
uint32_t latency;
uint32_t chunk_size;
} backend_info;
volatile int ready_for_data;
uint32_t rate;
uint32_t channels;
uint16_t format;
int samplesize;
struct {
sthread_t *thread;
slock_t *mutex;
slock_t *cond_mutex;
scond_t *cond;
} thread;
char identity[256];
rsd_audio_callback_t audio_callback;
rsd_error_callback_t error_callback;
size_t cb_max_size;
void *cb_data;
slock_t *cb_lock;
} rsound_t;
/* -- API --
All functions (except for rsd_write() return 0 for success, and -1 for error. errno is currently not set. */
/* Initializes an rsound_t structure. To make sure no memory leaks occur, you need to rsd_free() it after use.
A typical use of the API is as follows: A typical use of the API is as follows:
rsound_t *rd; rsound_t *rd;
rsd_init(&rd); rsd_init(&rd);
rsd_set_param(rd, RSD_HOST, "foohost"); rsd_set_param(rd, RSD_HOST, "foohost");
*sets more params* *sets more params*
rsd_start(rd); rsd_start(rd);
rsd_write(rd, buf, size); rsd_write(rd, buf, size);
rsd_stop(rd); rsd_stop(rd);
rsd_free(rd); rsd_free(rd);
*/ */
int rsd_init (rsound_t **rd); int rsd_init (rsound_t **rd);
/* This is a simpler function that initializes an rsound struct, sets params as given,
and starts the stream. Should this function fail, the structure will stay uninitialized.
Should NULL be passed in either host, port or ident, defaults will be used. */
/* This is a simpler function that initializes an rsound struct, sets params as given, int rsd_simple_start (rsound_t **rd, const char* host, const char* port, const char* ident,
and starts the stream. Should this function fail, the structure will stay uninitialized. int rate, int channels, enum rsd_format format);
Should NULL be passed in either host, port or ident, defaults will be used. */
int rsd_simple_start (rsound_t **rd, const char* host, const char* port, const char* ident, /* Sets params associated with an rsound_t. These options (int options) include:
int rate, int channels, enum rsd_format format);
RSD_HOST: Server to connect to. Expects (char *) in param.
If not set, will default to environmental variable RSD_SERVER or "localhost".
/* Sets params associated with an rsound_t. These options (int options) include: RSD_PORT: Set port. Expects (char *) in param.
If not set, will default to environmental variable RSD_PORT or "12345".
RSD_HOST: Server to connect to. Expects (char *) in param. RSD_CHANNELS: Set number of audio channels. Expects (int *) in param. Mandatory.
If not set, will default to environmental variable RSD_SERVER or "localhost".
RSD_PORT: Set port. Expects (char *) in param. RSD_SAMPLERATE: Set samplerate of audio stream. Expects (int *) in param. Mandatory.
If not set, will default to environmental variable RSD_PORT or "12345".
RSD_CHANNELS: Set number of audio channels. Expects (int *) in param. Mandatory. RSD_BUFSIZE: Sets internal buffersize for the stream.
Might be overridden if too small.
Expects (int *) in param. Optional.
RSD_SAMPLERATE: Set samplerate of audio stream. Expects (int *) in param. Mandatory. RSD_LATENCY: Sets maximum audio latency in milliseconds,
(must be used with rsd_delay_wait() or this will have no effect).
Most applications do not need this.
Might be overridden if too small.
Expects (int *) in param. Optional.
RSD_BUFSIZE: Sets internal buffersize for the stream. RSD_FORMAT: Sets sample format.
Might be overridden if too small. It defaults to S16_LE, so you probably will not use this.
Expects (int *) in param. Optional. Expects (int *) in param, with available values found in the format enum.
If invalid format is given, param might be changed to reflect the sample format the library will use.
RSD_LATENCY: Sets maximum audio latency in milliseconds, RSD_IDENTITY: Sets an identity string associated with the client.
(must be used with rsd_delay_wait() or this will have no effect). Takes a (char *) parameter with the stream name.
Most applications do not need this. Will be truncated if longer than 256 bytes.
Might be overridden if too small.
Expects (int *) in param. Optional.
RSD_FORMAT: Sets sample format. */
It defaults to S16_LE, so you probably will not use this.
Expects (int *) in param, with available values found in the format enum.
If invalid format is given, param might be changed to reflect the sample format the library will use.
RSD_IDENTITY: Sets an identity string associated with the client. int rsd_set_param (rsound_t *rd, enum rsd_settings option, void* param);
Takes a (char *) parameter with the stream name.
Will be truncated if longer than 256 bytes.
*/ /* Enables use of the callback interface. This must be set when stream is not active.
When callback is active, use of the blocking interface is disabled.
Only valid functions to call after rsd_start() is stopping the stream with either rsd_pause() or rsd_stop(). Calling any other function is undefined.
The callback is called at regular intervals and is asynchronous, so thread safety must be ensured by the caller.
If not enough data can be given to the callback, librsound will fill the rest of the callback data with silence.
librsound will attempt to obey latency information given with RSD_LATENCY as given before calling rsd_start().
max_size signifies the maximum size that will ever be requested by librsound. Set this to 0 to let librsound decide the maximum size.
Should an error occur to the stream, err_callback will be called, and the stream will be stopped. The stream can be started again.
int rsd_set_param (rsound_t *rd, enum rsd_settings option, void* param); Callbacks can be disabled by setting callbacks to NULL. */
/* Enables use of the callback interface. This must be set when stream is not active. void rsd_set_callback (rsound_t *rd, rsd_audio_callback_t callback, rsd_error_callback_t err_callback, size_t max_size, void *userdata);
When callback is active, use of the blocking interface is disabled.
Only valid functions to call after rsd_start() is stopping the stream with either rsd_pause() or rsd_stop(). Calling any other function is undefined.
The callback is called at regular intervals and is asynchronous, so thread safety must be ensured by the caller.
If not enough data can be given to the callback, librsound will fill the rest of the callback data with silence.
librsound will attempt to obey latency information given with RSD_LATENCY as given before calling rsd_start().
max_size signifies the maximum size that will ever be requested by librsound. Set this to 0 to let librsound decide the maximum size.
Should an error occur to the stream, err_callback will be called, and the stream will be stopped. The stream can be started again.
Callbacks can be disabled by setting callbacks to NULL. */ /* Lock and unlock the callback. When the callback lock is aquired, the callback is guaranteed to not be executing.
The lock has to be unlocked afterwards.
Attemping to call several rsd_callback_lock() in succession might cause a deadlock.
The lock should be held for as short period as possible.
Try to avoid calling code that may block when holding the lock. */
void rsd_callback_lock (rsound_t *rd);
void rsd_set_callback (rsound_t *rd, rsd_audio_callback_t callback, rsd_error_callback_t err_callback, size_t max_size, void *userdata); void rsd_callback_unlock (rsound_t *rd);
/* Lock and unlock the callback. When the callback lock is aquired, the callback is guaranteed to not be executing. /* Establishes connection to server. Might fail if connection can't be established or that one of
The lock has to be unlocked afterwards. the mandatory options isn't set in rsd_set_param(). This needs to be called after params have been set
Attemping to call several rsd_callback_lock() in succession might cause a deadlock. with rsd_set_param(), and before rsd_write(). */
The lock should be held for as short period as possible. int rsd_start (rsound_t *rd);
Try to avoid calling code that may block when holding the lock. */
void rsd_callback_lock (rsound_t *rd);
void rsd_callback_unlock (rsound_t *rd);
/* Establishes connection to server. Might fail if connection can't be established or that one of /* Shuts down the rsound data structures, but returns the file descriptor associated with the connection.
the mandatory options isn't set in rsd_set_param(). This needs to be called after params have been set The control socket will be shut down. If this function returns a negative number, the exec failed,
with rsd_set_param(), and before rsd_write(). */ but the data structures will not be teared down.
int rsd_start (rsound_t *rd); Should a valid file descriptor be returned, it will always be blocking.
This call will block until all internal buffers have been sent to the network. */
int rsd_exec (rsound_t *rd);
/* Shuts down the rsound data structures, but returns the file descriptor associated with the connection. /* Disconnects from server. All audio data still in network buffer and other buffers will be dropped.
The control socket will be shut down. If this function returns a negative number, the exec failed, To continue playing, you will need to rsd_start() again. */
but the data structures will not be teared down. int rsd_stop (rsound_t *rd);
Should a valid file descriptor be returned, it will always be blocking.
This call will block until all internal buffers have been sent to the network. */
int rsd_exec (rsound_t *rd);
/* Disconnects from server. All audio data still in network buffer and other buffers will be dropped. /* Writes from buf to the internal buffer. Might fail if no connection is established,
To continue playing, you will need to rsd_start() again. */ or there was an unexpected error. This function will block until all data has
int rsd_stop (rsound_t *rd); been written to the buffer. This function will return the number of bytes written to the buffer,
or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */
size_t rsd_write (rsound_t *rd, const void* buf, size_t size);
/* Writes from buf to the internal buffer. Might fail if no connection is established, /* Gets the position of the buffer pointer.
or there was an unexpected error. This function will block until all data has Not really interesting for normal applications.
been written to the buffer. This function will return the number of bytes written to the buffer, Might be useful for implementing rsound on top of other blocking APIs.
or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */ *NOTE* This function is deprecated, it should not be used in new applications. */
size_t rsd_write (rsound_t *rd, const void* buf, size_t size); size_t rsd_pointer (rsound_t *rd);
/* Gets the position of the buffer pointer. /* Aquires how much data can be written to the buffer without blocking */
Not really interesting for normal applications. size_t rsd_get_avail (rsound_t *rd);
Might be useful for implementing rsound on top of other blocking APIs.
*NOTE* This function is deprecated, it should not be used in new applications. */
size_t rsd_pointer (rsound_t *rd);
/* Aquires how much data can be written to the buffer without blocking */ /* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */
size_t rsd_get_avail (rsound_t *rd); size_t rsd_delay (rsound_t *rd);
/* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */ /* Utility for returning latency in milliseconds. */
size_t rsd_delay (rsound_t *rd); size_t rsd_delay_ms (rsound_t *rd);
/* Utility for returning latency in milliseconds. */ /* Returns bytes per sample */
size_t rsd_delay_ms (rsound_t *rd); int rsd_samplesize(rsound_t *rd);
/* Returns bytes per sample */ /* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
int rsd_samplesize(rsound_t *rd); Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
with RSD_LATENCY, this function will do nothing. */
void rsd_delay_wait(rsound_t *rd);
/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY /* Pauses or unpauses a stream. pause -> enable = 1
Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set This function essentially calls on start() and stop(). This behavior might be changed later. */
with RSD_LATENCY, this function will do nothing. */ int rsd_pause (rsound_t *rd, int enable);
void rsd_delay_wait(rsound_t *rd);
/* Frees an rsound_t struct. Make sure that the stream is properly closed down with rsd_stop() before calling rsd_free(). */
/* Pauses or unpauses a stream. pause -> enable = 1 int rsd_free (rsound_t *rd);
This function essentially calls on start() and stop(). This behavior might be changed later. */
int rsd_pause (rsound_t *rd, int enable);
/* Frees an rsound_t struct. Make sure that the stream is properly closed down with rsd_stop() before calling rsd_free(). */
int rsd_free (rsound_t *rd);
#ifndef HAVE_STRL
// Avoid possible naming collisions during link since we prefer to use the actual name.
#define strlcpy(dst, src, size) strlcpy_rarch__(dst, src, size)
#define strlcat(dst, src, size) strlcat_rarch__(dst, src, size)
size_t strlcpy(char *dest, const char *source, size_t size);
size_t strlcat(char *dest, const char *source, size_t size);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -69,6 +69,7 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <compat/strl.h>
#include <retro_inline.h> #include <retro_inline.h>
/* /*