obs-studio UI: Implement stream settings UI
- Updated the services API so that it links up with an output and the output gets data from that service rather than via settings. This allows the service context to have control over how an output is used, and makes it so that the URL/key/etc isn't necessarily some static setting. Also, if the service is attached to an output, it will stick around until the output is destroyed. - The settings interface has been updated so that it can allow the usage of service plugins. What this means is that now you can create a service plugin that can control aspects of the stream, and it allows each service to create their own user interface if they create a service plugin module. - Testing out saving of current service information. Saves/loads from JSON in to obs_data_t, seems to be working quite nicely, and the service object information is saved/preserved on exit, and loaded again on startup. - I agonized over the settings user interface for days, and eventually I just decided that the only way that users weren't going to be fumbling over options was to split up the settings in to simple/basic output, pre-configured, and then advanced for advanced use (such as multiple outputs or services, which I'll implement later). This was particularly painful to really design right, I wanted more features and wanted to include everything in one interface but ultimately just realized from experience that users are just not technically knowledgable about it and will end up fumbling with the settings rather than getting things done. Basically, what this means is that casual users only have to enter in about 3 things to configure their stream: Stream key, audio bitrate, and video bitrate. I am really happy with this interface for those types of users, but it definitely won't be sufficient for advanced usage or for custom outputs, so that stuff will have to be separated. - Improved the JSON usage for the 'common streaming services' context, I realized that JSON arrays are there to ensure sorting, while forgetting that general items are optimized for hashing. So basically I'm just using arrays now to sort items in it.
This commit is contained in:
@@ -224,6 +224,7 @@ set_target_properties(libobs PROPERTIES
|
||||
VERSION "0"
|
||||
SOVERSION "0")
|
||||
target_link_libraries(libobs
|
||||
jansson
|
||||
${libobs_PLATFORM_DEPS}
|
||||
${Libswscale_LIBRARIES}
|
||||
${Libswresample_LIBRARIES}
|
||||
|
@@ -57,8 +57,7 @@ static bool init_encoder(struct obs_encoder *encoder, const char *name,
|
||||
|
||||
static struct obs_encoder *create_encoder(const char *id,
|
||||
enum obs_encoder_type type, const char *name,
|
||||
obs_data_t settings, void *media,
|
||||
uint32_t timebase_num, uint32_t timebase_den)
|
||||
obs_data_t settings)
|
||||
{
|
||||
struct obs_encoder *encoder;
|
||||
struct obs_encoder_info *ei = get_encoder_info(id);
|
||||
@@ -68,10 +67,7 @@ static struct obs_encoder *create_encoder(const char *id,
|
||||
return NULL;
|
||||
|
||||
encoder = bzalloc(sizeof(struct obs_encoder));
|
||||
encoder->info = *ei;
|
||||
encoder->media = media;
|
||||
encoder->timebase_num = timebase_num;
|
||||
encoder->timebase_den = timebase_den;
|
||||
encoder->info = *ei;
|
||||
|
||||
success = init_encoder(encoder, name, settings);
|
||||
if (!success) {
|
||||
@@ -87,29 +83,17 @@ static struct obs_encoder *create_encoder(const char *id,
|
||||
}
|
||||
|
||||
obs_encoder_t obs_video_encoder_create(const char *id, const char *name,
|
||||
obs_data_t settings, video_t video)
|
||||
obs_data_t settings)
|
||||
{
|
||||
const struct video_output_info *voi;
|
||||
|
||||
if (!name || !id || !video)
|
||||
return NULL;
|
||||
|
||||
voi = video_output_getinfo(video);
|
||||
return create_encoder(id, OBS_ENCODER_VIDEO, name, settings, video,
|
||||
voi->fps_den, voi->fps_num);
|
||||
if (!name || !id) return NULL;
|
||||
return create_encoder(id, OBS_ENCODER_VIDEO, name, settings);
|
||||
}
|
||||
|
||||
obs_encoder_t obs_audio_encoder_create(const char *id, const char *name,
|
||||
obs_data_t settings, audio_t audio)
|
||||
obs_data_t settings)
|
||||
{
|
||||
const struct audio_output_info *aoi;
|
||||
|
||||
if (!name || !id || !audio)
|
||||
return NULL;
|
||||
|
||||
aoi = audio_output_getinfo(audio);
|
||||
return create_encoder(id, OBS_ENCODER_AUDIO, name, settings, audio,
|
||||
1, aoi->samples_per_sec);
|
||||
if (!name || !id) return NULL;
|
||||
return create_encoder(id, OBS_ENCODER_AUDIO, name, settings);
|
||||
}
|
||||
|
||||
static void receive_video(void *param, struct video_data *frame);
|
||||
@@ -418,6 +402,30 @@ const char *obs_encoder_get_codec(obs_encoder_t encoder)
|
||||
return encoder ? encoder->info.codec : NULL;
|
||||
}
|
||||
|
||||
void obs_encoder_set_video(obs_encoder_t encoder, video_t video)
|
||||
{
|
||||
const struct video_output_info *voi;
|
||||
|
||||
if (!video || !encoder || encoder->info.type != OBS_ENCODER_VIDEO)
|
||||
return;
|
||||
|
||||
voi = video_output_getinfo(video);
|
||||
|
||||
encoder->media = video;
|
||||
encoder->timebase_num = voi->fps_den;
|
||||
encoder->timebase_den = voi->fps_num;
|
||||
}
|
||||
|
||||
void obs_encoder_set_audio(obs_encoder_t encoder, audio_t audio)
|
||||
{
|
||||
if (!audio || !encoder || encoder->info.type != OBS_ENCODER_AUDIO)
|
||||
return;
|
||||
|
||||
encoder->media = audio;
|
||||
encoder->timebase_num = 1;
|
||||
encoder->timebase_den = audio_output_samplerate(audio);
|
||||
}
|
||||
|
||||
video_t obs_encoder_video(obs_encoder_t encoder)
|
||||
{
|
||||
return (encoder && encoder->info.type == OBS_ENCODER_VIDEO) ?
|
||||
|
@@ -322,6 +322,7 @@ struct obs_output {
|
||||
audio_t audio;
|
||||
obs_encoder_t video_encoder;
|
||||
obs_encoder_t audio_encoder;
|
||||
obs_service_t service;
|
||||
|
||||
bool video_conversion_set;
|
||||
bool audio_conversion_set;
|
||||
@@ -404,4 +405,11 @@ extern void obs_encoder_remove_output(struct obs_encoder *encoder,
|
||||
struct obs_service {
|
||||
struct obs_context_data context;
|
||||
struct obs_service_info info;
|
||||
|
||||
bool active;
|
||||
bool destroy;
|
||||
struct obs_output *output;
|
||||
};
|
||||
|
||||
void obs_service_activate(struct obs_service *service);
|
||||
void obs_service_deactivate(struct obs_service *service, bool remove);
|
||||
|
@@ -63,7 +63,7 @@ int obs_load_module(const char *path)
|
||||
mod.module = os_dlopen(plugin_path);
|
||||
bfree(plugin_path);
|
||||
if (!mod.module) {
|
||||
blog(LOG_DEBUG, "Module '%s' not found", path);
|
||||
blog(LOG_WARNING, "Module '%s' not found", path);
|
||||
return MODULE_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
@@ -108,6 +108,8 @@ void obs_output_destroy(obs_output_t output)
|
||||
|
||||
if (output->valid && output->active)
|
||||
output->info.stop(output->context.data);
|
||||
if (output->service)
|
||||
output->service->output = NULL;
|
||||
|
||||
free_packets(output);
|
||||
|
||||
@@ -283,6 +285,22 @@ obs_encoder_t obs_output_get_audio_encoder(obs_output_t output)
|
||||
return output ? output->audio_encoder : NULL;
|
||||
}
|
||||
|
||||
void obs_output_set_service(obs_output_t output, obs_service_t service)
|
||||
{
|
||||
if (!output || output->active || !service || service->active) return;
|
||||
|
||||
if (service->output)
|
||||
service->output->service = NULL;
|
||||
|
||||
output->service = service;
|
||||
service->output = output;
|
||||
}
|
||||
|
||||
obs_service_t obs_output_get_service(obs_output_t output)
|
||||
{
|
||||
return output ? output->service : NULL;
|
||||
}
|
||||
|
||||
void obs_output_set_video_conversion(obs_output_t output,
|
||||
const struct video_scale_info *conversion)
|
||||
{
|
||||
@@ -302,7 +320,7 @@ void obs_output_set_audio_conversion(obs_output_t output,
|
||||
}
|
||||
|
||||
static bool can_begin_data_capture(struct obs_output *output, bool encoded,
|
||||
bool has_video, bool has_audio)
|
||||
bool has_video, bool has_audio, bool has_service)
|
||||
{
|
||||
if (has_video) {
|
||||
if (encoded) {
|
||||
@@ -324,6 +342,9 @@ static bool can_begin_data_capture(struct obs_output *output, bool encoded,
|
||||
}
|
||||
}
|
||||
|
||||
if (has_service && !output->service)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -480,7 +501,8 @@ static inline void signal_stop(struct obs_output *output, int code)
|
||||
}
|
||||
|
||||
static inline void convert_flags(struct obs_output *output, uint32_t flags,
|
||||
bool *encoded, bool *has_video, bool *has_audio)
|
||||
bool *encoded, bool *has_video, bool *has_audio,
|
||||
bool *has_service)
|
||||
{
|
||||
*encoded = (output->info.flags & OBS_OUTPUT_ENCODED) != 0;
|
||||
if (!flags)
|
||||
@@ -488,30 +510,34 @@ static inline void convert_flags(struct obs_output *output, uint32_t flags,
|
||||
else
|
||||
flags &= output->info.flags;
|
||||
|
||||
*has_video = (flags & OBS_OUTPUT_VIDEO) != 0;
|
||||
*has_audio = (flags & OBS_OUTPUT_AUDIO) != 0;
|
||||
*has_video = (flags & OBS_OUTPUT_VIDEO) != 0;
|
||||
*has_audio = (flags & OBS_OUTPUT_AUDIO) != 0;
|
||||
*has_service = (flags & OBS_OUTPUT_SERVICE) != 0;
|
||||
}
|
||||
|
||||
bool obs_output_can_begin_data_capture(obs_output_t output, uint32_t flags)
|
||||
{
|
||||
bool encoded, has_video, has_audio;
|
||||
bool encoded, has_video, has_audio, has_service;
|
||||
|
||||
if (!output) return false;
|
||||
if (output->active) return false;
|
||||
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio);
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio,
|
||||
&has_service);
|
||||
|
||||
return can_begin_data_capture(output, encoded, has_video, has_audio);
|
||||
return can_begin_data_capture(output, encoded, has_video, has_audio,
|
||||
has_service);
|
||||
}
|
||||
|
||||
bool obs_output_initialize_encoders(obs_output_t output, uint32_t flags)
|
||||
{
|
||||
bool encoded, has_video, has_audio;
|
||||
bool encoded, has_video, has_audio, has_service;
|
||||
|
||||
if (!output) return false;
|
||||
if (output->active) return false;
|
||||
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio);
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio,
|
||||
&has_service);
|
||||
|
||||
if (!encoded)
|
||||
return false;
|
||||
@@ -532,17 +558,23 @@ bool obs_output_initialize_encoders(obs_output_t output, uint32_t flags)
|
||||
|
||||
bool obs_output_begin_data_capture(obs_output_t output, uint32_t flags)
|
||||
{
|
||||
bool encoded, has_video, has_audio;
|
||||
bool encoded, has_video, has_audio, has_service;
|
||||
|
||||
if (!output) return false;
|
||||
if (output->active) return false;
|
||||
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio);
|
||||
convert_flags(output, flags, &encoded, &has_video, &has_audio,
|
||||
&has_service);
|
||||
|
||||
if (!can_begin_data_capture(output, encoded, has_video, has_audio))
|
||||
if (!can_begin_data_capture(output, encoded, has_video, has_audio,
|
||||
has_service))
|
||||
return false;
|
||||
|
||||
hook_data_capture(output, encoded, has_video, has_audio);
|
||||
|
||||
if (has_service)
|
||||
obs_service_activate(output->service);
|
||||
|
||||
output->active = true;
|
||||
signal_start(output);
|
||||
return true;
|
||||
@@ -550,14 +582,15 @@ 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;
|
||||
bool encoded, has_video, has_audio, has_service;
|
||||
void (*encoded_callback)(void *data, struct encoder_packet *packet);
|
||||
void *param;
|
||||
|
||||
if (!output) return;
|
||||
if (!output->active) return;
|
||||
|
||||
convert_flags(output, 0, &encoded, &has_video, &has_audio);
|
||||
convert_flags(output, 0, &encoded, &has_video, &has_audio,
|
||||
&has_service);
|
||||
|
||||
if (encoded) {
|
||||
encoded_callback = (has_video && has_audio) ?
|
||||
@@ -582,6 +615,9 @@ void obs_output_end_data_capture(obs_output_t output)
|
||||
output->context.data);
|
||||
}
|
||||
|
||||
if (has_service)
|
||||
obs_service_deactivate(output->service, false);
|
||||
|
||||
output->active = false;
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,13 @@ obs_service_t obs_service_create(const char *id, const char *name,
|
||||
|
||||
service->info = *info;
|
||||
|
||||
service->context.data = service->info.create(service->context.settings,
|
||||
service);
|
||||
if (!service->context.data) {
|
||||
obs_service_destroy(service);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obs_context_data_insert(&service->context,
|
||||
&obs->data.services_mutex,
|
||||
&obs->data.first_service);
|
||||
@@ -60,19 +67,37 @@ obs_service_t obs_service_create(const char *id, const char *name,
|
||||
return service;
|
||||
}
|
||||
|
||||
static void actually_destroy_service(struct obs_service *service)
|
||||
{
|
||||
if (service->context.data)
|
||||
service->info.destroy(service->context.data);
|
||||
|
||||
if (service->output)
|
||||
service->output->service = NULL;
|
||||
|
||||
obs_context_data_free(&service->context);
|
||||
bfree(service);
|
||||
}
|
||||
|
||||
void obs_service_destroy(obs_service_t service)
|
||||
{
|
||||
if (service) {
|
||||
obs_context_data_remove(&service->context);
|
||||
|
||||
if (service->context.data)
|
||||
service->info.destroy(service->context.data);
|
||||
service->destroy = true;
|
||||
|
||||
obs_context_data_free(&service->context);
|
||||
bfree(service);
|
||||
/* do NOT destroy the service until the service is no
|
||||
* longer in use */
|
||||
if (!service->active)
|
||||
actually_destroy_service(service);
|
||||
}
|
||||
}
|
||||
|
||||
const char *obs_service_getname(obs_service_t service)
|
||||
{
|
||||
return service ? service->context.name : NULL;
|
||||
}
|
||||
|
||||
static inline obs_data_t get_defaults(const struct obs_service_info *info)
|
||||
{
|
||||
obs_data_t settings = obs_data_create();
|
||||
@@ -115,6 +140,11 @@ obs_properties_t obs_service_properties(obs_service_t service,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *obs_service_gettype(obs_service_t service)
|
||||
{
|
||||
return service ? service->info.id : NULL;
|
||||
}
|
||||
|
||||
void obs_service_update(obs_service_t service, obs_data_t settings)
|
||||
{
|
||||
if (!service) return;
|
||||
@@ -156,3 +186,39 @@ const char *obs_service_get_key(obs_service_t service)
|
||||
if (!service || !service->info.get_key) return NULL;
|
||||
return service->info.get_key(service->context.data);
|
||||
}
|
||||
|
||||
const char *obs_service_get_username(obs_service_t service)
|
||||
{
|
||||
if (!service || !service->info.get_username) return NULL;
|
||||
return service->info.get_username(service->context.data);
|
||||
}
|
||||
|
||||
const char *obs_service_get_password(obs_service_t service)
|
||||
{
|
||||
if (!service || !service->info.get_password) return NULL;
|
||||
return service->info.get_password(service->context.data);
|
||||
}
|
||||
|
||||
void obs_service_activate(struct obs_service *service)
|
||||
{
|
||||
if (!service || !service->output || service->active) return;
|
||||
|
||||
if (service->info.activate)
|
||||
service->info.activate(service->context.data,
|
||||
service->context.settings);
|
||||
service->active = true;
|
||||
}
|
||||
|
||||
void obs_service_deactivate(struct obs_service *service, bool remove)
|
||||
{
|
||||
if (!service || !service->output || !service->active) return;
|
||||
|
||||
if (service->info.deactivate)
|
||||
service->info.deactivate(service->context.data);
|
||||
service->active = false;
|
||||
|
||||
if (service->destroy)
|
||||
actually_destroy_service(service);
|
||||
else if (remove)
|
||||
service->output = NULL;
|
||||
}
|
||||
|
@@ -26,6 +26,9 @@ struct obs_service_info {
|
||||
void (*destroy)(void *data);
|
||||
|
||||
/* optional */
|
||||
void (*activate)(void *data, obs_data_t settings);
|
||||
void (*deactivate)(void *data);
|
||||
|
||||
void (*update)(void *data, obs_data_t settings);
|
||||
|
||||
void (*defaults)(obs_data_t settings);
|
||||
@@ -35,6 +38,9 @@ struct obs_service_info {
|
||||
const char *(*get_url)(void *data);
|
||||
const char *(*get_key)(void *data);
|
||||
|
||||
const char *(*get_username)(void *data);
|
||||
const char *(*get_password)(void *data);
|
||||
|
||||
/* TODO: more stuff later */
|
||||
};
|
||||
|
||||
|
40
libobs/obs.c
40
libobs/obs.c
@@ -908,6 +908,46 @@ obs_source_t obs_get_source_by_name(const char *name)
|
||||
return source;
|
||||
}
|
||||
|
||||
static inline void *get_context_by_name(void *vfirst, const char *name,
|
||||
pthread_mutex_t *mutex)
|
||||
{
|
||||
struct obs_context_data **first = vfirst;
|
||||
struct obs_context_data *context;
|
||||
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
context = *first;
|
||||
while (context) {
|
||||
if (strcmp(context->name, name) == 0)
|
||||
break;
|
||||
context = context->next;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(mutex);
|
||||
return context;
|
||||
}
|
||||
|
||||
obs_output_t obs_get_output_by_name(const char *name)
|
||||
{
|
||||
if (!obs) return NULL;
|
||||
return get_context_by_name(&obs->data.first_output, name,
|
||||
&obs->data.outputs_mutex);
|
||||
}
|
||||
|
||||
obs_encoder_t obs_get_encoder_by_name(const char *name)
|
||||
{
|
||||
if (!obs) return NULL;
|
||||
return get_context_by_name(&obs->data.first_encoder, name,
|
||||
&obs->data.encoders_mutex);
|
||||
}
|
||||
|
||||
obs_service_t obs_get_service_by_name(const char *name)
|
||||
{
|
||||
if (!obs) return NULL;
|
||||
return get_context_by_name(&obs->data.first_service, name,
|
||||
&obs->data.services_mutex);
|
||||
}
|
||||
|
||||
effect_t obs_get_default_effect(void)
|
||||
{
|
||||
if (!obs) return NULL;
|
||||
|
52
libobs/obs.h
52
libobs/obs.h
@@ -288,6 +288,10 @@ EXPORT void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t),
|
||||
EXPORT void obs_enum_encoders(bool (*enum_proc)(void*, obs_encoder_t),
|
||||
void *param);
|
||||
|
||||
/** Enumerates encoders */
|
||||
EXPORT void obs_enum_services(bool (*enum_proc)(void*, obs_service_t),
|
||||
void *param);
|
||||
|
||||
/**
|
||||
* Gets a source by its name.
|
||||
*
|
||||
@@ -296,6 +300,15 @@ EXPORT void obs_enum_encoders(bool (*enum_proc)(void*, obs_encoder_t),
|
||||
*/
|
||||
EXPORT obs_source_t obs_get_source_by_name(const char *name);
|
||||
|
||||
/** Gets an output by its name. */
|
||||
EXPORT obs_output_t obs_get_output_by_name(const char *name);
|
||||
|
||||
/** Gets an encoder by its name. */
|
||||
EXPORT obs_encoder_t obs_get_encoder_by_name(const char *name);
|
||||
|
||||
/** Gets an service by its name. */
|
||||
EXPORT obs_service_t obs_get_service_by_name(const char *name);
|
||||
|
||||
/**
|
||||
* Returns the location of a plugin data file.
|
||||
*
|
||||
@@ -737,6 +750,12 @@ EXPORT obs_encoder_t obs_output_get_video_encoder(obs_output_t output);
|
||||
/** Returns the current audio encoder associated with this output */
|
||||
EXPORT obs_encoder_t obs_output_get_audio_encoder(obs_output_t output);
|
||||
|
||||
/** Sets the current service associated with this output. */
|
||||
EXPORT void obs_output_set_service(obs_output_t output, obs_service_t service);
|
||||
|
||||
/** Gets the current service associated with this output. */
|
||||
EXPORT obs_service_t obs_output_get_service(obs_output_t output);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Functions used by outputs */
|
||||
|
||||
@@ -793,11 +812,10 @@ EXPORT const char *obs_encoder_getdisplayname(const char *id,
|
||||
* @param id Video encoder ID
|
||||
* @param name Name to assign to this context
|
||||
* @param settings Settings
|
||||
* @param video Video output context to encode data from
|
||||
* @return The video encoder context, or NULL if failed or not found.
|
||||
*/
|
||||
EXPORT obs_encoder_t obs_video_encoder_create(const char *id, const char *name,
|
||||
obs_data_t settings, video_t video);
|
||||
obs_data_t settings);
|
||||
|
||||
/**
|
||||
* Creates an audio encoder context
|
||||
@@ -805,11 +823,10 @@ EXPORT obs_encoder_t obs_video_encoder_create(const char *id, const char *name,
|
||||
* @param id Audio Encoder ID
|
||||
* @param name Name to assign to this context
|
||||
* @param settings Settings
|
||||
* @param audio Audio output context to encode data from
|
||||
* @return The video encoder context, or NULL if failed or not found.
|
||||
*/
|
||||
EXPORT obs_encoder_t obs_audio_encoder_create(const char *id, const char *name,
|
||||
obs_data_t settings, audio_t audio);
|
||||
obs_data_t settings);
|
||||
|
||||
/** Destroys an encoder context */
|
||||
EXPORT void obs_encoder_destroy(obs_encoder_t encoder);
|
||||
@@ -844,6 +861,12 @@ EXPORT bool obs_encoder_get_extra_data(obs_encoder_t encoder,
|
||||
/** Returns the current settings for this encoder */
|
||||
EXPORT obs_data_t obs_encoder_get_settings(obs_encoder_t encoder);
|
||||
|
||||
/** Sets the video output context to be used with this encoder */
|
||||
EXPORT void obs_encoder_set_video(obs_encoder_t encoder, video_t video);
|
||||
|
||||
/** Sets the audio output context to be used with this encoder */
|
||||
EXPORT void obs_encoder_set_audio(obs_encoder_t encoder, audio_t audio);
|
||||
|
||||
/**
|
||||
* Returns the video output context used with this encoder, or NULL if not
|
||||
* a video context
|
||||
@@ -873,6 +896,8 @@ EXPORT obs_service_t obs_service_create(const char *id, const char *name,
|
||||
obs_data_t settings);
|
||||
EXPORT void obs_service_destroy(obs_service_t service);
|
||||
|
||||
EXPORT const char *obs_service_getname(obs_service_t service);
|
||||
|
||||
/** Gets the default settings for a service */
|
||||
EXPORT obs_data_t obs_service_defaults(const char *id);
|
||||
|
||||
@@ -887,11 +912,26 @@ EXPORT obs_properties_t obs_get_service_properties(const char *id,
|
||||
EXPORT obs_properties_t obs_service_properties(obs_service_t service,
|
||||
const char *locale);
|
||||
|
||||
/** Gets the service type */
|
||||
EXPORT const char *obs_service_gettype(obs_service_t service);
|
||||
|
||||
/** Updates the settings of the service context */
|
||||
EXPORT void obs_service_update(obs_service_t service, obs_data_t settings);
|
||||
|
||||
/** Returns the current settings for this service */
|
||||
EXPORT obs_data_t obs_service_get_settings(obs_service_t service);
|
||||
|
||||
/** Returns the URL for this service context */
|
||||
const char *obs_service_get_url(obs_service_t service);
|
||||
EXPORT const char *obs_service_get_url(obs_service_t service);
|
||||
|
||||
/** Returns the stream key (if any) for this service context */
|
||||
const char *obs_service_get_key(obs_service_t service);
|
||||
EXPORT const char *obs_service_get_key(obs_service_t service);
|
||||
|
||||
/** Returns the username (if any) for this service context */
|
||||
EXPORT const char *obs_service_get_username(obs_service_t service);
|
||||
|
||||
/** Returns the password (if any) for this service context */
|
||||
EXPORT const char *obs_service_get_password(obs_service_t service);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@@ -359,8 +359,6 @@ static inline void darray_pop_back(const size_t element_size,
|
||||
static inline void darray_join(const size_t element_size, struct darray *dst,
|
||||
struct darray *da)
|
||||
{
|
||||
assert(element_size == element_size);
|
||||
|
||||
darray_push_back_darray(element_size, dst, da);
|
||||
darray_free(da);
|
||||
}
|
||||
|
Reference in New Issue
Block a user