2017-12-14 07:06:09 +00:00
|
|
|
/*
|
|
|
|
* Modern effects for a modern Streamer
|
|
|
|
* Copyright (C) 2017 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
|
|
|
|
*/
|
|
|
|
|
2019-01-14 10:23:21 +00:00
|
|
|
#include "source-mirror.hpp"
|
2018-04-27 21:38:49 +00:00
|
|
|
#include <bitset>
|
2018-11-07 14:24:25 +00:00
|
|
|
#include <cstring>
|
2018-04-27 21:38:49 +00:00
|
|
|
#include <functional>
|
2018-11-07 14:24:25 +00:00
|
|
|
#include <memory>
|
2019-10-16 02:24:18 +00:00
|
|
|
#include <sstream>
|
2019-09-04 01:03:41 +00:00
|
|
|
#include <stdexcept>
|
2018-11-07 14:24:25 +00:00
|
|
|
#include <vector>
|
2020-02-13 04:17:06 +00:00
|
|
|
#include "obs/gs/gs-helper.hpp"
|
2019-04-02 17:55:45 +00:00
|
|
|
#include "obs/obs-source-tracker.hpp"
|
2019-02-11 02:54:16 +00:00
|
|
|
#include "obs/obs-tools.hpp"
|
2019-01-14 10:23:21 +00:00
|
|
|
#include "strings.hpp"
|
2017-12-14 07:06:09 +00:00
|
|
|
|
2019-01-14 10:23:21 +00:00
|
|
|
// OBS
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(disable : 4201)
|
|
|
|
#endif
|
2019-10-16 02:24:18 +00:00
|
|
|
#include <graphics/matrix4.h>
|
2018-11-08 07:08:38 +00:00
|
|
|
#include <media-io/audio-io.h>
|
|
|
|
#include <obs-config.h>
|
2019-01-14 10:23:21 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma warning(pop)
|
|
|
|
#endif
|
2018-11-08 07:08:38 +00:00
|
|
|
|
2019-08-04 14:20:26 +00:00
|
|
|
#define ST "Source.Mirror"
|
2019-10-16 02:24:18 +00:00
|
|
|
#define ST_SOURCE ST ".Source"
|
|
|
|
#define ST_SOURCE_AUDIO ST_SOURCE ".Audio"
|
|
|
|
#define ST_SOURCE_AUDIO_LAYOUT ST_SOURCE_AUDIO ".Layout"
|
|
|
|
#define ST_SOURCE_AUDIO_LAYOUT_(x) ST_SOURCE_AUDIO_LAYOUT "." D_VSTR(x)
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
using namespace source;
|
|
|
|
|
|
|
|
mirror::mirror_instance::mirror_instance(obs_data_t* settings, obs_source_t* self)
|
2020-02-14 06:55:18 +00:00
|
|
|
: obs::source_instance(settings, self), _source(), _audio_enabled(), _audio_layout(), _audio_kill_thread(),
|
|
|
|
_audio_have_output()
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2019-10-16 02:24:18 +00:00
|
|
|
// Spawn Audio Thread
|
2020-01-13 21:40:15 +00:00
|
|
|
_audio_thread = std::thread(std::bind(&mirror::mirror_instance::audio_output_cb, this));
|
2019-12-17 22:52:10 +00:00
|
|
|
|
|
|
|
update(settings);
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
mirror::mirror_instance::~mirror_instance()
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2019-10-16 02:24:18 +00:00
|
|
|
release();
|
2019-01-23 20:05:10 +00:00
|
|
|
|
2019-10-16 02:24:18 +00:00
|
|
|
// Kill Audio Thread
|
|
|
|
_audio_kill_thread = true;
|
|
|
|
_audio_notify.notify_all();
|
|
|
|
if (_audio_thread.joinable()) {
|
|
|
|
_audio_thread.join();
|
2018-11-07 14:29:24 +00:00
|
|
|
}
|
2018-04-27 21:38:49 +00:00
|
|
|
}
|
2017-12-14 07:06:09 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
uint32_t mirror::mirror_instance::get_width()
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
return obs_source_get_width(_source.get());
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
uint32_t mirror::mirror_instance::get_height()
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
return obs_source_get_height(_source.get());
|
2019-10-16 02:24:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void convert_config(obs_data_t* data)
|
|
|
|
{
|
|
|
|
uint64_t version = static_cast<uint64_t>(obs_data_get_int(data, S_VERSION));
|
|
|
|
|
|
|
|
switch (version) {
|
|
|
|
case 0:
|
|
|
|
obs_data_set_int(data, ST_SOURCE_AUDIO_LAYOUT, obs_data_get_int(data, "Source.Mirror.Audio.Layout"));
|
|
|
|
obs_data_unset_user_value(data, "Source.Mirror.Audio.Layout");
|
2020-01-13 21:40:15 +00:00
|
|
|
case STREAMFX_VERSION:
|
2019-10-16 02:24:18 +00:00
|
|
|
break;
|
2018-11-07 13:11:38 +00:00
|
|
|
}
|
2019-10-16 02:24:18 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
obs_data_set_int(data, S_VERSION, STREAMFX_VERSION);
|
|
|
|
obs_data_set_string(data, S_COMMIT, STREAMFX_COMMIT);
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_instance::update(obs_data_t* data)
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2019-10-16 02:24:18 +00:00
|
|
|
convert_config(data);
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
// Acquire new source.
|
|
|
|
acquire(obs_data_get_string(data, ST_SOURCE));
|
2019-01-23 20:05:10 +00:00
|
|
|
|
|
|
|
// Audio
|
2020-02-14 06:55:18 +00:00
|
|
|
_audio_enabled = obs_data_get_bool(data, ST_SOURCE_AUDIO);
|
|
|
|
_audio_layout = static_cast<speaker_layout>(obs_data_get_int(data, ST_SOURCE_AUDIO_LAYOUT));
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_instance::load(obs_data_t* data)
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
update(data);
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_instance::save(obs_data_t* data)
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2019-10-16 02:24:18 +00:00
|
|
|
if (_source) {
|
2020-02-14 06:55:18 +00:00
|
|
|
obs_data_set_string(data, ST_SOURCE, obs_source_get_name(_source.get()));
|
|
|
|
} else {
|
|
|
|
obs_data_unset_user_value(data, ST_SOURCE);
|
2019-10-16 02:24:18 +00:00
|
|
|
}
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::show()
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
_visible = obs_source_showing(_self);
|
|
|
|
}
|
2019-10-16 02:24:18 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::hide()
|
|
|
|
{
|
|
|
|
_visible = obs_source_showing(_self);
|
|
|
|
}
|
2019-01-24 03:27:04 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::activate()
|
|
|
|
{
|
|
|
|
_active = obs_source_active(_self);
|
|
|
|
}
|
2019-10-16 02:24:18 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::deactivate()
|
|
|
|
{
|
|
|
|
_active = obs_source_active(_self);
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void mirror::mirror_instance::video_tick(float time) {}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_instance::video_render(gs_effect_t* effect)
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
if (!_source)
|
2017-12-14 07:06:09 +00:00
|
|
|
return;
|
2020-02-14 06:55:18 +00:00
|
|
|
if ((obs_source_get_output_flags(_source.get()) & OBS_SOURCE_VIDEO) == 0)
|
2019-01-31 01:57:18 +00:00
|
|
|
return;
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
obs_source_video_render(_source.get());
|
2017-12-14 07:06:09 +00:00
|
|
|
}
|
2018-04-24 11:48:42 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_instance::audio_output_cb() noexcept
|
2019-12-16 22:53:20 +00:00
|
|
|
try {
|
2020-02-14 06:55:18 +00:00
|
|
|
std::unique_lock<std::mutex> ulock(_audio_lock_outputter);
|
2018-04-27 21:38:49 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
while (!_audio_kill_thread) {
|
|
|
|
_audio_notify.wait(ulock, [this]() { return _audio_have_output || _audio_kill_thread; });
|
2019-04-03 00:58:54 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
if (_audio_have_output) { // Get used audio element
|
2019-04-03 00:58:54 +00:00
|
|
|
std::shared_ptr<mirror_audio_data> mad;
|
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
std::lock_guard<std::mutex> capture_lock(_audio_lock_capturer);
|
2019-08-04 14:20:26 +00:00
|
|
|
if (_audio_data_queue.size() > 0) {
|
|
|
|
mad = _audio_data_queue.front();
|
|
|
|
_audio_data_queue.pop();
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
2019-08-04 14:20:26 +00:00
|
|
|
if (_audio_data_queue.size() == 0) {
|
2020-02-14 06:55:18 +00:00
|
|
|
_audio_have_output = false;
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mad) {
|
|
|
|
ulock.unlock();
|
2020-02-14 06:55:18 +00:00
|
|
|
obs_source_output_audio(_self, &mad->audio);
|
2019-04-03 00:58:54 +00:00
|
|
|
ulock.lock();
|
|
|
|
|
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
std::lock_guard<std::mutex> capture_lock(_audio_lock_capturer);
|
2019-08-04 14:20:26 +00:00
|
|
|
_audio_data_free_queue.push(mad);
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-04-27 21:38:49 +00:00
|
|
|
}
|
2019-10-13 04:20:41 +00:00
|
|
|
} catch (const std::exception& ex) {
|
2020-01-13 21:40:15 +00:00
|
|
|
LOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what());
|
2019-09-05 16:42:28 +00:00
|
|
|
} catch (...) {
|
2020-01-13 21:40:15 +00:00
|
|
|
LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__);
|
2018-04-27 21:38:49 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void mirror::mirror_instance::enum_active_sources(obs_source_enum_proc_t cb, void* ptr)
|
2018-11-07 14:24:25 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
if (!_source || !_active)
|
|
|
|
return;
|
|
|
|
cb(_self, _source.get(), ptr);
|
2018-11-08 07:08:38 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::enum_all_sources(obs_source_enum_proc_t cb, void* ptr)
|
2019-10-15 11:34:47 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
if (!_source)
|
|
|
|
return;
|
|
|
|
|
|
|
|
cb(_self, _source.get(), ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mirror::mirror_instance::acquire(std::string source_name)
|
|
|
|
try {
|
|
|
|
// Find source by name if possible.
|
|
|
|
std::shared_ptr<obs_source_t> source =
|
|
|
|
std::shared_ptr<obs_source_t>{obs_get_source_by_name(source_name.c_str()), obs::obs_source_deleter};
|
|
|
|
if ((!source) || (source.get() == _self)) { // If we failed, just exit early.
|
|
|
|
return;
|
2018-11-08 07:08:38 +00:00
|
|
|
}
|
2020-02-14 06:55:18 +00:00
|
|
|
|
|
|
|
// Everything went well, store.
|
|
|
|
_source_child = std::make_shared<obs::tools::child_source>(_self, source);
|
|
|
|
_source = source;
|
|
|
|
|
|
|
|
// Listen to the rename event to update our own settings.
|
|
|
|
_signal_rename = std::make_shared<obs::source_signal_handler>("rename", _source);
|
|
|
|
_signal_rename->event.add(
|
|
|
|
std::bind(&source::mirror::mirror_instance::on_rename, this, std::placeholders::_1, std::placeholders::_2));
|
|
|
|
|
|
|
|
// Listen to any audio the source spews out.
|
|
|
|
_signal_audio = std::make_shared<obs::audio_signal_handler>(_source);
|
|
|
|
_signal_audio->event.add(std::bind(&source::mirror::mirror_instance::on_audio, this, std::placeholders::_1,
|
|
|
|
std::placeholders::_2, std::placeholders::_3));
|
|
|
|
} catch (...) {
|
|
|
|
release();
|
2018-11-08 07:08:38 +00:00
|
|
|
}
|
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void mirror::mirror_instance::release()
|
|
|
|
{
|
|
|
|
_signal_audio.reset();
|
|
|
|
_signal_rename.reset();
|
|
|
|
_source_child.reset();
|
|
|
|
_source.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void source::mirror::mirror_instance::on_rename(std::shared_ptr<obs_source_t>, calldata*)
|
2019-01-14 22:52:12 +00:00
|
|
|
{
|
2019-10-16 02:24:18 +00:00
|
|
|
obs_source_save(_self);
|
2018-04-24 11:48:42 +00:00
|
|
|
}
|
2019-04-02 17:44:48 +00:00
|
|
|
|
2020-02-14 06:55:18 +00:00
|
|
|
void source::mirror::mirror_instance::on_audio(std::shared_ptr<obs_source_t>, const audio_data* audio, bool)
|
2019-04-02 17:44:48 +00:00
|
|
|
{
|
2020-02-14 06:55:18 +00:00
|
|
|
if (!_audio_enabled) {
|
2019-04-02 17:44:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
audio_t* aud = obs_get_audio();
|
|
|
|
if (!aud) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
audio_output_info const* aoi = audio_output_get_info(aud);
|
|
|
|
if (!aoi) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-03 00:58:54 +00:00
|
|
|
std::shared_ptr<mirror_audio_data> mad;
|
|
|
|
{ // Get free audio data element.
|
2020-02-14 06:55:18 +00:00
|
|
|
std::lock_guard<std::mutex> capture_lock(_audio_lock_capturer);
|
2019-08-04 14:20:26 +00:00
|
|
|
if (_audio_data_free_queue.size() > 0) {
|
|
|
|
mad = _audio_data_free_queue.front();
|
|
|
|
_audio_data_free_queue.pop();
|
2019-04-03 00:58:54 +00:00
|
|
|
} else {
|
|
|
|
mad = std::make_shared<mirror_audio_data>();
|
|
|
|
mad->data.resize(MAX_AUDIO_CHANNELS);
|
|
|
|
for (size_t idx = 0; idx < mad->data.size(); idx++) {
|
|
|
|
mad->data[idx].resize(AUDIO_OUTPUT_FRAMES);
|
|
|
|
}
|
2019-04-02 17:44:48 +00:00
|
|
|
}
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ // Copy data
|
|
|
|
std::bitset<8> layout;
|
|
|
|
for (size_t plane = 0; plane < MAX_AV_PLANES; plane++) {
|
2019-04-19 07:42:15 +00:00
|
|
|
float* samples = reinterpret_cast<float_t*>(audio->data[plane]);
|
2019-04-03 00:58:54 +00:00
|
|
|
if (!samples) {
|
|
|
|
mad->audio.data[plane] = nullptr;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
layout.set(plane);
|
2019-04-02 17:44:48 +00:00
|
|
|
|
2019-04-03 00:58:54 +00:00
|
|
|
memcpy(mad->data[plane].data(), audio->data[plane], audio->frames * sizeof(float_t));
|
|
|
|
mad->audio.data[plane] = reinterpret_cast<uint8_t*>(mad->data[plane].data());
|
|
|
|
}
|
2019-08-24 10:59:32 +00:00
|
|
|
mad->audio.format = aoi->format;
|
2019-04-03 00:58:54 +00:00
|
|
|
mad->audio.frames = audio->frames;
|
|
|
|
mad->audio.timestamp = audio->timestamp;
|
|
|
|
mad->audio.samples_per_sec = aoi->samples_per_sec;
|
2020-02-14 06:55:18 +00:00
|
|
|
if (_audio_layout != SPEAKERS_UNKNOWN) {
|
|
|
|
mad->audio.speakers = _audio_layout;
|
2019-08-04 10:34:42 +00:00
|
|
|
} else {
|
|
|
|
mad->audio.speakers = aoi->speakers;
|
|
|
|
}
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ // Push used audio data element.
|
2020-02-14 06:55:18 +00:00
|
|
|
std::lock_guard<std::mutex> capture_lock(_audio_lock_capturer);
|
2019-08-04 14:20:26 +00:00
|
|
|
_audio_data_queue.push(mad);
|
2019-04-02 17:44:48 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 00:58:54 +00:00
|
|
|
{ // Signal other side.
|
2020-02-14 06:55:18 +00:00
|
|
|
std::lock_guard<std::mutex> output_lock(_audio_lock_outputter);
|
|
|
|
_audio_have_output = true;
|
2019-04-03 00:58:54 +00:00
|
|
|
}
|
2020-02-14 06:55:18 +00:00
|
|
|
_audio_notify.notify_all();
|
2019-04-02 17:44:48 +00:00
|
|
|
}
|
2019-10-15 11:34:47 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
std::shared_ptr<mirror::mirror_factory> mirror::mirror_factory::factory_instance;
|
2019-10-15 11:34:47 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
mirror::mirror_factory::mirror_factory()
|
2019-10-15 11:34:47 +00:00
|
|
|
{
|
|
|
|
_info.id = "obs-stream-effects-source-mirror";
|
|
|
|
_info.type = OBS_SOURCE_TYPE_INPUT;
|
2020-02-14 06:55:18 +00:00
|
|
|
_info.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | OBS_SOURCE_AUDIO;
|
2019-10-15 11:34:47 +00:00
|
|
|
|
2020-02-13 04:17:06 +00:00
|
|
|
set_have_active_child_sources(true);
|
2020-02-14 06:55:18 +00:00
|
|
|
set_have_child_sources(true);
|
|
|
|
set_visibility_tracking_enabled(true);
|
2019-12-14 01:37:04 +00:00
|
|
|
finish_setup();
|
2019-10-15 11:34:47 +00:00
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
mirror::mirror_factory::~mirror_factory() {}
|
2019-10-15 11:34:47 +00:00
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
const char* mirror::mirror_factory::get_name()
|
2019-10-15 11:34:47 +00:00
|
|
|
{
|
|
|
|
return D_TRANSLATE(ST);
|
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
void mirror::mirror_factory::get_defaults2(obs_data_t* data)
|
2019-10-15 11:34:47 +00:00
|
|
|
{
|
|
|
|
obs_data_set_default_string(data, ST_SOURCE, "");
|
2019-10-16 02:24:18 +00:00
|
|
|
obs_data_set_default_bool(data, ST_SOURCE_AUDIO, false);
|
|
|
|
obs_data_set_default_int(data, ST_SOURCE_AUDIO_LAYOUT, static_cast<int64_t>(SPEAKERS_UNKNOWN));
|
2019-10-15 11:34:47 +00:00
|
|
|
}
|
|
|
|
|
2019-12-16 22:53:20 +00:00
|
|
|
static bool modified_properties(obs_properties_t* pr, obs_property_t* p, obs_data_t* data) noexcept
|
|
|
|
try {
|
2019-10-16 02:24:18 +00:00
|
|
|
if (obs_properties_get(pr, ST_SOURCE_AUDIO) == p) {
|
|
|
|
bool show = obs_data_get_bool(data, ST_SOURCE_AUDIO);
|
|
|
|
obs_property_set_visible(obs_properties_get(pr, ST_SOURCE_AUDIO_LAYOUT), show);
|
2019-10-15 11:34:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} catch (...) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-01-13 21:40:15 +00:00
|
|
|
obs_properties_t* mirror::mirror_factory::get_properties2(mirror::mirror_instance* data)
|
2019-10-15 11:34:47 +00:00
|
|
|
{
|
|
|
|
obs_properties_t* pr = obs_properties_create();
|
|
|
|
obs_property_t* p = nullptr;
|
|
|
|
|
2019-10-16 02:24:18 +00:00
|
|
|
{
|
2020-02-13 04:18:28 +00:00
|
|
|
p = obs_properties_add_list(pr, ST_SOURCE, D_TRANSLATE(ST_SOURCE), OBS_COMBO_TYPE_LIST,
|
|
|
|
OBS_COMBO_FORMAT_STRING);
|
|
|
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SOURCE)));
|
|
|
|
obs_property_set_modified_callback(p, modified_properties);
|
|
|
|
|
|
|
|
obs_property_list_add_string(p, "", "");
|
|
|
|
obs::source_tracker::get()->enumerate(
|
|
|
|
[&p](std::string name, obs_source_t*) {
|
|
|
|
std::stringstream sstr;
|
|
|
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SOURCE) << ")";
|
|
|
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
obs::source_tracker::filter_sources);
|
|
|
|
obs::source_tracker::get()->enumerate(
|
|
|
|
[&p](std::string name, obs_source_t*) {
|
|
|
|
std::stringstream sstr;
|
|
|
|
sstr << name << " (" << D_TRANSLATE(S_SOURCETYPE_SCENE) << ")";
|
|
|
|
obs_property_list_add_string(p, sstr.str().c_str(), name.c_str());
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
obs::source_tracker::filter_scenes);
|
|
|
|
}
|
2019-10-16 02:24:18 +00:00
|
|
|
|
2020-02-13 04:18:28 +00:00
|
|
|
{
|
|
|
|
p = obs_properties_add_bool(pr, ST_SOURCE_AUDIO, D_TRANSLATE(ST_SOURCE_AUDIO));
|
|
|
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SOURCE_AUDIO)));
|
|
|
|
obs_property_set_modified_callback(p, modified_properties);
|
|
|
|
}
|
2019-10-16 02:24:18 +00:00
|
|
|
|
2020-02-13 04:18:28 +00:00
|
|
|
{
|
|
|
|
p = obs_properties_add_list(pr, ST_SOURCE_AUDIO_LAYOUT, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT),
|
|
|
|
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(Unknown)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_UNKNOWN));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(Mono)), static_cast<int64_t>(SPEAKERS_MONO));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(Stereo)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_STEREO));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(StereoLFE)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_2POINT1));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(Quadraphonic)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_4POINT0));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(QuadraphonicLFE)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_4POINT1));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(Surround)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_5POINT1));
|
|
|
|
obs_property_list_add_int(p, D_TRANSLATE(ST_SOURCE_AUDIO_LAYOUT_(FullSurround)),
|
|
|
|
static_cast<int64_t>(SPEAKERS_7POINT1));
|
|
|
|
obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_SOURCE_AUDIO_LAYOUT)));
|
2019-10-16 02:24:18 +00:00
|
|
|
}
|
|
|
|
|
2019-10-15 11:34:47 +00:00
|
|
|
return pr;
|
|
|
|
}
|