diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt
index c0132e6dd..3c98f4283 100644
--- a/libobs/CMakeLists.txt
+++ b/libobs/CMakeLists.txt
@@ -142,6 +142,7 @@ set(libobs_libobs_SOURCES
obs-data.c
obs-module.c
obs-display.c
+ obs-viewport.c
obs-scene.c
obs-video.c)
set(libobs_libobs_HEADERS
diff --git a/libobs/obs-display.c b/libobs/obs-display.c
index ba96f84e8..bec70665a 100644
--- a/libobs/obs-display.c
+++ b/libobs/obs-display.c
@@ -15,64 +15,156 @@
along with this program. If not, see .
******************************************************************************/
+#include "graphics/vec4.h"
#include "obs.h"
#include "obs-internal.h"
+bool obs_display_init(struct obs_display *display,
+ struct gs_init_data *graphics_data)
+{
+ pthread_mutex_init_value(&display->draw_callbacks_mutex);
+
+ if (graphics_data) {
+ display->swap = gs_create_swapchain(graphics_data);
+ if (!display->swap) {
+ blog(LOG_ERROR, "obs_display_init: Failed to "
+ "create swap chain");
+ return false;
+ }
+
+ display->cx = graphics_data->cx;
+ display->cy = graphics_data->cy;
+ }
+
+ if (pthread_mutex_init(&display->draw_callbacks_mutex, NULL) != 0) {
+ blog(LOG_ERROR, "obs_display_init: Failed to create mutex");
+ return false;
+ }
+
+ return true;
+}
+
obs_display_t obs_display_create(struct gs_init_data *graphics_data)
{
struct obs_display *display = bzalloc(sizeof(struct obs_display));
- if (graphics_data) {
- display->swap = gs_create_swapchain(graphics_data);
- if (!display->swap) {
- obs_display_destroy(display);
- return NULL;
- }
+ if (!obs_display_init(display, graphics_data)) {
+ obs_display_destroy(display);
+ display = NULL;
}
return display;
}
+void obs_display_free(obs_display_t display)
+{
+ pthread_mutex_destroy(&display->draw_callbacks_mutex);
+ da_free(display->draw_callbacks);
+
+ if (display->swap) {
+ swapchain_destroy(display->swap);
+ display->swap = NULL;
+ }
+}
+
void obs_display_destroy(obs_display_t display)
{
if (display) {
- size_t i;
-
pthread_mutex_lock(&obs->data.displays_mutex);
da_erase_item(obs->data.displays, &display);
pthread_mutex_unlock(&obs->data.displays_mutex);
- for (i = 0; i < MAX_CHANNELS; i++)
- obs_source_release(display->channels[i]);
-
- swapchain_destroy(display->swap);
+ obs_display_free(display);
bfree(display);
}
}
-obs_source_t obs_display_getsource(obs_display_t display, uint32_t channel)
+void obs_display_resize(obs_display_t display, uint32_t cx, uint32_t cy)
{
- obs_source_t source;
- assert(channel < MAX_CHANNELS);
+ if (!display) return;
- source = display->channels[channel];
- if (source)
- obs_source_addref(source);
+ pthread_mutex_lock(&display->draw_callbacks_mutex);
- return source;
+ display->cx = cx;
+ display->cy = cy;
+ display->size_changed = true;
+
+ pthread_mutex_unlock(&display->draw_callbacks_mutex);
}
-void obs_display_setsource(obs_display_t display, uint32_t channel,
- obs_source_t source)
+void obs_display_add_draw_callback(obs_display_t display,
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param)
{
- struct obs_source *prev_source;
- assert(channel < MAX_CHANNELS);
+ if (!display) return;
- prev_source = display->channels[channel];
- display->channels[channel] = source;
+ struct draw_callback data = {draw, param};
- if (source)
- obs_source_addref(source);
- if (prev_source)
- obs_source_release(prev_source);
+ pthread_mutex_lock(&display->draw_callbacks_mutex);
+ da_push_back(display->draw_callbacks, &data);
+ pthread_mutex_unlock(&display->draw_callbacks_mutex);
+}
+
+void obs_display_remove_draw_callback(obs_display_t display,
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param)
+{
+ if (!display) return;
+
+ struct draw_callback data = {draw, param};
+
+ pthread_mutex_lock(&display->draw_callbacks_mutex);
+ da_erase_item(display->draw_callbacks, &data);
+ pthread_mutex_unlock(&display->draw_callbacks_mutex);
+}
+
+static inline void render_display_begin(struct obs_display *display)
+{
+ struct vec4 clear_color;
+
+ gs_load_swapchain(display ? display->swap : NULL);
+
+ if (display->size_changed) {
+ gs_resize(display->cx, display->cy);
+ display->size_changed = false;
+ }
+
+ gs_beginscene();
+ vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f);
+ gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL,
+ &clear_color, 1.0f, 0);
+
+ gs_enable_depthtest(false);
+ /* gs_enable_blending(false); */
+ gs_setcullmode(GS_NEITHER);
+
+ gs_ortho(0.0f, (float)obs->video.base_width,
+ 0.0f, (float)obs->video.base_height, -100.0f, 100.0f);
+ gs_setviewport(0, 0, display->cx, display->cy);
+}
+
+static inline void render_display_end(struct obs_display *display)
+{
+ gs_endscene();
+ gs_present();
+}
+
+void render_display(struct obs_display *display)
+{
+ if (!display) return;
+
+ render_display_begin(display);
+
+ pthread_mutex_lock(&display->draw_callbacks_mutex);
+
+ for (size_t i = 0; i < display->draw_callbacks.num; i++) {
+ struct draw_callback *callback;
+ callback = display->draw_callbacks.array+i;
+
+ callback->draw(callback->param, display->cx, display->cy);
+ }
+
+ pthread_mutex_unlock(&display->draw_callbacks_mutex);
+
+ render_display_end(display);
}
diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h
index d704bb789..883e84b1e 100644
--- a/libobs/obs-internal.h
+++ b/libobs/obs-internal.h
@@ -35,8 +35,13 @@
#define NUM_TEXTURES 2
+struct draw_callback {
+ void (*draw)(void *param, uint32_t cx, uint32_t cy);
+ void *param;
+};
+
/* ------------------------------------------------------------------------- */
-/* core */
+/* modules */
struct obs_module {
char *name;
@@ -46,51 +51,82 @@ struct obs_module {
extern void free_module(struct obs_module *mod);
+/* ------------------------------------------------------------------------- */
+/* viewports */
+
+struct obs_viewport {
+ pthread_mutex_t channels_mutex;
+ obs_source_t channels[MAX_CHANNELS];
+};
+
+extern bool obs_viewport_init(struct obs_viewport *viewport);
+extern void obs_viewport_free(struct obs_viewport *viewport);
+
+
+/* ------------------------------------------------------------------------- */
+/* displays */
+
+struct obs_display {
+ bool size_changed;
+ uint32_t cx, cy;
+ swapchain_t swap;
+ pthread_mutex_t draw_callbacks_mutex;
+ DARRAY(struct draw_callback) draw_callbacks;
+};
+
+extern bool obs_display_init(struct obs_display *display,
+ struct gs_init_data *graphics_data);
+extern void obs_display_free(struct obs_display *display);
+
+
/* ------------------------------------------------------------------------- */
/* core */
struct obs_core_video {
- graphics_t graphics;
- stagesurf_t copy_surfaces[NUM_TEXTURES];
- texture_t render_textures[NUM_TEXTURES];
- texture_t output_textures[NUM_TEXTURES];
- bool textures_rendered[NUM_TEXTURES];
- bool textures_output[NUM_TEXTURES];
- bool textures_copied[NUM_TEXTURES];
- struct source_frame convert_frames[NUM_TEXTURES];
- effect_t default_effect;
- stagesurf_t mapped_surface;
- int cur_texture;
+ graphics_t graphics;
+ stagesurf_t copy_surfaces[NUM_TEXTURES];
+ texture_t render_textures[NUM_TEXTURES];
+ texture_t output_textures[NUM_TEXTURES];
+ bool textures_rendered[NUM_TEXTURES];
+ bool textures_output[NUM_TEXTURES];
+ bool textures_copied[NUM_TEXTURES];
+ struct source_frame convert_frames[NUM_TEXTURES];
+ effect_t default_effect;
+ stagesurf_t mapped_surface;
+ int cur_texture;
- video_t video;
- pthread_t video_thread;
- bool thread_initialized;
+ video_t video;
+ pthread_t video_thread;
+ bool thread_initialized;
- uint32_t base_width;
- uint32_t base_height;
+ uint32_t base_width;
+ uint32_t base_height;
+
+ struct obs_display main_display;
};
struct obs_core_audio {
/* TODO: sound output subsystem */
- audio_t audio;
+ audio_t audio;
};
/* user sources, output channels, and displays */
struct obs_core_data {
/* arrays of pointers jim? you should really stop being lazy and use
* linked lists. */
- DARRAY(struct obs_display*) displays;
- DARRAY(struct obs_source*) sources;
- DARRAY(struct obs_output*) outputs;
- DARRAY(struct obs_encoder*) encoders;
+ DARRAY(struct obs_display*) displays;
+ DARRAY(struct obs_source*) sources;
+ DARRAY(struct obs_output*) outputs;
+ DARRAY(struct obs_encoder*) encoders;
- obs_source_t channels[MAX_CHANNELS];
- pthread_mutex_t sources_mutex;
- pthread_mutex_t displays_mutex;
- pthread_mutex_t outputs_mutex;
- pthread_mutex_t encoders_mutex;
+ pthread_mutex_t sources_mutex;
+ pthread_mutex_t displays_mutex;
+ pthread_mutex_t outputs_mutex;
+ pthread_mutex_t encoders_mutex;
- volatile bool valid;
+ struct obs_viewport main_viewport;
+
+ volatile bool valid;
};
struct obs_core {
@@ -119,68 +155,57 @@ extern struct obs_core *obs;
extern void *obs_video_thread(void *param);
-/* ------------------------------------------------------------------------- */
-/* displays */
-
-struct obs_display {
- swapchain_t swap; /* can be NULL if just sound */
- obs_source_t channels[MAX_CHANNELS];
-
- /* TODO: sound output target */
-};
-
-
/* ------------------------------------------------------------------------- */
/* sources */
struct obs_source {
- volatile int refs;
- struct obs_source_info info;
+ volatile int refs;
+ struct obs_source_info info;
/* source-specific data */
- char *name; /* user-defined name */
- enum obs_source_type type;
- obs_data_t settings;
- void *data;
+ char *name; /* user-defined name */
+ enum obs_source_type type;
+ obs_data_t settings;
+ void *data;
- signal_handler_t signals;
- proc_handler_t procs;
+ signal_handler_t signals;
+ proc_handler_t procs;
/* used to indicate that the source has been removed and all
* references to it should be released (not exactly how I would prefer
* to handle things but it's the best option) */
- bool removed;
+ bool removed;
/* timing (if video is present, is based upon video) */
- volatile bool timing_set;
- volatile uint64_t timing_adjust;
- volatile int audio_reset_ref;
- uint64_t next_audio_ts_min;
- uint64_t last_frame_ts;
- uint64_t last_sys_timestamp;
+ volatile bool timing_set;
+ volatile uint64_t timing_adjust;
+ volatile int audio_reset_ref;
+ uint64_t next_audio_ts_min;
+ uint64_t last_frame_ts;
+ uint64_t last_sys_timestamp;
/* audio */
- bool audio_failed;
- struct resample_info sample_info;
- audio_resampler_t resampler;
- audio_line_t audio_line;
- pthread_mutex_t audio_mutex;
- struct filtered_audio audio_data;
- size_t audio_storage_size;
- float volume;
+ bool audio_failed;
+ struct resample_info sample_info;
+ audio_resampler_t resampler;
+ audio_line_t audio_line;
+ pthread_mutex_t audio_mutex;
+ struct filtered_audio audio_data;
+ size_t audio_storage_size;
+ float volume;
/* async video data */
- texture_t output_texture;
- DARRAY(struct source_frame*) video_frames;
- pthread_mutex_t video_mutex;
+ texture_t output_texture;
+ DARRAY(struct source_frame*) video_frames;
+ pthread_mutex_t video_mutex;
/* filters */
- struct obs_source *filter_parent;
- struct obs_source *filter_target;
- DARRAY(struct obs_source*) filters;
- pthread_mutex_t filter_mutex;
- texrender_t filter_texrender;
- bool rendering_filter;
+ struct obs_source *filter_parent;
+ struct obs_source *filter_target;
+ DARRAY(struct obs_source*) filters;
+ pthread_mutex_t filter_mutex;
+ texrender_t filter_texrender;
+ bool rendering_filter;
};
bool obs_source_init_handlers(struct obs_source *source);
@@ -196,27 +221,27 @@ extern void obs_source_video_tick(obs_source_t source, float seconds);
/* outputs */
struct obs_output {
- char *name;
- void *data;
- struct obs_output_info info;
- obs_data_t settings;
+ char *name;
+ void *data;
+ struct obs_output_info info;
+ obs_data_t settings;
};
/* ------------------------------------------------------------------------- */
/* encoders */
-struct obs_encoder_callback {
+struct encoder_callback {
void (*new_packet)(void *param, struct encoder_packet *packet);
void *param;
};
struct obs_encoder {
- char *name;
- void *data;
- struct obs_encoder_info info;
- obs_data_t settings;
+ char *name;
+ void *data;
+ struct obs_encoder_info info;
+ obs_data_t settings;
- pthread_mutex_t data_callbacks_mutex;
- DARRAY(struct obs_encoder_callback) data_callbacks;
+ pthread_mutex_t data_callbacks_mutex;
+ DARRAY(struct encoder_callback) data_callbacks;
};
diff --git a/libobs/obs-video.c b/libobs/obs-video.c
index dfd2f1cb2..b2d085e5f 100644
--- a/libobs/obs-video.c
+++ b/libobs/obs-video.c
@@ -1,5 +1,5 @@
/******************************************************************************
- Copyright (C) 2013 by Hugh Bailey
+ Copyright (C) 2013-2014 by Hugh Bailey
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,57 +37,8 @@ static void tick_sources(uint64_t cur_time, uint64_t *last_time)
*last_time = cur_time;
}
-static inline void render_display_begin(struct obs_display *display)
-{
- struct vec4 clear_color;
- uint32_t width, height;
-
- gs_load_swapchain(display ? display->swap : NULL);
-
- gs_getsize(&width, &height);
-
- gs_beginscene();
- vec4_set(&clear_color, 0.3f, 0.0f, 0.0f, 1.0f);
- gs_clear(GS_CLEAR_COLOR | GS_CLEAR_DEPTH | GS_CLEAR_STENCIL,
- &clear_color, 1.0f, 0);
-
- gs_enable_depthtest(false);
- /* gs_enable_blending(false); */
- gs_setcullmode(GS_NEITHER);
-
- gs_ortho(0.0f, (float)obs->video.base_width,
- 0.0f, (float)obs->video.base_height, -100.0f, 100.0f);
- gs_setviewport(0, 0, width, height);
-}
-
-static inline void render_display_end(struct obs_display *display)
-{
- gs_endscene();
- gs_present();
-}
-
-static void render_display(struct obs_display *display)
-{
- render_display_begin(display);
-
- for (size_t i = 0; i < MAX_CHANNELS; i++) {
- struct obs_source **p_source;
-
- p_source = (display) ? display->channels+i :
- obs->data.channels+i;
-
- if (*p_source) {
- if ((*p_source)->removed) {
- obs_source_release(*p_source);
- *p_source = NULL;
- } else {
- obs_source_video_render(*p_source);
- }
- }
- }
-
- render_display_end(display);
-}
+/* in obs-display.c */
+extern void render_display(struct obs_display *display);
static inline void render_displays(void)
{
@@ -105,7 +56,7 @@ static inline void render_displays(void)
pthread_mutex_unlock(&obs->data.displays_mutex);
/* render main display */
- render_display(NULL);
+ render_display(&obs->video.main_display);
gs_leavecontext();
}
@@ -119,17 +70,6 @@ static inline void set_render_size(uint32_t width, uint32_t height)
gs_setviewport(0, 0, width, height);
}
-static inline void render_channels(void)
-{
- struct obs_core_data *data = &obs->data;
-
- for (size_t i = 0; i < MAX_CHANNELS; i++) {
- struct obs_source *source = data->channels[i];
- if (source)
- obs_source_video_render(source);
- }
-}
-
static inline void unmap_last_surface(struct obs_core_video *video)
{
if (video->mapped_surface) {
@@ -148,7 +88,7 @@ static inline void render_main_texture(struct obs_core_video *video,
gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0);
set_render_size(video->base_width, video->base_height);
- render_channels();
+ obs_viewport_render(&obs->data.main_viewport);
video->textures_rendered[cur_texture] = true;
}
diff --git a/libobs/obs-viewport.c b/libobs/obs-viewport.c
new file mode 100644
index 000000000..f8714eae8
--- /dev/null
+++ b/libobs/obs-viewport.c
@@ -0,0 +1,126 @@
+/******************************************************************************
+ Copyright (C) 2014 by Hugh Bailey
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+******************************************************************************/
+
+#include "obs.h"
+#include "obs-internal.h"
+
+bool obs_viewport_init(struct obs_viewport *viewport)
+{
+ pthread_mutex_init_value(&viewport->channels_mutex);
+
+ if (pthread_mutex_init(&viewport->channels_mutex, NULL) != 0) {
+ blog(LOG_ERROR, "obs_viewport_init: Failed to create mutex");
+ return false;
+ }
+
+ return true;
+}
+
+obs_viewport_t obs_viewport_create(void)
+{
+ struct obs_viewport *viewport = bzalloc(sizeof(struct obs_viewport));
+
+ if (!obs_viewport_init(viewport)) {
+ bfree(viewport);
+ viewport = NULL;
+ }
+
+ return viewport;
+}
+
+void obs_viewport_free(struct obs_viewport *viewport)
+{
+ for (size_t i = 0; i < MAX_CHANNELS; i++)
+ obs_source_release(viewport->channels[i]);
+
+ memset(viewport->channels, 0, sizeof(viewport->channels));
+ pthread_mutex_destroy(&viewport->channels_mutex);
+}
+
+void obs_viewport_destroy(obs_viewport_t viewport)
+{
+ if (viewport) {
+ obs_viewport_free(viewport);
+ bfree(viewport);
+ }
+}
+
+obs_source_t obs_viewport_getsource(obs_viewport_t viewport, uint32_t channel)
+{
+ obs_source_t source;
+ assert(channel < MAX_CHANNELS);
+
+ if (!viewport) return NULL;
+ if (channel >= MAX_CHANNELS) return NULL;
+
+ pthread_mutex_lock(&viewport->channels_mutex);
+
+ source = viewport->channels[channel];
+ if (source)
+ obs_source_addref(source);
+
+ pthread_mutex_unlock(&viewport->channels_mutex);
+
+ return source;
+}
+
+void obs_viewport_setsource(obs_viewport_t viewport, uint32_t channel,
+ obs_source_t source)
+{
+ struct obs_source *prev_source;
+
+ assert(channel < MAX_CHANNELS);
+
+ if (!viewport) return;
+ if (channel >= MAX_CHANNELS) return;
+
+ pthread_mutex_lock(&viewport->channels_mutex);
+
+ prev_source = viewport->channels[channel];
+ viewport->channels[channel] = source;
+
+ if (source)
+ obs_source_addref(source);
+ if (prev_source)
+ obs_source_release(prev_source);
+
+ pthread_mutex_unlock(&viewport->channels_mutex);
+}
+
+void obs_viewport_render(obs_viewport_t viewport)
+{
+ if (!viewport) return;
+
+ pthread_mutex_lock(&viewport->channels_mutex);
+
+ for (size_t i = 0; i < MAX_CHANNELS; i++) {
+ struct obs_source *source;
+
+ source = viewport->channels[i];
+
+ if (source) {
+ if (source->removed) {
+ obs_source_release(source);
+ viewport->channels[i] = NULL;
+ } else {
+ obs_source_video_render(source);
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&viewport->channels_mutex);
+}
diff --git a/libobs/obs.c b/libobs/obs.c
index 3f51ab565..8a9ed95d4 100644
--- a/libobs/obs.c
+++ b/libobs/obs.c
@@ -1,5 +1,5 @@
/******************************************************************************
- Copyright (C) 2013 by Hugh Bailey
+ Copyright (C) 2013-2014 by Hugh Bailey
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -140,6 +140,12 @@ static bool obs_init_video(struct obs_video_info *ovi)
return false;
}
+ if (!obs_display_init(&video->main_display, NULL))
+ return false;
+
+ video->main_display.cx = ovi->window_width;
+ video->main_display.cy = ovi->window_height;
+
errorcode = pthread_create(&video->video_thread, NULL,
obs_video_thread, obs);
if (errorcode != 0)
@@ -149,25 +155,33 @@ static bool obs_init_video(struct obs_video_info *ovi)
return true;
}
-static void obs_free_video()
+static void stop_video(void)
{
struct obs_core_video *video = &obs->video;
+ void *thread_retval;
if (video->video) {
- void *thread_retval;
-
video_output_stop(video->video);
if (video->thread_initialized) {
pthread_join(video->video_thread, &thread_retval);
video->thread_initialized = false;
}
+ }
+}
+
+static void obs_free_video(void)
+{
+ struct obs_core_video *video = &obs->video;
+
+ if (video->video) {
+ obs_display_free(&video->main_display);
video_output_close(video->video);
video->video = NULL;
}
}
-static void obs_free_graphics()
+static void obs_free_graphics(void)
{
struct obs_core_video *video = &obs->video;
size_t i;
@@ -248,6 +262,8 @@ static bool obs_init_data(void)
goto fail;
if (pthread_mutex_init(&data->encoders_mutex, &attr) != 0)
goto fail;
+ if (!obs_viewport_init(&data->main_viewport))
+ goto fail;
data->valid = true;
@@ -263,8 +279,7 @@ static void obs_free_data(void)
data->valid = false;
- for (i = 0; i < MAX_CHANNELS; i++)
- obs_set_output_source(i, NULL);
+ obs_viewport_free(&data->main_viewport);
while (data->outputs.num)
obs_output_destroy(data->outputs.array[0]);
@@ -303,7 +318,7 @@ static bool obs_init(void)
return obs_init_handlers();
}
-bool obs_startup()
+bool obs_startup(void)
{
bool success;
@@ -334,6 +349,8 @@ void obs_shutdown(void)
da_free(obs->modal_ui_callbacks);
da_free(obs->modeless_ui_callbacks);
+ stop_video();
+
obs_free_data();
obs_free_video();
obs_free_graphics();
@@ -349,6 +366,11 @@ void obs_shutdown(void)
obs = NULL;
}
+bool obs_initialized(void)
+{
+ return obs != NULL;
+}
+
bool obs_reset_video(struct obs_video_info *ovi)
{
struct obs_core_video *video = &obs->video;
@@ -535,21 +557,23 @@ bool obs_add_source(obs_source_t source)
obs_source_t obs_get_output_source(uint32_t channel)
{
- struct obs_source *source;
- assert(channel < MAX_CHANNELS);
- source = obs->data.channels[channel];
-
- obs_source_addref(source);
- return source;
+ return obs_viewport_getsource(&obs->data.main_viewport, channel);
}
void obs_set_output_source(uint32_t channel, obs_source_t source)
{
- struct obs_source *prev_source;
- struct calldata params = {0};
assert(channel < MAX_CHANNELS);
- prev_source = obs->data.channels[channel];
+ if (!obs) return;
+ if (channel >= MAX_CHANNELS) return;
+
+ struct obs_source *prev_source;
+ struct obs_viewport *viewport = &obs->data.main_viewport;
+ struct calldata params = {0};
+
+ pthread_mutex_lock(&viewport->channels_mutex);
+
+ prev_source = viewport->channels[channel];
calldata_setuint32(¶ms, "channel", channel);
calldata_setptr(¶ms, "prev_source", prev_source);
@@ -558,14 +582,14 @@ void obs_set_output_source(uint32_t channel, obs_source_t source)
calldata_getptr(¶ms, "source", &source);
calldata_free(¶ms);
- obs->data.channels[channel] = source;
+ viewport->channels[channel] = source;
- if (source != prev_source) {
- if (source)
- obs_source_addref(source);
- if (prev_source)
- obs_source_release(prev_source);
- }
+ if (source)
+ obs_source_addref(source);
+ if (prev_source)
+ obs_source_release(prev_source);
+
+ pthread_mutex_unlock(&viewport->channels_mutex);
}
void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), void *param)
@@ -630,15 +654,48 @@ obs_source_t obs_get_source_by_name(const char *name)
effect_t obs_get_default_effect(void)
{
+ if (!obs) return NULL;
return obs->video.default_effect;
}
signal_handler_t obs_signalhandler(void)
{
+ if (!obs) return NULL;
return obs->signals;
}
proc_handler_t obs_prochandler(void)
{
+ if (!obs) return NULL;
return obs->procs;
}
+
+void obs_add_draw_callback(
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param)
+{
+ if (!obs) return;
+
+ obs_display_add_draw_callback(&obs->video.main_display, draw, param);
+}
+
+void obs_remove_draw_callback(
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param)
+{
+ if (!obs) return;
+
+ obs_display_remove_draw_callback(&obs->video.main_display, draw, param);
+}
+
+void obs_resize(uint32_t cx, uint32_t cy)
+{
+ if (!obs || !obs->video.video || !obs->video.graphics) return;
+ obs_display_resize(&obs->video.main_display, cx, cy);
+}
+
+void obs_render_main_viewport(void)
+{
+ if (!obs) return;
+ obs_viewport_render(&obs->data.main_viewport);
+}
diff --git a/libobs/obs.h b/libobs/obs.h
index 07e5cb96e..4377200c2 100644
--- a/libobs/obs.h
+++ b/libobs/obs.h
@@ -33,6 +33,7 @@
/* opaque types */
struct obs_display;
+struct obs_viewport;
struct obs_source;
struct obs_scene;
struct obs_scene_item;
@@ -41,6 +42,7 @@ struct obs_encoder;
struct obs_service;
typedef struct obs_display *obs_display_t;
+typedef struct obs_viewport *obs_viewport_t;
typedef struct obs_source *obs_source_t;
typedef struct obs_scene *obs_scene_t;
typedef struct obs_scene_item *obs_sceneitem_t;
@@ -189,6 +191,9 @@ EXPORT bool obs_startup(void);
/** Releases all data associated with OBS and terminates the OBS context */
EXPORT void obs_shutdown(void);
+/** @return true if the main OBS context has been initialized */
+EXPORT bool obs_initialized(void);
+
/**
* Sets base video ouput base resolution/fps/format
*
@@ -250,10 +255,13 @@ EXPORT bool obs_enum_transition_types(size_t idx, const char **id);
*/
EXPORT bool obs_enum_output_types(size_t idx, const char **id);
-/** Gets the graphics context for this OBS context */
+/** Gets the main graphics context for this OBS context */
EXPORT graphics_t obs_graphics(void);
+/** Gets the main audio output handler for this OBS context */
EXPORT audio_t obs_audio(void);
+
+/** Gets the main video output handler for this OBS context */
EXPORT video_t obs_video(void);
/**
@@ -317,25 +325,83 @@ EXPORT signal_handler_t obs_signalhandler(void);
/** Returns the primary obs procedure handler */
EXPORT proc_handler_t obs_prochandler(void);
+/** Adds a draw callback to the main render context */
+EXPORT void obs_add_draw_callback(
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param);
+
+/** Removes a draw callback to the main render context */
+EXPORT void obs_remove_draw_callback(
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param);
+
+/** Changes the size of the main viewport */
+EXPORT void obs_resize(uint32_t cx, uint32_t cy);
+
+/** Renders the main viewport */
+EXPORT void obs_render_main_viewport(void);
+
+
+/* ------------------------------------------------------------------------- */
+/* Viewport context */
+
+/**
+ * Creates a viewport context.
+ *
+ * A viewport can be used for things like separate previews, or drawing
+ * sources separately.
+ */
+EXPORT obs_viewport_t obs_viewport_create(void);
+
+/** Destroys this viewport context */
+EXPORT void obs_viewport_destroy(obs_viewport_t viewport);
+
+/** Sets the source to be used for this viewport context. */
+EXPORT void obs_viewport_setsource(obs_viewport_t viewport, uint32_t channel,
+ obs_source_t source);
+
+/** Gets the source currently in use for this viewport context */
+EXPORT obs_source_t obs_viewport_getsource(obs_viewport_t viewport,
+ uint32_t channel);
+
+/** Renders the sources of this viewport context */
+EXPORT void obs_viewport_render(obs_viewport_t viewport);
+
/* ------------------------------------------------------------------------- */
/* Display context */
/**
- * Creates an extra display context.
+ * Adds a new window display linked to the main render pipeline. This creates
+ * a new swap chain which updates every frame.
*
- * An extra display can be used for things like separate previews,
- * viewing sources independently, and other things. Creates a new swap chain
- * linked to a specific window to display a source.
+ * @param graphics_data The swap chain initialization data.
+ * @return The new display context, or NULL if failed.
*/
EXPORT obs_display_t obs_display_create(struct gs_init_data *graphics_data);
+
+/** Destroys a display context */
EXPORT void obs_display_destroy(obs_display_t display);
-/** Sets the source to be used for a display context. */
-EXPORT void obs_display_setsource(obs_display_t display, uint32_t channel,
- obs_source_t source);
-EXPORT obs_source_t obs_display_getsource(obs_display_t display,
- uint32_t channel);
+/** Changes the size of this display */
+EXPORT void obs_display_resize(obs_display_t display, uint32_t cx, uint32_t cy);
+
+/**
+ * Adds a draw callback for this display context
+ *
+ * @param display The display context.
+ * @param draw The draw callback which is called each time a frame
+ * updates.
+ * @param param The user data to be associated with this draw callback.
+ */
+EXPORT void obs_display_add_draw_callback(obs_display_t display,
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param);
+
+/** Removes a draw callback for this display context */
+EXPORT void obs_display_remove_draw_callback(obs_display_t display,
+ void (*draw)(void *param, uint32_t cx, uint32_t cy),
+ void *param);
/* ------------------------------------------------------------------------- */
diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp
index c9e59bf9c..93042c81f 100644
--- a/obs/window-basic-main.cpp
+++ b/obs/window-basic-main.cpp
@@ -1,5 +1,5 @@
/******************************************************************************
- Copyright (C) 2013 by Hugh Bailey
+ Copyright (C) 2013-2014 by Hugh Bailey
Copyright (C) 2014 by Zachary Lund
This program is free software: you can redistribute it and/or modify
@@ -55,6 +55,8 @@ void OBSBasic::OBSInit()
if (!InitAudio())
throw "Failed to initialize audio";
+ obs_add_draw_callback(OBSBasic::RenderMain, this);
+
signal_handler_connect(obs_signalhandler(), "source-add",
OBSBasic::SourceAdded, this);
signal_handler_connect(obs_signalhandler(), "source-remove",
@@ -262,6 +264,11 @@ void OBSBasic::ChannelChanged(void *data, calldata_t params)
Q_ARG(OBSSource, OBSSource(source)));
}
+void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
+{
+ obs_render_main_viewport();
+}
+
/* Main class functions */
bool OBSBasic::InitGraphics()
@@ -331,12 +338,8 @@ void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy)
ui->preview->setGeometry(x, y, cx, cy);
- graphics_t graphics = obs_graphics();
- if (graphics && isVisible()) {
- gs_entercontext(graphics);
- gs_resize(cx, cy);
- gs_leavecontext();
- }
+ if (isVisible())
+ obs_resize(cx, cy);
}
void OBSBasic::closeEvent(QCloseEvent *event)
diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp
index 2434a9bd0..3ce9a52a5 100644
--- a/obs/window-basic-main.hpp
+++ b/obs/window-basic-main.hpp
@@ -1,5 +1,5 @@
/******************************************************************************
- Copyright (C) 2013 by Hugh Bailey
+ Copyright (C) 2013-2014 by Hugh Bailey
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -52,6 +52,7 @@ private:
static void SourceAdded(void *data, calldata_t params);
static void SourceRemoved(void *data, calldata_t params);
static void ChannelChanged(void *data, calldata_t params);
+ static void RenderMain(void *data, uint32_t cx, uint32_t cy);
void ResizePreview(uint32_t cx, uint32_t cy);
diff --git a/vs/2013/libobs/libobs.vcxproj b/vs/2013/libobs/libobs.vcxproj
index 1a8fdfe08..e0c18f51b 100644
--- a/vs/2013/libobs/libobs.vcxproj
+++ b/vs/2013/libobs/libobs.vcxproj
@@ -102,6 +102,7 @@
+
diff --git a/vs/2013/libobs/libobs.vcxproj.filters b/vs/2013/libobs/libobs.vcxproj.filters
index a73830813..97fb4ed59 100644
--- a/vs/2013/libobs/libobs.vcxproj.filters
+++ b/vs/2013/libobs/libobs.vcxproj.filters
@@ -344,5 +344,8 @@
libobs\Source Files
+
+ libobs\Source Files
+
\ No newline at end of file