mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Some checks are pending
debian-build / build (push) Waiting to run
Check locale / ubuntu64 (push) Waiting to run
Push to master / Check Formatting 🔍 (push) Waiting to run
Push to master / Build Project 🧱 (push) Waiting to run
Push to master / Create Release 🛫 (push) Blocked by required conditions
New scene selections would have no canvas selected at all. This would cause issues in places which do not support an empty canvas selection. For example, the "scene changed" check of the scene condition would not work as without any canvas it is not clear which scene to check for.
354 lines
7.6 KiB
C++
354 lines
7.6 KiB
C++
#include "canvas-helpers.hpp"
|
|
#include "obs-module-helper.hpp"
|
|
#include "scene-group.hpp"
|
|
#include "scene-switch-helpers.hpp"
|
|
#include "selection-helpers.hpp"
|
|
#include "source-helpers.hpp"
|
|
#include "ui-helpers.hpp"
|
|
#include "utility.hpp"
|
|
#include "variable.hpp"
|
|
|
|
#include <obs-frontend-api.h>
|
|
|
|
#include <QLayout>
|
|
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
Q_DECLARE_METATYPE(advss::OBSWeakCanvas);
|
|
#else
|
|
Q_DECLARE_METATYPE(OBSWeakCanvas);
|
|
#endif
|
|
|
|
namespace advss {
|
|
|
|
void CanvasSelection::Populate()
|
|
{
|
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
static const auto enumCanvases = [](void *listPtr,
|
|
obs_canvas_t *canvas) -> bool {
|
|
auto list = static_cast<FilterComboBox *>(listPtr);
|
|
OBSWeakCanvas weakCanvas = obs_canvas_get_weak_canvas(canvas);
|
|
obs_weak_canvas_release(weakCanvas);
|
|
QVariant variant;
|
|
variant.setValue(weakCanvas);
|
|
list->addItem(obs_canvas_get_name(canvas), variant);
|
|
return true;
|
|
};
|
|
obs_enum_canvases(enumCanvases, this);
|
|
#endif
|
|
}
|
|
|
|
CanvasSelection::CanvasSelection(QWidget *parent)
|
|
: FilterComboBox(parent,
|
|
obs_module_text("AdvSceneSwitcher.selectScene"))
|
|
{
|
|
setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
|
|
Populate();
|
|
|
|
connect(this, &FilterComboBox::currentIndexChanged, this,
|
|
[this]() { emit CanvasChanged(GetCanvas()); });
|
|
}
|
|
|
|
void CanvasSelection::SetCanvas(const OBSWeakCanvas &canvas)
|
|
{
|
|
QVariant variant;
|
|
variant.setValue(canvas);
|
|
setCurrentIndex(findData(variant));
|
|
}
|
|
|
|
OBSWeakCanvas CanvasSelection::GetCanvas()
|
|
{
|
|
return itemData(currentIndex()).value<OBSWeakCanvas>();
|
|
}
|
|
|
|
int GetCanvasCount()
|
|
{
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
return 1;
|
|
#else
|
|
static const auto enumCanvases = [](void *countPtr,
|
|
obs_canvas_t *) -> bool {
|
|
auto count = static_cast<int *>(countPtr);
|
|
(*count)++;
|
|
return true;
|
|
};
|
|
int count = 0;
|
|
obs_enum_canvases(enumCanvases, &count);
|
|
return count;
|
|
#endif
|
|
}
|
|
|
|
OBSWeakCanvas GetWeakCanvasByName(const char *name)
|
|
{
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
return OBSWeakCanvas();
|
|
#else
|
|
struct Data {
|
|
OBSWeakCanvas canvas;
|
|
const std::string name;
|
|
};
|
|
|
|
static const auto enumCanvases = [](void *dataPtr,
|
|
obs_canvas_t *canvas) -> bool {
|
|
auto data = static_cast<Data *>(dataPtr);
|
|
if (data->name != obs_canvas_get_name(canvas)) {
|
|
return true;
|
|
}
|
|
|
|
data->canvas = obs_canvas_get_weak_canvas(canvas);
|
|
obs_weak_canvas_release(data->canvas);
|
|
return false;
|
|
};
|
|
Data data{nullptr, name};
|
|
obs_enum_canvases(enumCanvases, &data);
|
|
return data.canvas;
|
|
#endif
|
|
}
|
|
|
|
std::string GetWeakCanvasName(const OBSWeakCanvas &weakCanvas)
|
|
{
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
return "Main";
|
|
#else
|
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
|
return canvas ? obs_canvas_get_name(canvas) : "";
|
|
#endif
|
|
}
|
|
|
|
bool IsMainCanvas(obs_weak_canvas_t *weakCanvas)
|
|
{
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
return true;
|
|
#else
|
|
if (!weakCanvas) {
|
|
return false;
|
|
}
|
|
|
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
|
OBSCanvasAutoRelease main = obs_get_main_canvas();
|
|
return canvas == main;
|
|
#endif
|
|
}
|
|
|
|
OBSWeakSource GetActiveCanvasScene(const OBSWeakCanvas &weakCanvas)
|
|
{
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
OBSCanvasAutoRelease canvas;
|
|
#else
|
|
if (!weakCanvas) {
|
|
return nullptr;
|
|
}
|
|
|
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
|
if (!canvas) {
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
|
|
|
// The frontend scene order does not necessarily match the order of the
|
|
// scenes in the canvas.
|
|
if (canvas == mainCanvas) {
|
|
OBSSourceAutoRelease scene = obs_frontend_get_current_scene();
|
|
return OBSGetWeakRef(scene);
|
|
}
|
|
|
|
static const auto enumCanvasScenes = [](void *scenePtr,
|
|
obs_source_t *source) -> bool {
|
|
auto scene = static_cast<OBSWeakSource *>(scenePtr);
|
|
if (!obs_source_active(source)) {
|
|
return true;
|
|
}
|
|
|
|
*scene = obs_source_get_weak_source(source);
|
|
obs_weak_source_release(*scene);
|
|
return false;
|
|
};
|
|
|
|
OBSWeakSource scene;
|
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &scene);
|
|
return scene;
|
|
}
|
|
|
|
OBSWeakSource GetSceneAtIndex(const OBSWeakCanvas &weakCanvas, int idx)
|
|
{
|
|
if (idx < 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
OBSCanvas canvas;
|
|
#else
|
|
if (!weakCanvas) {
|
|
return nullptr;
|
|
}
|
|
|
|
OBSCanvas canvas = OBSGetStrongRef(weakCanvas);
|
|
if (!canvas) {
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
|
|
|
// The frontend scene order does not necessarily match the order of the
|
|
// scenes in the canvas.
|
|
// So, rely on obs_frontend_get_scenes() in case of the main canvas
|
|
// instead.
|
|
if (canvas == mainCanvas) {
|
|
struct obs_frontend_source_list scenes = {0};
|
|
obs_frontend_get_scenes(&scenes);
|
|
if (idx >= (int)scenes.sources.num) {
|
|
obs_frontend_source_list_free(&scenes);
|
|
return nullptr;
|
|
}
|
|
|
|
auto scene = OBSGetWeakRef(scenes.sources.array[idx]);
|
|
obs_frontend_source_list_free(&scenes);
|
|
return scene;
|
|
}
|
|
|
|
struct Data {
|
|
const int idx;
|
|
int currentIdx;
|
|
OBSSource scene;
|
|
};
|
|
|
|
static const auto enumCanvasScenes = [](void *dataPtr,
|
|
obs_source_t *source) -> bool {
|
|
auto data = static_cast<Data *>(dataPtr);
|
|
if (data->idx != data->currentIdx) {
|
|
data->currentIdx++;
|
|
return true;
|
|
}
|
|
|
|
data->scene = source;
|
|
return false;
|
|
};
|
|
|
|
Data data{idx, 0, nullptr};
|
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &data);
|
|
|
|
return OBSGetWeakRef(data.scene);
|
|
}
|
|
|
|
int GetIndexOfScene(const OBSWeakCanvas &weakCanvas, const OBSWeakSource &scene)
|
|
{
|
|
if (!scene) {
|
|
return 0;
|
|
}
|
|
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
OBSCanvas canvas;
|
|
#else
|
|
if (!weakCanvas) {
|
|
return 0;
|
|
}
|
|
|
|
OBSCanvas canvas = OBSGetStrongRef(weakCanvas);
|
|
if (!canvas) {
|
|
return 0;
|
|
}
|
|
#endif
|
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
|
|
|
// The frontend scene order does not necessarily match the order of the
|
|
// scenes in the canvas.
|
|
// So, rely on obs_frontend_get_scenes() in case of the main canvas
|
|
// instead.
|
|
if (canvas == mainCanvas) {
|
|
struct obs_frontend_source_list scenes = {0};
|
|
obs_frontend_get_scenes(&scenes);
|
|
|
|
OBSSourceAutoRelease sceneSource = OBSGetStrongRef(scene);
|
|
int idx = 0;
|
|
|
|
for (size_t i = 0; i < scenes.sources.num; i++) {
|
|
if (scenes.sources.array[i] == sceneSource) {
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
obs_frontend_source_list_free(&scenes);
|
|
return idx;
|
|
}
|
|
|
|
struct Data {
|
|
int idx;
|
|
OBSSource scene;
|
|
};
|
|
|
|
static const auto enumCanvasScenes = [](void *dataPtr,
|
|
obs_source_t *source) -> bool {
|
|
auto data = static_cast<Data *>(dataPtr);
|
|
if (source == data->scene) {
|
|
return false;
|
|
}
|
|
|
|
data->idx++;
|
|
return true;
|
|
};
|
|
|
|
Data data{0, OBSGetStrongRef(scene)};
|
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &data);
|
|
|
|
return data.idx;
|
|
}
|
|
|
|
OBSWeakCanvas GetMainCanvas()
|
|
{
|
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
|
return OBSGetWeakRef(mainCanvas);
|
|
}
|
|
|
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
|
|
|
obs_canvas_t *obs_canvas_get_ref(obs_canvas_t *)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void obs_canvas_release(obs_canvas_t *) {}
|
|
|
|
void obs_weak_canvas_addref(obs_weak_canvas_t *) {}
|
|
|
|
void obs_weak_canvas_release(obs_weak_canvas_t *) {}
|
|
|
|
OBSCanvas OBSGetStrongRef(obs_weak_object_t *weak)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
obs_weak_canvas_t *obs_canvas_get_weak_canvas(obs_canvas_t *)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
obs_canvas_t *obs_weak_canvas_get_canvas(obs_weak_canvas_t *)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void obs_canvas_enum_scenes(obs_canvas_t *,
|
|
bool (*enum_proc)(void *, obs_source_t *),
|
|
void *param)
|
|
{
|
|
obs_enum_scenes(enum_proc, param);
|
|
}
|
|
|
|
OBSCanvas OBSGetStrongRef(obs_weak_canvas_t *)
|
|
{
|
|
return OBSCanvas();
|
|
}
|
|
|
|
obs_canvas_t *obs_get_main_canvas()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
#endif
|
|
|
|
} // namespace advss
|