obs/source-tracker: Fix leaked source references
This functionality broke at some point in the past without anyone noticing, resulting in most dropdowns that rely on this functionality being blank. Fixes #1025
This commit is contained in:
parent
5e307a8e36
commit
e8ec23c4d4
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Modern effects for a modern Streamer
|
* Modern effects for a modern Streamer
|
||||||
* Copyright (C) 2017-2018 Michael Fabian Dirks
|
* Copyright (C) 2017-2023 Michael Fabian Dirks
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -863,13 +863,13 @@ obs_properties_t* blur_factory::get_properties2(blur_instance* data)
|
||||||
OBS_COMBO_FORMAT_STRING);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
obs_property_list_add_string(p, "", "");
|
obs_property_list_add_string(p, "", "");
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
obs_property_list_add_string(p, std::string(name + " (Source)").c_str(), name.c_str());
|
obs_property_list_add_string(p, std::string(name + " (Source)").c_str(), name.c_str());
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
obs::source_tracker::filter_video_sources);
|
obs::source_tracker::filter_video_sources);
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
obs_property_list_add_string(p, std::string(name + " (Scene)").c_str(), name.c_str());
|
obs_property_list_add_string(p, std::string(name + " (Scene)").c_str(), name.c_str());
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Modern effects for a modern Streamer
|
* Modern effects for a modern Streamer
|
||||||
* Copyright (C) 2019 Michael Fabian Dirks
|
* Copyright (C) 2019-2023 Michael Fabian Dirks
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -754,7 +754,7 @@ obs_properties_t* dynamic_mask_factory::get_properties2(dynamic_mask_instance* d
|
||||||
OBS_COMBO_FORMAT_STRING);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
obs_property_list_add_string(p, "", "");
|
obs_property_list_add_string(p, "", "");
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
@ -762,7 +762,7 @@ obs_properties_t* dynamic_mask_factory::get_properties2(dynamic_mask_instance* d
|
||||||
},
|
},
|
||||||
obs::source_tracker::filter_video_sources);
|
obs::source_tracker::filter_video_sources);
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Modern effects for a modern Streamer
|
// Modern effects for a modern Streamer
|
||||||
// Copyright (C) 2019 Michael Fabian Dirks
|
// Copyright (C) 2019-2023 Michael Fabian Dirks
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -215,7 +215,7 @@ void streamfx::gfx::shader::texture_parameter::properties(obs_properties_t* prop
|
||||||
OBS_COMBO_FORMAT_STRING);
|
OBS_COMBO_FORMAT_STRING);
|
||||||
obs_property_list_add_string(p, "", "");
|
obs_property_list_add_string(p, "", "");
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
@ -223,7 +223,7 @@ void streamfx::gfx::shader::texture_parameter::properties(obs_properties_t* prop
|
||||||
},
|
},
|
||||||
obs::source_tracker::filter_video_sources);
|
obs::source_tracker::filter_video_sources);
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Modern effects for a modern Streamer
|
* Modern effects for a modern Streamer
|
||||||
* Copyright (C) 2017-2018 Michael Fabian Dirks
|
* Copyright (C) 2017-2023 Michael Fabian Dirks
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -40,6 +40,158 @@
|
||||||
#define D_LOG_DEBUG(...) P_LOG_DEBUG(ST_PREFIX __VA_ARGS__)
|
#define D_LOG_DEBUG(...) P_LOG_DEBUG(ST_PREFIX __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
streamfx::obs::source_tracker::source_tracker() : _sources(), _mutex()
|
||||||
|
{
|
||||||
|
auto osi = obs_get_signal_handler();
|
||||||
|
if (osi) {
|
||||||
|
signal_handler_connect(osi, "source_create", &source_create_handler, this);
|
||||||
|
signal_handler_connect(osi, "source_destroy", &source_destroy_handler, this);
|
||||||
|
signal_handler_connect(osi, "source_rename", &source_rename_handler, this);
|
||||||
|
} else {
|
||||||
|
D_LOG_WARNING("No global signal handler was present at initialization.", nullptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enumerate all current sources and filters.
|
||||||
|
obs_enum_all_sources(
|
||||||
|
[](void* param, obs_source_t* source) {
|
||||||
|
auto* self = reinterpret_cast<::streamfx::obs::source_tracker*>(param);
|
||||||
|
self->insert_source(source);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::obs::source_tracker::~source_tracker()
|
||||||
|
{
|
||||||
|
auto osi = obs_get_signal_handler();
|
||||||
|
if (osi) {
|
||||||
|
signal_handler_disconnect(osi, "source_create", &source_create_handler, this);
|
||||||
|
signal_handler_disconnect(osi, "source_destroy", &source_destroy_handler, this);
|
||||||
|
signal_handler_disconnect(osi, "source_rename", &source_rename_handler, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_sources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::obs::source_tracker::enumerate(enumerate_cb_t ecb, filter_cb_t fcb)
|
||||||
|
{
|
||||||
|
// Need func-local copy, otherwise we risk corruption if a new source is created or destroyed.
|
||||||
|
decltype(_sources) _clone;
|
||||||
|
{
|
||||||
|
std::lock_guard<decltype(_mutex)> lock(_mutex);
|
||||||
|
_clone = _sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto kv : _clone) {
|
||||||
|
auto wsource = kv.second;
|
||||||
|
try {
|
||||||
|
auto source = wsource.lock();
|
||||||
|
|
||||||
|
if (fcb) {
|
||||||
|
if (fcb(kv.first, source)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecb) {
|
||||||
|
if (ecb(kv.first, source)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::obs::source_tracker::insert_source(obs_source_t* source)
|
||||||
|
{
|
||||||
|
const char* name = obs_source_get_name(source);
|
||||||
|
|
||||||
|
// Don't track unnamed sources.
|
||||||
|
if (!name || (strnlen(name, 1) == 0)) {
|
||||||
|
D_LOG_DEBUG("Unnamed source '0x%08zX' left untracked.", source);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the newly tracked source into the map.
|
||||||
|
std::lock_guard<decltype(_mutex)> lock(_mutex);
|
||||||
|
_sources.emplace(std::string{name}, ::streamfx::obs::weak_source{source});
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::obs::source_tracker::remove_source(obs_source_t* source)
|
||||||
|
{
|
||||||
|
std::lock_guard<decltype(_mutex)> lock(_mutex);
|
||||||
|
const char* name = obs_source_get_name(source);
|
||||||
|
|
||||||
|
// Try and find the source by name.
|
||||||
|
if (name) {
|
||||||
|
if (auto kv = _sources.find(std::string{name}); kv != _sources.end()) {
|
||||||
|
_sources.erase(kv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try and find the source by pointer.
|
||||||
|
for (auto kv = _sources.begin(); kv != _sources.end(); kv++) {
|
||||||
|
if (kv->second == source) {
|
||||||
|
_sources.erase(kv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're still here, there's something wrong.
|
||||||
|
if (name) {
|
||||||
|
D_LOG_ERROR("Attempt to remove untracked source '0x%08zX' with name %s failed.", source, name);
|
||||||
|
throw std::runtime_error("Failed to find given source.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::obs::source_tracker::rename_source(std::string_view old_name, std::string_view new_name,
|
||||||
|
obs_source_t* source)
|
||||||
|
{
|
||||||
|
if (old_name == new_name) {
|
||||||
|
throw std::runtime_error("New and old name are identical.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<decltype(_mutex)> lock(_mutex);
|
||||||
|
|
||||||
|
// Remove the previously tracked entry.
|
||||||
|
if (auto kv = _sources.find(std::string{old_name}); kv != _sources.end()) {
|
||||||
|
_sources.erase(kv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// And then add the new entry.
|
||||||
|
_sources.emplace(std::string{new_name}, ::streamfx::obs::weak_source{source});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::obs::source_tracker::filter_sources(std::string, ::streamfx::obs::source source)
|
||||||
|
{
|
||||||
|
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::obs::source_tracker::filter_audio_sources(std::string, ::streamfx::obs::source source)
|
||||||
|
{
|
||||||
|
uint32_t flags = obs_source_get_output_flags(source);
|
||||||
|
return !(flags & OBS_SOURCE_AUDIO) || (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::obs::source_tracker::filter_video_sources(std::string, ::streamfx::obs::source source)
|
||||||
|
{
|
||||||
|
uint32_t flags = obs_source_get_output_flags(source);
|
||||||
|
return !(flags & OBS_SOURCE_VIDEO) || (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::obs::source_tracker::filter_transitions(std::string, ::streamfx::obs::source source)
|
||||||
|
{
|
||||||
|
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_TRANSITION);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool streamfx::obs::source_tracker::filter_scenes(std::string, ::streamfx::obs::source source)
|
||||||
|
{
|
||||||
|
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE);
|
||||||
|
}
|
||||||
|
|
||||||
void streamfx::obs::source_tracker::source_create_handler(void* ptr, calldata_t* data) noexcept
|
void streamfx::obs::source_tracker::source_create_handler(void* ptr, calldata_t* data) noexcept
|
||||||
{
|
{
|
||||||
auto* self = reinterpret_cast<streamfx::obs::source_tracker*>(ptr);
|
auto* self = reinterpret_cast<streamfx::obs::source_tracker*>(ptr);
|
||||||
|
|
@ -66,6 +218,7 @@ void streamfx::obs::source_tracker::source_destroy_handler(void* ptr, calldata_t
|
||||||
throw std::runtime_error("Missing 'source' parameter.");
|
throw std::runtime_error("Missing 'source' parameter.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->remove_source(source);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
DLOG_ERROR("Event 'source_destroy' caused exception: %s", ex.what());
|
DLOG_ERROR("Event 'source_destroy' caused exception: %s", ex.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
@ -98,161 +251,6 @@ void streamfx::obs::source_tracker::source_rename_handler(void* ptr, calldata_t*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void streamfx::obs::source_tracker::insert_source(obs_source_t* source)
|
|
||||||
{
|
|
||||||
const auto* name = obs_source_get_name(source);
|
|
||||||
if (!name) { // Do not track unnamed sources.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<obs_weak_source_t> weak{obs_source_get_weak_source(source), streamfx::obs::obs_weak_source_deleter};
|
|
||||||
if (!weak) { // This source has already been deleted, do not track.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
|
||||||
_sources.insert({
|
|
||||||
std::string(name),
|
|
||||||
weak,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void streamfx::obs::source_tracker::remove_source(obs_source_t* source)
|
|
||||||
{
|
|
||||||
const char* name = obs_source_get_name(source);
|
|
||||||
|
|
||||||
// Lock read & write access to the map.
|
|
||||||
std::unique_lock<std::mutex> ul(_mutex);
|
|
||||||
|
|
||||||
// Try and remove the source by name.
|
|
||||||
if (name != nullptr) {
|
|
||||||
auto found = _sources.find(std::string(name));
|
|
||||||
if (found != _sources.end()) {
|
|
||||||
_sources.erase(found);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If that didn't work, try and remove it by handle.
|
|
||||||
for (auto iter = _sources.begin(); iter != _sources.end(); iter++) {
|
|
||||||
if (obs_weak_source_get_source(iter->second.get()) == source) {
|
|
||||||
_sources.erase(iter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If that all failed, and the source is named, throw and report an error.
|
|
||||||
if (name) {
|
|
||||||
D_LOG_WARNING("Source '%s' was not tracked.", name);
|
|
||||||
throw std::runtime_error("Failed to find given source.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void streamfx::obs::source_tracker::rename_source(std::string_view old_name, std::string_view new_name,
|
|
||||||
obs_source_t* source)
|
|
||||||
{
|
|
||||||
if (old_name == new_name) {
|
|
||||||
throw std::runtime_error("New and old name are identical.");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> ul(_mutex);
|
|
||||||
auto found = _sources.find(std::string(old_name));
|
|
||||||
if (found == _sources.end()) {
|
|
||||||
insert_source(source);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert at new key, remove old pair.
|
|
||||||
_sources.insert({new_name.data(), found->second});
|
|
||||||
_sources.erase(found);
|
|
||||||
}
|
|
||||||
|
|
||||||
streamfx::obs::source_tracker::source_tracker() : _sources(), _mutex()
|
|
||||||
{
|
|
||||||
auto osi = obs_get_signal_handler();
|
|
||||||
signal_handler_connect(osi, "source_create", &source_create_handler, this);
|
|
||||||
signal_handler_connect(osi, "source_destroy", &source_destroy_handler, this);
|
|
||||||
signal_handler_connect(osi, "source_rename", &source_rename_handler, this);
|
|
||||||
|
|
||||||
// Enumerate all current sources and filters.
|
|
||||||
obs_enum_all_sources(
|
|
||||||
[](void* param, obs_source_t* source) {
|
|
||||||
auto* self = reinterpret_cast<::streamfx::obs::source_tracker*>(param);
|
|
||||||
self->insert_source(source);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
this);
|
|
||||||
}
|
|
||||||
|
|
||||||
streamfx::obs::source_tracker::~source_tracker()
|
|
||||||
{
|
|
||||||
auto osi = obs_get_signal_handler();
|
|
||||||
if (osi) {
|
|
||||||
signal_handler_disconnect(osi, "source_create", &source_create_handler, this);
|
|
||||||
signal_handler_disconnect(osi, "source_destroy", &source_destroy_handler, this);
|
|
||||||
signal_handler_disconnect(osi, "source_rename", &source_rename_handler, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->_sources.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void streamfx::obs::source_tracker::enumerate(enumerate_cb_t ecb, filter_cb_t fcb)
|
|
||||||
{
|
|
||||||
// Need func-local copy, otherwise we risk corruption if a new source is created or destroyed.
|
|
||||||
decltype(_sources) _clone;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> ul(_mutex);
|
|
||||||
_clone = _sources;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto kv : _clone) {
|
|
||||||
auto source = std::shared_ptr<obs_source_t>(obs_weak_source_get_source(kv.second.get()),
|
|
||||||
streamfx::obs::obs_source_deleter);
|
|
||||||
if (!source) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fcb) {
|
|
||||||
if (fcb(kv.first, source.get())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ecb) {
|
|
||||||
if (ecb(kv.first, source.get())) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool streamfx::obs::source_tracker::filter_sources(std::string, obs_source_t* source)
|
|
||||||
{
|
|
||||||
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool streamfx::obs::source_tracker::filter_audio_sources(std::string, obs_source_t* source)
|
|
||||||
{
|
|
||||||
uint32_t flags = obs_source_get_output_flags(source);
|
|
||||||
return !(flags & OBS_SOURCE_AUDIO) || (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool streamfx::obs::source_tracker::filter_video_sources(std::string, obs_source_t* source)
|
|
||||||
{
|
|
||||||
uint32_t flags = obs_source_get_output_flags(source);
|
|
||||||
return !(flags & OBS_SOURCE_VIDEO) || (obs_source_get_type(source) != OBS_SOURCE_TYPE_INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool streamfx::obs::source_tracker::filter_transitions(std::string, obs_source_t* source)
|
|
||||||
{
|
|
||||||
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_TRANSITION);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool streamfx::obs::source_tracker::filter_scenes(std::string, obs_source_t* source)
|
|
||||||
{
|
|
||||||
return (obs_source_get_type(source) != OBS_SOURCE_TYPE_SCENE);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<streamfx::obs::source_tracker> streamfx::obs::source_tracker::get()
|
std::shared_ptr<streamfx::obs::source_tracker> streamfx::obs::source_tracker::get()
|
||||||
{
|
{
|
||||||
static std::mutex inst_mtx;
|
static std::mutex inst_mtx;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Modern effects for a modern Streamer
|
* Modern effects for a modern Streamer
|
||||||
* Copyright (C) 2017-2018 Michael Fabian Dirks
|
* Copyright (C) 2017-2023 Michael Fabian Dirks
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "obs/obs-weak-source.hpp"
|
||||||
|
|
||||||
#include "warning-disable.hpp"
|
#include "warning-disable.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -28,17 +29,8 @@
|
||||||
|
|
||||||
namespace streamfx::obs {
|
namespace streamfx::obs {
|
||||||
class source_tracker {
|
class source_tracker {
|
||||||
std::map<std::string, std::shared_ptr<obs_weak_source_t>> _sources;
|
std::map<std::string, ::streamfx::obs::weak_source> _sources;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
|
|
||||||
static void source_create_handler(void* ptr, calldata_t* data) noexcept;
|
|
||||||
static void source_destroy_handler(void* ptr, calldata_t* data) noexcept;
|
|
||||||
static void source_rename_handler(void* ptr, calldata_t* data) noexcept;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void insert_source(obs_source_t* source);
|
|
||||||
void remove_source(obs_source_t* source);
|
|
||||||
void rename_source(std::string_view old_name, std::string_view new_name, obs_source_t* source);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Callback function for enumerating sources.
|
// Callback function for enumerating sources.
|
||||||
|
|
@ -46,14 +38,14 @@ namespace streamfx::obs {
|
||||||
// @param std::string Name of the Source
|
// @param std::string Name of the Source
|
||||||
// @param obs_source_t* Source
|
// @param obs_source_t* Source
|
||||||
// @return true to abort enumeration, false to keep going.
|
// @return true to abort enumeration, false to keep going.
|
||||||
typedef std::function<bool(std::string, obs_source_t*)> enumerate_cb_t;
|
typedef std::function<bool(std::string, ::streamfx::obs::source)> enumerate_cb_t;
|
||||||
|
|
||||||
// Filter function for enumerating sources.
|
// Filter function for enumerating sources.
|
||||||
//
|
//
|
||||||
// @param std::string Name of the Source
|
// @param std::string Name of the Source
|
||||||
// @param obs_source_t* Source
|
// @param obs_source_t* Source
|
||||||
// @return true to skip, false to pass along.
|
// @return true to skip, false to pass along.
|
||||||
typedef std::function<bool(std::string, obs_source_t*)> filter_cb_t;
|
typedef std::function<bool(std::string, ::streamfx::obs::source)> filter_cb_t;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
source_tracker();
|
source_tracker();
|
||||||
|
|
@ -67,12 +59,22 @@ namespace streamfx::obs {
|
||||||
// @param filter_cb Filter function to narrow down results.
|
// @param filter_cb Filter function to narrow down results.
|
||||||
void enumerate(enumerate_cb_t enumerate_cb, filter_cb_t filter_cb = nullptr);
|
void enumerate(enumerate_cb_t enumerate_cb, filter_cb_t filter_cb = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void insert_source(obs_source_t* source);
|
||||||
|
void remove_source(obs_source_t* source);
|
||||||
|
void rename_source(std::string_view old_name, std::string_view new_name, obs_source_t* source);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool filter_sources(std::string name, obs_source_t* source);
|
static bool filter_sources(std::string name, ::streamfx::obs::source source);
|
||||||
static bool filter_audio_sources(std::string name, obs_source_t* source);
|
static bool filter_audio_sources(std::string name, ::streamfx::obs::source source);
|
||||||
static bool filter_video_sources(std::string name, obs_source_t* source);
|
static bool filter_video_sources(std::string name, ::streamfx::obs::source source);
|
||||||
static bool filter_transitions(std::string name, obs_source_t* source);
|
static bool filter_transitions(std::string name, ::streamfx::obs::source source);
|
||||||
static bool filter_scenes(std::string name, obs_source_t* source);
|
static bool filter_scenes(std::string name, ::streamfx::obs::source source);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void source_create_handler(void* ptr, calldata_t* data) noexcept;
|
||||||
|
static void source_destroy_handler(void* ptr, calldata_t* data) noexcept;
|
||||||
|
static void source_rename_handler(void* ptr, calldata_t* data) noexcept;
|
||||||
|
|
||||||
public: // Singleton
|
public: // Singleton
|
||||||
static std::shared_ptr<streamfx::obs::source_tracker> get();
|
static std::shared_ptr<streamfx::obs::source_tracker> get();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Modern effects for a modern Streamer
|
* Modern effects for a modern Streamer
|
||||||
* Copyright (C) 2017 Michael Fabian Dirks
|
* Copyright (C) 2017-2023 Michael Fabian Dirks
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -348,7 +348,7 @@ obs_properties_t* mirror_factory::get_properties2(mirror_instance* data)
|
||||||
|
|
||||||
obs_property_list_add_string(p, "", "");
|
obs_property_list_add_string(p, "", "");
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
@ -356,7 +356,7 @@ obs_properties_t* mirror_factory::get_properties2(mirror_instance* data)
|
||||||
},
|
},
|
||||||
obs::source_tracker::filter_sources);
|
obs::source_tracker::filter_sources);
|
||||||
obs::source_tracker::get()->enumerate(
|
obs::source_tracker::get()->enumerate(
|
||||||
[&p](std::string name, obs_source_t*) {
|
[&p](std::string name, ::streamfx::obs::source) {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
||||||
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue