aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-09-26 20:08:10 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-09-26 20:08:10 +0200
commit7e5561d02f257f5c2ae54f4d55dee1093cf2ad4b (patch)
treea447fe2a109da09d9f06c67a0534873f9ac3a27b
parenteac5ac91ba27ae8e6d24625d6fa170425c51d459 (diff)
downloadosc-graphics-7e5561d02f257f5c2ae54f4d55dee1093cf2ad4b.tar.gz
isolated OSC server specific code in OscServer class and allow to register methods in order to localize OSC method handling
i.e. every Layer class is stand-alone now
-rw-r--r--Makefile3
-rw-r--r--layer.cpp19
-rw-r--r--layer.h61
-rw-r--r--layer_box.cpp16
-rw-r--r--layer_box.h35
-rw-r--r--layer_image.cpp21
-rw-r--r--layer_image.h30
-rw-r--r--layer_video.cpp12
-rw-r--r--layer_video.h41
-rw-r--r--main.cpp419
-rw-r--r--osc_graphics.h7
-rw-r--r--osc_server.cpp198
-rw-r--r--osc_server.h99
13 files changed, 513 insertions, 448 deletions
diff --git a/Makefile b/Makefile
index bd614d4..8524586 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/layer.cpp b/layer.cpp
index d0516ab..8820834 100644
--- a/layer.cpp
+++ b/layer.cpp
@@ -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);
+}
diff --git a/layer.h b/layer.h
index 37208c3..9cf757c 100644
--- a/layer.h
+++ b/layer.h
@@ -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
diff --git a/main.cpp b/main.cpp
index 5461d82..1ef1606 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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