Skip to content

Commit ed16742

Browse files
authored
Merge branch 'master' into fix-sign-compare-warning
2 parents 109e9d6 + 8441c04 commit ed16742

17 files changed

+312
-6
lines changed

frontend/OBSStudioAPI.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,26 @@ void OBSStudioAPI::obs_frontend_add_undo_redo_action(const char *name, const und
689689
[redo](const std::string &data) { redo(data.c_str()); }, undo_data, redo_data, repeatable);
690690
}
691691

692+
void OBSStudioAPI::obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_list)
693+
{
694+
for (const auto &canvas : main->canvases) {
695+
obs_canvas_t *ref = obs_canvas_get_ref(canvas);
696+
if (ref)
697+
da_push_back(canvas_list->canvases, &ref);
698+
}
699+
}
700+
701+
obs_canvas_t *OBSStudioAPI::obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags)
702+
{
703+
auto &canvas = main->AddCanvas(std::string(name), ovi, flags);
704+
return obs_canvas_get_ref(canvas);
705+
}
706+
707+
bool OBSStudioAPI::obs_frontend_remove_canvas(obs_canvas_t *canvas)
708+
{
709+
return main->RemoveCanvas(canvas);
710+
}
711+
692712
void OBSStudioAPI::on_load(obs_data_t *settings)
693713
{
694714
for (size_t i = saveCallbacks.size(); i > 0; i--) {

frontend/OBSStudioAPI.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ struct OBSStudioAPI : obs_frontend_callbacks {
224224
void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
225225
const char *undo_data, const char *redo_data, bool repeatable) override;
226226

227+
void obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_list) override;
228+
229+
obs_canvas_t *obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags) override;
230+
231+
bool obs_frontend_remove_canvas(obs_canvas_t *canvas) override;
232+
227233
void on_load(obs_data_t *settings) override;
228234

229235
void on_preload(obs_data_t *settings) override;

frontend/api/obs-frontend-api.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -597,3 +597,19 @@ void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo
597597
if (callbacks_valid())
598598
c->obs_frontend_add_undo_redo_action(name, undo, redo, undo_data, redo_data, repeatable);
599599
}
600+
601+
void obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_list)
602+
{
603+
if (callbacks_valid())
604+
c->obs_frontend_get_canvases(canvas_list);
605+
}
606+
607+
obs_canvas_t *obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags)
608+
{
609+
return !!callbacks_valid() ? c->obs_frontend_add_canvas(name, ovi, flags) : nullptr;
610+
}
611+
612+
bool obs_frontend_remove_canvas(obs_canvas_t *canvas)
613+
{
614+
return !!callbacks_valid() ? c->obs_frontend_remove_canvas(canvas) : false;
615+
}

frontend/api/obs-frontend-api.h

+20
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ enum obs_frontend_event {
6262
OBS_FRONTEND_EVENT_SCENE_COLLECTION_RENAMED,
6363
OBS_FRONTEND_EVENT_THEME_CHANGED,
6464
OBS_FRONTEND_EVENT_SCREENSHOT_TAKEN,
65+
66+
OBS_FRONTEND_EVENT_CANVAS_ADDED,
67+
OBS_FRONTEND_EVENT_CANVAS_REMOVED,
6568
};
6669

6770
/* ------------------------------------------------------------------------- */
@@ -80,6 +83,19 @@ static inline void obs_frontend_source_list_free(struct obs_frontend_source_list
8083
da_free(source_list->sources);
8184
}
8285

86+
struct obs_frontend_canvas_list {
87+
DARRAY(obs_canvas_t *) canvases;
88+
};
89+
90+
static inline void obs_frontend_canvas_list_free(struct obs_frontend_canvas_list *canvas_list)
91+
{
92+
size_t num = canvas_list->canvases.num;
93+
for (size_t i = 0; i < num; i++)
94+
obs_canvas_release(canvas_list->canvases.array[i]);
95+
96+
da_free(canvas_list->canvases);
97+
}
98+
8399
#endif //!SWIG
84100

85101
/* ------------------------------------------------------------------------- */
@@ -238,6 +254,10 @@ typedef void (*undo_redo_cb)(const char *data);
238254
EXPORT void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
239255
const char *undo_data, const char *redo_data, bool repeatable);
240256

257+
EXPORT void obs_frontend_get_canvases(struct obs_frontend_canvas_list *canvas_list);
258+
EXPORT obs_canvas_t *obs_frontend_add_canvas(const char *name, struct obs_video_info *ovi, int flags);
259+
EXPORT bool obs_frontend_remove_canvas(obs_canvas_t *canvas);
260+
241261
/* ------------------------------------------------------------------------- */
242262

243263
#ifdef __cplusplus

frontend/api/obs-frontend-internal.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ struct obs_frontend_callbacks {
137137
virtual void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo,
138138
const undo_redo_cb redo, const char *undo_data,
139139
const char *redo_data, bool repeatable) = 0;
140+
141+
virtual obs_canvas_t *obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags) = 0;
142+
virtual bool obs_frontend_remove_canvas(obs_canvas_t *canvas) = 0;
143+
virtual void obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_list) = 0;
140144
};
141145

142146
EXPORT void obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks);

frontend/cmake/ui-utility.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ target_sources(
3333
utility/MultitrackVideoOutput.hpp
3434
utility/obf.c
3535
utility/obf.h
36+
utility/OBSCanvas.cpp
37+
utility/OBSCanvas.hpp
3638
utility/OBSEventFilter.hpp
3739
utility/OBSProxyStyle.cpp
3840
utility/OBSProxyStyle.hpp

frontend/cmake/ui-widgets.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ target_sources(
1515
widgets/OBSBasic.cpp
1616
widgets/OBSBasic.hpp
1717
widgets/OBSBasic_Browser.cpp
18+
widgets/OBSBasic_Canvases.cpp
1819
widgets/OBSBasic_Clipboard.cpp
1920
widgets/OBSBasic_ContextToolbar.cpp
2021
widgets/OBSBasic_Docks.cpp

frontend/docks/BrowserDock.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "BrowserDock.hpp"
22

33
#include <QCloseEvent>
4+
#include "moc_BrowserDock.cpp"
45

56
void BrowserDock::closeEvent(QCloseEvent *event)
67
{

frontend/docks/BrowserDock.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ extern QCef *cef;
88
extern QCefCookieManager *panel_cookies;
99

1010
class BrowserDock : public OBSDock {
11+
Q_OBJECT
12+
1113
private:
1214
QString title;
1315

frontend/utility/OBSCanvas.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/******************************************************************************
2+
Copyright (C) 2025 by Dennis Sädtler <[email protected]>
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
******************************************************************************/
17+
18+
#include "OBSCanvas.hpp"
19+
20+
#include <utility>
21+
22+
namespace OBS {
23+
24+
Canvas::Canvas(obs_canvas_t *canvas) : canvas(canvas) {}
25+
26+
Canvas::Canvas(Canvas &&other) noexcept
27+
{
28+
canvas = std::exchange(other.canvas, nullptr);
29+
}
30+
31+
Canvas::~Canvas() noexcept
32+
{
33+
if (!canvas)
34+
return;
35+
36+
obs_canvas_remove(canvas);
37+
obs_canvas_release(canvas);
38+
canvas = nullptr;
39+
}
40+
41+
Canvas &Canvas::operator=(Canvas &&other) noexcept
42+
{
43+
canvas = std::exchange(other.canvas, canvas);
44+
45+
return *this;
46+
}
47+
48+
std::optional<OBSDataAutoRelease> Canvas::Save() const
49+
{
50+
if (!canvas)
51+
return std::nullopt;
52+
if (obs_data_t *saved = obs_save_canvas(canvas))
53+
return saved;
54+
55+
return std::nullopt;
56+
}
57+
58+
std::optional<Canvas> Canvas::Load(obs_data_t *data)
59+
{
60+
if (OBSDataAutoRelease canvas_data = obs_data_get_obj(data, "info")) {
61+
if (obs_canvas_t *canvas = obs_load_canvas(canvas_data)) {
62+
return canvas;
63+
}
64+
}
65+
66+
return std::nullopt;
67+
}
68+
69+
std::vector<Canvas> Canvas::LoadCanvases(obs_data_array_t *canvases)
70+
{
71+
auto cb = [](obs_data_t *data, void *param) -> void {
72+
auto vec = static_cast<std::vector<Canvas> *>(param);
73+
if (auto canvas = Canvas::Load(data))
74+
vec->emplace_back(std::move(*canvas));
75+
};
76+
77+
std::vector<Canvas> ret;
78+
obs_data_array_enum(canvases, cb, &ret);
79+
80+
return ret;
81+
}
82+
83+
OBSDataArrayAutoRelease Canvas::SaveCanvases(const std::vector<Canvas> &canvases)
84+
{
85+
OBSDataArrayAutoRelease savedCanvases = obs_data_array_create();
86+
87+
for (auto &canvas : canvases) {
88+
auto canvas_data = canvas.Save();
89+
if (!canvas_data)
90+
continue;
91+
92+
OBSDataAutoRelease data = obs_data_create();
93+
obs_data_set_obj(data, "info", *canvas_data);
94+
obs_data_array_push_back(savedCanvases, data);
95+
}
96+
97+
return savedCanvases;
98+
}
99+
100+
} // namespace OBS

frontend/utility/OBSCanvas.hpp

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/******************************************************************************
2+
Copyright (C) 2025 by Dennis Sädtler <[email protected]>
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
******************************************************************************/
17+
18+
#pragma once
19+
20+
#include <optional>
21+
#include <vector>
22+
23+
#include "obs.h"
24+
#include "obs.hpp"
25+
26+
namespace OBS {
27+
class Canvas {
28+
29+
public:
30+
Canvas(obs_canvas_t *canvas);
31+
Canvas(Canvas &&other) noexcept;
32+
33+
~Canvas() noexcept;
34+
35+
// No default or copy/move constructors
36+
Canvas() = delete;
37+
Canvas(Canvas &other) = delete;
38+
39+
Canvas &operator=(Canvas &&other) noexcept;
40+
41+
operator obs_canvas_t *() const { return canvas; }
42+
43+
[[nodiscard]] std::optional<OBSDataAutoRelease> Save() const;
44+
static std::optional<Canvas> Load(obs_data_t *data);
45+
static std::vector<Canvas> LoadCanvases(obs_data_array_t *canvases);
46+
static OBSDataArrayAutoRelease SaveCanvases(const std::vector<Canvas> &canvases);
47+
48+
private:
49+
obs_canvas_t *canvas = nullptr;
50+
};
51+
} // namespace OBS

frontend/widgets/OBSBasic.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ void OBSBasic::InitOBSCallbacks()
842842
{
843843
ProfileScope("OBSBasic::InitOBSCallbacks");
844844

845-
signalHandlers.reserve(signalHandlers.size() + 9);
845+
signalHandlers.reserve(signalHandlers.size() + 10);
846846
signalHandlers.emplace_back(obs_get_signal_handler(), "source_create", OBSBasic::SourceCreated, this);
847847
signalHandlers.emplace_back(obs_get_signal_handler(), "source_remove", OBSBasic::SourceRemoved, this);
848848
signalHandlers.emplace_back(obs_get_signal_handler(), "source_activate", OBSBasic::SourceActivated, this);
@@ -866,6 +866,7 @@ void OBSBasic::InitOBSCallbacks()
866866
Qt::QueuedConnection);
867867
},
868868
this);
869+
signalHandlers.emplace_back(obs_get_signal_handler(), "canvas_remove", OBSBasic::CanvasRemoved, this);
869870
}
870871

871872
#define STARTUP_SEPARATOR "==== Startup complete ==============================================="

frontend/widgets/OBSBasic.hpp

+18
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <OBSApp.hpp>
2424
#include <oauth/Auth.hpp>
2525
#include <utility/BasicOutputHandler.hpp>
26+
#include <utility/OBSCanvas.hpp>
2627
#include <utility/VCamConfig.hpp>
2728
#include <utility/platform.hpp>
2829
#include <utility/undo_stack.hpp>
@@ -1108,6 +1109,23 @@ private slots:
11081109
std::optional<SceneCollection> GetSceneCollectionByName(const std::string &collectionName) const;
11091110
std::optional<SceneCollection> GetSceneCollectionByFileName(const std::string &fileName) const;
11101111

1112+
/* -------------------------------------
1113+
* MARK: - OBSBasic_Canvases
1114+
* -------------------------------------
1115+
*/
1116+
private:
1117+
std::vector<OBS::Canvas> canvases;
1118+
1119+
static void CanvasRemoved(void *data, calldata_t *params);
1120+
1121+
public:
1122+
const std::vector<OBS::Canvas> &GetCanvases() const noexcept { return canvases; }
1123+
1124+
const OBS::Canvas &AddCanvas(const std::string &name, obs_video_info *ovi = nullptr, int flags = 0);
1125+
1126+
public slots:
1127+
bool RemoveCanvas(obs_canvas_t *canvas);
1128+
11111129
/* -------------------------------------
11121130
* MARK: - OBSBasic_SceneItems
11131131
* -------------------------------------
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/******************************************************************************
2+
Copyright (C) 2025 by Dennis Sädtler <[email protected]>
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
******************************************************************************/
17+
18+
#include "OBSBasic.hpp"
19+
20+
void OBSBasic::CanvasRemoved(void *data, calldata_t *params)
21+
{
22+
obs_canvas_t *canvas = static_cast<obs_canvas_t *>(calldata_ptr(params, "canvas"));
23+
QMetaObject::invokeMethod(static_cast<OBSBasic *>(data), "RemoveCanvas", Q_ARG(OBSCanvas, OBSCanvas(canvas)));
24+
}
25+
26+
const OBS::Canvas &OBSBasic::AddCanvas(const std::string &name, obs_video_info *ovi, int flags)
27+
{
28+
OBSCanvas canvas = obs_canvas_create(name.c_str(), ovi, flags);
29+
auto &it = canvases.emplace_back(canvas);
30+
OnEvent(OBS_FRONTEND_EVENT_CANVAS_ADDED);
31+
return it;
32+
}
33+
34+
bool OBSBasic::RemoveCanvas(obs_canvas_t *canvas)
35+
{
36+
if (!canvas)
37+
return false;
38+
39+
auto canvas_it = std::find(std::begin(canvases), std::end(canvases), canvas);
40+
if (canvas_it != std::end(canvases)) {
41+
canvases.erase(canvas_it);
42+
OnEvent(OBS_FRONTEND_EVENT_CANVAS_REMOVED);
43+
return true;
44+
}
45+
46+
return false;
47+
}

0 commit comments

Comments
 (0)