summaryrefslogtreecommitdiff
path: root/modules/sdl
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
committerAlfred E. Heggestad <aeh@db.org>2014-02-09 11:50:07 +0100
commit98bf08bdcf2edd9d397f32650a8bfe62186fbecf (patch)
treeebc6ec71f44bff8c42e4eefced61948623df02fc /modules/sdl
parente6ad5cf4401b860ba402d4b7b3c7c254bc87a019 (diff)
baresip 0.4.10
Diffstat (limited to 'modules/sdl')
-rw-r--r--modules/sdl/module.mk19
-rw-r--r--modules/sdl/sdl.c319
-rw-r--r--modules/sdl/sdl.h9
-rw-r--r--modules/sdl/util.c54
4 files changed, 401 insertions, 0 deletions
diff --git a/modules/sdl/module.mk b/modules/sdl/module.mk
new file mode 100644
index 0000000..bf100e5
--- /dev/null
+++ b/modules/sdl/module.mk
@@ -0,0 +1,19 @@
+#
+# module.mk
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+MOD := sdl
+$(MOD)_SRCS += sdl.c
+$(MOD)_SRCS += util.c
+
+CFLAGS += -DUSE_SDL
+$(MOD)_LFLAGS += -lSDL
+ifeq ($(OS),darwin)
+# note: APP_LFLAGS is needed, as main.o links to -lSDLmain
+APP_LFLAGS += -lSDL -lSDLmain -lobjc \
+ -framework CoreFoundation -framework Foundation -framework Cocoa
+endif
+
+include mk/mod.mk
diff --git a/modules/sdl/sdl.c b/modules/sdl/sdl.c
new file mode 100644
index 0000000..eb902b3
--- /dev/null
+++ b/modules/sdl/sdl.c
@@ -0,0 +1,319 @@
+/**
+ * @file sdl/sdl.c SDL - Simple DirectMedia Layer v1.2
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <SDL/SDL.h>
+#include <string.h>
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include "sdl.h"
+
+
+/** Local constants */
+enum {
+ KEY_RELEASE_VAL = 250 /**< Key release value in [ms] */
+};
+
+struct vidisp_st {
+ struct vidisp *vd; /* inheritance */
+};
+
+/** Global SDL data */
+static struct {
+ struct tmr tmr;
+ SDL_Surface *screen; /**< SDL Surface */
+ SDL_Overlay *bmp; /**< SDL YUV Overlay */
+ struct vidsz size; /**< Current size */
+ vidisp_resize_h *resizeh; /**< Screen resize handler */
+ void *arg; /**< Handler argument */
+ bool fullscreen;
+ bool open;
+} sdl;
+
+
+static struct vidisp *vid;
+
+
+static void event_handler(void *arg);
+
+
+static void sdl_reset(void)
+{
+ if (sdl.bmp) {
+ SDL_FreeYUVOverlay(sdl.bmp);
+ sdl.bmp = NULL;
+ }
+
+ if (sdl.screen) {
+ SDL_FreeSurface(sdl.screen);
+ sdl.screen = NULL;
+ }
+}
+
+
+static void handle_resize(int w, int h)
+{
+ struct vidsz size;
+
+ size.w = w;
+ size.h = h;
+
+ /* notify app */
+ if (sdl.resizeh)
+ sdl.resizeh(&size, sdl.arg);
+}
+
+
+static void timeout(void *arg)
+{
+ (void)arg;
+
+ tmr_start(&sdl.tmr, 1, event_handler, NULL);
+
+ /* Emulate key-release */
+ ui_input(0x00);
+}
+
+
+static void event_handler(void *arg)
+{
+ SDL_Event event;
+ char ch;
+
+ (void)arg;
+
+ tmr_start(&sdl.tmr, 100, event_handler, NULL);
+
+ while (SDL_PollEvent(&event)) {
+
+ switch (event.type) {
+
+ case SDL_KEYDOWN:
+
+ switch (event.key.keysym.sym) {
+
+ case SDLK_ESCAPE:
+ if (!sdl.fullscreen)
+ break;
+
+ sdl.fullscreen = false;
+ sdl_reset();
+ break;
+
+ case SDLK_f:
+ if (sdl.fullscreen)
+ break;
+
+ sdl.fullscreen = true;
+ sdl_reset();
+ break;
+
+ default:
+ ch = event.key.keysym.unicode & 0x7f;
+
+ /* Relay key-press to UI subsystem */
+ if (isprint(ch)) {
+ tmr_start(&sdl.tmr, KEY_RELEASE_VAL,
+ timeout, NULL);
+ ui_input(ch);
+ }
+ break;
+ }
+
+ break;
+
+ case SDL_VIDEORESIZE:
+ handle_resize(event.resize.w, event.resize.h);
+ break;
+
+ case SDL_QUIT:
+ ui_input('q');
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+static int sdl_open(void)
+{
+ if (sdl.open)
+ return 0;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ warning("sdl: unable to init SDL: %s\n", SDL_GetError());
+ return ENODEV;
+ }
+
+ SDL_EnableUNICODE(1);
+
+ tmr_start(&sdl.tmr, 100, event_handler, NULL);
+ sdl.open = true;
+
+ return 0;
+}
+
+
+static void sdl_close(void)
+{
+ tmr_cancel(&sdl.tmr);
+ sdl_reset();
+
+ if (sdl.open) {
+ SDL_Quit();
+ sdl.open = false;
+ }
+}
+
+
+static void destructor(void *arg)
+{
+ struct vidisp_st *st = arg;
+
+ mem_deref(st->vd);
+ sdl_close();
+}
+
+
+static int alloc(struct vidisp_st **stp, struct vidisp *vd,
+ struct vidisp_prm *prm, const char *dev,
+ vidisp_resize_h *resizeh, void *arg)
+{
+ struct vidisp_st *st;
+ int err;
+
+ /* Not used by SDL */
+ (void)prm;
+ (void)dev;
+
+ if (sdl.open)
+ return EBUSY;
+
+ st = mem_zalloc(sizeof(*st), destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->vd = mem_ref(vd);
+
+ sdl.resizeh = resizeh;
+ sdl.arg = arg;
+
+ err = sdl_open();
+
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+/**
+ * Display a video frame
+ *
+ * @param st Video display state
+ * @param title Window title
+ * @param frame Video frame
+ *
+ * @return 0 if success, otherwise errorcode
+ *
+ * @note: On Darwin, this must be called from the main thread
+ */
+static int display(struct vidisp_st *st, const char *title,
+ const struct vidframe *frame)
+{
+ SDL_Rect rect;
+
+ if (!st || !sdl.open)
+ return EINVAL;
+
+ if (!vidsz_cmp(&sdl.size, &frame->size)) {
+ if (sdl.size.w && sdl.size.h) {
+ info("sdl: reset size %u x %u ---> %u x %u\n",
+ sdl.size.w, sdl.size.h,
+ frame->size.w, frame->size.h);
+ }
+ sdl_reset();
+ }
+
+ if (!sdl.screen) {
+ int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+ char capt[256];
+
+ if (sdl.fullscreen)
+ flags |= SDL_FULLSCREEN;
+ else if (sdl.resizeh)
+ flags |= SDL_RESIZABLE;
+
+ if (title) {
+ re_snprintf(capt, sizeof(capt), "%s - %u x %u",
+ title, frame->size.w, frame->size.h);
+ }
+ else {
+ re_snprintf(capt, sizeof(capt), "%u x %u",
+ frame->size.w, frame->size.h);
+ }
+
+ SDL_WM_SetCaption(capt, capt);
+
+ sdl.screen = SDL_SetVideoMode(frame->size.w, frame->size.h,
+ 0, flags);
+ if (!sdl.screen) {
+ warning("sdl: unable to get video screen: %s\n",
+ SDL_GetError());
+ return ENODEV;
+ }
+
+ sdl.size = frame->size;
+ }
+
+ if (!sdl.bmp) {
+ sdl.bmp = SDL_CreateYUVOverlay(frame->size.w, frame->size.h,
+ SDL_YV12_OVERLAY, sdl.screen);
+ if (!sdl.bmp) {
+ warning("sdl: unable to create overlay: %s\n",
+ SDL_GetError());
+ return ENODEV;
+ }
+ }
+
+ SDL_LockYUVOverlay(sdl.bmp);
+ picture_copy(sdl.bmp->pixels, sdl.bmp->pitches, frame);
+ SDL_UnlockYUVOverlay(sdl.bmp);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = sdl.size.w;
+ rect.h = sdl.size.h;
+
+ SDL_DisplayYUVOverlay(sdl.bmp, &rect);
+
+ return 0;
+}
+
+
+static int module_init(void)
+{
+ return vidisp_register(&vid, "sdl", alloc, NULL, display, NULL);
+}
+
+
+static int module_close(void)
+{
+ vid = mem_deref(vid);
+
+ return 0;
+}
+
+
+EXPORT_SYM const struct mod_export DECL_EXPORTS(sdl) = {
+ "sdl",
+ "vidisp",
+ module_init,
+ module_close,
+};
diff --git a/modules/sdl/sdl.h b/modules/sdl/sdl.h
new file mode 100644
index 0000000..992f70d
--- /dev/null
+++ b/modules/sdl/sdl.h
@@ -0,0 +1,9 @@
+/**
+ * @file sdl.h Simple DirectMedia Layer module -- internal interface
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+
+
+void picture_copy(uint8_t *data[4], uint16_t linesize[4],
+ const struct vidframe *frame);
diff --git a/modules/sdl/util.c b/modules/sdl/util.c
new file mode 100644
index 0000000..59a1cdd
--- /dev/null
+++ b/modules/sdl/util.c
@@ -0,0 +1,54 @@
+/**
+ * @file util.c Simple DirectMedia Layer module -- utilities
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re.h>
+#include <rem.h>
+#include <baresip.h>
+#include "sdl.h"
+
+
+static void img_copy_plane(uint8_t *dst, int dst_wrap,
+ const uint8_t *src, int src_wrap,
+ int width, int height)
+{
+ if (!dst || !src)
+ return;
+
+ for (;height > 0; height--) {
+ memcpy(dst, src, width);
+ dst += dst_wrap;
+ src += src_wrap;
+ }
+}
+
+
+static int get_plane_bytewidth(int width, int plane)
+{
+ if (plane == 1 || plane == 2)
+ width = -((-width) >> 1);
+
+ return (width * 8 + 7) >> 3;
+}
+
+
+void picture_copy(uint8_t *data[4], uint16_t linesize[4],
+ const struct vidframe *frame)
+{
+ const int map[3] = {0, 2, 1};
+ int i;
+
+ for (i=0; i<3; i++) {
+ int h;
+ int bwidth = get_plane_bytewidth(frame->size.w, i);
+ h = frame->size.h;
+ if (i == 1 || i == 2) {
+ h = -((-frame->size.h) >> 1);
+ }
+ img_copy_plane(data[map[i]], linesize[map[i]],
+ frame->data[i], frame->linesize[i],
+ bwidth, h);
+ }
+}