diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fa307f..70004bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,6 +333,8 @@ set(PROJECT_PRIVATE_SOURCE "${PROJECT_SOURCE_DIR}/source/obs/obs-tools.cpp" "${PROJECT_SOURCE_DIR}/source/obs/obs-source.hpp" "${PROJECT_SOURCE_DIR}/source/obs/obs-source.cpp" + "${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.hpp" + "${PROJECT_SOURCE_DIR}/source/obs/obs-source-factory.cpp" "${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.hpp" "${PROJECT_SOURCE_DIR}/source/obs/obs-source-tracker.cpp" diff --git a/source/obs/obs-source-factory.cpp b/source/obs/obs-source-factory.cpp new file mode 100644 index 0000000..f547d75 --- /dev/null +++ b/source/obs/obs-source-factory.cpp @@ -0,0 +1,21 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2018 Michael Fabian Dirks + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "obs-source-factory.hpp" + diff --git a/source/obs/obs-source-factory.hpp b/source/obs/obs-source-factory.hpp new file mode 100644 index 0000000..0d30103 --- /dev/null +++ b/source/obs/obs-source-factory.hpp @@ -0,0 +1,447 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2018 Michael Fabian Dirks + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef STREAMEFFECTS_SOURCE_FACTORY_HPP +#define STREAMEFFECTS_SOURCE_FACTORY_HPP + +#pragma once +#include "plugin.hpp" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4201) +#endif +#include +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace obs { + template + class source_factory { + protected: + obs_source_info _info = {}; + + public: + source_factory() + { + _info.type_data = this; + + _info.get_name = _get_name; + _info.create = _create; + _info.destroy = _destroy; + _info.get_defaults2 = _get_defaults2; + _info.get_properties2 = _get_properties2; + + _info.get_width = _get_width; + _info.get_height = _get_height; + _info.update = _update; + _info.activate = _activate; + _info.deactivate = _deactivate; + _info.show = _show; + _info.hide = _hide; + _info.video_tick = _video_tick; + _info.video_render = _video_render; + _info.filter_video = _filter_video; + _info.filter_audio = _filter_audio; + _info.enum_active_sources = _enum_active_sources; + _info.save = _save; + _info.load = _load; + _info.mouse_click = _mouse_click; + _info.mouse_move = _mouse_move; + _info.mouse_wheel = _mouse_wheel; + _info.focus = _focus; + _info.key_click = _key_click; + _info.filter_remove = _filter_remove; + _info.audio_render = _audio_render; + _info.enum_all_sources = _enum_all_sources; + _info.transition_start = _transition_start; + _info.transition_stop = _transition_stop; + _info.audio_mix = _audio_mix; + } + virtual ~source_factory() {} + + private /* Factory */: + static const char* _get_name(void* type_data) noexcept try { + return reinterpret_cast<_factory*>(type_data)->get_name(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return nullptr; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return nullptr; + } + + static void* _create(obs_data_t* settings, obs_source_t* source) noexcept try { + return reinterpret_cast<_factory*>(obs_source_get_type_data(source))->create(settings, source); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return nullptr; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return nullptr; + } + + static void _get_defaults2(void* type_data, obs_data_t* settings) noexcept try { + reinterpret_cast<_factory*>(type_data)->get_defaults2(settings); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static obs_properties_t* _get_properties2(void* data, void* type_data) noexcept try { + return reinterpret_cast<_factory*>(type_data)->get_properties2(reinterpret_cast<_instance*>(data)); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return nullptr; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return nullptr; + } + + private /* Instance */: + static void _destroy(void* data) noexcept try { + delete reinterpret_cast<_instance*>(data); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static uint32_t _get_width(void* data) noexcept try { + return reinterpret_cast<_instance*>(data)->get_width(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return 0; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return 0; + } + + static uint32_t _get_height(void* data) noexcept try { + return reinterpret_cast<_instance*>(data)->get_height(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return 0; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return 0; + } + + static void _update(void* data, obs_data_t* settings) noexcept try { + reinterpret_cast<_instance*>(data)->update(settings); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _activate(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->activate(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _deactivate(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->deactivate(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _show(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->show(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _hide(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->hide(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _video_tick(void* data, float seconds) noexcept try { + reinterpret_cast<_instance*>(data)->video_tick(seconds); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _video_render(void* data, gs_effect_t* effect) noexcept try { + reinterpret_cast<_instance*>(data)->video_render(effect); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static struct obs_source_frame* _filter_video(void* data, struct obs_source_frame* frame) noexcept try { + return reinterpret_cast<_instance*>(data)->filter_video(frame); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return frame; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return frame; + } + + static struct obs_audio_data* _filter_audio(void* data, struct obs_audio_data* frame) noexcept try { + return reinterpret_cast<_instance*>(data)->filter_audio(frame); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return frame; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return frame; + } + + static void _enum_active_sources(void* data, obs_source_enum_proc_t enum_callback, void* param) noexcept try { + reinterpret_cast<_instance*>(data)->enum_active_sources(enum_callback, param); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _save(void* data, obs_data_t* settings) noexcept try { + reinterpret_cast<_instance*>(data)->save(settings); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _load(void* data, obs_data_t* settings) noexcept try { + reinterpret_cast<_instance*>(data)->load(settings); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _mouse_click(void* data, const struct obs_mouse_event* event, int32_t type, bool mouse_up, + uint32_t click_count) noexcept try { + reinterpret_cast<_instance*>(data)->mouse_click(event, type, mouse_up, click_count); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _mouse_move(void* data, const struct obs_mouse_event* event, bool mouse_leave) noexcept try { + reinterpret_cast<_instance*>(data)->mouse_move(event, mouse_leave); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _mouse_wheel(void* data, const struct obs_mouse_event* event, int x_delta, + int y_delta) noexcept try { + reinterpret_cast<_instance*>(data)->mouse_wheel(event, x_delta, y_delta); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _focus(void* data, bool focus) noexcept try { + reinterpret_cast<_instance*>(data)->focus(focus); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _key_click(void* data, const struct obs_key_event* event, bool key_up) noexcept try { + reinterpret_cast<_instance*>(data)->key_click(event, key_up); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _filter_remove(void* data, obs_source_t* source) noexcept try { + reinterpret_cast<_instance*>(data)->filter_remove(source); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static bool _audio_render(void* data, uint64_t* ts_out, struct obs_source_audio_mix* audio_output, + uint32_t mixers, size_t channels, size_t sample_rate) noexcept try { + return reinterpret_cast<_instance*>(data)->audio_render(ts_out, audio_output, mixers, channels, + sample_rate); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return false; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; + } + + static void _enum_all_sources(void* data, obs_source_enum_proc_t enum_callback, void* param) noexcept try { + reinterpret_cast<_instance*>(data)->enum_all_sources(enum_callback, param); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _transition_start(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->transition_start(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static void _transition_stop(void* data) noexcept try { + reinterpret_cast<_instance*>(data)->transition_stop(); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + } + + static bool _audio_mix(void* data, uint64_t* ts_out, struct audio_output_data* audio_output, size_t channels, + size_t sample_rate) noexcept try { + return reinterpret_cast<_instance*>(data)->audio_mix(ts_out, audio_output, channels, sample_rate); + } catch (const std::exception& ex) { + P_LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); + return false; + } catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; + } + + public: + virtual const char* get_name() + { + return "Not Implemented Yet"; + } + + virtual void* create(obs_data_t* settings, obs_source_t* source) + { + return reinterpret_cast(new _instance(settings, source)); + } + + virtual void get_defaults2(obs_data_t* data) {} + + virtual obs_properties_t* get_properties2(_instance* data) + { + return nullptr; + } + }; + + class source_instance { + protected: + obs_source_t* _self; + + public: + source_instance(obs_data_t* settings, obs_source_t* source) : _self(source) {} + virtual ~source_instance(){}; + + virtual uint32_t get_width() + { + return 0; + } + + virtual uint32_t get_height() + { + return 0; + } + + virtual void update(obs_data_t* settings) {} + + virtual void activate() {} + + virtual void deactivate() {} + + virtual void show() {} + + virtual void hide() {} + + virtual void video_tick(float seconds) {} + + virtual void video_render(gs_effect_t* effect) {} + + virtual struct obs_source_frame* filter_video(struct obs_source_frame* frame) + { + return frame; + } + + virtual struct obs_audio_data* filter_audio(struct obs_audio_data* audio) + { + return audio; + } + + virtual void enum_active_sources(obs_source_enum_proc_t enum_callback, void* param) {} + + virtual void save(obs_data_t* settings) {} + + virtual void load(obs_data_t* settings) {} + + virtual void mouse_click(const struct obs_mouse_event* event, int32_t type, bool mouse_up, uint32_t click_count) + {} + + virtual void mouse_move(const struct obs_mouse_event* event, bool mouse_leave) {} + + virtual void mouse_wheel(const struct obs_mouse_event* event, int x_delta, int y_delta) {} + + virtual void focus(bool focus) {} + + virtual void key_click(const struct obs_key_event* event, bool key_up) {} + + virtual void filter_remove(obs_source_t* source) {} + + virtual bool audio_render(uint64_t* ts_out, struct obs_source_audio_mix* audio_output, uint32_t mixers, + size_t channels, size_t sample_rate) + { + return false; + } + + virtual void enum_all_sources(obs_source_enum_proc_t enum_callback, void* param) {} + + virtual void transition_start() {} + + virtual void transition_stop() {} + + virtual bool audio_mix(uint64_t* ts_out, struct audio_output_data* audio_output, size_t channels, + size_t sample_rate) + { + return false; + } + }; + +} // namespace obs + +#endif