diff --git a/src/guacenc/Makefile.am b/src/guacenc/Makefile.am index 39b31e0e..7a6ec48f 100644 --- a/src/guacenc/Makefile.am +++ b/src/guacenc/Makefile.am @@ -51,6 +51,7 @@ guacenc_SOURCES = \ instruction-size.c \ instruction-sync.c \ instruction-transfer.c \ + layer.c \ log.c guacenc_CFLAGS = \ diff --git a/src/guacenc/display.c b/src/guacenc/display.c index 9e18bd01..8a17eadf 100644 --- a/src/guacenc/display.c +++ b/src/guacenc/display.c @@ -46,12 +46,80 @@ int guacenc_display_sync(guacenc_display* display, guac_timestamp timestamp) { } +guacenc_layer* guacenc_display_get_layer(guacenc_display* display, + int index) { + + /* Do not lookup / allocate if index is invalid */ + if (index < 0 || index > GUACENC_DISPLAY_MAX_LAYERS) { + guacenc_log(GUAC_LOG_DEBUG, "Layer index out of bounds: %i", index); + return NULL; + } + + /* Lookup layer, allocating a new layer if necessary */ + guacenc_layer* layer = display->layers[index]; + if (layer == NULL) { + + /* Attempt to allocate layer */ + layer = guacenc_layer_alloc(); + if (layer == NULL) { + guacenc_log(GUAC_LOG_DEBUG, "Layer allocation failed"); + return NULL; + } + + /* Store layer within display for future retrieval / management */ + display->layers[index] = layer; + + } + + return layer; + +} + +int guacenc_display_free_layer(guacenc_display* display, + int index) { + + /* Do not lookup / allocate if index is invalid */ + if (index < 0 || index > GUACENC_DISPLAY_MAX_LAYERS) { + guacenc_log(GUAC_LOG_DEBUG, "Layer index out of bounds: %i", index); + return 1; + } + + /* Free layer (if allocated) */ + guacenc_layer_free(display->layers[index]); + + /* Mark layer as freed */ + display->layers[index] = NULL; + + return 0; + +} + guacenc_display* guacenc_display_alloc() { return (guacenc_display*) calloc(1, sizeof(guacenc_display)); } int guacenc_display_free(guacenc_display* display) { + + int i; + + /* Ignore NULL display */ + if (display == NULL) + return 0; + + /* Free all buffers */ + for (i = 0; i < GUACENC_DISPLAY_MAX_BUFFERS; i++) + free(display->buffers[i]); + + /* Free all layers */ + for (i = 0; i < GUACENC_DISPLAY_MAX_LAYERS; i++) + guacenc_layer_free(display->layers[i]); + + /* Free all streams */ + for (i = 0; i < GUACENC_DISPLAY_MAX_STREAMS; i++) + free(display->image_streams[i]); + free(display); return 0; + } diff --git a/src/guacenc/display.h b/src/guacenc/display.h index e4638db0..b5fb1ca4 100644 --- a/src/guacenc/display.h +++ b/src/guacenc/display.h @@ -114,15 +114,45 @@ guacenc_display* guacenc_display_alloc(); /** * Frees all memory associated with the given Guacamole video encoder display, - * and finishes any underlying encoding process. + * and finishes any underlying encoding process. If the given display is NULL, + * this function has no effect. * * @param display - * The Guacamole video encoder display to free. + * The Guacamole video encoder display to free, which may be NULL. * * @return * Zero if the encoding process completed successfully, non-zero otherwise. */ int guacenc_display_free(guacenc_display* display); +/** + * Returns the layer having the given index. A new layer will be allocated if + * necessary. If the layer having the given index already exists, it will be + * returned. + * + * @param index + * The index of the layer to retrieve. + * + * @return + * The layer having the given index, or NULL if the index is invalid or + * a new layer cannot be allocated. + */ +guacenc_layer* guacenc_display_get_layer(guacenc_display* display, + int index); + +/** + * Frees all resources associated with the layer having the given index. If + * the layer has not been allocated, this function has no effect. + * + * @param index + * The index of the layer to free. + * + * @return + * Zero if the layer was successfully freed or was not allocated, non-zero + * if the layer could not be freed as the index was invalid. + */ +int guacenc_display_free_layer(guacenc_display* display, + int index); + #endif diff --git a/src/guacenc/instruction-dispose.c b/src/guacenc/instruction-dispose.c index 8d8333f3..fef6f363 100644 --- a/src/guacenc/instruction-dispose.c +++ b/src/guacenc/instruction-dispose.c @@ -39,9 +39,8 @@ int guacenc_handle_dispose(guacenc_display* display, int argc, char** argv) { /* Parse arguments */ int index = atoi(argv[0]); - /* STUB */ - guacenc_log(GUAC_LOG_DEBUG, "dispose: layer=%i", index); - return 0; + /* Dispose of layer */ + return guacenc_display_free_layer(display, index); } diff --git a/src/guacenc/instruction-move.c b/src/guacenc/instruction-move.c index 88e5d606..f929ee83 100644 --- a/src/guacenc/instruction-move.c +++ b/src/guacenc/instruction-move.c @@ -43,9 +43,21 @@ int guacenc_handle_move(guacenc_display* display, int argc, char** argv) { int y = atoi(argv[3]); int z = atoi(argv[4]); - /* STUB */ - guacenc_log(GUAC_LOG_DEBUG, "move: layer=%i parent=%i (%i, %i) z=%i", - layer_index, parent_index, x, y, z); + /* Retrieve requested layer */ + guacenc_layer* layer = guacenc_display_get_layer(display, layer_index); + if (layer == NULL) + return 1; + + /* Validate parent layer */ + if (guacenc_display_get_layer(display, parent_index) == NULL) + return 1; + + /* Update layer properties */ + layer->parent_index = parent_index; + layer->x = x; + layer->y = y; + layer->z = z; + return 0; } diff --git a/src/guacenc/instruction-shade.c b/src/guacenc/instruction-shade.c index 466568c9..414eafbc 100644 --- a/src/guacenc/instruction-shade.c +++ b/src/guacenc/instruction-shade.c @@ -40,8 +40,14 @@ int guacenc_handle_shade(guacenc_display* display, int argc, char** argv) { int index = atoi(argv[0]); int opacity = atoi(argv[1]); - /* STUB */ - guacenc_log(GUAC_LOG_DEBUG, "shade: layer=%i opacity=0x%X", index, opacity); + /* Retrieve requested layer */ + guacenc_layer* layer = guacenc_display_get_layer(display, index); + if (layer == NULL) + return 1; + + /* Update layer properties */ + layer->opacity = opacity; + return 0; } diff --git a/src/guacenc/layer.c b/src/guacenc/layer.c new file mode 100644 index 00000000..1265622b --- /dev/null +++ b/src/guacenc/layer.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Glyptodon, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config.h" +#include "layer.h" + +#include + +guacenc_layer* guacenc_layer_alloc() { + + /* Allocate new layer */ + guacenc_layer* layer = (guacenc_layer*) calloc(1, sizeof(guacenc_layer)); + if (layer == NULL) + return NULL; + + /* Layers default to fully opaque */ + layer->opacity = 0xFF; + + return layer; + +} + +void guacenc_layer_free(guacenc_layer* layer) { + free(layer); +} + diff --git a/src/guacenc/layer.h b/src/guacenc/layer.h index 739d2aa1..50f47040 100644 --- a/src/guacenc/layer.h +++ b/src/guacenc/layer.h @@ -41,7 +41,7 @@ typedef struct guacenc_layer { * The actual image contents of this layer, as well as this layer's size * (width and height). */ - guacenc_buffer buffer; + guacenc_buffer* buffer; /** * The index of the layer that contains this layer. If this layer is the @@ -76,5 +76,25 @@ typedef struct guacenc_layer { } guacenc_layer; +/** + * Allocates and initializes a new layer object. This allocation is independent + * of the Guacamole video encoder display; the allocated guacenc_layer will not + * automatically be associated with the active display. + * + * @return + * A newly-allocated and initialized guacenc_layer, or NULL if allocation + * fails. + */ +guacenc_layer* guacenc_layer_alloc(); + +/** + * Frees all memory associated with the given layer object. If the layer + * provided is NULL, this function has no effect. + * + * @param layer + * The layer to free, which may be NULL. + */ +void guacenc_layer_free(guacenc_layer* layer); + #endif