-
Notifications
You must be signed in to change notification settings - Fork 0
/
obs.hh
329 lines (255 loc) · 9.88 KB
/
obs.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#ifndef _OBS_HH
#define _OBS_HH 1
#include <chrono>
#include <condition_variable>
#include <functional>
#include <list>
#include <mutex>
#include <optional>
#include <queue>
#include <string>
#include <thread>
#include <type_traits>
#include <unordered_map>
#include <vector>
#include <libconfig.h++>
#include <streamdeckpp.hh>
#include <json/json.h>
#include <Magick++.h>
#include "ftlibrary.hh"
namespace obs {
// Forward declaration.
struct info;
enum struct keyop_type {
live_scene,
preview_scene,
cut,
auto_rate,
ftb,
transition,
source,
record,
stream,
virtualcam,
};
struct source {
std::string name;
bool enabled;
};
struct scene {
scene() = default;
scene(unsigned nr_, const std::string& name_) : nr(nr_), name(name_), sources() { }
unsigned nr = 0;
std::string name;
std::vector<source> sources;
};
struct transition {
transition() = default;
transition(unsigned nr_, const std::string& name_) : nr(nr_), name(name_) { }
unsigned nr = 0;
std::string name;
};
using set_key_image_cb = std::function<void(unsigned,unsigned,unsigned,Magick::Image&&)>;
using set_key_handle_cb = std::function<void(unsigned,unsigned,unsigned,int)>;
struct button {
button(unsigned nr_, set_key_image_cb setkey_image_, set_key_handle_cb set_key_handle_, info* i_, unsigned page_, unsigned row_, unsigned column_, int icon1_, int icon2_, keyop_type keyop_);
unsigned nr;
set_key_image_cb setkey_image;
set_key_handle_cb setkey_handle;
info* i;
const unsigned page;
const unsigned row;
const unsigned column;
int icon1;
int icon2;
keyop_type keyop;
void call();
virtual void show_icon();
bool visible() const { return true; }
void initialize();
};
struct auto_button : button {
using base_type = button;
auto_button(unsigned nr_, set_key_image_cb setkey_image_, set_key_handle_cb setkey_handle_, info* i_, unsigned page_, unsigned row_, unsigned column_, Magick::Image&& icon1_, keyop_type keyop_, ftlibrary& ftobj, const std::string& font_, const std::string& color_, std::pair<double,double>&& center_, unsigned& duration_ms_)
: base_type(nr_, setkey_image_, setkey_handle_, i_, page_, row_, column_, -1, -1, keyop_), background(std::move(icon1_)), fontobj(ftobj, font_), duration_ms(duration_ms_), color(color_), center(std::move(center_))
{
}
void show_icon() override ;
Magick::Image background;
ftface fontobj;
unsigned& duration_ms;
Magick::Color color;
std::pair<double,double> center;
};
struct scene_button : button {
using base_type = button;
scene_button(unsigned nr_, set_key_image_cb setkey_image_, set_key_handle_cb setkey_handle_, info* i_, unsigned page_, unsigned row_, unsigned column_, Magick::Image&& icon1_, Magick::Image&& icon2_, keyop_type keyop_, ftlibrary& ftobj, const std::string& font_)
: base_type(nr_, setkey_image_, setkey_handle_, i_, page_, row_, column_, -1, -1, keyop_), background(std::move(icon1_)), background_off(std::move(icon2_)), fontobj(ftobj, font_)
{
}
void show_icon() override;
Magick::Image background;
Magick::Image background_off;
ftface fontobj;
};
struct transition_button : button {
using base_type = button;
transition_button(unsigned nr_, set_key_image_cb setkey_image_, set_key_handle_cb setkey_handle_, info* i_, unsigned page_, unsigned row_, unsigned column_, Magick::Image&& icon1_, Magick::Image&& icon2_, keyop_type keyop_, ftlibrary& ftobj, const std::string& font_)
: base_type(nr_, setkey_image_, setkey_handle_, i_, page_, row_, column_, -1, -1, keyop_), background(std::move(icon1_)), background_off(std::move(icon2_)), fontobj(ftobj, std::move(font_))
{
}
void show_icon() override;
Magick::Image background;
Magick::Image background_off;
ftface fontobj;
};
struct source_button : button {
using base_type = button;
source_button(unsigned nr_, set_key_image_cb setkey_image_image_, set_key_handle_cb setkey_handle_, info* i_, unsigned page_, unsigned row_, unsigned column_, Magick::Image&& icon1_, Magick::Image&& icon2_, keyop_type keyop_, ftlibrary& ftobj, const std::string& font_)
: base_type(nr_, setkey_image_image_, setkey_handle_, i_, page_, row_, column_, -1, -1, keyop_), background(std::move(icon1_)), background_off(std::move(icon2_)), fontobj(ftobj, std::move(font_))
{
}
void show_icon() override;
Magick::Image background;
Magick::Image background_off;
ftface fontobj;
};
struct work_request {
enum struct work_type {
none,
new_session,
buttons,
scene,
visible,
preview,
transition,
new_scene,
delete_scene,
recording,
streaming,
virtualcam,
sceneschanged,
studiomode,
sourcename,
transitionend,
duration,
sourceorder,
new_source,
remove_source,
} type;
unsigned nr = 0;
std::vector<std::string> names;
};
struct info {
using register_image_cb = std::function<int(Magick::Image&&)>;
info(const libconfig::Setting& config, ftlibrary& ftobj_, register_image_cb register_image_);
~info();
void get_session_data();
button* parse_key(set_key_image_cb setkey_image, set_key_handle_cb setkey_handle, unsigned page, unsigned row, unsigned column, const libconfig::Setting& config);
void add_scene(unsigned idx, const char* name);
unsigned scene_count() const { return scenes.size(); }
unsigned transition_count() const { return transitions.size(); }
scene& get_current_scene();
scene& get_current_preview();
int get_current_duration() const { return current_duration_ms; }
scene& get_preview(const std::string& s);
transition& get_current_transition();
std::string& get_scene_name(unsigned nr) { for (auto& p : scenes) if (p.second.nr == nr) return p.second.name; throw std::runtime_error("invalid scene number"); }
std::string& get_transition_name(unsigned nr) { for (auto& p : transitions) if (p.second.nr == nr) return p.second.name; throw std::runtime_error("invalid transition number"); }
void worker_thread();
void callback(const Json::Value& val);
void connection_update(bool connected_);
bool prohibit_sleep() const { return is_recording || is_streaming || provide_virtualcam; }
enum struct button_class : unsigned {
none = 0u,
live = 1u << 0,
preview = 1u << 1,
cut = 1u << 2,
auto_ = 1u << 3,
ftb = 1u << 4,
transition = 1u << 5,
record = 1u << 6,
sources = 1u << 7,
all = live | preview | cut | auto_ | ftb | transition | record | sources
};
void button_update(button_class bc);
const register_image_cb register_image;
ftlibrary& ftobj;
bool created_ws = false;
bool connected = false;
std::queue<work_request> worker_queue;
work_request get_request();
using timeout_clock = std::chrono::system_clock;
std::optional<work_request> get_request(const std::chrono::time_point<timeout_clock>& to);
std::condition_variable worker_cv;
std::mutex worker_m;
std::atomic<bool> terminate = false;
std::thread worker;
bool log_unknown_events = false;
bool studio_mode = false;
bool is_recording = false;
bool is_streaming = false;
bool provide_virtualcam = false;
bool ignore_next_transition_change = false;
struct name_enabled_type {
std::string uuid { };
std::string name { };
unsigned id = 0;
bool enabled = false;
};
std::unordered_map<std::string,obs::scene> scenes;
std::string current_scene;
std::string saved_scene;
std::vector<name_enabled_type> current_sources;
std::string current_preview;
std::string saved_preview;
std::unordered_map<std::string,obs::transition> transitions;
std::string current_transition;
unsigned current_duration_ms;
std::atomic_flag handle_next_transition_change = true;
std::unordered_multimap<unsigned,scene_button> scene_live_buttons;
std::unordered_multimap<unsigned,source_button> source_buttons;
std::unordered_multimap<unsigned,scene_button> scene_preview_buttons;
std::list<button> cut_buttons;
std::list<auto_button> auto_buttons;
std::list<button> ftb_buttons;
std::unordered_multimap<unsigned,transition_button> transition_buttons;
std::list<button> record_buttons;
std::string open;
const Magick::Color im_black;
const Magick::Color im_white;
const Magick::Color im_darkgray;
const int obsicon;
const int live_unused_icon;
const int preview_unused_icon;
const int source_unused_icon;
const int transition_unused_icon;
struct ftb_handler {
std::vector<int> icons;
std::atomic<int> cycle = -1;
bool active() const { return cycle >= 0; }
void operator++() { if (cycle >= 0) { if (size_t(++cycle) == 2 * icons.size()) cycle = 0; } }
operator int() const { return cycle.load(); }
void start() { cycle = 0; }
void stop() { cycle = -1; }
int get() const { return icons[size_t(cycle) >= icons.size() ? int(2 * icons.size() - 1 - cycle) : int(cycle)]; }
} ftb;
const std::string obsfont;
};
inline constexpr info::button_class operator|(info::button_class l, info::button_class r)
{
using int_type = std::underlying_type_t<info::button_class>;
return info::button_class(int_type(l) | int_type(r));
}
inline constexpr info::button_class operator&(info::button_class l, info::button_class r)
{
using int_type = std::underlying_type_t<info::button_class>;
return info::button_class(int_type(l) & int_type(r));
}
inline consteval info::button_class operator^(info::button_class l, info::button_class r)
{
using int_type = std::underlying_type_t<info::button_class>;
return info::button_class(int_type(l) ^ int_type(r));
}
} // namespace obs
#endif // obs.hh