1 /*
2  * Modern effects for a modern Streamer
3  * Copyright (C) 2017 Michael Fabian Dirks
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18 */
19 
20 #include "plugin.hpp"
21 #include <fstream>
22 #include <stdexcept>
23 #include "configuration.hpp"
24 #include "obs/gs/gs-vertexbuffer.hpp"
25 #include "obs/obs-source-tracker.hpp"
26 
27 #ifdef ENABLE_ENCODER_FFMPEG
28 #include "encoders/encoder-ffmpeg.hpp"
29 #endif
30 
31 #ifdef ENABLE_FILTER_BLUR
32 #include "filters/filter-blur.hpp"
33 #endif
34 #ifdef ENABLE_FILTER_COLOR_GRADE
35 #include "filters/filter-color-grade.hpp"
36 #endif
37 #ifdef ENABLE_FILTER_DISPLACEMENT
38 #include "filters/filter-displacement.hpp"
39 #endif
40 #ifdef ENABLE_FILTER_DYNAMIC_MASK
41 #include "filters/filter-dynamic-mask.hpp"
42 #endif
43 #ifdef ENABLE_FILTER_NVIDIA_FACE_TRACKING
44 #include "filters/filter-nv-face-tracking.hpp"
45 #endif
46 #ifdef ENABLE_FILTER_SDF_EFFECTS
47 #include "filters/filter-sdf-effects.hpp"
48 #endif
49 #ifdef ENABLE_FILTER_SHADER
50 #include "filters/filter-shader.hpp"
51 #endif
52 #ifdef ENABLE_FILTER_TRANSFORM
53 #include "filters/filter-transform.hpp"
54 #endif
55 
56 #ifdef ENABLE_SOURCE_MIRROR
57 #include "sources/source-mirror.hpp"
58 #endif
59 #ifdef ENABLE_SOURCE_SHADER
60 #include "sources/source-shader.hpp"
61 #endif
62 
63 #ifdef ENABLE_TRANSITION_SHADER
64 #include "transitions/transition-shader.hpp"
65 #endif
66 
67 #ifdef ENABLE_FRONTEND
68 #include "ui/ui.hpp"
69 #endif
70 
71 #ifdef ENABLE_UPDATER
72 #include "updater.hpp"
73 //static std::shared_ptr<streamfx::updater> _updater;
74 #endif
75 
76 static std::shared_ptr<util::threadpool>  _threadpool;
77 static std::shared_ptr<gs::vertex_buffer> _gs_fstri_vb;
78 
obs_module_load(void)79 MODULE_EXPORT bool obs_module_load(void)
80 try {
81 	DLOG_INFO("Loading Version %s", STREAMFX_VERSION_STRING);
82 
83 	// Initialize global configuration.
84 	streamfx::configuration::initialize();
85 
86 	// Initialize global Thread Pool.
87 	_threadpool = std::make_shared<util::threadpool>();
88 
89 	// Initialize Source Tracker
90 	obs::source_tracker::initialize();
91 
92 	// GS Stuff
93 	{
94 		_gs_fstri_vb = std::make_shared<gs::vertex_buffer>(uint32_t(3), uint8_t(1));
95 		{
96 			auto vtx = _gs_fstri_vb->at(0);
97 			vec3_set(vtx.position, 0, 0, 0);
98 			vec4_set(vtx.uv[0], 0, 0, 0, 0);
99 		}
100 		{
101 			auto vtx = _gs_fstri_vb->at(1);
102 			vec3_set(vtx.position, 2, 0, 0);
103 			vec4_set(vtx.uv[0], 2, 0, 0, 0);
104 		}
105 		{
106 			auto vtx = _gs_fstri_vb->at(2);
107 			vec3_set(vtx.position, 0, 2, 0);
108 			vec4_set(vtx.uv[0], 0, 2, 0, 0);
109 		}
110 		_gs_fstri_vb->update();
111 	}
112 
113 	// Encoders
114 	{
115 #ifdef ENABLE_ENCODER_FFMPEG
116 		using namespace streamfx::encoder::ffmpeg;
117 		ffmpeg_manager::initialize();
118 #endif
119 	}
120 
121 	// Filters
122 	{
123 #ifdef ENABLE_FILTER_BLUR
124 		streamfx::filter::blur::blur_factory::initialize();
125 #endif
126 #ifdef ENABLE_FILTER_COLOR_GRADE
127 		streamfx::filter::color_grade::color_grade_factory::initialize();
128 #endif
129 #ifdef ENABLE_FILTER_DISPLACEMENT
130 		streamfx::filter::displacement::displacement_factory::initialize();
131 #endif
132 #ifdef ENABLE_FILTER_DYNAMIC_MASK
133 		streamfx::filter::dynamic_mask::dynamic_mask_factory::initialize();
134 #endif
135 #ifdef ENABLE_FILTER_NVIDIA_FACE_TRACKING
136 		streamfx::filter::nvidia::face_tracking_factory::initialize();
137 #endif
138 #ifdef ENABLE_FILTER_SDF_EFFECTS
139 		streamfx::filter::sdf_effects::sdf_effects_factory::initialize();
140 #endif
141 #ifdef ENABLE_FILTER_SHADER
142 		streamfx::filter::shader::shader_factory::initialize();
143 #endif
144 #ifdef ENABLE_FILTER_TRANSFORM
145 		streamfx::filter::transform::transform_factory::initialize();
146 #endif
147 	}
148 
149 	// Sources
150 	{
151 #ifdef ENABLE_SOURCE_MIRROR
152 		streamfx::source::mirror::mirror_factory::initialize();
153 #endif
154 #ifdef ENABLE_SOURCE_SHADER
155 		streamfx::source::shader::shader_factory::initialize();
156 #endif
157 	}
158 
159 	// Transitions
160 	{
161 #ifdef ENABLE_TRANSITION_SHADER
162 		streamfx::transition::shader::shader_factory::initialize();
163 #endif
164 	}
165 
166 // Frontend
167 #ifdef ENABLE_FRONTEND
168 	streamfx::ui::handler::initialize();
169 #endif
170 
171 	DLOG_INFO("Loaded Version %s", STREAMFX_VERSION_STRING);
172 	return true;
173 } catch (...) {
174 	DLOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
175 	return false;
176 }
177 
obs_module_unload(void)178 MODULE_EXPORT void obs_module_unload(void)
179 try {
180 	DLOG_INFO("Unloading Version %s", STREAMFX_VERSION_STRING);
181 
182 	// Frontend
183 #ifdef ENABLE_FRONTEND
184 	streamfx::ui::handler::finalize();
185 #endif
186 
187 	// Transitions
188 	{
189 #ifdef ENABLE_TRANSITION_SHADER
190 		streamfx::transition::shader::shader_factory::finalize();
191 #endif
192 	}
193 
194 	// Sources
195 	{
196 #ifdef ENABLE_SOURCE_MIRROR
197 		streamfx::source::mirror::mirror_factory::finalize();
198 #endif
199 #ifdef ENABLE_SOURCE_SHADER
200 		streamfx::source::shader::shader_factory::finalize();
201 #endif
202 	}
203 
204 	// Filters
205 	{
206 #ifdef ENABLE_FILTER_BLUR
207 		streamfx::filter::blur::blur_factory::finalize();
208 #endif
209 #ifdef ENABLE_FILTER_COLOR_GRADE
210 		streamfx::filter::color_grade::color_grade_factory::finalize();
211 #endif
212 #ifdef ENABLE_FILTER_DISPLACEMENT
213 		streamfx::filter::displacement::displacement_factory::finalize();
214 #endif
215 #ifdef ENABLE_FILTER_DYNAMIC_MASK
216 		streamfx::filter::dynamic_mask::dynamic_mask_factory::finalize();
217 #endif
218 #ifdef ENABLE_FILTER_NVIDIA_FACE_TRACKING
219 		streamfx::filter::nvidia::face_tracking_factory::finalize();
220 #endif
221 #ifdef ENABLE_FILTER_SDF_EFFECTS
222 		streamfx::filter::sdf_effects::sdf_effects_factory::finalize();
223 #endif
224 #ifdef ENABLE_FILTER_SHADER
225 		streamfx::filter::shader::shader_factory::finalize();
226 #endif
227 #ifdef ENABLE_FILTER_TRANSFORM
228 		streamfx::filter::transform::transform_factory::finalize();
229 #endif
230 	}
231 
232 	// Encoders
233 	{
234 #ifdef ENABLE_ENCODER_FFMPEG
235 		streamfx::encoder::ffmpeg::ffmpeg_manager::finalize();
236 #endif
237 	}
238 
239 	// GS Stuff
240 	{
241 		_gs_fstri_vb.reset();
242 	}
243 
244 	// Finalize Source Tracker
245 	obs::source_tracker::finalize();
246 
247 	//	// Auto-Updater
248 	//#ifdef ENABLE_UPDATER
249 	//	_updater.reset();
250 	//#endif
251 
252 	// Finalize Thread Pool
253 	_threadpool.reset();
254 
255 	// Finalize Configuration
256 	streamfx::configuration::finalize();
257 
258 	DLOG_INFO("Unloaded Version %s", STREAMFX_VERSION_STRING);
259 } catch (...) {
260 	DLOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
261 }
262 
threadpool()263 std::shared_ptr<util::threadpool> streamfx::threadpool()
264 {
265 	return _threadpool;
266 }
267 
gs_draw_fullscreen_tri()268 void streamfx::gs_draw_fullscreen_tri()
269 {
270 	gs_load_vertexbuffer(_gs_fstri_vb->update(false));
271 	gs_draw(GS_TRIS, 0, 3); //_gs_fstri_vb->size());
272 }
273 
data_file_path(std::string_view file)274 std::filesystem::path streamfx::data_file_path(std::string_view file)
275 {
276 	const char* root_path = obs_get_module_data_path(obs_current_module());
277 	if (root_path) {
278 		auto ret = std::filesystem::u8path(root_path);
279 		ret.append(file.data());
280 		return ret;
281 	} else {
282 		throw std::runtime_error("obs_get_module_data_path returned nullptr");
283 	}
284 }
285 
config_file_path(std::string_view file)286 std::filesystem::path streamfx::config_file_path(std::string_view file)
287 {
288 	char* root_path = obs_module_get_config_path(obs_current_module(), file.data());
289 	if (root_path) {
290 		auto ret = std::filesystem::u8path(root_path);
291 		bfree(root_path);
292 		return ret;
293 	} else {
294 		throw std::runtime_error("obs_module_get_config_path returned nullptr");
295 	}
296 }
297