From fbdb6876d97fd97dbce8388235aea6caa03f70b9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 24 Sep 2013 12:01:02 -0700 Subject: [PATCH] Migrate to libguac audio. Migrate to improved stream protocol. --- src/libguac/audio.c | 13 +- src/libguac/client.c | 9 - src/libguac/guacamole/protocol.h | 157 ++----------- src/libguac/guacamole/stream.h | 12 +- src/libguac/protocol.c | 94 ++------ src/protocols/rdp/Makefile.am | 21 +- src/protocols/rdp/audio.c | 176 --------------- src/protocols/rdp/audio.h | 212 ------------------ src/protocols/rdp/client.c | 34 +-- src/protocols/rdp/client.h | 4 +- src/protocols/rdp/guac_handlers.c | 4 - .../rdp/guac_rdpsnd/rdpsnd_messages.c | 20 +- .../rdp/guac_rdpsnd/rdpsnd_messages.h | 12 +- .../rdp/guac_rdpsnd/rdpsnd_service.c | 10 +- .../rdp/guac_rdpsnd/rdpsnd_service.h | 4 +- src/protocols/rdp/ogg_encoder.c | 211 ----------------- src/protocols/rdp/ogg_encoder.h | 67 ------ src/protocols/rdp/wav_encoder.c | 201 ----------------- src/protocols/rdp/wav_encoder.h | 144 ------------ 19 files changed, 80 insertions(+), 1325 deletions(-) delete mode 100644 src/protocols/rdp/audio.c delete mode 100644 src/protocols/rdp/audio.h delete mode 100644 src/protocols/rdp/ogg_encoder.c delete mode 100644 src/protocols/rdp/ogg_encoder.h delete mode 100644 src/protocols/rdp/wav_encoder.c delete mode 100644 src/protocols/rdp/wav_encoder.h diff --git a/src/libguac/audio.c b/src/libguac/audio.c index fb8bcd3c..84e4c334 100644 --- a/src/libguac/audio.c +++ b/src/libguac/audio.c @@ -104,9 +104,6 @@ guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encod audio->encoder = encoder; audio->stream = guac_client_alloc_stream(client); - /* Ensure socket within new stream is threadsafe */ - guac_socket_require_threadsafe(audio->stream->socket); - return audio; } @@ -138,9 +135,13 @@ void guac_audio_stream_end(guac_audio_stream* audio) { / audio->rate / audio->channels / audio->bps; /* Send audio */ - guac_protocol_send_audio(audio->stream->socket, - 0, audio->encoder->mimetype, - duration, audio->encoded_data, audio->encoded_data_used); + guac_protocol_send_audio(audio->client->socket, audio->stream, + audio->encoder->mimetype, duration); + + guac_protocol_send_blob(audio->client->socket, audio->stream, + audio->encoded_data, audio->encoded_data_used); + + guac_protocol_send_end(audio->client->socket, audio->stream); /* Clear data */ audio->encoded_data_used = 0; diff --git a/src/libguac/client.c b/src/libguac/client.c index 62b60885..effbfcd7 100644 --- a/src/libguac/client.c +++ b/src/libguac/client.c @@ -101,12 +101,6 @@ guac_stream* guac_client_alloc_stream(guac_client* client) { guac_stream* allocd_stream = malloc(sizeof(guac_stream)); allocd_stream->index = guac_pool_next_int(client->__stream_pool); - /* Nest socket */ - allocd_stream->socket = guac_socket_nest( - client->socket, - allocd_stream->index - ); - return allocd_stream; } @@ -116,9 +110,6 @@ void guac_client_free_stream(guac_client* client, guac_stream* stream) { /* Release index to pool */ guac_pool_free_int(client->__stream_pool, stream->index - 1); - /* Release socket */ - guac_socket_free(stream->socket); - /* Free stream */ free(stream); diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h index e6c7ad13..cad8e90c 100644 --- a/src/libguac/guacamole/protocol.h +++ b/src/libguac/guacamole/protocol.h @@ -42,6 +42,7 @@ #include "layer.h" #include "socket.h" +#include "stream.h" #include "timestamp.h" /** @@ -280,78 +281,13 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param channel The index of the audio channel the sound should play on. + * @param stream The stream to use. * @param mimetype The mimetype of the data being sent. * @param duration The duration of the sound being sent, in milliseconds. - * @param data The audio data to be sent. - * @param size The number of bytes of audio data to send. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_audio(guac_socket* socket, int channel, - const char* mimetype, double duration, void* data, int size); - -/** - * Begins a audio instruction over the given guac_socket connection. Only the - * initial non-data part of the instruction and the length of the data part - * of the instruction are sent. The actual contents of the data must be - * sent with guac_protocol_send_audio_data(), and the instruction must be - * completed with guac_protocol_send_audio_end(). - * - * Note that the size of the audio to be sent MUST be known ahead of time, - * even though the data of the audio may be sent in chunks. - * - * No further instruction data may be sent along the givven guac_socket - * except via guac_protocol_send_audio_data() until the audio instruction - * is completed with guac_protocol_send_audio_end(). - * - * Note that if you send this instruction over a threadsafe socket, you - * MUST also call guac_protocol_send_audio_end() or the socket will be - * left in an unsafe state. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param channel The index of the audio channel the sound should play on. - * @param mimetype The mimetype of the data being sent. - * @param duration The duration of the audio being sent, in milliseconds. - * @param size The number of bytes of audio data to send. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_audio_header(guac_socket* socket, - int channel, const char* mimetype, double duration, int size); - -/** - * Writes a block of audio data to the currently in-progress audio instruction - * which was started with guac_protocol_send_audio_header(). Exactly the - * number of requested bytes are written unless an error occurs. This function - * may be called multiple times per audio instruction for each chunk of audio - * data being written, allowing the potentially huge audio instruction to be - * split across multiple writes. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param data The audio data to write. - * @param count The number of bytes within the given buffer of audio data - * that must be written. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_audio_data(guac_socket* socket, void* data, int count); - -/** - * Completes the audio instruction which was started with - * guac_protocol_send_audio_header(), and whose data has been written with - * guac_protocol_send_audio_data(). - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_audio_end(guac_socket* socket); +int guac_protocol_send_audio(guac_socket* socket, const guac_stream* stream, + const char* mimetype, double duration); /** * Sends a file instruction over the given guac_socket connection. @@ -360,13 +296,13 @@ int guac_protocol_send_audio_end(guac_socket* socket); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param index The index of the blob that will contain the contents - * of this file. + * @param stream The stream to use. * @param mimetype The mimetype of the data being sent. * @param name A name describing the file being sent. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_file(guac_socket* socket, int index, const char* mimetype, const char* name); +int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream, + const char* mimetype, const char* name); /** * Writes a block of data to the currently in-progress blob which was already @@ -376,13 +312,14 @@ int guac_protocol_send_file(guac_socket* socket, int index, const char* mimetype * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param index The index of the blob to append data to. + * @param stream The stream to use. * @param data The file data to write. * @param count The number of bytes within the given buffer of file data * that must be written. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_blob(guac_socket* socket, int index, void* data, int count); +int guac_protocol_send_blob(guac_socket* socket, const guac_stream* stream, + void* data, int count); /** * Sends an end instruction over the given guac_socket connection. @@ -391,10 +328,10 @@ int guac_protocol_send_blob(guac_socket* socket, int index, void* data, int coun * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param index The index of the blob which is now complete. + * @param stream The stream to use. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_end(guac_socket* socket, int index); +int guac_protocol_send_end(guac_socket* socket, const guac_stream* stream); /** * Sends a video instruction over the given guac_socket connection. @@ -403,78 +340,14 @@ int guac_protocol_send_end(guac_socket* socket, int index); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. + * @param stream The stream to use. * @param layer The destination layer. * @param mimetype The mimetype of the data being sent. * @param duration The duration of the video being sent, in milliseconds. - * @param data The video data to be sent. - * @param size The number of bytes of video data to send. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, - const char* mimetype, double duration, void* data, int size); - -/** - * Begins a video instruction over the given guac_socket connection. Only the - * initial non-data part of the instruction and the length of the data part - * of the instruction are sent. The actual contents of the data must be - * sent with guac_protocol_send_video_data(), and the instruction must be - * completed with guac_protocol_send_video_end(). - * - * Note that the size of the video to be sent MUST be known ahead of time, - * even though the data of the video may be sent in chunks. - * - * No further instruction data may be sent along the givven guac_socket - * except via guac_protocol_send_video_data() until the video instruction - * is completed with guac_protocol_send_video_end(). - * - * Note that if you send this instruction over a threadsafe socket, you - * MUST also call guac_protocol_send_video_end() or the socket will be - * left in an unsafe state. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param mimetype The mimetype of the data being sent. - * @param duration The duration of the video being sent, in milliseconds. - * @param size The number of bytes of video data to send. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_video_header(guac_socket* socket, - const guac_layer* layer, const char* mimetype, double duration, int size); - -/** - * Writes a block of video data to the currently in-progress video instruction - * which was started with guac_protocol_send_video_header(). Exactly the - * number of requested bytes are written unless an error occurs. This function - * may be called multiple times per video instruction for each chunk of video - * data being written, allowing the potentially huge video instruction to be - * split across multiple writes. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param data The video data to write. - * @param count The number of bytes within the given buffer of video data - * that must be written. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_video_data(guac_socket* socket, void* data, int count); - -/** - * Completes the video instruction which was started with - * guac_protocol_send_video_header(), and whose data has been written with - * guac_protocol_send_video_data(). - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_video_end(guac_socket* socket); +int guac_protocol_send_video(guac_socket* socket, const guac_stream* stream, + const guac_layer* layer, const char* mimetype, double duration); /* DRAWING INSTRUCTIONS */ diff --git a/src/libguac/guacamole/stream.h b/src/libguac/guacamole/stream.h index fa0bb089..a5ecea30 100644 --- a/src/libguac/guacamole/stream.h +++ b/src/libguac/guacamole/stream.h @@ -39,8 +39,7 @@ #define _GUAC_STREAM_H /** - * Provides functions and structures required for allocating and using nested - * streams. + * Provides functions and structures required for allocating and using streams. * * @file stream.h */ @@ -48,20 +47,15 @@ typedef struct guac_stream guac_stream; /** - * Represents a single nested stream within the Guacamole protocol. + * Represents a single stream within the Guacamole protocol. */ struct guac_stream { /** - * The index of this layer. + * The index of this stream. */ int index; - /** - * A guac_socket which writes to this stream. - */ - guac_socket* socket; - }; #endif diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c index 4e2c4cfa..cba5980c 100644 --- a/src/libguac/protocol.c +++ b/src/libguac/protocol.c @@ -416,55 +416,28 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_audio(guac_socket* socket, int channel, - const char* mimetype, double duration, void* data, int size) { +int guac_protocol_send_audio(guac_socket* socket, const guac_stream* stream, + const char* mimetype, double duration) { - /* By the spec, guac_protocol_send_audio_end() must be called */ - return - (guac_protocol_send_audio_header(socket, channel, - mimetype, duration, size) - || guac_protocol_send_audio_data(socket, data, size)) - | guac_protocol_send_audio_end(socket); - -} - -int guac_protocol_send_audio_header(guac_socket* socket, - int channel, const char* mimetype, double duration, int size) { - - int base64_length = (size + 2) / 3 * 4; + int ret_val; guac_socket_instruction_begin(socket); - return + ret_val = guac_socket_write_string(socket, "5.audio,") - || __guac_socket_write_length_int(socket, channel) + || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, duration) - || guac_socket_write_string(socket, ",") - || guac_socket_write_int(socket, base64_length) - || guac_socket_write_string(socket, "."); - -} - -int guac_protocol_send_audio_data(guac_socket* socket, void* data, int count) { - - return guac_socket_write_base64(socket, data, count); - -} - -int guac_protocol_send_audio_end(guac_socket* socket) { - - int ret_val = - guac_socket_flush_base64(socket) || guac_socket_write_string(socket, ";"); - guac_socket_instruction_end(socket); + return ret_val; } -int guac_protocol_send_blob(guac_socket* socket, int index, void* data, int count) { +int guac_protocol_send_blob(guac_socket* socket, const guac_stream* stream, + void* data, int count) { int base64_length = (count + 2) / 3 * 4; @@ -473,7 +446,7 @@ int guac_protocol_send_blob(guac_socket* socket, int index, void* data, int coun guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.blob,") - || __guac_socket_write_length_int(socket, index) + || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) || guac_socket_write_string(socket, ".") @@ -777,14 +750,14 @@ int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_end(guac_socket* socket, int index) { +int guac_protocol_send_end(guac_socket* socket, const guac_stream* stream) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "3.end,") - || __guac_socket_write_length_int(socket, index) + || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ";"); guac_socket_instruction_end(socket); @@ -809,14 +782,15 @@ int guac_protocol_send_error(guac_socket* socket, const char* error) { } -int guac_protocol_send_file(guac_socket* socket, int index, const char* mimetype, const char* name) { +int guac_protocol_send_file(guac_socket* socket, const guac_stream* stream, + const char* mimetype, const char* name) { int ret_val; guac_socket_instruction_begin(socket); ret_val = guac_socket_write_string(socket, "4.file,") - || __guac_socket_write_length_int(socket, index) + || __guac_socket_write_length_int(socket, stream->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") @@ -1250,50 +1224,24 @@ int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, - const char* mimetype, double duration, void* data, int size) { +int guac_protocol_send_video(guac_socket* socket, const guac_stream* stream, + const guac_layer* layer, const char* mimetype, double duration) { - /* By the spec, guac_protocol_send_video_end() must be called */ - return - (guac_protocol_send_video_header(socket, layer, - mimetype, duration, size) - || guac_protocol_send_video_data(socket, data, size)) - | guac_protocol_send_video_end(socket); - -} - -int guac_protocol_send_video_header(guac_socket* socket, - const guac_layer* layer, const char* mimetype, double duration, int size) { - - int base64_length = (size + 2) / 3 * 4; + int ret_val; guac_socket_instruction_begin(socket); - return + ret_val = guac_socket_write_string(socket, "5.video,") + || __guac_socket_write_length_int(socket, stream->index) + || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, duration) - || guac_socket_write_string(socket, ",") - || guac_socket_write_int(socket, base64_length) - || guac_socket_write_string(socket, "."); - -} - -int guac_protocol_send_video_data(guac_socket* socket, void* data, int count) { - - return guac_socket_write_base64(socket, data, count); - -} - -int guac_protocol_send_video_end(guac_socket* socket) { - - int ret_val = - guac_socket_flush_base64(socket) || guac_socket_write_string(socket, ";"); - guac_socket_instruction_end(socket); + return ret_val; } diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index bcc6cd1f..cb0eee80 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -42,7 +42,6 @@ AM_CFLAGS = -Werror -Wall -Iinclude @LIBGUAC_INCLUDE@ lib_LTLIBRARIES = libguac-client-rdp.la libguac_client_rdp_la_SOURCES = \ - audio.c \ client.c \ default_pointer.c \ guac_handlers.c \ @@ -57,13 +56,11 @@ libguac_client_rdp_la_SOURCES = \ rdp_keymap_fr_fr.c \ rdp_keymap_en_us.c \ rdp_pointer.c \ - rdp_settings.c \ - wav_encoder.c + rdp_settings.c guacsnd_sources = \ guac_rdpsnd/rdpsnd_messages.c \ - guac_rdpsnd/rdpsnd_service.c \ - audio.c + guac_rdpsnd/rdpsnd_service.c guacdr_sources = \ guac_rdpdr/rdpdr_messages.c \ @@ -77,7 +74,6 @@ noinst_HEADERS = \ guac_rdpdr/rdpdr_service.h \ guac_rdpsnd/rdpsnd_messages.h \ guac_rdpsnd/rdpsnd_service.h \ - audio.h \ client.h \ config.h \ default_pointer.h \ @@ -88,8 +84,7 @@ noinst_HEADERS = \ rdp_glyph.h \ rdp_keymap.h \ rdp_pointer.h \ - rdp_settings.h \ - wav_encoder.h + rdp_settings.h # Add compatibility layer for WinPR if not available if ! ENABLE_WINPR @@ -98,14 +93,8 @@ if ! ENABLE_WINPR guacdr_sources += compat/winpr-stream.c endif -# Compile OGG support if available -if ENABLE_OGG - libguac_client_rdp_la_SOURCES += ogg_encoder.c - noinst_HEADERS += ogg_encoder.h -endif - -libguac_client_rdp_la_LDFLAGS = -version-info 0:0:0 @RDP_LIBS@ @VORBIS_LIBS@ @PTHREAD_LIBS@ @CAIRO_LIBS@ -guacsnd_ldflags = -module -avoid-version -shared @RDP_LIBS@ @VORBIS_LIBS@ @PTHREAD_LIBS@ +libguac_client_rdp_la_LDFLAGS = -version-info 0:0:0 @RDP_LIBS@ @PTHREAD_LIBS@ @CAIRO_LIBS@ +guacsnd_ldflags = -module -avoid-version -shared @RDP_LIBS@ @PTHREAD_LIBS@ guacdr_ldflags = -module -avoid-version -shared @RDP_LIBS@ @PTHREAD_LIBS@ libguac_client_rdp_la_LIBADD = @LIBGUAC_LTLIB@ diff --git a/src/protocols/rdp/audio.c b/src/protocols/rdp/audio.c deleted file mode 100644 index 5eb8a1fb..00000000 --- a/src/protocols/rdp/audio.c +++ /dev/null @@ -1,176 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include -#include -#include -#include -#include -#include - -#include "audio.h" -#include "client.h" - -audio_stream* audio_stream_alloc(guac_client* client, audio_encoder* encoder) { - - /* Allocate stream */ - audio_stream* audio = (audio_stream*) malloc(sizeof(audio_stream)); - audio->client = client; - - /* Reset buffer stats */ - audio->used = 0; - audio->length = 0x40000; - - audio->encoded_data_used = 0; - audio->encoded_data_length = 0x40000; - - /* Allocate buffers */ - audio->pcm_data = malloc(audio->length); - audio->encoded_data = malloc(audio->encoded_data_length); - - /* Assign encoder */ - audio->encoder = encoder; - audio->stream = guac_client_alloc_stream(client); - - /* Ensure socket within new stream is threadsafe */ - guac_socket_require_threadsafe(audio->stream->socket); - - return audio; -} - -void audio_stream_begin(audio_stream* audio, int rate, int channels, int bps) { - - /* Load PCM properties */ - audio->rate = rate; - audio->channels = channels; - audio->bps = bps; - - /* Reset write counter */ - audio->pcm_bytes_written = 0; - - /* Call handler */ - audio->encoder->begin_handler(audio); - -} - -void audio_stream_end(audio_stream* audio) { - - double duration; - - /* Flush stream and finish encoding */ - audio_stream_flush(audio); - audio->encoder->end_handler(audio); - - /* Calculate duration of PCM data */ - duration = ((double) (audio->pcm_bytes_written * 1000 * 8)) - / audio->rate / audio->channels / audio->bps; - - /* Send audio */ - guac_protocol_send_audio(audio->stream->socket, - 0, audio->encoder->mimetype, - duration, audio->encoded_data, audio->encoded_data_used); - - /* Clear data */ - audio->encoded_data_used = 0; - -} - -void audio_stream_free(audio_stream* audio) { - free(audio->pcm_data); - free(audio); -} - -void audio_stream_write_pcm(audio_stream* audio, - unsigned char* data, int length) { - - /* Update counter */ - audio->pcm_bytes_written += length; - - /* Resize audio buffer if necessary */ - if (length > audio->length) { - - /* Resize to double provided length */ - audio->length = length*2; - audio->pcm_data = realloc(audio->pcm_data, audio->length); - - } - - /* Flush if necessary */ - if (audio->used + length > audio->length) - audio_stream_flush(audio); - - /* Append to buffer */ - memcpy(&(audio->pcm_data[audio->used]), data, length); - audio->used += length; - -} - -void audio_stream_flush(audio_stream* audio) { - - /* If data in buffer */ - if (audio->used != 0) { - - /* Write data */ - audio->encoder->write_handler(audio, - audio->pcm_data, audio->used); - - /* Reset buffer */ - audio->used = 0; - - } - -} - -void audio_stream_write_encoded(audio_stream* audio, - unsigned char* data, int length) { - - /* Resize audio buffer if necessary */ - if (audio->encoded_data_used + length > audio->encoded_data_length) { - - /* Increase to double concatenated size to accomodate */ - audio->encoded_data_length = (audio->encoded_data_length + length)*2; - audio->encoded_data = realloc(audio->encoded_data, - audio->encoded_data_length); - - } - - /* Append to buffer */ - memcpy(&(audio->encoded_data[audio->encoded_data_used]), data, length); - audio->encoded_data_used += length; - -} - diff --git a/src/protocols/rdp/audio.h b/src/protocols/rdp/audio.h deleted file mode 100644 index 441856df..00000000 --- a/src/protocols/rdp/audio.h +++ /dev/null @@ -1,212 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __GUAC_TEST_AUDIO_H -#define __GUAC_TEST_AUDIO_H - -#include -#include - -typedef struct audio_stream audio_stream; - -/** - * Handler which is called when the audio stream is opened. - */ -typedef void audio_encoder_begin_handler(audio_stream* audio); - -/** - * Handler which is called when the audio stream is closed. - */ -typedef void audio_encoder_end_handler(audio_stream* audio); - -/** - * Handler which is called when the audio stream is flushed. - */ -typedef void audio_encoder_write_handler(audio_stream* audio, - unsigned char* pcm_data, int length); - -/** - * Arbitrary audio codec encoder. - */ -typedef struct audio_encoder { - - /** - * The mimetype of the audio data encoded by this audio - * encoder. - */ - const char* mimetype; - - /** - * Handler which will be called when the audio stream is opened. - */ - audio_encoder_begin_handler* begin_handler; - - /** - * Handler which will be called when the audio stream is flushed. - */ - audio_encoder_write_handler* write_handler; - - /** - * Handler which will be called when the audio stream is closed. - */ - audio_encoder_end_handler* end_handler; - -} 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 { - - /** - * PCM data buffer, 16-bit samples, 2-channel, 44100 Hz. - */ - unsigned char* pcm_data; - - /** - * Number of bytes in buffer. - */ - int used; - - /** - * Maximum number of bytes in buffer. - */ - int length; - - /** - * Encoded audio data buffer, as written by the encoder. - */ - unsigned char* encoded_data; - - /** - * Number of bytes in the encoded data buffer. - */ - int encoded_data_used; - - /** - * Maximum number of bytes in the encoded data buffer. - */ - int encoded_data_length; - - /** - * Arbitrary codec encoder. When the PCM buffer is flushed, PCM data will - * be sent to this encoder. - */ - audio_encoder* encoder; - - /** - * The client associated with this audio stream. - */ - guac_client* client; - - /** - * The actual stream associated with this audio stream. - */ - guac_stream* stream; - - /** - * The number of samples per second of PCM data sent to this stream. - */ - int rate; - - /** - * The number of audio channels per sample of PCM data. Legal values are - * 1 or 2. - */ - int channels; - - /** - * The number of bits per sample per channel for PCM data. Legal values are - * 8 or 16. - */ - int bps; - - /** - * The number of PCM bytes written since the audio chunk began. - */ - int pcm_bytes_written; - - /** - * Encoder-specific state data. - */ - void* data; - -}; - -/** - * Allocates a new audio stream. - */ -audio_stream* audio_stream_alloc(guac_client* client, - audio_encoder* encoder); - -/** - * Frees the given audio stream. - */ -void audio_stream_free(audio_stream* stream); - -/** - * Begins a new audio stream. - */ -void audio_stream_begin(audio_stream* stream, int rate, int channels, int bps); - -/** - * Ends the current audio stream. - */ -void audio_stream_end(audio_stream* stream); - -/** - * Writes PCM data to the given audio stream. - */ -void audio_stream_write_pcm(audio_stream* stream, - unsigned char* data, int length); - -/** - * Flushes the given audio stream. - */ -void audio_stream_flush(audio_stream* stream); - -/** - * Appends arbitrarily-encoded data to the encoded_data buffer - * within the given audio stream. - */ -void audio_stream_write_encoded(audio_stream* audio, - unsigned char* data, int length); - -#endif - diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 93bc6e21..b22eeab2 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -75,15 +75,9 @@ #include #include #include +#include #include -#include "audio.h" -#include "wav_encoder.h" - -#ifdef ENABLE_OGG -#include "ogg_encoder.h" -#endif - #include "client.h" #include "guac_handlers.h" #include "rdp_keymap.h" @@ -151,7 +145,6 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { rdpPointer* pointer; rdpPrimaryUpdate* primary; CLRCONV* clrconv; - int i; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; @@ -169,30 +162,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { /* If audio enabled, choose an encoder */ if (guac_client_data->settings.audio_enabled) { - /* Choose an encoding */ - for (i=0; client->info.audio_mimetypes[i] != NULL; i++) { - - const char* mimetype = client->info.audio_mimetypes[i]; - -#ifdef ENABLE_OGG - /* If Ogg is supported, done. */ - if (strcmp(mimetype, ogg_encoder->mimetype) == 0) { - guac_client_log_info(client, "Loading Ogg Vorbis encoder."); - guac_client_data->audio = audio_stream_alloc(client, - ogg_encoder); - break; - } -#endif - - /* If wav is supported, done. */ - if (strcmp(mimetype, wav_encoder->mimetype) == 0) { - guac_client_log_info(client, "Loading wav encoder."); - guac_client_data->audio = audio_stream_alloc(client, - wav_encoder); - break; - } - - } + guac_client_data->audio = guac_audio_stream_alloc(client, NULL); /* If an encoding is available, load the sound plugin */ if (guac_client_data->audio != NULL) { diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 41b887dc..5950b539 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -46,8 +46,8 @@ #include #include +#include -#include "audio.h" #include "rdp_keymap.h" #include "rdp_settings.h" @@ -166,7 +166,7 @@ typedef struct rdp_guac_client_data { /** * Audio output, if any. */ - audio_stream* audio; + guac_audio_stream* audio; /** * Lock which is locked and unlocked for each RDP message. diff --git a/src/protocols/rdp/guac_handlers.c b/src/protocols/rdp/guac_handlers.c index 258d2ead..50420d04 100644 --- a/src/protocols/rdp/guac_handlers.c +++ b/src/protocols/rdp/guac_handlers.c @@ -247,10 +247,6 @@ int rdp_guac_client_handle_messages(guac_client* client) { return 1; } - /* Flush any audio */ - if (guac_client_data->audio != NULL) - guac_socket_flush(guac_client_data->audio->stream->socket); - pthread_mutex_unlock(&(guac_client_data->rdp_lock)); /* Calculate time remaining in frame */ diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c index 72b9fdb0..f20ccbe7 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.c @@ -49,9 +49,9 @@ #include "compat/winpr-wtypes.h" #endif +#include #include -#include "audio.h" #include "rdpsnd_service.h" #include "rdpsnd_messages.h" #include "client.h" @@ -59,7 +59,7 @@ /* MESSAGE HANDLERS */ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int server_format_count; @@ -209,7 +209,7 @@ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, /* server is getting a feel of the round trip time */ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int data_size; @@ -237,7 +237,7 @@ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, } void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header) { unsigned char buffer[4]; @@ -261,18 +261,18 @@ void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, rdpsnd->next_pdu_is_wave = TRUE; /* Init stream with requested format */ - audio_stream_begin(audio, + guac_audio_stream_begin(audio, rdpsnd->formats[format].rate, rdpsnd->formats[format].channels, rdpsnd->formats[format].bps); /* Write initial 4 bytes of data */ - audio_stream_write_pcm(audio, buffer, 4); + guac_audio_stream_write_pcm(audio, buffer, 4); } void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header) { rdpSvcPlugin* plugin = (rdpSvcPlugin*)rdpsnd; @@ -287,8 +287,8 @@ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, unsigned char* buffer = Stream_Buffer(input_stream) + 4; /* Write rest of audio packet */ - audio_stream_write_pcm(audio, buffer, rdpsnd->incoming_wave_size); - audio_stream_end(audio); + guac_audio_stream_write_pcm(audio, buffer, rdpsnd->incoming_wave_size); + guac_audio_stream_end(audio); /* Write Wave Confirmation PDU */ Stream_Write_UINT8(output_stream, SNDC_WAVECONFIRM); @@ -309,7 +309,7 @@ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, } void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header) { /* STUB: Do nothing for now */ diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h index 55832a39..6d7277e1 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_messages.h @@ -38,6 +38,8 @@ #ifndef __GUAC_RDPSND_MESSAGES_H #define __GUAC_RDPSND_MESSAGES_H +#include + /* * PDU Message Types */ @@ -127,35 +129,35 @@ typedef struct guac_rdpsnd_pdu_header { * Handler for the SNDC_FORMATS (Server Audio Formats and Version) PDU. */ void guac_rdpsnd_formats_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_TRAINING (Training) PDU. */ void guac_rdpsnd_training_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_WAVE (WaveInfo) PDU. */ void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDWAV (Wave) PDU which follows any WaveInfo PDU. */ void guac_rdpsnd_wave_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header); /** * Handler for the SNDC_CLOSE (Close) PDU. */ void guac_rdpsnd_close_handler(guac_rdpsndPlugin* rdpsnd, - audio_stream* audio, wStream* input_stream, + guac_audio_stream* audio, wStream* input_stream, guac_rdpsnd_pdu_header* header); #endif diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c index 3d4b8084..e5e30c36 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.c @@ -51,8 +51,8 @@ #endif #include +#include -#include "audio.h" #include "rdpsnd_service.h" #include "rdpsnd_messages.h" @@ -91,10 +91,10 @@ void guac_rdpsnd_process_connect(rdpSvcPlugin* plugin) { guac_rdpsndPlugin* rdpsnd = (guac_rdpsndPlugin*) plugin; /* Get audio stream from plugin parameters */ - audio_stream* audio = rdpsnd->audio = - (audio_stream*) plugin->channel_entry_points.pExtendedData; + guac_audio_stream* audio = rdpsnd->audio = + (guac_audio_stream*) plugin->channel_entry_points.pExtendedData; - /* NULL out pExtendedData so we don't lose our audio_stream due to an + /* NULL out pExtendedData so we don't lose our guac_audio_stream due to an * automatic free() within libfreerdp */ plugin->channel_entry_points.pExtendedData = NULL; @@ -123,7 +123,7 @@ void guac_rdpsnd_process_receive(rdpSvcPlugin* plugin, guac_rdpsnd_pdu_header header; /* Get audio stream from plugin */ - audio_stream* audio = rdpsnd->audio; + guac_audio_stream* audio = rdpsnd->audio; /* Read RDPSND PDU header */ Stream_Read_UINT8(input_stream, header.message_type); diff --git a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h index 263e8eaf..52e871b2 100644 --- a/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h +++ b/src/protocols/rdp/guac_rdpsnd/rdpsnd_service.h @@ -38,6 +38,8 @@ #ifndef __GUAC_RDPSND_SERVICE_H #define __GUAC_RDPSND_SERVICE_H +#include + /** * The maximum number of PCM formats to accept during the initial RDPSND * handshake with the RDP server. @@ -87,7 +89,7 @@ typedef struct guac_rdpsndPlugin { /** * The current audio stream. */ - audio_stream* audio; + guac_audio_stream* audio; /** * The block number of the last SNDC_WAVE (WaveInfo) PDU received. diff --git a/src/protocols/rdp/ogg_encoder.c b/src/protocols/rdp/ogg_encoder.c deleted file mode 100644 index 8c6f97d2..00000000 --- a/src/protocols/rdp/ogg_encoder.c +++ /dev/null @@ -1,211 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include - -#include -#include - -#include - -#include "audio.h" -#include "ogg_encoder.h" - -void ogg_encoder_begin_handler(audio_stream* audio) { - - /* Allocate stream state */ - ogg_encoder_state* state = (ogg_encoder_state*) - malloc(sizeof(ogg_encoder_state)); - - /* Init state */ - vorbis_info_init(&(state->info)); - vorbis_encode_init_vbr(&(state->info), audio->channels, audio->rate, 0.4); - - vorbis_analysis_init(&(state->vorbis_state), &(state->info)); - vorbis_block_init(&(state->vorbis_state), &(state->vorbis_block)); - - vorbis_comment_init(&(state->comment)); - vorbis_comment_add_tag(&(state->comment), "ENCODER", "libguac-client-rdp"); - - ogg_stream_init(&(state->ogg_state), rand()); - - /* Write headers */ - { - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; - - vorbis_analysis_headerout( - &(state->vorbis_state), - &(state->comment), - &header, &header_comm, &header_code); - - ogg_stream_packetin(&(state->ogg_state), &header); - ogg_stream_packetin(&(state->ogg_state), &header_comm); - ogg_stream_packetin(&(state->ogg_state), &header_code); - - /* For each packet */ - while (ogg_stream_flush(&(state->ogg_state), &(state->ogg_page)) != 0) { - - /* Write packet header */ - audio_stream_write_encoded(audio, - state->ogg_page.header, - state->ogg_page.header_len); - - /* Write packet body */ - audio_stream_write_encoded(audio, - state->ogg_page.body, - state->ogg_page.body_len); - } - - } - - audio->data = state; - -} - -void ogg_encoder_write_blocks(audio_stream* audio) { - - /* Get state */ - ogg_encoder_state* state = (ogg_encoder_state*) audio->data; - - while (vorbis_analysis_blockout(&(state->vorbis_state), - &(state->vorbis_block)) == 1) { - - /* Analyze */ - vorbis_analysis(&(state->vorbis_block), NULL); - vorbis_bitrate_addblock(&(state->vorbis_block)); - - /* Flush Ogg pages */ - while (vorbis_bitrate_flushpacket(&(state->vorbis_state), - &(state->ogg_packet))) { - - /* Weld packet into bitstream */ - ogg_stream_packetin(&(state->ogg_state), &(state->ogg_packet)); - - /* Write out pages */ - while (ogg_stream_pageout(&(state->ogg_state), - &(state->ogg_page)) != 0) { - - /* Write packet header */ - audio_stream_write_encoded(audio, - state->ogg_page.header, - state->ogg_page.header_len); - - /* Write packet body */ - audio_stream_write_encoded(audio, - state->ogg_page.body, - state->ogg_page.body_len); - - if (ogg_page_eos(&(state->ogg_page))) - break; - - } - - } - - } - -} - -void ogg_encoder_end_handler(audio_stream* audio) { - - /* Get state */ - ogg_encoder_state* state = (ogg_encoder_state*) audio->data; - - /* Write end-of-stream */ - vorbis_analysis_wrote(&(state->vorbis_state), 0); - ogg_encoder_write_blocks(audio); - - /* Clean up encoder */ - ogg_stream_clear(&(state->ogg_state)); - vorbis_block_clear(&(state->vorbis_block)); - vorbis_dsp_clear(&(state->vorbis_state)); - vorbis_comment_clear(&(state->comment)); - vorbis_info_clear(&(state->info)); - - /* Free stream state */ - free(audio->data); - -} - -void ogg_encoder_write_handler(audio_stream* audio, - unsigned char* pcm_data, int length) { - - /* Get state */ - ogg_encoder_state* state = (ogg_encoder_state*) audio->data; - - /* Calculate samples */ - int samples = length / audio->channels * 8 / audio->bps; - int i; - - /* Get buffer */ - float** buffer = vorbis_analysis_buffer(&(state->vorbis_state), samples); - - signed char* readbuffer = (signed char*) pcm_data; - - for (i=0; ivorbis_state), samples); - - /* Write data */ - ogg_encoder_write_blocks(audio); - -} - -/* Encoder handlers */ -audio_encoder _ogg_encoder = { - .mimetype = "audio/ogg", - .begin_handler = ogg_encoder_begin_handler, - .write_handler = ogg_encoder_write_handler, - .end_handler = ogg_encoder_end_handler -}; - -/* Actual encoder */ -audio_encoder* ogg_encoder = &_ogg_encoder; - diff --git a/src/protocols/rdp/ogg_encoder.h b/src/protocols/rdp/ogg_encoder.h deleted file mode 100644 index 78bfa6e5..00000000 --- a/src/protocols/rdp/ogg_encoder.h +++ /dev/null @@ -1,67 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __GUAC_OGG_ENCODER_H -#define __GUAC_OGG_ENCODER_H - -#include "audio.h" - -#include - -typedef struct ogg_encoder_state { - - /** - * Ogg state - */ - ogg_stream_state ogg_state; - ogg_page ogg_page; - ogg_packet ogg_packet; - - /** - * Vorbis state - */ - vorbis_info info; - vorbis_comment comment; - vorbis_dsp_state vorbis_state; - vorbis_block vorbis_block; - -} ogg_encoder_state; - -extern audio_encoder* ogg_encoder; - -#endif - diff --git a/src/protocols/rdp/wav_encoder.c b/src/protocols/rdp/wav_encoder.c deleted file mode 100644 index 0a306675..00000000 --- a/src/protocols/rdp/wav_encoder.c +++ /dev/null @@ -1,201 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#define WAV_BUFFER_SIZE 0x4000 - -#include -#include - -#include -#include - -#include "audio.h" -#include "wav_encoder.h" - -void wav_encoder_begin_handler(audio_stream* audio) { - - /* Allocate stream state */ - wav_encoder_state* state = (wav_encoder_state*) - malloc(sizeof(wav_encoder_state)); - - /* Initialize buffer */ - state->length = WAV_BUFFER_SIZE; - state->used = 0; - state->data_buffer = (unsigned char*) malloc(state->length); - - audio->data = state; - -} - -void _wav_encoder_write_le(unsigned char* buffer, int value, int length) { - - int offset; - - /* Write all bytes in the given value in little-endian byte order */ - for (offset=0; offset>= 8; - buffer++; - - } - -} - -void wav_encoder_end_handler(audio_stream* audio) { - - /* - * Static header init - */ - - wav_encoder_riff_header riff_header = { - .chunk_id = "RIFF", - .chunk_format = "WAVE" - }; - - wav_encoder_fmt_header fmt_header = { - .subchunk_id = "fmt ", - .subchunk_size = {0x10, 0x00, 0x00, 0x00}, /* 16 */ - .subchunk_format = {0x01, 0x00} /* 1 = PCM */ - }; - - wav_encoder_data_header data_header = { - .subchunk_id = "data" - }; - - /* Get state */ - wav_encoder_state* state = (wav_encoder_state*) audio->data; - - /* - * RIFF HEADER - */ - - /* Chunk size */ - _wav_encoder_write_le(riff_header.chunk_size, - 4 + sizeof(fmt_header) + sizeof(data_header) + state->used, - sizeof(riff_header.chunk_size)); - - audio_stream_write_encoded(audio, - (unsigned char*) &riff_header, - sizeof(riff_header)); - - /* - * FMT HEADER - */ - - /* Channels */ - _wav_encoder_write_le(fmt_header.subchunk_channels, - audio->channels, sizeof(fmt_header.subchunk_channels)); - - /* Sample rate */ - _wav_encoder_write_le(fmt_header.subchunk_sample_rate, - audio->rate, sizeof(fmt_header.subchunk_sample_rate)); - - /* Byte rate */ - _wav_encoder_write_le(fmt_header.subchunk_byte_rate, - audio->rate * audio->channels * audio->bps / 8, - sizeof(fmt_header.subchunk_byte_rate)); - - /* Block align */ - _wav_encoder_write_le(fmt_header.subchunk_block_align, - audio->channels * audio->bps / 8, - sizeof(fmt_header.subchunk_block_align)); - - /* Bits per second */ - _wav_encoder_write_le(fmt_header.subchunk_bps, - audio->bps, sizeof(fmt_header.subchunk_bps)); - - audio_stream_write_encoded(audio, - (unsigned char*) &fmt_header, - sizeof(fmt_header)); - - /* - * DATA HEADER - */ - - /* PCM data size */ - _wav_encoder_write_le(data_header.subchunk_size, - state->used, sizeof(data_header.subchunk_size)); - - 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); - - /* Free stream state */ - free(state); - -} - -void wav_encoder_write_handler(audio_stream* audio, - unsigned char* pcm_data, int length) { - - /* Get state */ - wav_encoder_state* state = (wav_encoder_state*) audio->data; - - /* Increase size of buffer if necessary */ - if (state->used + length > state->length) { - - /* Increase to double concatenated size to accomodate */ - state->length = (state->length + length)*2; - state->data_buffer = realloc(state->data_buffer, - state->length); - - } - - /* Append to buffer */ - memcpy(&(state->data_buffer[state->used]), pcm_data, length); - state->used += length; - -} - -/* Encoder handlers */ -audio_encoder _wav_encoder = { - .mimetype = "audio/wav", - .begin_handler = wav_encoder_begin_handler, - .write_handler = wav_encoder_write_handler, - .end_handler = wav_encoder_end_handler -}; - -/* Actual encoder */ -audio_encoder* wav_encoder = &_wav_encoder; - diff --git a/src/protocols/rdp/wav_encoder.h b/src/protocols/rdp/wav_encoder.h deleted file mode 100644 index ce575ae9..00000000 --- a/src/protocols/rdp/wav_encoder.h +++ /dev/null @@ -1,144 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac-client-rdp. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __GUAC_WAV_ENCODER_H -#define __GUAC_WAV_ENCODER_H - -#include "audio.h" - -typedef struct wav_encoder_riff_header { - - /** - * The RIFF chunk header, normally the string "RIFF". - */ - unsigned char chunk_id[4]; - - /** - * Size of the entire file, not including chunk_id or chunk_size. - */ - unsigned char chunk_size[4]; - - /** - * The format of this file, normally the string "WAVE". - */ - unsigned char chunk_format[4]; - -} wav_encoder_riff_header; - -typedef struct wav_encoder_fmt_header { - - /** - * ID of this subchunk. For the fmt subchunk, this should be "fmt ". - */ - unsigned char subchunk_id[4]; - - /** - * The size of the rest of this subchunk. For PCM, this will be 16. - */ - unsigned char subchunk_size[4]; - - /** - * Format of this subchunk. For PCM, this will be 1. - */ - unsigned char subchunk_format[2]; - - /** - * The number of channels in the PCM data. - */ - unsigned char subchunk_channels[2]; - - /** - * The sample rate of the PCM data. - */ - unsigned char subchunk_sample_rate[4]; - - /** - * The sample rate of the PCM data in bytes per second. - */ - unsigned char subchunk_byte_rate[4]; - - /** - * The number of bytes per sample. - */ - unsigned char subchunk_block_align[2]; - - /** - * The number of bits per sample. - */ - unsigned char subchunk_bps[2]; - -} wav_encoder_fmt_header; - -typedef struct wav_encoder_state { - - /** - * Arbitrary PCM data available for writing when the overall WAV is - * flushed. - */ - unsigned char* data_buffer; - - /** - * The number of bytes currently present in the data buffer. - */ - int used; - - /** - * The total number of bytes that can be written into the data buffer - * without requiring resizing. - */ - int length; - -} wav_encoder_state; - -typedef struct wav_encoder_data_header { - - /** - * ID of this subchunk. For the data subchunk, this should be "data". - */ - unsigned char subchunk_id[4]; - - /** - * The number of bytes in the PCM data. - */ - unsigned char subchunk_size[4]; - -} wav_encoder_data_header; - -extern audio_encoder* wav_encoder; - -#endif -