diff --git a/src/libguac/audio.c b/src/libguac/audio.c index 91770890..da9ea487 100644 --- a/src/libguac/audio.c +++ b/src/libguac/audio.c @@ -49,9 +49,9 @@ #include "wav_encoder.h" -audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) { +guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encoder* encoder) { - audio_stream* audio; + guac_audio_stream* audio; /* Choose an encoding if not specified */ if (encoder == NULL) { @@ -79,10 +79,14 @@ audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) { } /* end for each mimetype */ + /* If still no encoder could be found, fail */ + if (encoder == NULL) + return NULL; + } /* Allocate stream */ - audio = (audio_stream*) malloc(sizeof(audio_stream)); + audio = (guac_audio_stream*) malloc(sizeof(guac_audio_stream)); audio->client = client; /* Reset buffer stats */ @@ -106,7 +110,7 @@ audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) { return audio; } -void audio_stream_begin(audio_stream* audio, int rate, int channels, int bps) { +void guac_audio_stream_begin(guac_audio_stream* audio, int rate, int channels, int bps) { /* Load PCM properties */ audio->rate = rate; @@ -121,12 +125,12 @@ void audio_stream_begin(audio_stream* audio, int rate, int channels, int bps) { } -void audio_stream_end(audio_stream* audio) { +void guac_audio_stream_end(guac_audio_stream* audio) { double duration; /* Flush stream and finish encoding */ - audio_stream_flush(audio); + guac_audio_stream_flush(audio); audio->encoder->end_handler(audio); /* Calculate duration of PCM data */ @@ -143,12 +147,12 @@ void audio_stream_end(audio_stream* audio) { } -void audio_stream_free(audio_stream* audio) { +void guac_audio_stream_free(guac_audio_stream* audio) { free(audio->pcm_data); free(audio); } -void audio_stream_write_pcm(audio_stream* audio, +void guac_audio_stream_write_pcm(guac_audio_stream* audio, unsigned char* data, int length) { /* Update counter */ @@ -165,7 +169,7 @@ void audio_stream_write_pcm(audio_stream* audio, /* Flush if necessary */ if (audio->used + length > audio->length) - audio_stream_flush(audio); + guac_audio_stream_flush(audio); /* Append to buffer */ memcpy(&(audio->pcm_data[audio->used]), data, length); @@ -173,7 +177,7 @@ void audio_stream_write_pcm(audio_stream* audio, } -void audio_stream_flush(audio_stream* audio) { +void guac_audio_stream_flush(guac_audio_stream* audio) { /* If data in buffer */ if (audio->used != 0) { @@ -189,7 +193,7 @@ void audio_stream_flush(audio_stream* audio) { } -void audio_stream_write_encoded(audio_stream* audio, +void guac_audio_stream_write_encoded(guac_audio_stream* audio, unsigned char* data, int length) { /* Resize audio buffer if necessary */ diff --git a/src/libguac/guacamole/audio.h b/src/libguac/guacamole/audio.h index d71e1c57..898f543e 100644 --- a/src/libguac/guacamole/audio.h +++ b/src/libguac/guacamole/audio.h @@ -41,28 +41,34 @@ #include #include -typedef struct audio_stream audio_stream; +/** + * Provides functions and structures used for providing simple streaming audio. + * + * @file audio.h + */ + +typedef struct guac_audio_stream guac_audio_stream; /** * Handler which is called when the audio stream is opened. */ -typedef void audio_encoder_begin_handler(audio_stream* audio); +typedef void guac_audio_encoder_begin_handler(guac_audio_stream* audio); /** * Handler which is called when the audio stream is closed. */ -typedef void audio_encoder_end_handler(audio_stream* audio); +typedef void guac_audio_encoder_end_handler(guac_audio_stream* audio); /** * Handler which is called when the audio stream is flushed. */ -typedef void audio_encoder_write_handler(audio_stream* audio, +typedef void guac_audio_encoder_write_handler(guac_audio_stream* audio, unsigned char* pcm_data, int length); /** * Arbitrary audio codec encoder. */ -typedef struct audio_encoder { +typedef struct guac_audio_encoder { /** * The mimetype of the audio data encoded by this audio @@ -73,26 +79,26 @@ typedef struct audio_encoder { /** * Handler which will be called when the audio stream is opened. */ - audio_encoder_begin_handler* begin_handler; + guac_audio_encoder_begin_handler* begin_handler; /** * Handler which will be called when the audio stream is flushed. */ - audio_encoder_write_handler* write_handler; + guac_audio_encoder_write_handler* write_handler; /** * Handler which will be called when the audio stream is closed. */ - audio_encoder_end_handler* end_handler; + guac_audio_encoder_end_handler* end_handler; -} audio_encoder; +} guac_audio_encoder; /** * Basic audio stream. PCM data is added to the stream. When the stream is * flushed, a write handler receives PCM data packets and, presumably, streams * them to the guac_stream provided. */ -struct audio_stream { +struct guac_audio_stream { /** * PCM data buffer, 16-bit samples, 2-channel, 44100 Hz. @@ -128,7 +134,7 @@ struct audio_stream { * Arbitrary codec encoder. When the PCM buffer is flushed, PCM data will * be sent to this encoder. */ - audio_encoder* encoder; + guac_audio_encoder* encoder; /** * The client associated with this audio stream. @@ -170,42 +176,81 @@ struct audio_stream { }; /** - * Allocates a new audio stream. + * Allocates a new audio stream which encodes audio data using the given + * encoder. If NULL is specified for the encoder, an appropriate encoder + * will be selected based on the encoders built into libguac and the level + * of client support. + * + * @param client The guac_client for which this audio stream is being + * allocated. + * @param encoder The guac_audio_encoder to use when encoding audio, or + * NULL if libguac should select an appropriate built-in + * encoder on its own. + * @return The newly allocated guac_audio_stream, or NULL if no audio + * stream could be allocated due to lack of client support. */ -audio_stream* audio_stream_alloc(guac_client* client, - audio_encoder* encoder); +guac_audio_stream* guac_audio_stream_alloc(guac_client* client, + guac_audio_encoder* encoder); /** * Frees the given audio stream. + * + * @param stream The guac_audio_stream to free. */ -void audio_stream_free(audio_stream* stream); +void guac_audio_stream_free(guac_audio_stream* stream); /** - * Begins a new audio stream. + * Begins a new audio packet within the given audio stream. This packet will be + * built up with repeated writes of PCM data, finally being sent when complete + * via guac_audio_stream_end(). + * + * @param stream The guac_audio_stream which should start a new audio packet. + * @param rate The audio rate of the packet, in Hz. + * @param channels The number of audio channels. + * @param bps The number of bits per audio sample. */ -void audio_stream_begin(audio_stream* stream, int rate, int channels, int bps); +void guac_audio_stream_begin(guac_audio_stream* stream, int rate, int channels, int bps); /** - * Ends the current audio stream. + * Ends the current audio packet, writing the finished packet as an audio + * instruction. + * + * @param stream The guac_audio_stream whose current audio packet should be + * completed and sent. */ -void audio_stream_end(audio_stream* stream); +void guac_audio_stream_end(guac_audio_stream* stream); /** - * Writes PCM data to the given audio stream. + * Writes PCM data to the given audio stream. This PCM data will be + * automatically encoded by the audio encoder associated with this stream. This + * function must only be called after an audio packet has been started with + * guac_audio_stream_begin(). + * + * @param stream The guac_audio_stream to write PCM data through. + * @param data The PCM data to write. + * @param length The number of bytes of PCM data provided. */ -void audio_stream_write_pcm(audio_stream* stream, +void guac_audio_stream_write_pcm(guac_audio_stream* stream, unsigned char* data, int length); /** * Flushes the given audio stream. + * + * @param stream The guac_audio_stream to flush. */ -void audio_stream_flush(audio_stream* stream); +void guac_audio_stream_flush(guac_audio_stream* stream); /** - * Appends arbitrarily-encoded data to the encoded_data buffer - * within the given audio stream. + * Appends arbitrarily-encoded data to the encoded_data buffer within the given + * audio stream. This data must be encoded in the output format of the encoder + * used by the stream. This function is mainly for use by encoder + * implementations. + * + * @param audio The guac_audio_stream to write data through. + * @param data Arbitrary encoded data to write through the audio stream. + * @param length The number of bytes of data provided. */ -void audio_stream_write_encoded(audio_stream* audio, +void guac_audio_stream_write_encoded(guac_audio_stream* audio, unsigned char* data, int length); #endif diff --git a/src/libguac/ogg_encoder.c b/src/libguac/ogg_encoder.c index d1ec6721..25abd7bf 100644 --- a/src/libguac/ogg_encoder.c +++ b/src/libguac/ogg_encoder.c @@ -45,7 +45,7 @@ #include "ogg_encoder.h" -void ogg_encoder_begin_handler(audio_stream* audio) { +void ogg_encoder_begin_handler(guac_audio_stream* audio) { /* Allocate stream state */ ogg_encoder_state* state = (ogg_encoder_state*) @@ -82,12 +82,12 @@ void ogg_encoder_begin_handler(audio_stream* audio) { while (ogg_stream_flush(&(state->ogg_state), &(state->ogg_page)) != 0) { /* Write packet header */ - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, state->ogg_page.header, state->ogg_page.header_len); /* Write packet body */ - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, state->ogg_page.body, state->ogg_page.body_len); } @@ -98,7 +98,7 @@ void ogg_encoder_begin_handler(audio_stream* audio) { } -void ogg_encoder_write_blocks(audio_stream* audio) { +void ogg_encoder_write_blocks(guac_audio_stream* audio) { /* Get state */ ogg_encoder_state* state = (ogg_encoder_state*) audio->data; @@ -122,12 +122,12 @@ void ogg_encoder_write_blocks(audio_stream* audio) { &(state->ogg_page)) != 0) { /* Write packet header */ - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, state->ogg_page.header, state->ogg_page.header_len); /* Write packet body */ - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, state->ogg_page.body, state->ogg_page.body_len); @@ -142,7 +142,7 @@ void ogg_encoder_write_blocks(audio_stream* audio) { } -void ogg_encoder_end_handler(audio_stream* audio) { +void ogg_encoder_end_handler(guac_audio_stream* audio) { /* Get state */ ogg_encoder_state* state = (ogg_encoder_state*) audio->data; @@ -163,7 +163,7 @@ void ogg_encoder_end_handler(audio_stream* audio) { } -void ogg_encoder_write_handler(audio_stream* audio, +void ogg_encoder_write_handler(guac_audio_stream* audio, unsigned char* pcm_data, int length) { /* Get state */ @@ -199,7 +199,7 @@ void ogg_encoder_write_handler(audio_stream* audio, } /* Encoder handlers */ -audio_encoder _ogg_encoder = { +guac_audio_encoder _ogg_encoder = { .mimetype = "audio/ogg", .begin_handler = ogg_encoder_begin_handler, .write_handler = ogg_encoder_write_handler, @@ -207,5 +207,5 @@ audio_encoder _ogg_encoder = { }; /* Actual encoder */ -audio_encoder* ogg_encoder = &_ogg_encoder; +guac_audio_encoder* ogg_encoder = &_ogg_encoder; diff --git a/src/libguac/ogg_encoder.h b/src/libguac/ogg_encoder.h index 3b2b5fbb..97d81ebd 100644 --- a/src/libguac/ogg_encoder.h +++ b/src/libguac/ogg_encoder.h @@ -61,7 +61,7 @@ typedef struct ogg_encoder_state { } ogg_encoder_state; -extern audio_encoder* ogg_encoder; +extern guac_audio_encoder* ogg_encoder; #endif diff --git a/src/libguac/wav_encoder.c b/src/libguac/wav_encoder.c index 55d64580..23c9f110 100644 --- a/src/libguac/wav_encoder.c +++ b/src/libguac/wav_encoder.c @@ -46,7 +46,7 @@ #include "wav_encoder.h" -void wav_encoder_begin_handler(audio_stream* audio) { +void wav_encoder_begin_handler(guac_audio_stream* audio) { /* Allocate stream state */ wav_encoder_state* state = (wav_encoder_state*) @@ -79,7 +79,7 @@ void _wav_encoder_write_le(unsigned char* buffer, int value, int length) { } -void wav_encoder_end_handler(audio_stream* audio) { +void wav_encoder_end_handler(guac_audio_stream* audio) { /* * Static header init @@ -112,7 +112,7 @@ void wav_encoder_end_handler(audio_stream* audio) { 4 + sizeof(fmt_header) + sizeof(data_header) + state->used, sizeof(riff_header.chunk_size)); - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, (unsigned char*) &riff_header, sizeof(riff_header)); @@ -142,7 +142,7 @@ void wav_encoder_end_handler(audio_stream* audio) { _wav_encoder_write_le(fmt_header.subchunk_bps, audio->bps, sizeof(fmt_header.subchunk_bps)); - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, (unsigned char*) &fmt_header, sizeof(fmt_header)); @@ -154,19 +154,19 @@ void wav_encoder_end_handler(audio_stream* audio) { _wav_encoder_write_le(data_header.subchunk_size, state->used, sizeof(data_header.subchunk_size)); - audio_stream_write_encoded(audio, + guac_audio_stream_write_encoded(audio, (unsigned char*) &data_header, sizeof(data_header)); /* Write .wav data */ - audio_stream_write_encoded(audio, state->data_buffer, state->used); + guac_audio_stream_write_encoded(audio, state->data_buffer, state->used); /* Free stream state */ free(state); } -void wav_encoder_write_handler(audio_stream* audio, +void wav_encoder_write_handler(guac_audio_stream* audio, unsigned char* pcm_data, int length) { /* Get state */ @@ -189,7 +189,7 @@ void wav_encoder_write_handler(audio_stream* audio, } /* Encoder handlers */ -audio_encoder _wav_encoder = { +guac_audio_encoder _wav_encoder = { .mimetype = "audio/wav", .begin_handler = wav_encoder_begin_handler, .write_handler = wav_encoder_write_handler, @@ -197,5 +197,5 @@ audio_encoder _wav_encoder = { }; /* Actual encoder */ -audio_encoder* wav_encoder = &_wav_encoder; +guac_audio_encoder* wav_encoder = &_wav_encoder; diff --git a/src/libguac/wav_encoder.h b/src/libguac/wav_encoder.h index 3083456e..c860ad11 100644 --- a/src/libguac/wav_encoder.h +++ b/src/libguac/wav_encoder.h @@ -138,7 +138,7 @@ typedef struct wav_encoder_data_header { } wav_encoder_data_header; -extern audio_encoder* wav_encoder; +extern guac_audio_encoder* wav_encoder; #endif