Implement properties definition interface

Implement a properties definition interface to allow modules to export
general properties associated with objects of libobs.

The properties definition interface allows the option for automatic
settings UI generation (which will make simple plugins easier to develop
without the need for user interface), as well as allow real-time
property editing of values of things like sources/outputs/etc without
having to open property dialogs.  More property types can be added in
the future as needed as well.
This commit is contained in:
jp9000 2014-02-01 18:01:31 -07:00
parent 6f51567c93
commit 0d17d13116
6 changed files with 435 additions and 1 deletions

View file

@ -138,6 +138,7 @@ set(libobs_libobs_SOURCES
obs-source.c
obs-output.c
obs.c
obs-properties.c
obs-data.c
obs-module.c
obs-display.c
@ -150,6 +151,7 @@ set(libobs_libobs_HEADERS
obs-internal.h
obs.h
obs-ui.h
obs-properties.h
obs-data.h
obs-module.h
obs-scene.h

323
libobs/obs-properties.c Normal file
View file

@ -0,0 +1,323 @@
/******************************************************************************
Copyright (C) 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
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 <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "obs-properties.h"
struct float_data {
double min, max, step;
};
struct int_data {
int min, max, step;
};
struct list_data {
const char **strings;
enum obs_dropdown_type type;
};
struct obs_property {
const char *name;
const char *desc;
enum obs_property_type type;
struct obs_property *next;
};
struct obs_category {
const char *name;
struct obs_property *first_property;
struct obs_category *next;
};
struct obs_property_list {
struct obs_category *first_category;
};
obs_property_list_t obs_property_list_create()
{
struct obs_property_list *list;
list = bmalloc(sizeof(struct obs_property_list));
memset(list, 0, sizeof(struct obs_property_list));
return list;
}
static void obs_property_destroy(struct obs_property *property)
{
bfree(property);
}
static void obs_category_destroy(struct obs_category *category)
{
struct obs_property *p = category->first_property;
while (p) {
struct obs_property *next = p->next;
obs_property_destroy(p);
p = next;
}
bfree(category);
}
void obs_property_list_destroy(obs_property_list_t props)
{
struct obs_category *c = props->first_category;
while (c) {
struct obs_category *next = c->next;
obs_category_destroy(c);
c = next;
}
bfree(props);
}
obs_category_t obs_property_list_add_category(obs_property_list_t props,
const char *name)
{
struct obs_category *c = bmalloc(sizeof(struct obs_category));
memset(c, 0, sizeof(struct obs_category));
c->name = name;
c->next = props->first_category;
props->first_category = c;
return c;
}
obs_category_t obs_property_list_categories(obs_property_list_t props)
{
return props->first_category;
}
/* ------------------------------------------------------------------------- */
static inline void category_add(struct obs_category *cat,
struct obs_property *p)
{
p->next = cat->first_property;
cat->first_property = p;
}
static inline size_t get_property_size(enum obs_property_type type)
{
switch (type) {
case OBS_PROPERTY_INVALID: return 0;
case OBS_PROPERTY_INT: return sizeof(struct int_data);
case OBS_PROPERTY_FLOAT: return sizeof(struct float_data);
case OBS_PROPERTY_TEXT: return 0;
case OBS_PROPERTY_PATH: return 0;
case OBS_PROPERTY_ENUM: return sizeof(struct list_data);
case OBS_PROPERTY_TEXT_LIST: return sizeof(struct list_data);
case OBS_PROPERTY_COLOR: return 0;
}
return 0;
}
static inline struct obs_property *new_prop(struct obs_category *cat,
const char *name, const char *desc,
enum obs_property_type type)
{
size_t data_size = get_property_size(type);
struct obs_property *p;
p = bmalloc(sizeof(struct obs_property) + data_size);
memset(p, 0, sizeof(struct obs_property) + data_size);
p->type = type;
p->name = name;
p->desc = desc;
category_add(cat, p);
return p;
}
static inline void *get_property_data(struct obs_property *prop)
{
return (uint8_t*)prop + sizeof(struct obs_property);
}
static inline void *get_type_data(struct obs_property *prop,
enum obs_property_type type)
{
if (!prop || prop->type != type)
return NULL;
return get_property_data(prop);
}
void obs_category_add_int(obs_category_t cat, const char *name,
const char *desc, int min, int max, int step)
{
struct obs_property *p = new_prop(cat, name, desc, OBS_PROPERTY_INT);
struct int_data *data = get_property_data(p);
data->min = min;
data->max = max;
data->step = step;
}
void obs_category_add_float(obs_category_t cat, const char *name,
const char *desc, double min, double max, double step)
{
struct obs_property *p = new_prop(cat, name, desc, OBS_PROPERTY_FLOAT);
struct float_data *data = get_property_data(p);
data->min = min;
data->max = max;
data->step = step;
}
void obs_category_add_text(obs_category_t cat, const char *name,
const char *desc)
{
new_prop(cat, name, desc, OBS_PROPERTY_TEXT);
}
void obs_category_add_path(obs_category_t cat, const char *name,
const char *desc)
{
new_prop(cat, name, desc, OBS_PROPERTY_PATH);
}
void obs_category_add_enum_list(obs_category_t cat, const char *name,
const char *desc, const char **strings)
{
struct obs_property *p = new_prop(cat, name, desc, OBS_PROPERTY_ENUM);
struct list_data *data = get_property_data(p);
data->strings = strings;
data->type = OBS_DROPDOWN_LIST;
}
void obs_category_add_text_list(obs_category_t cat, const char *name,
const char *desc, const char **strings,
enum obs_dropdown_type type)
{
struct obs_property *p = new_prop(cat, name, desc,
OBS_PROPERTY_TEXT_LIST);
struct list_data *data = get_property_data(p);
data->strings = strings;
data->type = type;
}
void obs_category_add_color(obs_category_t cat, const char *name,
const char *desc)
{
new_prop(cat, name, desc, OBS_PROPERTY_COLOR);
}
bool obs_category_next(obs_category_t *cat)
{
if (!cat || !*cat)
return false;
*cat = (*cat)->next;
return *cat != NULL;
}
obs_property_t obs_category_properties(obs_category_t cat)
{
if (!cat)
return NULL;
return cat->first_property;
}
/* ------------------------------------------------------------------------- */
bool obs_property_next(obs_property_t *p)
{
if (!p || !*p)
return false;
*p = (*p)->next;
return *p != NULL;
}
const char *obs_property_name(obs_property_t p)
{
return p->name;
}
const char *obs_property_description(obs_property_t p)
{
return p->desc;
}
enum obs_property_type obs_property_type(obs_property_t p)
{
return p->type;
}
int obs_property_int_min(obs_property_t p)
{
struct int_data *data = get_type_data(p, OBS_PROPERTY_INT);
return data ? data->min : 0;
}
int obs_property_int_max(obs_property_t p)
{
struct int_data *data = get_type_data(p, OBS_PROPERTY_INT);
return data ? data->max : 0;
}
int obs_property_int_step(obs_property_t p)
{
struct int_data *data = get_type_data(p, OBS_PROPERTY_INT);
return data ? data->step : 0;
}
double obs_property_float_min(obs_property_t p)
{
struct float_data *data = get_type_data(p, OBS_PROPERTY_FLOAT);
return data ? data->min : 0;
}
double obs_property_float_max(obs_property_t p)
{
struct float_data *data = get_type_data(p, OBS_PROPERTY_FLOAT);
return data ? data->max : 0;
}
double obs_property_float_step(obs_property_t p)
{
struct float_data *data = get_type_data(p, OBS_PROPERTY_FLOAT);
return data ? data->step : 0;
}
static inline bool is_dropdown(struct obs_property *p)
{
return p->type == OBS_PROPERTY_ENUM ||
p->type == OBS_PROPERTY_TEXT_LIST;
}
const char **obs_property_dropdown_strings(obs_property_t p)
{
if (!p || !is_dropdown(p))
return NULL;
struct list_data *data = get_property_data(p);
return data->strings;
}
enum obs_dropdown_type obs_property_dropdown_type(obs_property_t p)
{
if (!p || !is_dropdown(p))
return OBS_DROPDOWN_INVALID;
struct list_data *data = get_property_data(p);
return data->type;
}

101
libobs/obs-properties.h Normal file
View file

@ -0,0 +1,101 @@
/******************************************************************************
Copyright (C) 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
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 <http://www.gnu.org/licenses/>.
******************************************************************************/
#pragma once
#include "obs.h"
#ifdef __cplusplus
extern "C" {
#endif
enum obs_property_type {
OBS_PROPERTY_INVALID,
OBS_PROPERTY_INT,
OBS_PROPERTY_FLOAT,
OBS_PROPERTY_TEXT,
OBS_PROPERTY_PATH,
OBS_PROPERTY_ENUM,
OBS_PROPERTY_TEXT_LIST,
OBS_PROPERTY_COLOR,
};
enum obs_dropdown_type {
OBS_DROPDOWN_INVALID,
OBS_DROPDOWN_EDIT,
OBS_DROPDOWN_LIST,
};
struct obs_property_list;
struct obs_category;
struct obs_property;
typedef struct obs_property_list *obs_property_list_t;
typedef struct obs_category *obs_category_t;
typedef struct obs_property *obs_property_t;
/* ------------------------------------------------------------------------- */
EXPORT obs_property_list_t obs_property_list_create();
EXPORT void obs_property_list_destroy(obs_property_list_t props);
EXPORT obs_category_t obs_property_list_add_category(obs_property_list_t props,
const char *name);
EXPORT obs_category_t obs_property_list_categories(obs_property_list_t props);
/* ------------------------------------------------------------------------- */
EXPORT void obs_category_add_int(obs_category_t cat, const char *name,
const char *description, int min, int max, int step);
EXPORT void obs_category_add_float(obs_category_t cat, const char *name,
const char *description, double min, double max, double step);
EXPORT void obs_category_add_text(obs_category_t cat, const char *name,
const char *description);
EXPORT void obs_category_add_path(obs_category_t cat, const char *name,
const char *description);
EXPORT void obs_category_add_enum_list(obs_category_t cat,
const char *name, const char *description,
const char **strings);
EXPORT void obs_category_add_text_list(obs_category_t cat,
const char *name, const char *description,
const char **strings, enum obs_dropdown_type type);
EXPORT void obs_category_add_color(obs_category_t cat, const char *name,
const char *description);
EXPORT bool obs_category_next(obs_category_t *cat);
EXPORT obs_property_t obs_category_properties(obs_category_t cat);
/* ------------------------------------------------------------------------- */
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 bool obs_property_next(obs_property_t *p);
EXPORT int obs_property_int_min(obs_property_t p);
EXPORT int obs_property_int_max(obs_property_t p);
EXPORT int obs_property_int_step(obs_property_t p);
EXPORT double obs_property_float_min(obs_property_t p);
EXPORT double obs_property_float_max(obs_property_t p);
EXPORT double obs_property_float_step(obs_property_t p);
EXPORT const char ** obs_property_dropdown_strings(obs_property_t p);
EXPORT enum obs_dropdown_type obs_property_dropdown_type(obs_property_t p);
#ifdef __cplusplus
}
#endif

View file

@ -28,8 +28,8 @@
#include "obs-defs.h"
#include "obs-data.h"
#include "obs-ui.h"
#include "obs-properties.h"
/*
* Main libobs header used by applications.

View file

@ -49,6 +49,7 @@
<ClInclude Include="..\..\..\libobs\obs-internal.h" />
<ClInclude Include="..\..\..\libobs\obs-module.h" />
<ClInclude Include="..\..\..\libobs\obs-output.h" />
<ClInclude Include="..\..\..\libobs\obs-properties.h" />
<ClInclude Include="..\..\..\libobs\obs-scene.h" />
<ClInclude Include="..\..\..\libobs\obs-service.h" />
<ClInclude Include="..\..\..\libobs\obs-source.h" />
@ -97,6 +98,7 @@
<ClCompile Include="..\..\..\libobs\obs-encoder.c" />
<ClCompile Include="..\..\..\libobs\obs-module.c" />
<ClCompile Include="..\..\..\libobs\obs-output.c" />
<ClCompile Include="..\..\..\libobs\obs-properties.c" />
<ClCompile Include="..\..\..\libobs\obs-scene.c" />
<ClCompile Include="..\..\..\libobs\obs-source.c" />
<ClCompile Include="..\..\..\libobs\obs-video.c" />

View file

@ -204,6 +204,9 @@
<ClInclude Include="..\..\..\libobs\obs-data.h">
<Filter>libobs\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\libobs\obs-properties.h">
<Filter>libobs\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\libobs\obs-output.c">
@ -338,5 +341,8 @@
<ClCompile Include="..\..\..\libobs\obs-data.c">
<Filter>libobs\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\libobs\obs-properties.c">
<Filter>libobs\Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>