Add source properties window (very preliminary)

- Add a properties window for sources so that you can now actually edit
   the settings for sources.  Also, display the source by itself in the
   window (Note: not working on mac, and possibly not working on linux).

   When changing the settings for a source, it will call
   obs_source_update on that source when you have modified any values
   automatically.

 - Add a properties 'widget', eventually I want to turn this in to a
   regular nice properties view like you'd see in the designer, but
   right now it just uses a form layout in a QScrollArea with regular
   controls to display the properties.  It's clunky but works for the
   time being.

 - Make it so that swap chains and the main graphics subsystem will
   automatically use at least one backbuffer if none was specified

 - Fix bug where displays weren't added to the main display array

 - Make it so that you can get the properties of a source via the actual
   pointer of a source/encoder/output in addition to being able to look
   up properties via identifier.

 - When registering source types, check for required functions (wasn't
   doing it before).  getheight/getwidth should not be optional if it's
   a video source as well.

 - Add an RAII OBSObj wrapper to obs.hpp for non-reference-counted
   libobs pointers

 - Add an RAII OBSSignal wrapper to obs.hpp for libobs signals to
   automatically disconnect them on destruction

 - Move the "scale and center" calculation in window-basic-main.cpp to
   its own function and in its own source file

 - Add an 'update' callback to WASAPI audio sources
This commit is contained in:
jp9000
2014-03-23 01:07:54 -07:00
parent 6c904650b3
commit d9251f9e87
26 changed files with 991 additions and 74 deletions

View File

@@ -114,6 +114,9 @@ int gs_create(graphics_t *pgraphics, const char *module,
graphics_t graphics = bzalloc(sizeof(struct graphics_subsystem));
pthread_mutex_init_value(&graphics->mutex);
if (!data->num_backbuffers)
data->num_backbuffers = 1;
graphics->module = os_dlopen(module);
if (!graphics->module) {
errcode = GS_ERROR_MODULENOTFOUND;

View File

@@ -48,11 +48,22 @@ obs_display_t obs_display_create(struct gs_init_data *graphics_data)
{
struct obs_display *display = bzalloc(sizeof(struct obs_display));
gs_entercontext(obs_graphics());
if (!graphics_data->num_backbuffers)
graphics_data->num_backbuffers = 1;
if (!obs_display_init(display, graphics_data)) {
obs_display_destroy(display);
display = NULL;
} else {
pthread_mutex_lock(&obs->data.displays_mutex);
da_push_back(obs->data.displays, &display);
pthread_mutex_unlock(&obs->data.displays_mutex);
}
gs_leavecontext();
return display;
}
@@ -74,7 +85,10 @@ void obs_display_destroy(obs_display_t display)
da_erase_item(obs->data.displays, &display);
pthread_mutex_unlock(&obs->data.displays_mutex);
gs_entercontext(obs_graphics());
obs_display_free(display);
gs_leavecontext();
bfree(display);
}
}

View File

@@ -208,7 +208,7 @@ obs_data_t obs_encoder_defaults(const char *id)
return NULL;
}
obs_properties_t obs_encoder_properties(const char *id, const char *locale)
obs_properties_t obs_get_encoder_properties(const char *id, const char *locale)
{
const struct obs_encoder_info *ei = get_encoder_info(id);
if (ei && ei->properties)
@@ -216,6 +216,14 @@ obs_properties_t obs_encoder_properties(const char *id, const char *locale)
return NULL;
}
obs_properties_t obs_encoder_properties(obs_encoder_t encoder,
const char *locale)
{
if (encoder && encoder->info.properties)
return encoder->info.properties(locale);
return NULL;
}
void obs_encoder_update(obs_encoder_t encoder, obs_data_t settings)
{
if (!encoder) return;

View File

@@ -130,14 +130,42 @@ void free_module(struct obs_module *mod)
bfree(mod->name);
}
#define REGISTER_OBS_DEF(size_var, structure, dest, info) \
do { \
struct structure data = {0}; \
if (!size_var) { \
blog(LOG_ERROR, "Tried to register " #structure \
" outside of obs_module_load"); \
return; \
} \
\
memcpy(&data, info, size_var); \
da_push_back(dest, &data); \
} while (false)
#define CHECK_REQUIRED_VAL(info, val, func) \
do { \
if (!info->val) {\
blog(LOG_ERROR, "Required value '" #val " for" \
"'%s' not found. " #func \
" failed.", info->id); \
return; \
} \
} while (false)
void obs_register_source(const struct obs_source_info *info)
{
struct obs_source_info data = {0};
struct darray *array;
if (!info) {
blog(LOG_ERROR, "obs_register_source: NULL info");
return;
CHECK_REQUIRED_VAL(info, getname, obs_register_source);
CHECK_REQUIRED_VAL(info, create, obs_register_source);
CHECK_REQUIRED_VAL(info, destroy, obs_register_source);
if (info->type == OBS_SOURCE_TYPE_INPUT &&
info->output_flags & OBS_SOURCE_VIDEO) {
CHECK_REQUIRED_VAL(info, getwidth, obs_register_source);
CHECK_REQUIRED_VAL(info, getheight, obs_register_source);
}
if (!cur_source_info_size) {
@@ -163,29 +191,6 @@ void obs_register_source(const struct obs_source_info *info)
darray_push_back(sizeof(struct obs_source_info), array, &data);
}
#define REGISTER_OBS_DEF(size_var, structure, dest, info) \
do { \
struct structure data = {0}; \
if (!size_var) { \
blog(LOG_ERROR, "Tried to register " #structure \
" outside of obs_module_load"); \
return; \
} \
\
memcpy(&data, info, size_var); \
da_push_back(dest, &data); \
} while (false)
#define CHECK_REQUIRED_VAL(info, val, func) \
do { \
if (!info->val) {\
blog(LOG_ERROR, "Required value '" #val " for" \
"'%s' not found. " #func \
" failed.", info->id); \
return; \
} \
} while (false)
void obs_register_output(const struct obs_output_info *info)
{
CHECK_REQUIRED_VAL(info, getname, obs_register_output);

View File

@@ -128,7 +128,7 @@ obs_data_t obs_output_defaults(const char *id)
return NULL;
}
obs_properties_t obs_output_properties(const char *id, const char *locale)
obs_properties_t obs_get_output_properties(const char *id, const char *locale)
{
const struct obs_output_info *info = find_output(id);
if (info && info->properties)
@@ -136,6 +136,13 @@ obs_properties_t obs_output_properties(const char *id, const char *locale)
return NULL;
}
obs_properties_t obs_output_properties(obs_output_t output, const char *locale)
{
if (output && output->info.properties)
return output->info.properties(locale);
return NULL;
}
void obs_output_update(obs_output_t output, obs_data_t settings)
{
if (!output) return;

View File

@@ -315,7 +315,7 @@ const char *obs_property_description(obs_property_t p)
return p ? p->desc : NULL;
}
enum obs_property_type obs_property_type(obs_property_t p)
enum obs_property_type obs_property_get_type(obs_property_t p)
{
return p ? p->type : OBS_PROPERTY_INVALID;
}

View File

@@ -87,7 +87,7 @@ EXPORT void obs_property_list_add_item(obs_property_t p,
EXPORT const char * obs_property_name(obs_property_t p);
EXPORT const char * obs_property_description(obs_property_t p);
EXPORT enum obs_property_type obs_property_type(obs_property_t p);
EXPORT enum obs_property_type obs_property_get_type(obs_property_t p);
EXPORT bool obs_property_next(obs_property_t *p);

View File

@@ -327,7 +327,7 @@ obs_data_t obs_source_settings(enum obs_source_type type, const char *id)
return NULL;
}
obs_properties_t obs_source_properties(enum obs_source_type type,
obs_properties_t obs_get_source_properties(enum obs_source_type type,
const char *id, const char *locale)
{
const struct obs_source_info *info = get_source_info(type, id);
@@ -336,6 +336,13 @@ obs_properties_t obs_source_properties(enum obs_source_type type,
return NULL;
}
obs_properties_t obs_source_properties(obs_source_t source, const char *locale)
{
if (source && source->info.properties)
return source->info.properties(locale);
return NULL;
}
uint32_t obs_source_get_output_flags(obs_source_t source)
{
return source ? source->info.output_flags : 0;

View File

@@ -132,6 +132,12 @@ struct obs_source_info {
/** Destroys the private data for the source */
void (*destroy)(void *data);
/** Returns the width of the source. Required if input and video */
uint32_t (*getwidth)(void *data);
/** Returns the height of the source. Required if input and video */
uint32_t (*getheight)(void *data);
/* ----------------------------------------------------------------- */
/* Optional implementation */
@@ -210,12 +216,6 @@ struct obs_source_info {
*/
void (*video_render)(void *data, effect_t effect);
/** @return The width of the source */
uint32_t (*getwidth)(void *data);
/** @return The height of the source */
uint32_t (*getheight)(void *data);
/**
* Called to filter raw async video data.
*

View File

@@ -1,5 +1,5 @@
/******************************************************************************
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
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
@@ -42,7 +42,7 @@ struct obs_encoder;
struct obs_service;
typedef struct obs_display *obs_display_t;
typedef struct obs_view *obs_view_t;
typedef struct obs_view *obs_view_t;
typedef struct obs_source *obs_source_t;
typedef struct obs_scene *obs_scene_t;
typedef struct obs_scene_item *obs_sceneitem_t;
@@ -438,13 +438,20 @@ EXPORT bool obs_source_removed(obs_source_t source);
EXPORT uint32_t obs_source_get_output_flags(obs_source_t source);
/** Gets the default settings for a source type */
EXPORT obs_data_t obs_source_defaults(enum obs_source_type type,
EXPORT obs_data_t obs_get_source_defaults(enum obs_source_type type,
const char *id);
/** Returns the property list, if any. Free with obs_properties_destroy */
EXPORT obs_properties_t obs_source_properties(enum obs_source_type type,
EXPORT obs_properties_t obs_get_source_properties(enum obs_source_type type,
const char *id, const char *locale);
/**
* Returns the properties list for a specific existing source. Free with
* obs_properties_destroy
*/
EXPORT obs_properties_t obs_source_properties(obs_source_t source,
const char *locale);
/** Updates settings for this source */
EXPORT void obs_source_update(obs_source_t source, obs_data_t settings);
@@ -662,7 +669,14 @@ EXPORT bool obs_output_active(obs_output_t output);
EXPORT obs_data_t obs_output_defaults(const char *id);
/** Returns the property list, if any. Free with obs_properties_destroy */
EXPORT obs_properties_t obs_output_properties(const char *id,
EXPORT obs_properties_t obs_get_output_properties(const char *id,
const char *locale);
/**
* Returns the property list of an existing output, if any. Free with
* obs_properties_destroy
*/
EXPORT obs_properties_t obs_output_properties(obs_output_t output,
const char *locale);
/** Updates the settings for this output context */
@@ -742,7 +756,14 @@ EXPORT void obs_encoder_stop(obs_encoder_t encoder,
EXPORT obs_data_t obs_encoder_defaults(const char *id);
/** Returns the property list, if any. Free with obs_properties_destroy */
EXPORT obs_properties_t obs_encoder_properties(const char *id,
EXPORT obs_properties_t obs_get_encoder_properties(const char *id,
const char *locale);
/**
* Returns the property list of an existing encoder, if any. Free with
* obs_properties_destroy
*/
EXPORT obs_properties_t obs_encoder_properties(obs_encoder_t encoder,
const char *locale);
/**

View File

@@ -63,10 +63,91 @@ public:
};
using OBSSource = OBSRef<obs_source_t, obs_source_addref, obs_source_release>;
using OBSScene = OBSRef<obs_scene_t, obs_scene_addref, obs_scene_release>;
using OBSScene = OBSRef<obs_scene_t, obs_scene_addref, obs_scene_release>;
using OBSSceneItem = OBSRef<obs_sceneitem_t, obs_sceneitem_addref,
obs_sceneitem_release>;
using OBSData = OBSRef<obs_data_t, obs_data_addref, obs_data_release>;
using OBSDataArray = OBSRef<obs_data_array_t, obs_data_array_addref,
obs_data_array_release>;
/* objects that are not meant to be instanced */
template<typename T, void destroy(T)> class OBSObj {
T obj;
public:
inline OBSObj() : obj(nullptr) {}
inline OBSObj(T obj_) : obj(obj_) {}
inline ~OBSObj() {destroy(obj);}
inline OBSObj &operator=(T obj_)
{
if (obj_ != obj)
destroy(obj);
obj = obj_;
return *this;
}
inline operator T() const {return obj;}
inline bool operator==(T p) const {return obj == p;}
inline bool operator!=(T p) const {return obj != p;}
};
using OBSDisplay = OBSObj<obs_display_t, obs_display_destroy>;
using OBSEncoder = OBSObj<obs_encoder_t, obs_encoder_destroy>;
using OBSView = OBSObj<obs_view_t, obs_view_destroy>;
using OBSOutput = OBSObj<obs_output_t, obs_output_destroy>;
/* signal handler connection */
class OBSSignal {
signal_handler_t handler;
const char *signal;
signal_callback_t callback;
void *param;
public:
inline OBSSignal()
: handler (nullptr),
signal (nullptr),
callback (nullptr),
param (nullptr)
{}
inline OBSSignal(signal_handler_t handler_,
const char *signal_,
signal_callback_t callback_,
void *param_)
: handler (handler_),
signal (signal_),
callback (callback_),
param (param_)
{
signal_handler_connect(handler, signal, callback, param);
}
inline void Disconnect()
{
signal_handler_disconnect(handler, signal, callback, param);
handler = nullptr;
signal = nullptr;
callback = nullptr;
param = nullptr;
}
inline ~OBSSignal() {Disconnect();}
inline void Connect(signal_handler_t handler_,
const char *signal_,
signal_callback_t callback_,
void *param_)
{
Disconnect();
handler = handler_;
signal = signal_;
callback = callback_;
param = param_;
signal_handler_connect(handler, signal, callback, param);
}
};