diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | layer.cpp | 19 | ||||
-rw-r--r-- | layer.h | 61 | ||||
-rw-r--r-- | layer_box.cpp | 16 | ||||
-rw-r--r-- | layer_box.h | 35 | ||||
-rw-r--r-- | layer_image.cpp | 21 | ||||
-rw-r--r-- | layer_image.h | 30 | ||||
-rw-r--r-- | layer_video.cpp | 12 | ||||
-rw-r--r-- | layer_video.h | 41 | ||||
-rw-r--r-- | main.cpp | 419 | ||||
-rw-r--r-- | osc_graphics.h | 7 | ||||
-rw-r--r-- | osc_server.cpp | 198 | ||||
-rw-r--r-- | osc_server.h | 99 |
13 files changed, 513 insertions, 448 deletions
@@ -29,7 +29,8 @@ LDFLAGS := -lm -lsupc++ \ all : osc-graphics -osc-graphics : main.o layer.o layer_box.o layer_image.o layer_video.o +osc-graphics : main.o osc_server.o \ + layer.o layer_box.o layer_image.o layer_video.o $(CC) $^ $(LDFLAGS) -o $@ install : all @@ -4,8 +4,18 @@ #include <SDL.h> #include "osc_graphics.h" +#include "osc_server.h" #include "layer.h" +Layer::Layer(const char *name) +{ + mutex = SDL_CreateMutex(); + Layer::name = strdup(name); + + geo_osc_id = register_method("geo", GEO_TYPES, geo_osc); + alpha_osc_id = register_method("alpha", "f", alpha_osc); +} + void LayerList::insert(int pos, Layer *layer) { @@ -58,3 +68,12 @@ LayerList::render(SDL_Surface *target) unlock(); } + +Layer::~Layer() +{ + unregister_method(alpha_osc_id); + unregister_method(geo_osc_id); + + free(name); + SDL_DestroyMutex(mutex); +} @@ -7,6 +7,13 @@ #include <SDL.h> #include <SDL_thread.h> +#include <lo/lo.h> + +#include "osc_graphics.h" +#include "osc_server.h" + +extern OscServer osc_server; + class Layer { SDL_mutex *mutex; @@ -15,16 +22,8 @@ public: char *name; - Layer(const char *name) - { - mutex = SDL_CreateMutex(); - Layer::name = strdup(name); - } - virtual ~Layer() - { - free(name); - SDL_DestroyMutex(mutex); - } + Layer(const char *name); + virtual ~Layer(); inline void lock() @@ -37,10 +36,50 @@ public: SDL_UnlockMutex(mutex); } + /* + * Frame render method + */ + virtual void frame(SDL_Surface *target) = 0; + +protected: + inline OscServer::MethodHandlerId * + register_method(const char *method, const char *types, + OscServer::MethodHandlerCb method_cb) + { + return osc_server.register_method(this, method, types, method_cb); + } + inline void + unregister_method(OscServer::MethodHandlerId *hnd) + { + osc_server.unregister_method(hnd); + } + + /* + * Default methods + */ virtual void geo(SDL_Rect geo) = 0; virtual void alpha(float opacity) = 0; - virtual void frame(SDL_Surface *target) = 0; +private: + /* + * OSC handler methods + */ + OscServer::MethodHandlerId *geo_osc_id; + static void + geo_osc(Layer *obj, lo_arg **argv) + { + SDL_Rect geo = { + (Sint16)argv[0]->i, (Sint16)argv[1]->i, + (Uint16)argv[2]->i, (Uint16)argv[3]->i + }; + obj->geo(geo); + } + OscServer::MethodHandlerId *alpha_osc_id; + static void + alpha_osc(Layer *obj, lo_arg **argv) + { + obj->alpha(argv[0]->f); + } }; class LayerList { diff --git a/layer_box.cpp b/layer_box.cpp index d229833..0ccaf7c 100644 --- a/layer_box.cpp +++ b/layer_box.cpp @@ -6,6 +6,17 @@ #include "osc_graphics.h" #include "layer_box.h" +LayerBox::LayerBox(const char *name, SDL_Rect geo, float opacity, + SDL_Color color) : Layer(name) +{ + color_osc_id = register_method("color", "iii", + (OscServer::MethodHandlerCb)color_osc); + + LayerBox::geo(geo); + LayerBox::color(color); + LayerBox::alpha(opacity); +} + void LayerBox::geo(SDL_Rect geo) { @@ -27,3 +38,8 @@ LayerBox::frame(SDL_Surface *target) boxRGBA(target, x1, y1, x2 ? : target->w, y2 ? : target->h, r, g, b, a); } + +LayerBox::~LayerBox() +{ + unregister_method(color_osc_id); +} diff --git a/layer_box.h b/layer_box.h index bba2f98..3c9dace 100644 --- a/layer_box.h +++ b/layer_box.h @@ -4,34 +4,53 @@ #include <SDL.h> #include "osc_graphics.h" +#include "osc_server.h" #include "layer.h" +#define LayerBox_Info_Name "box" +#define LayerBox_Info_Types "iii" /* r, g, b */ + class LayerBox : public Layer { Sint16 x1, y1, x2, y2; Uint8 r, g, b, a; public: + static void register_layer() {} + LayerBox(const char *name, SDL_Rect geo, float opacity, - SDL_Color color) : Layer(name) + SDL_Color color); + static Layer * + ctor_osc(const char *name, SDL_Rect geo, float opacity, lo_arg **argv) { - LayerBox::geo(geo); - LayerBox::color(color); - LayerBox::alpha(opacity); + SDL_Color color = { + (Uint8)argv[0]->i, (Uint8)argv[1]->i, (Uint8)argv[2]->i + }; + return new LayerBox(name, geo, opacity, color); } + ~LayerBox(); + void frame(SDL_Surface *target); + +private: void geo(SDL_Rect geo); void alpha(float opacity); - void + inline void color(SDL_Color color) { r = color.r; g = color.g; b = color.b; } - - - void frame(SDL_Surface *target); + OscServer::MethodHandlerId *color_osc_id; + static void + color_osc(LayerBox *obj, lo_arg **argv) + { + SDL_Color color = { + (Uint8)argv[0]->i, (Uint8)argv[1]->i, (Uint8)argv[2]->i + }; + obj->color(color); + } }; #endif
\ No newline at end of file diff --git a/layer_image.cpp b/layer_image.cpp index 11079be..21bba43 100644 --- a/layer_image.cpp +++ b/layer_image.cpp @@ -57,6 +57,18 @@ rgba_blit_with_alpha(SDL_Surface *src_surf, SDL_Surface *dst_surf, Uint8 alpha) #endif +LayerImage::LayerImage(const char *name, SDL_Rect geo, float opacity, + const char *file) : Layer(name), surf_alpha(NULL), + surf_scaled(NULL), surf(NULL) +{ + file_osc_id = register_method("file", "s", + (OscServer::MethodHandlerCb)file_osc); + + LayerImage::alpha(opacity); + LayerImage::geo(geo); + LayerImage::file(file); +} + void LayerImage::geo(SDL_Rect geo) { @@ -155,3 +167,12 @@ LayerImage::frame(SDL_Surface *target) SDL_BlitSurface(surf_alpha ? : surf_scaled ? : surf, NULL, target, &geov); } + +LayerImage::~LayerImage() +{ + unregister_method(file_osc_id); + + SDL_FREESURFACE_SAFE(surf_alpha); + SDL_FREESURFACE_SAFE(surf_scaled); + SDL_FREESURFACE_SAFE(surf); +} diff --git a/layer_image.h b/layer_image.h index 2a313d6..69a3a7c 100644 --- a/layer_image.h +++ b/layer_image.h @@ -9,6 +9,9 @@ #include "osc_graphics.h" #include "layer.h" +#define LayerImage_Info_Name "image" +#define LayerImage_Info_Types "s" /* file */ + class LayerImage : public Layer { SDL_Surface *surf_alpha; /* with per-surface alpha */ SDL_Surface *surf_scaled; /* scaled image */ @@ -18,29 +21,32 @@ class LayerImage : public Layer { float alphav; public: + static void register_layer() {} + LayerImage(const char *name, SDL_Rect geo = (SDL_Rect){0, 0, 0, 0}, float opacity = 1., - const char *file = NULL) : Layer(name), surf_alpha(NULL), surf_scaled(NULL), surf(NULL) + const char *file = NULL); + static Layer * + ctor_osc(const char *name, SDL_Rect geo, float opacity, lo_arg **argv) { - LayerImage::alpha(opacity); - LayerImage::geo(geo); - LayerImage::file(file); + return new LayerImage(name, geo, opacity, &argv[0]->s); } + ~LayerImage(); - ~LayerImage() - { - SDL_FREESURFACE_SAFE(surf_alpha); - SDL_FREESURFACE_SAFE(surf_scaled); - SDL_FREESURFACE_SAFE(surf); - } + void frame(SDL_Surface *target); +private: void geo(SDL_Rect geo); void alpha(float opacity); void file(const char *file = NULL); - - void frame(SDL_Surface *target); + OscServer::MethodHandlerId *file_osc_id; + static void + file_osc(LayerImage *obj, lo_arg **argv) + { + obj->file(&argv[0]->s); + } }; /* diff --git a/layer_video.cpp b/layer_video.cpp index ec9e258..bcedda0 100644 --- a/layer_video.cpp +++ b/layer_video.cpp @@ -43,6 +43,13 @@ LayerVideo::LayerVideo(const char *name, SDL_Rect geo, float opacity, "--no-xlib" /* tell VLC to not use Xlib */ }; + url_osc_id = register_method("url", "s", (OscServer::MethodHandlerCb)url_osc); + rate_osc_id = register_method("rate", "f", (OscServer::MethodHandlerCb)rate_osc); + position_osc_id = register_method("position", "f", + (OscServer::MethodHandlerCb)position_osc); + paused_osc_id = register_method("paused", "i", + (OscServer::MethodHandlerCb)paused_osc); + LayerVideo::geo(geo); LayerVideo::alpha(opacity); LayerVideo::rate(1.); @@ -223,6 +230,11 @@ LayerVideo::frame(SDL_Surface *target) LayerVideo::~LayerVideo() { + unregister_method(url_osc_id); + unregister_method(rate_osc_id); + unregister_method(position_osc_id); + unregister_method(paused_osc_id); + if (mp) libvlc_media_player_release(mp); libvlc_release(vlcinst); diff --git a/layer_video.h b/layer_video.h index 7130039..4917b40 100644 --- a/layer_video.h +++ b/layer_video.h @@ -4,11 +4,16 @@ #include <SDL.h> #include <SDL_thread.h> +#include <lo/lo.h> + #include <vlc/vlc.h> #include "osc_graphics.h" #include "layer.h" +#define LayerVideo_Info_Name "video" +#define LayerVideo_Info_Types "s" /* url */ + class LayerVideo : public Layer { libvlc_instance_t *vlcinst; libvlc_media_player_t *mp; @@ -23,10 +28,17 @@ class LayerVideo : public Layer { bool pausedv; public: + static void register_layer() {} + LayerVideo(const char *name, SDL_Rect geo = (SDL_Rect){0, 0, 0, 0}, float opacity = 1., const char *url = NULL); + static Layer * + ctor_osc(const char *name, SDL_Rect geo, float opacity, lo_arg **argv) + { + return new LayerVideo(name, geo, opacity, &argv[0]->s); + } ~LayerVideo(); inline void * @@ -43,15 +55,40 @@ public: SDL_UnlockMutex(mutex); } + void frame(SDL_Surface *target); + +private: void geo(SDL_Rect geo); void alpha(float opacity); void url(const char *url = NULL); + OscServer::MethodHandlerId *url_osc_id; + static void + url_osc(LayerVideo *obj, lo_arg **argv) + { + obj->url(&argv[0]->s); + } void rate(float rate); + OscServer::MethodHandlerId *rate_osc_id; + static void + rate_osc(LayerVideo *obj, lo_arg **argv) + { + obj->rate(argv[0]->f); + } void position(float position); + OscServer::MethodHandlerId *position_osc_id; + static void + position_osc(LayerVideo *obj, lo_arg **argv) + { + obj->position(argv[0]->f); + } void paused(bool paused); - - void frame(SDL_Surface *target); + OscServer::MethodHandlerId *paused_osc_id; + static void + paused_osc(LayerVideo *obj, lo_arg **argv) + { + obj->paused(argv[0]->i); + } }; #endif @@ -9,432 +9,30 @@ #include <lo/lo.h> #include "osc_graphics.h" +#include "osc_server.h" #include "layer.h" #include "layer_box.h" #include "layer_image.h" #include "layer_video.h" -#define GEO_TYPES "iiii" /* x, y, width, height */ -#define NEW_LAYER_TYPES "is" GEO_TYPES "f" /* position, name, GEO, alpha */ -#define COLOR_TYPES "iii" /* r, g, b */ - /* * Default values */ #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define FRAMERATE 20 /* Hz */ +#define PORT "7770" /* * Declarations */ SDL_Surface *screen; -static LayerList layers; - -static int config_dump_osc = 0; - -static void -lo_server_thread_add_method_v(lo_server_thread server, const char *types, - lo_method_handler handler, void *data, - const char *fmt, ...) -{ - char buf[255]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - lo_server_thread_add_method(server, buf, types, handler, data); - va_end(ap); -} - -static void -lo_server_thread_del_method_v(lo_server_thread server, const char *types, - const char *fmt, ...) -{ - char buf[255]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - lo_server_thread_del_method(server, buf, types); - va_end(ap); -} - -static void -osc_error(int num, const char *msg, const char *path) -{ - fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, msg); -} - -/* catch any incoming messages and display them. returning 1 means that the - * message has not been fully handled and the server should try other methods */ -static int -osc_generic_handler(const char *path, const char *types, lo_arg **argv, - int argc, void *data, - void *user_data __attribute__((unused))) -{ - if (!config_dump_osc) - return 1; - - printf("path: <%s>\n", path); - for (int i = 0; i < argc; i++) { - printf("arg %d '%c' ", i, types[i]); - lo_arg_pp((lo_type)types[i], argv[i]); - printf("\n"); - } - printf("\n"); - - return 1; -} - -static inline char * -get_layer_name_from_path(const char *path) -{ - /* path is /layer/[name]/... */ - char *name = strdup(path + 7); - *strchr(name, '/') = '\0'; - - return name; -} - -static int -osc_layer_delete(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = user_data; - char *name; - - name = get_layer_name_from_path(path); - layers.delete_by_name(name); - free(name); +OscServer osc_server(PORT); +LayerList layers; - lo_server_thread_del_method(server, path, types); - - return 1; -} - -static inline void -osc_add_layer_delete(lo_server_thread server, const char *name, - lo_method_handler custom_delete) -{ - if (custom_delete) - lo_server_thread_add_method_v(server, "", custom_delete, server, - "/layer/%s/delete", name); - lo_server_thread_add_method_v(server, "", osc_layer_delete, server, - "/layer/%s/delete", name); -} - -static int -osc_image_geo(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerImage *ctx = (LayerImage *)user_data; - - ctx->lock(); - ctx->geo((SDL_Rect){argv[0]->i, argv[1]->i, argv[2]->i, argv[3]->i}); - ctx->unlock(); - return 0; -} - -static int -osc_image_alpha(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerImage *ctx = (LayerImage *)user_data; - - ctx->lock(); - ctx->alpha(argv[0]->f); - ctx->unlock(); - return 0; -} - -static int -osc_image_file(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerImage *ctx = (LayerImage *)user_data; - - ctx->lock(); - ctx->file(&argv[0]->s); - ctx->unlock(); - return 0; -} - -static int -osc_image_delete(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - char *name; - - name = get_layer_name_from_path(path); - - lo_server_thread_del_method_v(server, GEO_TYPES, "/layer/%s/geo", name); - lo_server_thread_del_method_v(server, "f", "/layer/%s/alpha", name); - lo_server_thread_del_method_v(server, "s", "/layer/%s/file", name); - - free(name); - - lo_server_thread_del_method(server, path, types); - - return 1; -} - -static int -osc_image_new(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - SDL_Rect geo = { - (Sint16)argv[2]->i, (Sint16)argv[3]->i, - (Uint16)argv[4]->i, (Uint16)argv[5]->i - }; - - LayerImage *ctx = new LayerImage(&argv[1]->s, geo, argv[6]->f, &argv[7]->s); - - layers.insert(argv[0]->i, ctx); - - lo_server_thread_add_method_v(server, GEO_TYPES, osc_image_geo, ctx, - "/layer/%s/geo", &argv[1]->s); - lo_server_thread_add_method_v(server, "f", osc_image_alpha, ctx, - "/layer/%s/alpha", &argv[1]->s); - lo_server_thread_add_method_v(server, "s", osc_image_file, ctx, - "/layer/%s/file", &argv[1]->s); - - osc_add_layer_delete(server, &argv[1]->s, osc_image_delete); - - return 0; -} - -static int -osc_video_geo(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->geo((SDL_Rect){argv[0]->i, argv[1]->i, argv[2]->i, argv[3]->i}); - ctx->unlock(); - return 0; -} - -static int -osc_video_alpha(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->alpha(argv[0]->f); - ctx->unlock(); - return 0; -} - -static int -osc_video_url(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->url(&argv[0]->s); - ctx->unlock(); - return 0; -} - -static int -osc_video_rate(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->rate(argv[0]->f); - ctx->unlock(); - return 0; -} - -static int -osc_video_position(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->position(argv[0]->f); - ctx->unlock(); - return 0; -} - -static int -osc_video_paused(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerVideo *ctx = (LayerVideo *)user_data; - - ctx->lock(); - ctx->paused(argv[0]->i); - ctx->unlock(); - return 0; -} - -static int -osc_video_delete(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - char *name; - - name = get_layer_name_from_path(path); - - lo_server_thread_del_method_v(server, GEO_TYPES, "/layer/%s/geo", name); - lo_server_thread_del_method_v(server, "f", "/layer/%s/alpha", name); - lo_server_thread_del_method_v(server, "s", "/layer/%s/url", name); - lo_server_thread_del_method_v(server, "f", "/layer/%s/rate", name); - lo_server_thread_del_method_v(server, "f", "/layer/%s/position", name); - lo_server_thread_del_method_v(server, "i", "/layer/%s/paused", name); - - free(name); - - lo_server_thread_del_method(server, path, types); - - return 1; -} - -static int -osc_video_new(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - SDL_Rect geo = { - (Sint16)argv[2]->i, (Sint16)argv[3]->i, - (Uint16)argv[4]->i, (Uint16)argv[5]->i - }; - - LayerVideo *ctx = new LayerVideo(&argv[1]->s, geo, argv[6]->f, &argv[7]->s); - - layers.insert(argv[0]->i, ctx); - - lo_server_thread_add_method_v(server, GEO_TYPES, osc_video_geo, ctx, - "/layer/%s/geo", &argv[1]->s); - lo_server_thread_add_method_v(server, "f", osc_video_alpha, ctx, - "/layer/%s/alpha", &argv[1]->s); - lo_server_thread_add_method_v(server, "s", osc_video_url, ctx, - "/layer/%s/url", &argv[1]->s); - lo_server_thread_add_method_v(server, "f", osc_video_rate, ctx, - "/layer/%s/rate", &argv[1]->s); - lo_server_thread_add_method_v(server, "f", osc_video_position, ctx, - "/layer/%s/position", &argv[1]->s); - lo_server_thread_add_method_v(server, "i", osc_video_paused, ctx, - "/layer/%s/paused", &argv[1]->s); - osc_add_layer_delete(server, &argv[1]->s, osc_video_delete); - - return 0; -} - -static int -osc_box_geo(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerBox *ctx = (LayerBox *)user_data; - - ctx->lock(); - ctx->geo((SDL_Rect){argv[0]->i, argv[1]->i, argv[2]->i, argv[3]->i}); - ctx->unlock(); - return 0; -} - -static int -osc_box_alpha(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerBox *ctx = (LayerBox *)user_data; - - ctx->lock(); - ctx->alpha(argv[0]->f); - ctx->unlock(); - return 0; -} - -static int -osc_box_color(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - LayerBox *ctx = (LayerBox *)user_data; - - ctx->lock(); - ctx->color((SDL_Color){argv[0]->i, argv[1]->i, argv[2]->i}); - ctx->unlock(); - return 0; -} - -static int -osc_box_delete(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - char *name; - - name = get_layer_name_from_path(path); - - lo_server_thread_del_method_v(server, GEO_TYPES, "/layer/%s/geo", name); - lo_server_thread_del_method_v(server, "f", "/layer/%s/alpha", name); - lo_server_thread_del_method_v(server, COLOR_TYPES, "/layer/%s/color", name); - - free(name); - - lo_server_thread_del_method(server, path, types); - - return 1; -} - -static int -osc_box_new(const char *path, const char *types, lo_arg **argv, - int argc, void *data, void *user_data) -{ - lo_server_thread server = (lo_server_thread)user_data; - SDL_Rect geo = { - (Sint16)argv[2]->i, (Sint16)argv[3]->i, - (Uint16)argv[4]->i, (Uint16)argv[5]->i - }; - SDL_Color color = { - (Uint8)argv[7]->i, (Uint8)argv[8]->i, (Uint8)argv[9]->i - }; - - LayerBox *ctx = new LayerBox(&argv[1]->s, geo, argv[6]->f, color); - - layers.insert(argv[0]->i, ctx); - - lo_server_thread_add_method_v(server, GEO_TYPES, osc_box_geo, ctx, - "/layer/%s/geo", &argv[1]->s); - lo_server_thread_add_method_v(server, "f", osc_box_alpha, ctx, - "/layer/%s/alpha", &argv[1]->s); - lo_server_thread_add_method_v(server, COLOR_TYPES, osc_box_color, ctx, - "/layer/%s/color", &argv[1]->s); - - osc_add_layer_delete(server, &argv[1]->s, osc_box_delete); - - return 0; -} - -static inline lo_server_thread -osc_init(const char *port) -{ - lo_server_thread server = lo_server_thread_new(port, osc_error); - - lo_server_thread_add_method(server, NULL, NULL, osc_generic_handler, NULL); - - lo_server_thread_add_method(server, "/layer/new/image", NEW_LAYER_TYPES "s", - osc_image_new, server); - lo_server_thread_add_method(server, "/layer/new/video", NEW_LAYER_TYPES "s", - osc_video_new, server); - lo_server_thread_add_method(server, "/layer/new/box", NEW_LAYER_TYPES COLOR_TYPES, - osc_box_new, server); - - return server; -} +int config_dump_osc = 0; static inline void sdl_process_events(void) @@ -480,13 +78,8 @@ sdl_process_events(void) int main(int argc, char **argv) { - lo_server_thread osc_server; FPSmanager fpsm; - osc_server = osc_init("7770"); - if (!osc_server) - return EXIT_FAILURE; - if (SDL_Init(SDL_INIT_VIDEO)) { SDL_ERROR("SDL_Init"); return EXIT_FAILURE; @@ -502,7 +95,7 @@ main(int argc, char **argv) return EXIT_FAILURE; } - lo_server_thread_start(osc_server); + osc_server.start(); SDL_initFramerate(&fpsm); SDL_setFramerate(&fpsm, FRAMERATE); diff --git a/osc_graphics.h b/osc_graphics.h index f05f34f..2a08678 100644 --- a/osc_graphics.h +++ b/osc_graphics.h @@ -5,6 +5,9 @@ #include <SDL.h> +#include "osc_server.h" +#include "layer.h" + /* * Macros */ @@ -38,4 +41,6 @@ */ extern SDL_Surface *screen; -#endif
\ No newline at end of file +extern int config_dump_osc; + +#endif diff --git a/osc_server.cpp b/osc_server.cpp new file mode 100644 index 0000000..aae7b1a --- /dev/null +++ b/osc_server.cpp @@ -0,0 +1,198 @@ +#include <stdarg.h> +#include <stdio.h> + +#include <SDL.h> + +#include <lo/lo.h> + +#include "osc_graphics.h" + +#include "layer.h" +#include "layer_image.h" +#include "layer_video.h" +#include "layer_box.h" + +#include "osc_server.h" + +static void error_handler(int num, const char *msg, const char *path); +static int generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, void *user_data); + +static int dtor_generic_handler(const char *path, const char *types, + lo_arg **argv, int argc, + void *data, void *user_data); +static int ctor_generic_handler(const char *path, const char *types, + lo_arg **argv, int argc, + void *data, void *user_data); +static int method_generic_handler(const char *path, const char *types, + lo_arg **argv, int argc, + void *data, void *user_data); + +extern LayerList layers; + +static void +error_handler(int num, const char *msg, const char *path) +{ + fprintf(stderr, "liblo server error %d in path %s: %s\n", + num, path, msg); +} + +/* catch any incoming messages and display them. returning 1 means that the + * message has not been fully handled and the server should try other methods */ +static int +generic_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, + void *user_data __attribute__((unused))) +{ + if (!config_dump_osc) + return 1; + + printf("path: <%s>\n", path); + for (int i = 0; i < argc; i++) { + printf("arg %d '%c' ", i, types[i]); + lo_arg_pp((lo_type)types[i], argv[i]); + printf("\n"); + } + printf("\n"); + + return 1; +} + +static int +dtor_generic_handler(const char *path, + const char *types __attribute__((unused)), + lo_arg **argv __attribute__((unused)), + int argc __attribute__((unused)), + void *data __attribute__((unused)), + void *user_data) +{ + Layer *layer = (Layer *)user_data; + + /* FIXME: double-linked list allows more effecient layer delete */ + layers.delete_by_name(layer->name); + + osc_server.del_method("", "%s", path); + + return 0; +} + +static int +ctor_generic_handler(const char *path __attribute__((unused)), + const char *types __attribute__((unused)), + lo_arg **argv, int argc, + void *data __attribute__((unused)), + void *user_data) +{ + OscServer::ConstructorHandlerCb const_cb = + (OscServer::ConstructorHandlerCb)user_data; + Layer *layer; + + SDL_Rect geo = { + (Sint16)argv[2]->i, (Sint16)argv[3]->i, + (Uint16)argv[4]->i, (Uint16)argv[5]->i + }; + + layer = const_cb(&argv[1]->s, geo, argv[6]->f, argv + 7); + layers.insert(argv[0]->i, layer); + + osc_server.add_method("", dtor_generic_handler, layer, + "/layer/%s/delete", layer->name); + + return 0; +} + +#define REGISTER_LAYER(CLASS) \ + do { \ + CLASS::register_layer(); \ + add_method(NEW_LAYER_TYPES CLASS##_Info_Types, \ + ctor_generic_handler, (void *)CLASS::ctor_osc, \ + "/layer/new/%s", CLASS##_Info_Name); \ + } while (0) + +OscServer::OscServer(const char *port) +{ + server = lo_server_thread_new(port, error_handler); + + add_method(NULL, generic_handler, NULL, ""); + + REGISTER_LAYER(LayerImage); + REGISTER_LAYER(LayerVideo); + REGISTER_LAYER(LayerBox); +} + +#undef REGISTER_LAYER + +void +OscServer::add_method_v(MethodHandlerId **hnd, const char *types, + lo_method_handler handler, void *data, + const char *fmt, va_list ap) +{ + char buf[255]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + lo_server_thread_add_method(server, buf, types, handler, data); + + if (hnd) + *hnd = new MethodHandlerId(types, buf, data); +} + +void +OscServer::del_method(const char *types, const char *fmt, ...) +{ + char buf[255]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + lo_server_thread_del_method(server, buf, types); + va_end(ap); +} + +struct OscMethodDefaultCtx { + Layer *layer; + OscServer::MethodHandlerCb method_cb; +}; + +static int +method_generic_handler(const char *path __attribute__((unused)), + const char *types __attribute__((unused)), + lo_arg **argv, int argc, + void *data __attribute__((unused)), + void *user_data) +{ + struct OscMethodDefaultCtx *ctx = (struct OscMethodDefaultCtx *)user_data; + + ctx->layer->lock(); + ctx->method_cb(ctx->layer, argv); + ctx->layer->unlock(); + + return 0; +} + +OscServer::MethodHandlerId * +OscServer::register_method(Layer *layer, const char *method, const char *types, + MethodHandlerCb method_cb) +{ + MethodHandlerId *hnd; + struct OscMethodDefaultCtx *ctx = new struct OscMethodDefaultCtx; + + ctx->layer = layer; + ctx->method_cb = method_cb; + + add_method(&hnd, types, method_generic_handler, ctx, + "/layer/%s/%s", layer->name, method); + + return hnd; +} + +void +OscServer::unregister_method(MethodHandlerId *hnd) +{ + delete (struct OscMethodDefaultCtx *)hnd->data; + del_method(hnd); +} + +OscServer::~OscServer() +{ + lo_server_thread_free(server); +} diff --git a/osc_server.h b/osc_server.h new file mode 100644 index 0000000..362ded9 --- /dev/null +++ b/osc_server.h @@ -0,0 +1,99 @@ +#ifndef __OSC_SERVER_H +#define __OSC_SERVER_H + +#include <string.h> +#include <stdarg.h> + +#include <SDL.h> + +#include <lo/lo.h> + +#include "osc_graphics.h" + +class Layer; + +class OscServer { + lo_server_thread server; + +public: + struct MethodHandlerId { + char *types; + char *path; + void *data; + + MethodHandlerId(const char *types, const char *path, + void *d = NULL) : data(d) + { + MethodHandlerId::types = strdup(types); + MethodHandlerId::path = strdup(path); + } + ~MethodHandlerId() + { + free(types); + free(path); + } + }; + +private: + void add_method_v(MethodHandlerId **hnd, const char *types, + lo_method_handler handler, void *data, + const char *fmt, va_list ap); + +public: + typedef void (*MethodHandlerCb)(Layer *obj, lo_arg **argv); + typedef Layer *(*ConstructorHandlerCb)(const char *name, SDL_Rect geo, + float alpha, lo_arg **argv); + + OscServer(const char *port); + ~OscServer(); + + inline void + start() + { + lo_server_thread_start(server); + } + inline void + stop() + { + lo_server_thread_stop(server); + } + + inline void + add_method(MethodHandlerId **hnd, const char *types, + lo_method_handler handler, void *data, + const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + add_method_v(hnd, types, handler, data, fmt, ap); + va_end(ap); + } + inline void + add_method(const char *types, + lo_method_handler handler, void *data, + const char *fmt, ...) + { + va_list ap; + va_start(ap, fmt); + add_method_v(NULL, types, handler, data, fmt, ap); + va_end(ap); + } + + void del_method(const char *types, const char *fmt, ...); + inline void + del_method(MethodHandlerId *hnd) + { + del_method(hnd->types, "%s", hnd->path); + delete hnd; + } + + MethodHandlerId *register_method(Layer *layer, const char *method, + const char *types, + MethodHandlerCb method_cb); + void unregister_method(MethodHandlerId *hnd); +}; + +#define GEO_TYPES "iiii" /* x, y, width, height */ +#define NEW_LAYER_TYPES "is" GEO_TYPES "f" /* position, name, GEO, alpha */ + +#endif |