Improve properties API

Improve the properties API so that it can actually respond somewhat to
user input.  Maybe later this might be further improved or replaced with
something script-based.

When creating a property, you can now add a callback to that property
that notifies when the property has been changed in the user interface.
Return true if you want the properties to be refreshed, or false if not.
Though now that I think about it I doubt there would ever be a case
where you would have this callback and *not* refresh the properties.

Regardless, this allows functions to change the values of properties or
settings, or enable/disable/hide other property controls from view
dynamically.
master
jp9000 2014-04-04 00:30:37 -07:00
parent baa57d4c39
commit 1bca7e0a3e
18 changed files with 466 additions and 174 deletions

View File

@ -219,32 +219,44 @@ void obs_encoder_destroy(obs_encoder_t encoder)
}
}
static inline obs_data_t get_defaults(const struct obs_encoder_info *info)
{
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
obs_data_t obs_encoder_defaults(const char *id)
{
const struct obs_encoder_info *info = get_encoder_info(id);
if (info) {
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
return NULL;
return (info) ? get_defaults(info) : NULL;
}
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)
return ei->properties(locale);
if (ei && ei->properties) {
obs_data_t defaults = get_defaults(ei);
obs_properties_t properties;
properties = ei->properties(locale);
obs_properties_apply_settings(properties, defaults);
obs_data_release(defaults);
return properties;
}
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);
if (encoder && encoder->info.properties) {
obs_properties_t props;
props = encoder->info.properties(locale);
obs_properties_apply_settings(props, encoder->settings);
return props;
}
return NULL;
}

View File

@ -36,11 +36,11 @@ struct encoder_packet {
enum obs_encoder_type type; /**< Encoder type */
bool keyframe; /**< Is a keyframe */
/* ---------------------------------------------------------------- */
/* Internal video variables (will be parsed automatically) */
bool keyframe; /**< Is a keyframe */
/**
* Packet priority
*

View File

@ -268,6 +268,9 @@ struct obs_output {
signal_handler_t signals;
proc_handler_t procs;
pthread_mutex_t interleaved_mutex;
DARRAY(struct encoder_packet) interleaved_packets;
bool active;
video_t video;
audio_t audio;

View File

@ -98,8 +98,10 @@ int obs_load_module(const char *path)
mod.module = os_dlopen(plugin_path);
bfree(plugin_path);
if (!mod.module)
if (!mod.module) {
blog(LOG_DEBUG, "Module '%s' not found", path);
return MODULE_FILE_NOT_FOUND;
}
errorcode = call_module_load(mod.module, path);
if (errorcode != MODULE_SUCCESS) {
@ -200,7 +202,7 @@ void obs_register_output(const struct obs_output_info *info)
CHECK_REQUIRED_VAL(info, stop, obs_register_output);
if (info->flags & OBS_OUTPUT_ENCODED) {
CHECK_REQUIRED_VAL(info, encoded_data, obs_register_output);
CHECK_REQUIRED_VAL(info, encoded_packet, obs_register_output);
} else {
if (info->flags & OBS_OUTPUT_VIDEO)
CHECK_REQUIRED_VAL(info, raw_video,

View File

@ -60,7 +60,10 @@ obs_output_t obs_output_create(const char *id, const char *name,
}
output = bzalloc(sizeof(struct obs_output));
pthread_mutex_init_value(&output->interleaved_mutex);
if (pthread_mutex_init(&output->interleaved_mutex, NULL) != 0)
goto fail;
if (!init_output_handlers(output))
goto fail;
@ -90,6 +93,13 @@ fail:
return NULL;
}
static inline void free_packets(struct obs_output *output)
{
for (size_t i = 0; i < output->interleaved_packets.num; i++)
obs_free_encoder_packet(output->interleaved_packets.array+i);
da_free(output->interleaved_packets);
}
void obs_output_destroy(obs_output_t output)
{
if (output) {
@ -102,6 +112,8 @@ void obs_output_destroy(obs_output_t output)
pthread_mutex_unlock(&obs->data.outputs_mutex);
}
free_packets(output);
if (output->data)
output->info.destroy(output->data);
@ -109,6 +121,7 @@ void obs_output_destroy(obs_output_t output)
proc_handler_destroy(output->procs);
obs_data_release(output->settings);
pthread_mutex_destroy(&output->interleaved_mutex);
bfree(output->name);
bfree(output);
}
@ -130,31 +143,44 @@ bool obs_output_active(obs_output_t output)
return (output != NULL) ? output->active : false;
}
static inline obs_data_t get_defaults(const struct obs_output_info *info)
{
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
obs_data_t obs_output_defaults(const char *id)
{
const struct obs_output_info *info = find_output(id);
if (info) {
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
return NULL;
return (info) ? get_defaults(info) : NULL;
}
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)
return info->properties(locale);
if (info && info->properties) {
obs_data_t defaults = get_defaults(info);
obs_properties_t properties;
properties = info->properties(locale);
obs_properties_apply_settings(properties, defaults);
obs_data_release(defaults);
return properties;
}
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);
if (output && output->info.properties) {
obs_properties_t props;
props = output->info.properties(locale);
obs_properties_apply_settings(props, output->settings);
return props;
}
return NULL;
}
@ -316,18 +342,28 @@ static inline struct audio_convert_info *get_audio_conversion(
return output->audio_conversion_set ? &output->audio_conversion : NULL;
}
static void interleave_packets(void *data, struct encoder_packet *packet)
{
}
static void hook_data_capture(struct obs_output *output, bool encoded,
bool has_video, bool has_audio)
{
void (*encoded_callback)(void *data, struct encoder_packet *packet);
void *param;
if (encoded) {
encoded_callback = (has_video && has_audio) ?
interleave_packets : output->info.encoded_packet;
param = (has_video && has_audio) ? output : output->data;
if (has_video)
obs_encoder_start(output->video_encoder,
output->info.encoded_data,
output->data);
encoded_callback, param);
if (has_audio)
obs_encoder_start(output->audio_encoder,
output->info.encoded_data,
output->data);
encoded_callback, param);
} else {
if (has_video)
video_output_connect(output->video,
@ -405,6 +441,8 @@ bool obs_output_begin_data_capture(obs_output_t output, uint32_t flags)
void obs_output_end_data_capture(obs_output_t output)
{
bool encoded, has_video, has_audio;
void (*encoded_callback)(void *data, struct encoder_packet *packet);
void *param;
if (!output) return;
if (!output->active) return;
@ -412,14 +450,16 @@ void obs_output_end_data_capture(obs_output_t output)
convert_flags(output, 0, &encoded, &has_video, &has_audio);
if (encoded) {
encoded_callback = (has_video && has_audio) ?
interleave_packets : output->info.encoded_packet;
param = (has_video && has_audio) ? output : output->data;
if (has_video)
obs_encoder_stop(output->video_encoder,
output->info.encoded_data,
output->data);
encoded_callback, param);
if (has_audio)
obs_encoder_stop(output->audio_encoder,
output->info.encoded_data,
output->data);
encoded_callback, param);
} else {
if (has_video)
video_output_disconnect(output->video,

View File

@ -42,7 +42,7 @@ struct obs_output_info {
void (*raw_video)(void *data, struct video_data *frame);
void (*raw_audio)(void *data, struct audio_data *frames);
void (*encoded_data)(void *data, struct encoder_packet *packet);
void (*encoded_packet)(void *data, struct encoder_packet *packet);
/* optional */
void (*update)(void *data, obs_data_t settings);

View File

@ -33,7 +33,12 @@ struct int_data {
struct list_item {
char *name;
char *value;
union {
char *str;
long long ll;
double d;
};
};
struct text_data {
@ -46,34 +51,51 @@ struct list_data {
enum obs_combo_format format;
};
static inline void list_item_free(struct list_data *data,
struct list_item *item)
{
bfree(item->name);
if (data->format == OBS_COMBO_FORMAT_STRING)
bfree(item->str);
}
static inline void list_data_free(struct list_data *data)
{
for (size_t i = 0; i < data->items.num; i++) {
bfree(data->items.array[i].name);
bfree(data->items.array[i].value);
}
for (size_t i = 0; i < data->items.num; i++)
list_item_free(data, data->items.array+i);
da_free(data->items);
}
struct obs_property {
const char *name;
const char *desc;
enum obs_property_type type;
struct obs_properties;
struct obs_property *next;
struct obs_property {
const char *name;
const char *desc;
enum obs_property_type type;
bool visible;
bool enabled;
struct obs_properties *parent;
obs_property_modified_t modified;
struct obs_property *next;
};
struct obs_properties {
struct obs_property *first_property;
struct obs_property **last;
const char *locale;
struct obs_property *first_property;
struct obs_property **last;
};
obs_properties_t obs_properties_create()
obs_properties_t obs_properties_create(const char *locale)
{
struct obs_properties *props;
props = bzalloc(sizeof(struct obs_properties));
props->last = &props->first_property;
props->locale = locale;
props->last = &props->first_property;
return props;
}
@ -101,6 +123,11 @@ void obs_properties_destroy(obs_properties_t props)
}
}
const char *obs_properties_locale(obs_properties_t props)
{
return props ? props->locale : NULL;
}
obs_property_t obs_properties_first(obs_properties_t props)
{
return (props != NULL) ? props->first_property : NULL;
@ -124,6 +151,17 @@ obs_property_t obs_properties_get(obs_properties_t props, const char *name)
return NULL;
}
void obs_properties_apply_settings(obs_properties_t props, obs_data_t settings)
{
struct obs_property *p = props->first_property;
while (p) {
if (p->modified)
p->modified(props, p, settings);
p = p->next;
}
}
/* ------------------------------------------------------------------------- */
static inline void propertes_add(struct obs_properties *props,
@ -157,9 +195,12 @@ static inline struct obs_property *new_prop(struct obs_properties *props,
struct obs_property *p;
p = bzalloc(sizeof(struct obs_property) + data_size);
p->type = type;
p->name = name;
p->desc = desc;
p->parent = props;
p->enabled = true;
p->visible = true;
p->type = type;
p->name = name;
p->desc = desc;
propertes_add(props, p);
return p;
@ -195,29 +236,31 @@ static inline void *get_type_data(struct obs_property *prop,
return get_property_data(prop);
}
void obs_properties_add_bool(obs_properties_t props, const char *name,
obs_property_t obs_properties_add_bool(obs_properties_t props, const char *name,
const char *desc)
{
if (!props || has_prop(props, name)) return;
new_prop(props, name, desc, OBS_PROPERTY_BOOL);
if (!props || has_prop(props, name)) return NULL;
return new_prop(props, name, desc, OBS_PROPERTY_BOOL);
}
void obs_properties_add_int(obs_properties_t props, const char *name,
obs_property_t obs_properties_add_int(obs_properties_t props, const char *name,
const char *desc, int min, int max, int step)
{
if (!props || has_prop(props, name)) return;
if (!props || has_prop(props, name)) return NULL;
struct obs_property *p = new_prop(props, name, desc, OBS_PROPERTY_INT);
struct int_data *data = get_property_data(p);
data->min = min;
data->max = max;
data->step = step;
return p;
}
void obs_properties_add_float(obs_properties_t props, const char *name,
const char *desc, double min, double max, double step)
obs_property_t obs_properties_add_float(obs_properties_t props,
const char *name, const char *desc,
double min, double max, double step)
{
if (!props || has_prop(props, name)) return;
if (!props || has_prop(props, name)) return NULL;
struct obs_property *p = new_prop(props, name, desc,
OBS_PROPERTY_FLOAT);
@ -225,23 +268,25 @@ void obs_properties_add_float(obs_properties_t props, const char *name,
data->min = min;
data->max = max;
data->step = step;
return p;
}
void obs_properties_add_text(obs_properties_t props, const char *name,
obs_property_t obs_properties_add_text(obs_properties_t props, const char *name,
const char *desc, enum obs_text_type type)
{
if (!props || has_prop(props, name)) return;
if (!props || has_prop(props, name)) return NULL;
struct obs_property *p = new_prop(props, name, desc, OBS_PROPERTY_TEXT);
struct text_data *data = get_property_data(p);
data->type = type;
return p;
}
void obs_properties_add_path(obs_properties_t props, const char *name,
obs_property_t obs_properties_add_path(obs_properties_t props, const char *name,
const char *desc)
{
if (!props || has_prop(props, name)) return;
new_prop(props, name, desc, OBS_PROPERTY_PATH);
if (!props || has_prop(props, name)) return NULL;
return new_prop(props, name, desc, OBS_PROPERTY_PATH);
}
obs_property_t obs_properties_add_list(obs_properties_t props,
@ -266,11 +311,11 @@ obs_property_t obs_properties_add_list(obs_properties_t props,
return p;
}
void obs_properties_add_color(obs_properties_t props, const char *name,
const char *desc)
obs_property_t obs_properties_add_color(obs_properties_t props,
const char *name, const char *desc)
{
if (!props || has_prop(props, name)) return;
new_prop(props, name, desc, OBS_PROPERTY_COLOR);
if (!props || has_prop(props, name)) return NULL;
return new_prop(props, name, desc, OBS_PROPERTY_COLOR);
}
@ -287,18 +332,11 @@ static inline struct list_data *get_list_data(struct obs_property *p)
return get_property_data(p);
}
void obs_property_list_add_item(obs_property_t p,
const char *name, const char *value)
static inline struct list_data *get_list_fmt_data(struct obs_property *p,
enum obs_combo_format format)
{
struct list_data *data = get_list_data(p);
if (data) {
struct list_item item = {
.name = bstrdup(name),
.value = bstrdup(value)
};
da_push_back(data->items, &item);
}
return (data->format == format) ? data : NULL;
}
/* ------------------------------------------------------------------------- */
@ -312,6 +350,29 @@ bool obs_property_next(obs_property_t *p)
return *p != NULL;
}
void obs_property_set_modified_callback(obs_property_t p,
obs_property_modified_t modified)
{
if (p) p->modified = modified;
}
bool obs_property_modified(obs_property_t p, obs_data_t settings)
{
if (p && p->modified)
return p->modified(p->parent, p, settings);
return false;
}
void obs_property_set_visible(obs_property_t p, bool visible)
{
if (p) p->visible = visible;
}
void obs_property_set_enabled(obs_property_t p, bool enabled)
{
if (p) p->enabled = enabled;
}
const char *obs_property_name(obs_property_t p)
{
return p ? p->name : NULL;
@ -327,6 +388,16 @@ enum obs_property_type obs_property_get_type(obs_property_t p)
return p ? p->type : OBS_PROPERTY_INVALID;
}
bool obs_property_enabled(obs_property_t p)
{
return p ? p->enabled : false;
}
bool obs_property_visible(obs_property_t p)
{
return p ? p->visible : false;
}
int obs_property_int_min(obs_property_t p)
{
struct int_data *data = get_type_data(p, OBS_PROPERTY_INT);
@ -381,6 +452,61 @@ enum obs_combo_format obs_property_list_format(obs_property_t p)
return data ? data->format : OBS_COMBO_FORMAT_INVALID;
}
void obs_property_list_clear(obs_property_t p)
{
struct list_data *data = get_list_data(p);
if (data)
list_data_free(data);
}
static void add_item(struct list_data *data, const char *name, const void *val)
{
struct list_item item;
item.name = bstrdup(name);
if (data->format == OBS_COMBO_FORMAT_INT)
item.ll = *(const long long*)val;
else if (data->format == OBS_COMBO_FORMAT_FLOAT)
item.d = *(const double*)val;
else
item.str = bstrdup(val);
da_push_back(data->items, &item);
}
void obs_property_list_add_string(obs_property_t p,
const char *name, const char *val)
{
struct list_data *data = get_list_data(p);
if (data && data->format == OBS_COMBO_FORMAT_STRING)
add_item(data, name, val);
}
void obs_property_list_add_int(obs_property_t p,
const char *name, long long val)
{
struct list_data *data = get_list_data(p);
if (data && data->format == OBS_COMBO_FORMAT_INT)
add_item(data, name, &val);
}
void obs_property_list_add_float(obs_property_t p,
const char *name, double val)
{
struct list_data *data = get_list_data(p);
if (data && data->format == OBS_COMBO_FORMAT_FLOAT)
add_item(data, name, &val);
}
void obs_property_list_item_remove(obs_property_t p, size_t idx)
{
struct list_data *data = get_list_data(p);
if (data && idx < data->items.num) {
list_item_free(data, data->items.array+idx);
da_erase(data->items, idx);
}
}
size_t obs_property_list_item_count(obs_property_t p)
{
struct list_data *data = get_list_data(p);
@ -394,9 +520,23 @@ const char *obs_property_list_item_name(obs_property_t p, size_t idx)
data->items.array[idx].name : NULL;
}
const char *obs_property_list_item_value(obs_property_t p, size_t idx)
const char *obs_property_list_item_string(obs_property_t p, size_t idx)
{
struct list_data *data = get_list_data(p);
struct list_data *data = get_list_fmt_data(p, OBS_COMBO_FORMAT_STRING);
return (data && idx < data->items.num) ?
data->items.array[idx].value : NULL;
data->items.array[idx].str : "";
}
long long obs_property_list_item_int(obs_property_t p, size_t idx)
{
struct list_data *data = get_list_fmt_data(p, OBS_COMBO_FORMAT_INT);
return (data && idx < data->items.num) ?
data->items.array[idx].ll : 0;
}
double obs_property_list_item_float(obs_property_t p, size_t idx)
{
struct list_data *data = get_list_fmt_data(p, OBS_COMBO_FORMAT_FLOAT);
return (data && idx < data->items.num) ?
data->items.array[idx].d : 0.0;
}

View File

@ -18,6 +18,7 @@
#pragma once
#include "util/c99defs.h"
#include "obs-data.h"
#ifdef __cplusplus
extern "C" {
@ -59,40 +60,64 @@ typedef struct obs_property *obs_property_t;
/* ------------------------------------------------------------------------- */
EXPORT obs_properties_t obs_properties_create();
EXPORT obs_properties_t obs_properties_create(const char *locale);
EXPORT void obs_properties_destroy(obs_properties_t props);
EXPORT const char *obs_properties_locale(obs_properties_t props);
EXPORT obs_property_t obs_properties_first(obs_properties_t props);
EXPORT obs_property_t obs_properties_get(obs_properties_t props,
const char *property);
/* used internally by libobs */
extern void obs_properties_apply_settings(obs_properties_t props,
obs_data_t settings);
/* ------------------------------------------------------------------------- */
EXPORT void obs_properties_add_bool(obs_properties_t props, const char *name,
const char *description);
EXPORT void obs_properties_add_int(obs_properties_t props, const char *name,
const char *description, int min, int max, int step);
EXPORT void obs_properties_add_float(obs_properties_t props, const char *name,
const char *description, double min, double max, double step);
EXPORT void obs_properties_add_text(obs_properties_t props, const char *name,
const char *description, enum obs_text_type type);
EXPORT void obs_properties_add_path(obs_properties_t props, const char *name,
const char *description);
EXPORT obs_property_t obs_properties_add_bool(obs_properties_t props,
const char *name, const char *description);
EXPORT obs_property_t obs_properties_add_int(obs_properties_t props,
const char *name, const char *description,
int min, int max, int step);
EXPORT obs_property_t obs_properties_add_float(obs_properties_t props,
const char *name, const char *description,
double min, double max, double step);
EXPORT obs_property_t obs_properties_add_text(obs_properties_t props,
const char *name, const char *description,
enum obs_text_type type);
EXPORT obs_property_t obs_properties_add_path(obs_properties_t props,
const char *name, const char *description);
EXPORT obs_property_t obs_properties_add_list(obs_properties_t props,
const char *name, const char *description,
enum obs_combo_type type, enum obs_combo_format format);
EXPORT void obs_properties_add_color(obs_properties_t props, const char *name,
const char *description);
EXPORT void obs_property_list_add_item(obs_property_t p,
const char *name, const char *value);
EXPORT obs_property_t obs_properties_add_color(obs_properties_t props,
const char *name, const char *description);
/* ------------------------------------------------------------------------- */
/**
* Optional callback for when a property is modified. If the properties
* need to be refreshed due to changes to the property layout, return true,
* otherwise return false.
*/
typedef bool (*obs_property_modified_t)(obs_properties_t props,
obs_property_t property, obs_data_t settings);
EXPORT void obs_property_set_modified_callback(obs_property_t p,
obs_property_modified_t modified);
EXPORT bool obs_property_modified(obs_property_t p, obs_data_t settings);
EXPORT void obs_property_set_visible(obs_property_t p, bool visible);
EXPORT void obs_property_set_enabled(obs_property_t p, bool enabled);
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_get_type(obs_property_t p);
EXPORT bool obs_property_enabled(obs_property_t p);
EXPORT bool obs_property_visible(obs_property_t p);
EXPORT bool obs_property_next(obs_property_t *p);
@ -106,9 +131,22 @@ EXPORT enum obs_text_type obs_proprety_text_type(obs_property_t p);
EXPORT enum obs_combo_type obs_property_list_type(obs_property_t p);
EXPORT enum obs_combo_format obs_property_list_format(obs_property_t p);
EXPORT void obs_property_list_clear(obs_property_t p);
EXPORT void obs_property_list_add_string(obs_property_t p,
const char *name, const char *val);
EXPORT void obs_property_list_add_int(obs_property_t p,
const char *name, long long val);
EXPORT void obs_property_list_add_float(obs_property_t p,
const char *name, double val);
EXPORT void obs_property_list_remove(obs_property_t p, size_t idx);
EXPORT size_t obs_property_list_item_count(obs_property_t p);
EXPORT const char *obs_property_list_item_name(obs_property_t p, size_t idx);
EXPORT const char *obs_property_list_item_value(obs_property_t p, size_t idx);
EXPORT const char *obs_property_list_item_string(obs_property_t p, size_t idx);
EXPORT long long obs_property_list_item_int(obs_property_t p, size_t idx);
EXPORT double obs_property_list_item_float(obs_property_t p, size_t idx);
#ifdef __cplusplus
}

View File

@ -314,32 +314,45 @@ bool obs_source_removed(obs_source_t source)
return source ? source->removed : true;
}
static inline obs_data_t get_defaults(const struct obs_source_info *info)
{
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
obs_data_t obs_source_settings(enum obs_source_type type, const char *id)
{
const struct obs_source_info *info = get_source_info(type, id);
if (info) {
obs_data_t settings = obs_data_create();
if (info->defaults)
info->defaults(settings);
return settings;
}
return NULL;
return (info) ? get_defaults(info) : NULL;
}
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);
if (info && info->properties)
return info->properties(locale);
if (info && info->properties) {
obs_data_t defaults = get_defaults(info);
obs_properties_t properties;
properties = info->properties(locale);
obs_properties_apply_settings(properties, defaults);
obs_data_release(defaults);
return properties;
}
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);
if (source && source->info.properties) {
obs_properties_t props;
props = source->info.properties(locale);
obs_properties_apply_settings(props, source->settings);
return props;
}
return NULL;
}

View File

@ -11,15 +11,12 @@
using namespace std;
OBSPropertiesView::OBSPropertiesView(OBSData settings_,
obs_properties_t properties_, void *obj_,
PropertiesUpdateCallback callback_)
: QScrollArea (nullptr),
properties (properties_),
settings (settings_),
obj (obj_),
callback (callback_)
void OBSPropertiesView::RefreshProperties()
{
children.clear();
if (widget)
widget->deleteLater();
widget = new QWidget();
QFormLayout *layout = new QFormLayout;
@ -41,6 +38,19 @@ OBSPropertiesView::OBSPropertiesView(OBSData settings_,
setSizePolicy(policy);
}
OBSPropertiesView::OBSPropertiesView(OBSData settings_,
obs_properties_t properties_, void *obj_,
PropertiesUpdateCallback callback_)
: QScrollArea (nullptr),
widget (nullptr),
properties (properties_),
settings (settings_),
obj (obj_),
callback (callback_)
{
RefreshProperties();
}
QWidget *OBSPropertiesView::NewWidget(obs_property_t prop, QWidget *widget,
const char *signal)
{
@ -76,11 +86,12 @@ QWidget *OBSPropertiesView::AddText(obs_property_t prop)
return NewWidget(prop, edit, SIGNAL(textEdited(const QString &)));
}
void OBSPropertiesView::AddPath(obs_property_t prop, QFormLayout *layout)
QWidget *OBSPropertiesView::AddPath(obs_property_t prop, QFormLayout *layout)
{
/* TODO */
UNUSED_PARAMETER(prop);
UNUSED_PARAMETER(layout);
return nullptr;
}
QWidget *OBSPropertiesView::AddInt(obs_property_t prop)
@ -111,6 +122,27 @@ QWidget *OBSPropertiesView::AddFloat(obs_property_t prop)
return NewWidget(prop, spin, SIGNAL(valueChanged(double)));
}
static void AddComboItem(QComboBox *combo, obs_property_t prop,
obs_combo_format format, size_t idx)
{
const char *name = obs_property_list_item_name(prop, idx);
QVariant var;
if (format == OBS_COMBO_FORMAT_INT) {
long long val = obs_property_list_item_int(prop, idx);
var = QVariant::fromValue<long long>(val);
} else if (format == OBS_COMBO_FORMAT_FLOAT) {
double val = obs_property_list_item_float(prop, idx);
var = QVariant::fromValue<double>(val);
} else if (format == OBS_COMBO_FORMAT_STRING) {
var = obs_property_list_item_string(prop, idx);
}
combo->addItem(QT_UTF8(name), var);
}
QWidget *OBSPropertiesView::AddList(obs_property_t prop)
{
const char *name = obs_property_name(prop);
@ -120,11 +152,8 @@ QWidget *OBSPropertiesView::AddList(obs_property_t prop)
size_t count = obs_property_list_item_count(prop);
int idx = -1;
for (size_t i = 0; i < count; i++) {
const char *name = obs_property_list_item_name(prop, i);
const char *val = obs_property_list_item_value(prop, i);
combo->addItem(QT_UTF8(name), QT_UTF8(val));
}
for (size_t i = 0; i < count; i++)
AddComboItem(combo, prop, format, i);
if (format == OBS_COMBO_FORMAT_INT) {
int val = (int)obs_data_getint(settings, name);
@ -154,7 +183,16 @@ QWidget *OBSPropertiesView::AddList(obs_property_t prop)
if (idx != -1)
combo->setCurrentIndex(idx);
return NewWidget(prop, combo, SIGNAL(currentIndexChanged(int)));
WidgetInfo *info = new WidgetInfo(this, prop, combo);
connect(combo, SIGNAL(currentIndexChanged(int)), info,
SLOT(ControlChanged()));
children.push_back(std::move(unique_ptr<WidgetInfo>(info)));
/* trigger a settings update if the index was not found */
if (idx == -1)
info->ControlChanged();
return combo;
}
void OBSPropertiesView::AddProperty(obs_property_t property,
@ -162,6 +200,9 @@ void OBSPropertiesView::AddProperty(obs_property_t property,
{
obs_property_type type = obs_property_get_type(property);
if (!obs_property_visible(property))
return;
QWidget *widget = nullptr;
switch (type) {
@ -193,6 +234,9 @@ void OBSPropertiesView::AddProperty(obs_property_t property,
if (!widget)
return;
if (!obs_property_enabled(property))
widget->setEnabled(false);
QLabel *label = nullptr;
if (type != OBS_PROPERTY_BOOL)
label = new QLabel(QT_UTF8(obs_property_description(property)));
@ -236,29 +280,32 @@ void WidgetInfo::ListChanged(const char *setting)
QComboBox *combo = static_cast<QComboBox*>(widget);
obs_combo_format format = obs_property_list_format(property);
obs_combo_type type = obs_property_list_type(property);
QVariant data;
string val;
if (type == OBS_COMBO_TYPE_EDITABLE) {
val = QT_TO_UTF8(combo->currentText());
data = combo->currentText();
} else {
int index = combo->currentIndex();
if (index != -1) {
QVariant variant = combo->itemData(index);
val = QT_TO_UTF8(variant.toString());
}
if (index != -1)
data = combo->itemData(index);
else
return;
}
switch (format) {
case OBS_COMBO_FORMAT_INVALID:
return;
case OBS_COMBO_FORMAT_INT:
obs_data_setint(view->settings, setting, stol(val));
obs_data_setint(view->settings, setting,
data.value<long long>());
break;
case OBS_COMBO_FORMAT_FLOAT:
obs_data_setdouble(view->settings, setting, stod(val));
obs_data_setdouble(view->settings, setting,
data.value<double>());
break;
case OBS_COMBO_FORMAT_STRING:
obs_data_setstring(view->settings, setting, val.c_str());
obs_data_setstring(view->settings, setting,
QT_TO_UTF8(data.toString()));
break;
}
}
@ -286,4 +333,6 @@ void WidgetInfo::ControlChanged()
}
view->callback(view->obj, view->settings);
if (obs_property_modified(property, view->settings))
view->RefreshProperties();
}

View File

@ -53,12 +53,14 @@ private:
PropertiesUpdateCallback callback;
std::vector<std::unique_ptr<WidgetInfo>> children;
void RefreshProperties();
QWidget *NewWidget(obs_property_t prop, QWidget *widget,
const char *signal);
QWidget *AddCheckbox(obs_property_t prop);
QWidget *AddText(obs_property_t prop);
void AddPath(obs_property_t prop, QFormLayout *layout);
QWidget *AddPath(obs_property_t prop, QFormLayout *layout);
QWidget *AddInt(obs_property_t prop);
QWidget *AddFloat(obs_property_t prop);
QWidget *AddList(obs_property_t prop);

View File

@ -354,7 +354,7 @@ void OBSBasicSettings::LoadListValues(QComboBox *widget, obs_property_t prop,
for (size_t i = 0; i < count; i++) {
const char *name = obs_property_list_item_name(prop, i);
const char *val = obs_property_list_item_value(prop, i);
const char *val = obs_property_list_item_string(prop, i);
LoadListValue(widget, name, val);
}

View File

@ -506,7 +506,7 @@ static void pulse_source_info(pa_context *c, const pa_source_info *i, int eol,
blog(LOG_DEBUG, "pulse-input: Got source #%u '%s'",
i->index, i->description);
obs_property_list_add_item(e->devices, i->description, i->name);
obs_property_list_add_string(e->devices, i->description, i->name);
pa_threaded_mainloop_signal(e->mainloop, 0);
}
@ -553,11 +553,9 @@ fail:
*/
static obs_properties_t pulse_properties(const char *locale, bool input)
{
UNUSED_PARAMETER(locale);
blog(LOG_DEBUG, "pulse-input: properties requested !");
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
pulse_enumerate_devices(props, input);

View File

@ -709,7 +709,7 @@ static void *coreaudio_create_output_capture(obs_data_t settings,
static obs_properties_t coreaudio_properties(const char *locale, bool input)
{
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
obs_property_t property;
struct device_list devices;
@ -723,17 +723,15 @@ static obs_properties_t coreaudio_properties(const char *locale, bool input)
/* TODO: translate */
if (devices.items.num)
obs_property_list_add_item(property, "Default", "default");
obs_property_list_add_string(property, "Default", "default");
for (size_t i = 0; i < devices.items.num; i++) {
struct device_item *item = devices.items.array+i;
obs_property_list_add_item(property,
obs_property_list_add_string(property,
item->name.array, item->value.array);
}
device_list_free(&devices);
UNUSED_PARAMETER(locale);
return props;
}

View File

@ -383,7 +383,7 @@ static void rtmp_stream_data(void *data, struct encoder_packet *packet)
static obs_properties_t rtmp_stream_properties(const char *locale)
{
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
/* TODO: locale */
obs_properties_add_text(props, "path", "Stream URL", OBS_TEXT_DEFAULT);
@ -392,19 +392,18 @@ static obs_properties_t rtmp_stream_properties(const char *locale)
OBS_TEXT_DEFAULT);
obs_properties_add_text(props, "password", "Password",
OBS_TEXT_PASSWORD);
UNUSED_PARAMETER(locale);
return props;
}
struct obs_output_info rtmp_output_info = {
.id = "rtmp_output",
.flags = OBS_OUTPUT_AV | OBS_OUTPUT_ENCODED | OBS_OUTPUT_SERVICE,
.getname = rtmp_stream_getname,
.create = rtmp_stream_create,
.destroy = rtmp_stream_destroy,
.start = rtmp_stream_start,
.stop = rtmp_stream_stop,
.encoded_data = rtmp_stream_data,
.id = "rtmp_output",
.flags = OBS_OUTPUT_AV |
OBS_OUTPUT_ENCODED,
.getname = rtmp_stream_getname,
.create = rtmp_stream_create,
.destroy = rtmp_stream_destroy,
.start = rtmp_stream_start,
.stop = rtmp_stream_stop,
.encoded_packet = rtmp_stream_data,
.properties = rtmp_stream_properties
};

View File

@ -86,17 +86,16 @@ static void obs_x264_defaults(obs_data_t settings)
static inline void add_strings(obs_property_t list, const char *const *strings)
{
while (*strings) {
obs_property_list_add_item(list, *strings, *strings);
obs_property_list_add_string(list, *strings, *strings);
strings++;
}
}
static obs_properties_t obs_x264_props(const char *locale)
{
UNUSED_PARAMETER(locale);
/* TODO: locale */
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
obs_property_t list;
obs_properties_add_int(props, "bitrate", "Bitrate", 50, 100000, 1);
@ -113,9 +112,9 @@ static obs_properties_t obs_x264_props(const char *locale)
list = obs_properties_add_list(props, "profile", "Profile",
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_list_add_item(list, "baseline", "baseline");
obs_property_list_add_item(list, "main", "main");
obs_property_list_add_item(list, "high", "high");
obs_property_list_add_string(list, "baseline", "baseline");
obs_property_list_add_string(list, "main", "main");
obs_property_list_add_string(list, "high", "high");
list = obs_properties_add_list(props, "tune", "Tune",
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);

View File

@ -468,7 +468,7 @@ static void UpdateWASAPISource(void *obj, obs_data_t settings)
static obs_properties_t GetWASAPIProperties(const char *locale, bool input)
{
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
vector<AudioDeviceInfo> devices;
/* TODO: translate */
@ -479,15 +479,16 @@ static obs_properties_t GetWASAPIProperties(const char *locale, bool input)
GetWASAPIAudioDevices(devices, input);
if (devices.size())
obs_property_list_add_item(device_prop, "Default", "default");
obs_property_list_add_string(device_prop, "Default", "default");
for (size_t i = 0; i < devices.size(); i++) {
AudioDeviceInfo &device = devices[i];
obs_property_list_add_item(device_prop,
obs_property_list_add_string(device_prop,
device.name.c_str(), device.id.c_str());
}
obs_properties_add_bool(props, "use_device_timing",
obs_property_t prop;
prop = obs_properties_add_bool(props, "use_device_timing",
"Use Device Timing");
return props;

View File

@ -263,18 +263,16 @@ static void display_capture_update(void *data, obs_data_t settings)
static obs_properties_t display_capture_properties(char const *locale)
{
UNUSED_PARAMETER(locale);
obs_properties_t props = obs_properties_create();
obs_properties_t props = obs_properties_create(locale);
obs_property_t list = obs_properties_add_list(props,
"display", "Display",
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
for (unsigned i = 0; i < [NSScreen screens].count; i++)
{
for (unsigned i = 0; i < [NSScreen screens].count; i++) {
char buf[10];
sprintf(buf, "%u", i);
obs_property_list_add_item(list, buf, buf);
obs_property_list_add_int(list, buf, i);
}
return props;