New upstream version 24.0.1+dfsg1

This commit is contained in:
Sebastian Ramacher 2019-09-22 23:19:10 +02:00
parent b14f9eae6d
commit 5a730d6ec3
842 changed files with 42245 additions and 33385 deletions

View file

@ -17,7 +17,7 @@
using namespace std;
static Display* xdisplay = 0;
static Display *xdisplay = 0;
Display *disp()
{
@ -39,31 +39,22 @@ void cleanupDisplay()
static bool ewmhIsSupported()
{
Display *display = disp();
Atom netSupportingWmCheck = XInternAtom(display,
"_NET_SUPPORTING_WM_CHECK", true);
Atom netSupportingWmCheck =
XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true);
Atom actualType;
int format = 0;
unsigned long num = 0, bytes = 0;
unsigned char *data = NULL;
Window ewmh_window = 0;
int status = XGetWindowProperty(
display,
DefaultRootWindow(display),
netSupportingWmCheck,
0L,
1L,
false,
XA_WINDOW,
&actualType,
&format,
&num,
&bytes,
&data);
int status = XGetWindowProperty(display, DefaultRootWindow(display),
netSupportingWmCheck, 0L, 1L, false,
XA_WINDOW, &actualType, &format, &num,
&bytes, &data);
if (status == Success) {
if (num > 0) {
ewmh_window = ((Window*)data)[0];
ewmh_window = ((Window *)data)[0];
}
if (data) {
XFree(data);
@ -72,21 +63,12 @@ static bool ewmhIsSupported()
}
if (ewmh_window) {
status = XGetWindowProperty(
display,
ewmh_window,
netSupportingWmCheck,
0L,
1L,
false,
XA_WINDOW,
&actualType,
&format,
&num,
&bytes,
&data);
status = XGetWindowProperty(display, ewmh_window,
netSupportingWmCheck, 0L, 1L, false,
XA_WINDOW, &actualType, &format,
&num, &bytes, &data);
if (status != Success || num == 0 ||
ewmh_window != ((Window*)data)[0]) {
ewmh_window != ((Window *)data)[0]) {
ewmh_window = 0;
}
if (status == Success && data) {
@ -111,24 +93,15 @@ static std::vector<Window> getTopLevelWindows()
Atom actualType;
int format;
unsigned long num, bytes;
Window* data = 0;
Window *data = 0;
for (int i = 0; i < ScreenCount(disp()); ++i) {
Window rootWin = RootWindow(disp(), i);
int status = XGetWindowProperty(
disp(),
rootWin,
netClList,
0L,
~0L,
false,
AnyPropertyType,
&actualType,
&format,
&num,
&bytes,
(uint8_t**)&data);
int status = XGetWindowProperty(disp(), rootWin, netClList, 0L,
~0L, false, AnyPropertyType,
&actualType, &format, &num,
&bytes, (uint8_t **)&data);
if (status != Success) {
continue;
@ -147,11 +120,10 @@ static std::string GetWindowTitle(size_t i)
{
Window w = getTopLevelWindows().at(i);
std::string windowTitle;
char* name;
char *name;
int status = XFetchName(disp(), w, &name);
if (status >= Success && name != nullptr)
{
if (status >= Success && name != nullptr) {
std::string str(name);
windowTitle = str;
}
@ -165,7 +137,7 @@ void GetWindowList(vector<string> &windows)
{
windows.resize(0);
for (size_t i = 0; i < getTopLevelWindows().size(); ++i){
for (size_t i = 0; i < getTopLevelWindows().size(); ++i) {
if (GetWindowTitle(i) != "")
windows.emplace_back(GetWindowTitle(i));
}
@ -181,24 +153,14 @@ void GetCurrentWindowTitle(string &title)
Atom actualType;
int format;
unsigned long num, bytes;
Window* data = 0;
char* name;
Window *data = 0;
char *name;
Window rootWin = RootWindow(disp(), 0);
XGetWindowProperty(
disp(),
rootWin,
active,
0L,
~0L,
false,
AnyPropertyType,
&actualType,
&format,
&num,
&bytes,
(uint8_t**)&data);
XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false,
AnyPropertyType, &actualType, &format, &num, &bytes,
(uint8_t **)&data);
int status = XFetchName(disp(), data[0], &name);

View file

@ -32,7 +32,7 @@ static bool WindowValid(HWND window)
return false;
GetClientRect(window, &rect);
styles = GetWindowLongPtr(window, GWL_STYLE);
styles = GetWindowLongPtr(window, GWL_STYLE);
ex_styles = GetWindowLongPtr(window, GWL_EXSTYLE);
if (ex_styles & WS_EX_TOOLWINDOW)

View file

@ -69,23 +69,19 @@ struct SwitcherData {
}
}
inline ~SwitcherData()
{
Stop();
}
inline ~SwitcherData() { Stop(); }
};
static SwitcherData *switcher = nullptr;
static inline QString MakeSwitchName(const QString &scene,
const QString &window)
const QString &window)
{
return QStringLiteral("[") + scene + QStringLiteral("]: ") + window;
}
SceneSwitcher::SceneSwitcher(QWidget *parent)
: QDialog(parent),
ui(new Ui_SceneSwitcher)
: QDialog(parent), ui(new Ui_SceneSwitcher)
{
ui->setupUi(this);
@ -95,7 +91,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
switcher->Prune();
BPtr<char*> scenes = obs_frontend_get_scene_names();
BPtr<char *> scenes = obs_frontend_get_scene_names();
char **temp = scenes;
while (*temp) {
const char *name = *temp;
@ -110,7 +106,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
ui->noMatchDontSwitch->setChecked(true);
ui->noMatchSwitchScene->setCurrentText(
GetWeakSourceName(switcher->nonMatchingScene).c_str());
GetWeakSourceName(switcher->nonMatchingScene).c_str());
ui->checkInterval->setValue(switcher->interval);
vector<string> windows;
@ -121,11 +117,10 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
for (auto &s : switcher->switches) {
string sceneName = GetWeakSourceName(s.scene);
QString text = MakeSwitchName(sceneName.c_str(),
s.window.c_str());
QString text =
MakeSwitchName(sceneName.c_str(), s.window.c_str());
QListWidgetItem *item = new QListWidgetItem(text,
ui->switches);
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, s.window.c_str());
}
@ -137,7 +132,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
loading = false;
}
void SceneSwitcher::closeEvent(QCloseEvent*)
void SceneSwitcher::closeEvent(QCloseEvent *)
{
obs_frontend_save();
}
@ -149,8 +144,7 @@ int SceneSwitcher::FindByData(const QString &window)
for (int i = 0; i < count; i++) {
QListWidgetItem *item = ui->switches->item(i);
QString itemWindow =
item->data(Qt::UserRole).toString();
QString itemWindow = item->data(Qt::UserRole).toString();
if (itemWindow == window) {
idx = i;
@ -206,16 +200,16 @@ void SceneSwitcher::on_add_clicked()
if (idx == -1) {
try {
lock_guard<mutex> lock(switcher->m);
switcher->switches.emplace_back(source,
windowName.toUtf8().constData());
QListWidgetItem *item = new QListWidgetItem(text,
ui->switches);
switcher->switches.emplace_back(
source, windowName.toUtf8().constData());
QListWidgetItem *item =
new QListWidgetItem(text, ui->switches);
item->setData(Qt::UserRole, v);
} catch (const regex_error &) {
QMessageBox::warning(this,
obs_module_text("InvalidRegex.Title"),
obs_module_text("InvalidRegex.Text"));
QMessageBox::warning(
this, obs_module_text("InvalidRegex.Title"),
obs_module_text("InvalidRegex.Text"));
}
} else {
QListWidgetItem *item = ui->switches->item(idx);
@ -274,8 +268,7 @@ void SceneSwitcher::on_startAtLaunch_toggled(bool value)
void SceneSwitcher::UpdateNonMatchingScene(const QString &name)
{
obs_source_t *scene = obs_get_source_by_name(
name.toUtf8().constData());
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
switcher->nonMatchingScene = ws;
@ -303,8 +296,7 @@ void SceneSwitcher::on_noMatchSwitch_clicked()
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
}
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
const QString &text)
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString &text)
{
if (loading)
return;
@ -357,13 +349,13 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
for (SceneSwitch &s : switcher->switches) {
obs_data_t *array_obj = obs_data_create();
obs_source_t *source = obs_weak_source_get_source(
s.scene);
obs_source_t *source =
obs_weak_source_get_source(s.scene);
if (source) {
const char *n = obs_source_get_name(source);
obs_data_set_string(array_obj, "scene", n);
obs_data_set_string(array_obj, "window_title",
s.window.c_str());
s.window.c_str());
obs_data_array_push_back(array, array_obj);
obs_source_release(source);
}
@ -376,9 +368,9 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
obs_data_set_int(obj, "interval", switcher->interval);
obs_data_set_string(obj, "non_matching_scene",
nonMatchingSceneName.c_str());
nonMatchingSceneName.c_str());
obs_data_set_bool(obj, "switch_if_not_matching",
switcher->switchIfNotMatching);
switcher->switchIfNotMatching);
obs_data_set_bool(obj, "active", switcher->th.joinable());
obs_data_set_array(obj, "switches", array);
@ -389,8 +381,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
} else {
switcher->m.lock();
obs_data_t *obj = obs_data_get_obj(save_data,
"auto-scene-switcher");
obs_data_t *obj =
obs_data_get_obj(save_data, "auto-scene-switcher");
obs_data_array_t *array = obs_data_get_array(obj, "switches");
size_t count = obs_data_array_count(array);
@ -420,8 +412,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
obs_data_get_string(array_obj, "window_title");
switcher->switches.emplace_back(
GetWeakSourceByName(scene),
window);
GetWeakSourceByName(scene), window);
obs_data_release(array_obj);
}
@ -476,18 +467,18 @@ void SwitcherData::Thread()
for (SceneSwitch &s : switches) {
try {
bool matches = regex_match(
title, s.re);
title, s.re);
if (matches) {
match = true;
scene = s.scene;
break;
}
} catch (const regex_error &) {}
} catch (const regex_error &) {
}
}
}
if (!match && switchIfNotMatching &&
nonMatchingScene) {
if (!match && switchIfNotMatching && nonMatchingScene) {
match = true;
scene = nonMatchingScene;
}
@ -513,7 +504,7 @@ void SwitcherData::Thread()
void SwitcherData::Start()
{
if (!switcher->th.joinable())
switcher->th = thread([] () {switcher->Thread();});
switcher->th = thread([]() { switcher->Thread(); });
}
void SwitcherData::Stop()
@ -542,17 +533,16 @@ static void OBSEvent(enum obs_frontend_event event, void *)
extern "C" void InitSceneSwitcher()
{
QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
obs_module_text("SceneSwitcher"));
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
obs_module_text("SceneSwitcher"));
switcher = new SwitcherData;
auto cb = [] ()
{
auto cb = []() {
obs_frontend_push_ui_translation(obs_module_get_string);
QMainWindow *window =
(QMainWindow*)obs_frontend_get_main_window();
(QMainWindow *)obs_frontend_get_main_window();
SceneSwitcher ss(window);
ss.exec();

View file

@ -1,33 +1,24 @@
#include "captions-handler.hpp"
captions_handler::captions_handler(
captions_cb callback,
enum audio_format format,
uint32_t sample_rate)
captions_handler::captions_handler(captions_cb callback,
enum audio_format format,
uint32_t sample_rate)
: cb(callback)
{
if (!reset_resampler(format, sample_rate))
throw CAPTIONS_ERROR_GENERIC_FAIL;
}
bool captions_handler::reset_resampler(
enum audio_format format,
uint32_t sample_rate)
bool captions_handler::reset_resampler(enum audio_format format,
uint32_t sample_rate)
try {
obs_audio_info ai;
if (!obs_get_audio_info(&ai))
throw std::string("Failed to get OBS audio info");
resample_info src = {
ai.samples_per_sec,
AUDIO_FORMAT_FLOAT_PLANAR,
ai.speakers
};
resample_info dst = {
sample_rate,
format,
SPEAKERS_MONO
};
resample_info src = {ai.samples_per_sec, AUDIO_FORMAT_FLOAT_PLANAR,
ai.speakers};
resample_info dst = {sample_rate, format, SPEAKERS_MONO};
if (!resampler.reset(dst, src))
throw std::string("Failed to create audio resampler");
@ -46,9 +37,9 @@ void captions_handler::push_audio(const audio_data *audio)
uint64_t ts_offset;
bool success;
success = audio_resampler_resample(resampler,
out, &frames, &ts_offset,
(const uint8_t *const *)audio->data, audio->frames);
success = audio_resampler_resample(resampler, out, &frames, &ts_offset,
(const uint8_t *const *)audio->data,
audio->frames);
if (success)
pcm_data(out[0], frames);
}

View file

@ -9,10 +9,7 @@ class resampler_obj {
audio_resampler_t *resampler = nullptr;
public:
inline ~resampler_obj()
{
audio_resampler_destroy(resampler);
}
inline ~resampler_obj() { audio_resampler_destroy(resampler); }
inline bool reset(const resample_info &dst, const resample_info &src)
{
@ -21,15 +18,15 @@ public:
return !!resampler;
}
inline operator audio_resampler_t*() {return resampler;}
inline operator audio_resampler_t *() { return resampler; }
};
/* ------------------------------------------------------------------------- */
typedef std::function<void (const std::string &)> captions_cb;
typedef std::function<void(const std::string &)> captions_cb;
#define captions_error(s) std::string(obs_module_text("Captions.Error." ## s))
#define CAPTIONS_ERROR_GENERIC_FAIL captions_error("GenericFail")
#define captions_error(s) std::string(obs_module_text("Captions.Error."##s))
#define CAPTIONS_ERROR_GENERIC_FAIL captions_error("GenericFail")
/* ------------------------------------------------------------------------- */
@ -38,22 +35,17 @@ class captions_handler {
resampler_obj resampler;
protected:
inline void callback(const std::string &text)
{
cb(text);
}
inline void callback(const std::string &text) { cb(text); }
virtual void pcm_data(const void *data, size_t frames)=0;
virtual void pcm_data(const void *data, size_t frames) = 0;
/* always resamples to 1 channel */
bool reset_resampler(enum audio_format format, uint32_t sample_rate);
public:
/* throw std::string for errors shown to users */
captions_handler(
captions_cb callback,
enum audio_format format,
uint32_t sample_rate);
captions_handler(captions_cb callback, enum audio_format format,
uint32_t sample_rate);
virtual ~captions_handler() {}
void push_audio(const audio_data *audio);
@ -62,6 +54,6 @@ public:
/* ------------------------------------------------------------------------- */
struct captions_handler_info {
std::string (*name)(void);
std::string (*name)(void);
captions_handler *(*create)(captions_cb cb, const std::string &lang);
};

View file

@ -8,16 +8,17 @@
using namespace std;
#if 0
#define debugfunc(format, ...) blog(LOG_DEBUG, "[Captions] %s(" format ")", \
__FUNCTION__, ##__VA_ARGS__)
#define debugfunc(format, ...) \
blog(LOG_DEBUG, "[Captions] %s(" format ")", __FUNCTION__, \
##__VA_ARGS__)
#else
#define debugfunc(format, ...)
#endif
CaptionStream::CaptionStream(DWORD samplerate_, mssapi_captions *handler_) :
handler(handler_),
samplerate(samplerate_),
event(CreateEvent(nullptr, false, false, nullptr))
CaptionStream::CaptionStream(DWORD samplerate_, mssapi_captions *handler_)
: handler(handler_),
samplerate(samplerate_),
event(CreateEvent(nullptr, false, false, nullptr))
{
buf_info.ulMsMinNotification = 50;
buf_info.ulMsBufferSize = 500;
@ -66,15 +67,15 @@ STDMETHODIMP CaptionStream::QueryInterface(REFIID riid, void **ppv)
} else if (riid == IID_IStream) {
AddRef();
*ppv = (IStream*)this;
*ppv = (IStream *)this;
} else if (riid == IID_ISpStreamFormat) {
AddRef();
*ppv = (ISpStreamFormat*)this;
*ppv = (ISpStreamFormat *)this;
} else if (riid == IID_ISpAudio) {
AddRef();
*ppv = (ISpAudio*)this;
*ppv = (ISpAudio *)this;
} else {
*ppv = nullptr;
@ -134,8 +135,7 @@ STDMETHODIMP CaptionStream::Read(void *data, ULONG bytes, ULONG *read_bytes)
return hr;
}
STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes,
ULONG*)
STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes, ULONG *)
{
debugfunc("data, %lu, written_bytes", bytes);
UNUSED_PARAMETER(bytes);
@ -146,7 +146,7 @@ STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes,
// IStream methods
STDMETHODIMP CaptionStream::Seek(LARGE_INTEGER move, DWORD origin,
ULARGE_INTEGER *new_pos)
ULARGE_INTEGER *new_pos)
{
debugfunc("%lld, %lx, new_pos", move, origin);
UNUSED_PARAMETER(move);
@ -170,8 +170,8 @@ STDMETHODIMP CaptionStream::SetSize(ULARGE_INTEGER new_size)
}
STDMETHODIMP CaptionStream::CopyTo(IStream *stream, ULARGE_INTEGER bytes,
ULARGE_INTEGER *read_bytes,
ULARGE_INTEGER *written_bytes)
ULARGE_INTEGER *read_bytes,
ULARGE_INTEGER *written_bytes)
{
HRESULT hr;
@ -213,7 +213,7 @@ STDMETHODIMP CaptionStream::Revert(void)
}
STDMETHODIMP CaptionStream::LockRegion(ULARGE_INTEGER offset,
ULARGE_INTEGER size, DWORD type)
ULARGE_INTEGER size, DWORD type)
{
debugfunc("%llu, %llu, %ld", offset, size, type);
UNUSED_PARAMETER(offset);
@ -224,7 +224,7 @@ STDMETHODIMP CaptionStream::LockRegion(ULARGE_INTEGER offset,
}
STDMETHODIMP CaptionStream::UnlockRegion(ULARGE_INTEGER offset,
ULARGE_INTEGER size, DWORD type)
ULARGE_INTEGER size, DWORD type)
{
debugfunc("%llu, %llu, %ld", offset, size, type);
UNUSED_PARAMETER(offset);
@ -250,7 +250,7 @@ STDMETHODIMP CaptionStream::Stat(STATSTG *stg, DWORD flag)
if (flag == STATFLAG_DEFAULT) {
size_t byte_size = (wcslen(stat_name) + 1) * sizeof(wchar_t);
stg->pwcsName = (wchar_t*)CoTaskMemAlloc(byte_size);
stg->pwcsName = (wchar_t *)CoTaskMemAlloc(byte_size);
memcpy(stg->pwcsName, stat_name, byte_size);
}
@ -267,7 +267,7 @@ STDMETHODIMP CaptionStream::Clone(IStream **stream)
// ISpStreamFormat methods
STDMETHODIMP CaptionStream::GetFormat(GUID *guid,
WAVEFORMATEX **co_mem_wfex_out)
WAVEFORMATEX **co_mem_wfex_out)
{
debugfunc("guid, co_mem_wfex_out");
@ -282,7 +282,7 @@ STDMETHODIMP CaptionStream::GetFormat(GUID *guid,
void *wfex = CoTaskMemAlloc(sizeof(format));
memcpy(wfex, &format, sizeof(format));
*co_mem_wfex_out = (WAVEFORMATEX*)wfex;
*co_mem_wfex_out = (WAVEFORMATEX *)wfex;
return S_OK;
}
@ -296,7 +296,7 @@ STDMETHODIMP CaptionStream::SetState(SPAUDIOSTATE state_, ULONGLONG)
}
STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref,
const WAVEFORMATEX *wfex)
const WAVEFORMATEX *wfex)
{
debugfunc("guid, wfex");
if (!wfex)
@ -306,7 +306,7 @@ STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref,
lock_guard<mutex> lock(m);
memcpy(&format, wfex, sizeof(format));
if (!handler->reset_resampler(AUDIO_FORMAT_16BIT,
wfex->nSamplesPerSec))
wfex->nSamplesPerSec))
return E_FAIL;
/* 50 msec */
@ -354,7 +354,7 @@ STDMETHODIMP CaptionStream::GetBufferInfo(SPAUDIOBUFFERINFO *buf_info_)
}
STDMETHODIMP CaptionStream::GetDefaultFormat(GUID *format,
WAVEFORMATEX **co_mem_wfex_out)
WAVEFORMATEX **co_mem_wfex_out)
{
debugfunc("format, co_mem_wfex_out");
@ -365,7 +365,7 @@ STDMETHODIMP CaptionStream::GetDefaultFormat(GUID *format,
memcpy(wfex, &format, sizeof(format));
*format = SPDFID_WaveFormatEx;
*co_mem_wfex_out = (WAVEFORMATEX*)wfex;
*co_mem_wfex_out = (WAVEFORMATEX *)wfex;
return S_OK;
}

View file

@ -13,10 +13,11 @@
class CircleBuf {
circlebuf buf = {};
public:
inline ~CircleBuf() {circlebuf_free(&buf);}
inline operator circlebuf*() {return &buf;}
inline circlebuf *operator->() {return &buf;}
inline ~CircleBuf() { circlebuf_free(&buf); }
inline operator circlebuf *() { return &buf; }
inline circlebuf *operator->() { return &buf; }
};
class mssapi_captions;
@ -54,38 +55,38 @@ public:
// ISequentialStream methods
STDMETHODIMP Read(void *data, ULONG bytes, ULONG *read_bytes) override;
STDMETHODIMP Write(const void *data, ULONG bytes, ULONG *written_bytes)
override;
STDMETHODIMP Write(const void *data, ULONG bytes,
ULONG *written_bytes) override;
// IStream methods
STDMETHODIMP Seek(LARGE_INTEGER move, DWORD origin,
ULARGE_INTEGER *new_pos) override;
ULARGE_INTEGER *new_pos) override;
STDMETHODIMP SetSize(ULARGE_INTEGER new_size) override;
STDMETHODIMP CopyTo(IStream *stream, ULARGE_INTEGER bytes,
ULARGE_INTEGER *read_bytes,
ULARGE_INTEGER *written_bytes) override;
ULARGE_INTEGER *read_bytes,
ULARGE_INTEGER *written_bytes) override;
STDMETHODIMP Commit(DWORD commit_flags) override;
STDMETHODIMP Revert(void) override;
STDMETHODIMP LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
DWORD type) override;
DWORD type) override;
STDMETHODIMP UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
DWORD type) override;
DWORD type) override;
STDMETHODIMP Stat(STATSTG *stg, DWORD flags) override;
STDMETHODIMP Clone(IStream **stream) override;
// ISpStreamFormat methods
STDMETHODIMP GetFormat(GUID *guid, WAVEFORMATEX **co_mem_wfex_out)
override;
STDMETHODIMP GetFormat(GUID *guid,
WAVEFORMATEX **co_mem_wfex_out) override;
// ISpAudio methods
STDMETHODIMP SetState(SPAUDIOSTATE state, ULONGLONG reserved) override;
STDMETHODIMP SetFormat(REFGUID guid_ref, const WAVEFORMATEX *wfex)
override;
STDMETHODIMP SetFormat(REFGUID guid_ref,
const WAVEFORMATEX *wfex) override;
STDMETHODIMP GetStatus(SPAUDIOSTATUS *status) override;
STDMETHODIMP SetBufferInfo(const SPAUDIOBUFFERINFO *buf_info) override;
STDMETHODIMP GetBufferInfo(SPAUDIOBUFFERINFO *buf_info) override;
STDMETHODIMP GetDefaultFormat(GUID *format,
WAVEFORMATEX **co_mem_wfex_out) override;
WAVEFORMATEX **co_mem_wfex_out) override;
STDMETHODIMP_(HANDLE) EventHandle(void) override;
STDMETHODIMP GetVolumeLevel(ULONG *level) override;
STDMETHODIMP SetVolumeLevel(ULONG level) override;

View file

@ -1,16 +1,13 @@
#include "captions-mssapi.hpp"
#define do_log(type, format, ...) blog(type, "[Captions] " format, \
##__VA_ARGS__)
#define do_log(type, format, ...) \
blog(type, "[Captions] " format, ##__VA_ARGS__)
#define error(format, ...) do_log(LOG_ERROR, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
mssapi_captions::mssapi_captions(
captions_cb callback,
const std::string &lang) try
: captions_handler(callback, AUDIO_FORMAT_16BIT, 16000)
{
mssapi_captions::mssapi_captions(captions_cb callback, const std::string &lang)
try : captions_handler(callback, AUDIO_FORMAT_16BIT, 16000) {
HRESULT hr;
std::wstring wlang;
@ -33,7 +30,7 @@ mssapi_captions::mssapi_captions(
throw HRError("SpFindBestToken failed", hr);
hr = CoCreateInstance(CLSID_SpInprocRecognizer, nullptr, CLSCTX_ALL,
__uuidof(ISpRecognizer), (void**)&recognizer);
__uuidof(ISpRecognizer), (void **)&recognizer);
if (FAILED(hr))
throw HRError("CoCreateInstance for recognizer failed", hr);
@ -50,7 +47,7 @@ mssapi_captions::mssapi_captions(
throw HRError("CreateRecoContext failed", hr);
ULONGLONG interest = SPFEI(SPEI_RECOGNITION) |
SPFEI(SPEI_END_SR_STREAM);
SPFEI(SPEI_END_SR_STREAM);
hr = context->SetInterest(interest, interest);
if (FAILED(hr))
throw HRError("SetInterest failed", hr);
@ -80,7 +77,7 @@ mssapi_captions::mssapi_captions(
throw HRError("LoadDictation failed", hr);
try {
t = std::thread([this] () {main_thread();});
t = std::thread([this]() { main_thread(); });
} catch (...) {
throw "Failed to create thread";
}
@ -133,8 +130,8 @@ try {
ISpRecoResult *result = event.RecoResult();
CoTaskMemPtr<wchar_t> text;
hr = result->GetText((ULONG)-1, (ULONG)-1,
true, &text, nullptr);
hr = result->GetText((ULONG)-1, (ULONG)-1, true,
&text, nullptr);
if (FAILED(hr))
continue;
@ -168,12 +165,7 @@ void mssapi_captions::pcm_data(const void *data, size_t frames)
}
captions_handler_info mssapi_info = {
[] () -> std::string
{
return "Microsoft Speech-to-Text";
},
[] (captions_cb cb, const std::string &lang) -> captions_handler *
{
[]() -> std::string { return "Microsoft Speech-to-Text"; },
[](captions_cb cb, const std::string &lang) -> captions_handler * {
return new mssapi_captions(cb, lang);
}
};
}};

View file

@ -27,16 +27,16 @@
class mssapi_captions : public captions_handler {
friend class CaptionStream;
ComPtr<CaptionStream> audio;
ComPtr<CaptionStream> audio;
ComPtr<ISpObjectToken> token;
ComPtr<ISpRecoGrammar> grammar;
ComPtr<ISpRecognizer> recognizer;
ComPtr<ISpRecognizer> recognizer;
ComPtr<ISpRecoContext> context;
HANDLE notify;
WinHandle stop;
std::thread t;
bool started = false;
HANDLE notify;
WinHandle stop;
std::thread t;
bool started = false;
void main_thread();

View file

@ -31,8 +31,8 @@
#include "captions-mssapi.hpp"
#define do_log(type, format, ...) blog(type, "[Captions] " format, \
##__VA_ARGS__)
#define do_log(type, format, ...) \
blog(type, "[Captions] " format, ##__VA_ARGS__)
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
@ -48,10 +48,10 @@ struct obs_captions {
unique_ptr<captions_handler> handler;
LANGID lang_id = GetUserDefaultUILanguage();
std::unordered_map<std::string, captions_handler_info&> handler_types;
std::unordered_map<std::string, captions_handler_info &> handler_types;
inline void register_handler(const char *id,
captions_handler_info &info)
captions_handler_info &info)
{
handler_types.emplace(id, info);
}
@ -60,7 +60,7 @@ struct obs_captions {
void stop();
obs_captions();
inline ~obs_captions() {stop();}
inline ~obs_captions() { stop(); }
};
static obs_captions *captions = nullptr;
@ -74,9 +74,9 @@ struct locale_info {
inline locale_info() {}
inline locale_info(const locale_info &) = delete;
inline locale_info(locale_info &&li)
: name(std::move(li.name)),
id(li.id)
{}
: name(std::move(li.name)), id(li.id)
{
}
};
static void get_valid_locale_names(vector<locale_info> &names);
@ -84,16 +84,14 @@ static bool valid_lang(LANGID id);
/* ------------------------------------------------------------------------- */
CaptionsDialog::CaptionsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui_CaptionsDialog)
CaptionsDialog::CaptionsDialog(QWidget *parent)
: QDialog(parent), ui(new Ui_CaptionsDialog)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
auto cb = [this] (obs_source_t *source)
{
auto cb = [this](obs_source_t *source) {
uint32_t caps = obs_source_get_output_flags(source);
QString name = obs_source_get_name(source);
@ -111,8 +109,11 @@ CaptionsDialog::CaptionsDialog(QWidget *parent) :
ui->source->blockSignals(true);
ui->source->addItem(QStringLiteral(""));
ui->source->setCurrentIndex(0);
obs_enum_sources([] (void *data, obs_source_t *source) {
return (*static_cast<cb_t*>(data))(source);}, &cb);
obs_enum_sources(
[](void *data, obs_source_t *source) {
return (*static_cast<cb_t *>(data))(source);
},
&cb);
ui->source->blockSignals(false);
for (auto &ht : captions->handler_types) {
@ -232,8 +233,8 @@ static void caption_text(const std::string &text)
}
}
static void audio_capture(void*, obs_source_t*,
const struct audio_data *audio, bool)
static void audio_capture(void *, obs_source_t *,
const struct audio_data *audio, bool)
{
captions->handler->push_audio(audio);
}
@ -245,14 +246,13 @@ void obs_captions::start()
auto pair = handler_types.find(handler_id);
if (pair == handler_types.end()) {
warn("Failed to find handler '%s'",
handler_id.c_str());
warn("Failed to find handler '%s'", handler_id.c_str());
return;
}
if (!LCIDToLocaleName(lang_id, wname, 256, 0)) {
warn("Failed to get locale name: %d",
(int)GetLastError());
(int)GetLastError());
return;
}
@ -271,24 +271,24 @@ void obs_captions::start()
}
try {
captions_handler *h = pair->second.create(caption_text,
lang_name);
captions_handler *h =
pair->second.create(caption_text, lang_name);
handler.reset(h);
OBSSource s = OBSGetStrongRef(source);
obs_source_add_audio_capture_callback(s,
audio_capture, nullptr);
obs_source_add_audio_capture_callback(s, audio_capture,
nullptr);
} catch (std::string text) {
QWidget *window =
(QWidget*)obs_frontend_get_main_window();
(QWidget *)obs_frontend_get_main_window();
warn("Failed to create handler: %s", text.c_str());
QMessageBox::warning(window,
QMessageBox::warning(
window,
obs_module_text("Captions.Error.GenericFail"),
text.c_str());
}
}
}
@ -297,8 +297,8 @@ void obs_captions::stop()
{
OBSSource s = OBSGetStrongRef(source);
if (s)
obs_source_remove_audio_capture_callback(s,
audio_capture, nullptr);
obs_source_remove_audio_capture_callback(s, audio_capture,
nullptr);
handler.reset();
}
@ -332,42 +332,18 @@ static void get_valid_locale_names(vector<locale_info> &locales)
char locale_name[256];
static const LANGID default_locales[] = {
0x0409,
0x0401,
0x0402,
0x0403,
0x0404,
0x0405,
0x0406,
0x0407,
0x0408,
0x040a,
0x040b,
0x040c,
0x040d,
0x040e,
0x040f,
0x0410,
0x0411,
0x0412,
0x0413,
0x0414,
0x0415,
0x0416,
0x0417,
0x0418,
0x0419,
0x041a,
0
};
0x0409, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
0x0407, 0x0408, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e,
0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0};
/* ---------------------------------- */
LANGID def_id = GetUserDefaultUILanguage();
LANGID id = def_id;
if (valid_lang(id) && get_locale_name(id, locale_name)) {
dstr_copy(cur.name, obs_module_text(
"Captions.CurrentSystemLanguage"));
dstr_copy(cur.name,
obs_module_text("Captions.CurrentSystemLanguage"));
dstr_replace(cur.name, "%1", locale_name);
cur.id = id;
@ -381,8 +357,7 @@ static void get_valid_locale_names(vector<locale_info> &locales)
while (*locale) {
id = *locale;
if (id != def_id &&
valid_lang(id) &&
if (id != def_id && valid_lang(id) &&
get_locale_name(id, locale_name)) {
dstr_copy(cur.name, locale_name);
@ -418,17 +393,17 @@ static void obs_event(enum obs_frontend_event event, void *)
FreeCaptions();
}
static void save_caption_data(obs_data_t *save_data, bool saving, void*)
static void save_caption_data(obs_data_t *save_data, bool saving, void *)
{
if (saving) {
obs_data_t *obj = obs_data_create();
obs_data_set_string(obj, "source",
captions->source_name.c_str());
captions->source_name.c_str());
obs_data_set_bool(obj, "enabled", !!captions->handler);
obs_data_set_int(obj, "lang_id", captions->lang_id);
obs_data_set_string(obj, "provider",
captions->handler_id.c_str());
captions->handler_id.c_str());
obs_data_set_obj(save_data, "captions", obj);
obs_data_release(obj);
@ -440,15 +415,15 @@ static void save_caption_data(obs_data_t *save_data, bool saving, void*)
obj = obs_data_create();
obs_data_set_default_int(obj, "lang_id",
GetUserDefaultUILanguage());
GetUserDefaultUILanguage());
obs_data_set_default_string(obj, "provider", DEFAULT_HANDLER);
bool enabled = obs_data_get_bool(obj, "enabled");
captions->source_name = obs_data_get_string(obj, "source");
captions->lang_id = (int)obs_data_get_int(obj, "lang_id");
captions->handler_id = obs_data_get_string(obj, "provider");
captions->source = GetWeakSourceByName(
captions->source_name.c_str());
captions->source =
GetWeakSourceByName(captions->source_name.c_str());
obs_data_release(obj);
if (enabled)
@ -458,17 +433,15 @@ static void save_caption_data(obs_data_t *save_data, bool saving, void*)
extern "C" void InitCaptions()
{
QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
obs_module_text("Captions"));
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
obs_module_text("Captions"));
captions = new obs_captions;
auto cb = [] ()
{
auto cb = []() {
obs_frontend_push_ui_translation(obs_module_get_string);
QWidget *window =
(QWidget*)obs_frontend_get_main_window();
QWidget *window = (QWidget *)obs_frontend_get_main_window();
CaptionsDialog dialog(window);
dialog.exec();

View file

@ -0,0 +1,7 @@
Start="Begin"
Stop="Stop"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="سيتم إيقاف البث بعد:"
OutputTimer.Record.StoppingIn="سيتم إيقاف التسجيل بعد:"
OutputTimer.Stream.EnableEverytime="تفعيل مؤقِّت البث في كل مرة"
OutputTimer.Record.EnableEverytime="تفعيل مؤقِّت التسجيل في كل مرة"
OutputTimer.Record.PauseTimer="إيقاف المُؤَقِت عندما يكون التسجيل متوقف"
Scripts="سكريبتات"
LoadedScripts="السكريبتات المحملة"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="La transmissió s'aturarà en:"
OutputTimer.Record.StoppingIn="La gravació s'aturarà en:"
OutputTimer.Stream.EnableEverytime="Activa el temporitzador en cada transmissió"
OutputTimer.Record.EnableEverytime="Activa el temporitzador en cada enregistrament"
OutputTimer.Record.PauseTimer="Pausa el temporitzador en pausar l'enregistrament"
Scripts="Scripts"
LoadedScripts="Scripts carregats"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Vysílání se zastaví za:"
OutputTimer.Record.StoppingIn="Nahrávání se zastaví za:"
OutputTimer.Stream.EnableEverytime="Pokaždé povolit časovač vysílání"
OutputTimer.Record.EnableEverytime="Pokaždé povolit časovač nahrávání"
OutputTimer.Record.PauseTimer="Pozastavit časovač při pozastavení nahrávání"
Scripts="Skripty"
LoadedScripts="Načtené skripty"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Streaming standser om:"
OutputTimer.Record.StoppingIn="Optagelse standser om:"
OutputTimer.Stream.EnableEverytime="Aktivér streamingtimer hver gang"
OutputTimer.Record.EnableEverytime="Aktivér optagetimer hver gang"
OutputTimer.Record.PauseTimer="Sæt timer på pause, når optagelsen er sat på pause"
Scripts="Scripts"
LoadedScripts="Indlæste scripts"

View file

@ -4,7 +4,7 @@ SceneSwitcher.OnNoMatch.DontSwitch="Nicht wechseln"
SceneSwitcher.OnNoMatch.SwitchTo="Wechseln zu:"
SceneSwitcher.CheckInterval="Titel des aktiven Fensters überprüfen alle:"
SceneSwitcher.ActiveOrNotActive="Szenenwechsler ist:"
InvalidRegex.Title="Ungültiger regulärer Ausdruck"
InvalidRegex.Title="Ungültiger, regulärer Ausdruck"
InvalidRegex.Text="Der reguläre Ausdruck, den Sie eingegeben haben, ist ungültig."
Active="Aktiv"
Inactive="Inaktiv"
@ -24,16 +24,17 @@ OutputTimer.Stream.StoppingIn="Stream stoppt in:"
OutputTimer.Record.StoppingIn="Aufnahme stoppt in:"
OutputTimer.Stream.EnableEverytime="Streamingtimer jedes Mal aktivieren"
OutputTimer.Record.EnableEverytime="Aufnahmetimer jedes Mal aktivieren"
OutputTimer.Record.PauseTimer="Timer beim Pausieren der Aufnahme anhalten"
Scripts="Skripte"
LoadedScripts="Geladene Skripte"
AddScripts="Skripte hinzufügen"
RemoveScripts="Skripte entfernen"
ReloadScripts="Skripte neu laden"
PythonSettings="Python-Einstellungen"
PythonSettings.PythonInstallPath32bit="Python-Installationspfad (32bit)"
PythonSettings.PythonInstallPath64bit="Python-Installationspfad (64bit)"
PythonSettings.BrowsePythonPath="Python-Pfad öffnen"
ReloadScripts="Skripte neuladen"
PythonSettings="PythonEinstellungen"
PythonSettings.PythonInstallPath32bit="PythonInstallationspfad (32bit)"
PythonSettings.PythonInstallPath64bit="PythonInstallationspfad (64bit)"
PythonSettings.BrowsePythonPath="PythonPfad öffnen"
ScriptLogWindow="Skriptprotokoll"
Description="Beschreibung"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Streaming stopping in:"
OutputTimer.Record.StoppingIn="Recording stopping in:"
OutputTimer.Stream.EnableEverytime="Enable streaming timer every time"
OutputTimer.Record.EnableEverytime="Enable recording timer every time"
OutputTimer.Record.PauseTimer="Pause timer when recording is paused"
Scripts="Scripts"
LoadedScripts="Loaded Scripts"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Finalizando transmisión en:"
OutputTimer.Record.StoppingIn="Finalizando grabación en:"
OutputTimer.Stream.EnableEverytime="Activar temporizador en cada transmisión"
OutputTimer.Record.EnableEverytime="Activar temporizador en cada grabación"
OutputTimer.Record.PauseTimer="Pausar temporizador cuando la grabación se pause"
Scripts="Scripts"
LoadedScripts="Scripts Cargados"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Transmisioa geldituko da: hau barru:"
OutputTimer.Record.StoppingIn="Grabazioa geldituko da hau barru:"
OutputTimer.Stream.EnableEverytime="Gaitu transmisio tenporizadorea aldiro"
OutputTimer.Record.EnableEverytime="Gaitu grabazio tenporizadorea aldiro"
OutputTimer.Record.PauseTimer="Pausatu tenporizadorea grabazioa pausatuta dagoenean"
Scripts="Script-ak"
LoadedScripts="Kargatutako script-ak"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Arrêt du streaming dans :"
OutputTimer.Record.StoppingIn="Arrêt de l'enregistrement dans :"
OutputTimer.Stream.EnableEverytime="Démarrer le minuteur automatiquement à chaque stream"
OutputTimer.Record.EnableEverytime="Démarrer le minuteur automatiquement à chaque enregistrement"
OutputTimer.Record.PauseTimer="Mettre en pause le minuteur quand l'enregistrement est mis en pause"
Scripts="Scripts"
LoadedScripts="Scripts chargés"

View file

@ -0,0 +1,43 @@
SceneSwitcher="Conmutador automático de escena"
SceneSwitcher.OnNoMatch="Cando non coincida ningunha xanela:"
SceneSwitcher.OnNoMatch.DontSwitch="Non conmutar"
SceneSwitcher.OnNoMatch.SwitchTo="Cambiar a:"
SceneSwitcher.CheckInterval="Comprobar o título da xanela activa cada:"
SceneSwitcher.ActiveOrNotActive="O conmutador de escena está:"
InvalidRegex.Title="Expresión regular non válida"
InvalidRegex.Text="A expresión regular que introduciu non é válida."
Active="Activo"
Inactive="Inactivo"
Start="Iniciar"
Stop="Parar"
Captions="Subtítulos (experimental)"
Captions.AudioSource="Fonte de son"
Captions.CurrentSystemLanguage="Idioma actual do sistema (%1)"
Captions.Provider="Fornecedor"
Captions.Error.GenericFail="Produciuse un erro ao iniciar os suntítulos"
OutputTimer="Temporizador de Saída"
OutputTimer.Stream="Deter a emisión após:"
OutputTimer.Record="Deter a gravación após:"
OutputTimer.Stream.StoppingIn="Detendo a emisión en:"
OutputTimer.Record.StoppingIn="Detendo a gravación en:"
OutputTimer.Stream.EnableEverytime="Activar o temporizador en cada emisión"
OutputTimer.Record.EnableEverytime="Activar o temporizador en cada gravación"
OutputTimer.Record.PauseTimer="Pór en pausa o temporizador ao pór en pausa a gravación"
Scripts="Scripts"
LoadedScripts="Scripts cargados"
AddScripts="Engadir scripts"
RemoveScripts="Retirar scripts"
ReloadScripts="Volver cargar scripts"
PythonSettings="Axustes de Python"
PythonSettings.PythonInstallPath32bit="Ruta de instalación de Python (32bit)"
PythonSettings.PythonInstallPath64bit="Ruta de instalación de Python (64bit)"
PythonSettings.BrowsePythonPath="Examinar a ruta de Python"
ScriptLogWindow="Rexistro de script"
Description="Descrición"
FileFilter.ScriptFiles="Ficheiros de scripts"
FileFilter.AllFiles="Todos os ficheiros"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="A stream leáll:"
OutputTimer.Record.StoppingIn="Felvétel leáll:"
OutputTimer.Stream.EnableEverytime="Stream időzítő indítása minden alkalommal"
OutputTimer.Record.EnableEverytime="Felvétel időzítő indítása minden alkalommal"
OutputTimer.Record.PauseTimer="Idő megállítása, ha a felvétel is megáll"
Scripts="Szkriptek"
LoadedScripts="Betöltött szkriptek"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="La diretta terminerà tra:"
OutputTimer.Record.StoppingIn="La registrazione terminerà tra:"
OutputTimer.Stream.EnableEverytime="Attiva il conto alla rovescia per le dirette ogni volta"
OutputTimer.Record.EnableEverytime="Attiva il conto alla rovescia per le registrazioni ogni volta"
OutputTimer.Record.PauseTimer="Pausa il timer quando la registrazione è in pausa"
Scripts="Script"
LoadedScripts="Script caricati"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="配信停止まで:"
OutputTimer.Record.StoppingIn="録画停止まで:"
OutputTimer.Stream.EnableEverytime="毎回配信タイマーを有効にする"
OutputTimer.Record.EnableEverytime="毎回録画タイマーを有効にする"
OutputTimer.Record.PauseTimer="録画が一時停止したときにタイマーを一時停止"
Scripts="スクリプト"
LoadedScripts="ロードしたスクリプト"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="ნაკადის შეწყვეტის
OutputTimer.Record.StoppingIn="ჩაწერის შეწყვეტის დრო:"
OutputTimer.Stream.EnableEverytime="ნაკადის წამზომის ჩართვა ყოველ ჯერზე"
OutputTimer.Record.EnableEverytime="ჩაწერის წამზომის ჩართვა ყოველ ჯერზე"
OutputTimer.Record.PauseTimer="წამზომის შეჩერება ჩაწერის შეჩერებისას"
Scripts="სკრიპტები"
LoadedScripts="ჩატვირთული სკრიპტები"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="방송 중지까지 남은 시간:"
OutputTimer.Record.StoppingIn="녹화 중지까지 남은 시간:"
OutputTimer.Stream.EnableEverytime="매번 방송 시간 기록기 활성화"
OutputTimer.Record.EnableEverytime="매번 녹화 시간 기록기 활성화"
OutputTimer.Record.PauseTimer="녹화가 중지되었을 때 타이머 일시 정지"
Scripts="스크립트"
LoadedScripts="입력한 스크립트"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Stream stopt over:"
OutputTimer.Record.StoppingIn="Opname stopt over:"
OutputTimer.Stream.EnableEverytime="Schakel streaming timer elke keer in"
OutputTimer.Record.EnableEverytime="Schakel opnametimer elke keer in"
OutputTimer.Record.PauseTimer="Pauzeer timer tijdens het pauzeren van de opname"
Scripts="Scripts"
LoadedScripts="Geladen Scripts"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Zatrzymanie streamu za:"
OutputTimer.Record.StoppingIn="Zatrzymanie nagrywania za:"
OutputTimer.Stream.EnableEverytime="Włącz timer streamu za każdym razem"
OutputTimer.Record.EnableEverytime="Włącz timer nagrywania za każdym razem"
OutputTimer.Record.PauseTimer="Zatrzymaj czas, gdy nagrywanie jest spauzowane"
Scripts="Skrypty"
LoadedScripts="Wczytane skrypty"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="A transmissão irá parar em:"
OutputTimer.Record.StoppingIn="A gravação irá parar em:"
OutputTimer.Stream.EnableEverytime="Ativar o timer streaming o tempo todo"
OutputTimer.Record.EnableEverytime="Ativar o timer de gravação o tempo todo"
OutputTimer.Record.PauseTimer="Pausar o temporizador quando a gravação é pausada"
Scripts="Scripts"
LoadedScripts="Scripts Carregados"

View file

@ -10,11 +10,11 @@ Start="Pornește"
Stop="Oprește"
Captions="Subtitrări (experimentale)"
Captions.AudioSource="Sursa audio"
Captions.AudioSource="Sursă audio"
Captions.CurrentSystemLanguage="Limba actuală a sistemului (%1)"
Captions.Provider="Furnizor"
OutputTimer.Record="Opriți înregistrarea după:"
OutputTimer.Record="Oprește înregistrarea după:"
OutputTimer.Stream.StoppingIn="Se oprește transmisiunea în:"
OutputTimer.Record.StoppingIn="Înregistrarea se oprește în:"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Стрим будет завершён через
OutputTimer.Record.StoppingIn="Запись будет завершена через:"
OutputTimer.Stream.EnableEverytime="Включать таймер трансляции каждый раз"
OutputTimer.Record.EnableEverytime="Включать таймер записи каждый раз"
OutputTimer.Record.PauseTimer="Таймер паузы при приостановке записи"
Scripts="Скрипты"
LoadedScripts="Загруженные скрипты"

View file

@ -0,0 +1,43 @@
SceneSwitcher="Samodejno preklapljanje prizorov"
SceneSwitcher.OnNoMatch="Ko se nobeno okno ne ujema:"
SceneSwitcher.OnNoMatch.DontSwitch="Ne preklopi"
SceneSwitcher.OnNoMatch.SwitchTo="Preklopi na:"
SceneSwitcher.CheckInterval="Preveri naziv dejavnega okna vsakih:"
SceneSwitcher.ActiveOrNotActive="Preklopnik prizorov je:"
InvalidRegex.Title="Neveljaven regularni izraz"
InvalidRegex.Text="Vneseni regularni izraz ni veljaven."
Active="Dejaven"
Inactive="Nedejaven"
Start="Začni"
Stop="Ustavi"
Captions="Napisi (preizkusno)"
Captions.AudioSource="Zvočni vir"
Captions.CurrentSystemLanguage="Trenutni jezik sistema (%1)"
Captions.Provider="Ponudnik"
Captions.Error.GenericFail="Zagon napisov je spodletel"
OutputTimer="Odštevalnik izhoda"
OutputTimer.Stream="Prenehaj pretakati po:"
OutputTimer.Record="Prenehaj snemati po:"
OutputTimer.Stream.StoppingIn="Pretok se bo ustavil čez:"
OutputTimer.Record.StoppingIn="Snemanje se bo ustavilo čez:"
OutputTimer.Stream.EnableEverytime="Vsakič omogoči odštevalnik pretakanja"
OutputTimer.Record.EnableEverytime="Vsakič omogoči odštevalnik snemanja"
OutputTimer.Record.PauseTimer="Premor odštevalnika ob premoru snemanja"
Scripts="Skripti"
LoadedScripts="Naloženi skripti"
AddScripts="Dodaj skripte"
RemoveScripts="Odstrani skripte"
ReloadScripts="Ponovno naloži skripte"
PythonSettings="Nastavitve Python"
PythonSettings.PythonInstallPath32bit="Namestitvena pot Pythona (32-bitni)"
PythonSettings.PythonInstallPath64bit="Namestitvena pot Pythona (64-bitni)"
PythonSettings.BrowsePythonPath="Prebrskaj pot do Pythona"
ScriptLogWindow="Dnevnik skriptov"
Description="Opis"
FileFilter.ScriptFiles="Datoteke skriptov"
FileFilter.AllFiles="Vse datoteke"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Streamen stoppas om:"
OutputTimer.Record.StoppingIn="Inspelningen stoppas om:"
OutputTimer.Stream.EnableEverytime="Aktivera strömtimer varje gång"
OutputTimer.Record.EnableEverytime="Aktivera inspelningstimer varje gång"
OutputTimer.Record.PauseTimer="Pausa timer när inspelning pausas"
Scripts="Skript"
LoadedScripts="Inlästa skript"

View file

@ -1,3 +1,8 @@
SceneSwitcher="สลับฉากอัตโนมัติ"
SceneSwitcher.OnNoMatch="เมื่อหน้าต่างไม่สัมพันธ์กัน:"
SceneSwitcher.OnNoMatch.DontSwitch="ไม่สลับ"
SceneSwitcher.OnNoMatch.SwitchTo="สลับไปยัง:"
SceneSwitcher.CheckInterval="ตรวจสอบหน้าต่างที่ถูกเลือกทุกๆ"
Active="ใช้งานอยู่"
Inactive="ไม่ใช้งาน"
Start="เริ่ม"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Yayın durduruluyor:"
OutputTimer.Record.StoppingIn="Kayıt durduruluyor:"
OutputTimer.Stream.EnableEverytime="Her zaman yayın zamanlayıcıyı etkinleştir"
OutputTimer.Record.EnableEverytime="Her zaman kayıt zamanlayıcıyı etkinleştir"
OutputTimer.Record.PauseTimer="Kayıt durdurulduğunda sayacı durdur"
Scripts="Betikler"
LoadedScripts="Yüklü Betikler"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="Трансляція припиниться за:
OutputTimer.Record.StoppingIn="Запис зупиниться за:"
OutputTimer.Stream.EnableEverytime="Щоразу запускається трансляція - вмикати Таймер для Виводу"
OutputTimer.Record.EnableEverytime="Щоразу починається запис - вмикати Таймер для Виводу"
OutputTimer.Record.PauseTimer="Призупиняти таймер коли запис Призупинено"
Scripts="Скрипти"
LoadedScripts="Завантажені скрипти"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="串流停止在:"
OutputTimer.Record.StoppingIn="录制停止在:"
OutputTimer.Stream.EnableEverytime="每次启用流计时器"
OutputTimer.Record.EnableEverytime="每次启用录制计时器"
OutputTimer.Record.PauseTimer="暂停录制时暂停计时器"
Scripts="脚本"
LoadedScripts="已载入脚本"

View file

@ -24,6 +24,7 @@ OutputTimer.Stream.StoppingIn="串流將在下面時間內停止"
OutputTimer.Record.StoppingIn="錄影將在下面時間內停止"
OutputTimer.Stream.EnableEverytime="每次都啟動串流計時器"
OutputTimer.Record.EnableEverytime="每次都啟動錄影計時器"
OutputTimer.Record.PauseTimer="錄影暫停時,計時器也暫停。"
Scripts="腳本"
LoadedScripts="已載入腳本"

View file

@ -0,0 +1,44 @@
obs = obslua
pause_scene = ""
function on_event(event)
if event == obs.OBS_FRONTEND_EVENT_SCENE_CHANGED then
local scene = obs.obs_frontend_get_current_scene()
local scene_name = obs.obs_source_get_name(scene)
if pause_scene == scene_name then
obs.obs_frontend_recording_pause(true)
else
obs.obs_frontend_recording_pause(false)
end
obs.obs_source_release(scene);
end
end
function script_properties()
local props = obs.obs_properties_create()
local p = obs.obs_properties_add_list(props, "pause_scene", "Pause Scene", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
local scenes = obs.obs_frontend_get_scenes()
if scenes ~= nil then
for _, scene in ipairs(scenes) do
local name = obs.obs_source_get_name(scene);
obs.obs_property_list_add_string(p, name, name)
end
end
obs.source_list_release(scenes)
return props
end
function script_description()
return "Adds the ability to pause recording when switching to a specific scene"
end
function script_update(settings)
pause_scene = obs.obs_data_get_string(settings, "pause_scene")
end
function script_load(settings)
obs.obs_frontend_add_event_callback(on_event)
end

View file

@ -1,215 +1,237 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OutputTimer</class>
<widget class="QDialog" name="OutputTimer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string>OutputTimer</string>
</property>
<layout class="QGridLayout" name="timerLayout">
<item row="0" column="1">
<widget class="QLabel" name="streamingLabel">
<property name="text">
<string>OutputTimer.Stream</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="streamingTimerHours">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>24</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="hoursLabel">
<property name="text">
<string>Hours</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="streamingTimerMinutes">
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="minutesLabel">
<property name="text">
<string>Minutes</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QSpinBox" name="streamingTimerSeconds">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="secondsLabel">
<property name="text">
<string>Seconds</string>
</property>
</widget>
</item>
<item row="0" column="8">
<widget class="QPushButton" name="outputTimerStream">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="streamStoppingIn">
<property name="text">
<string>OutputTimer.Stream.StoppingIn</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="streamTime">
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="recordingLabel">
<property name="text">
<string>OutputTimer.Record</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="recordingTimerHours">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>24</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="hoursLabel_2">
<property name="text">
<string>Hours</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QSpinBox" name="recordingTimerMinutes">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QLabel" name="minutesLabel_2">
<property name="text">
<string>Minutes</string>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QSpinBox" name="recordingTimerSeconds">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QLabel" name="secondsLabel_2">
<property name="text">
<string>Seconds</string>
</property>
</widget>
</item>
<item row="3" column="8">
<widget class="QPushButton" name="outputTimerRecord">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="recordStoppingIn">
<property name="text">
<string>OutputTimer.Record.StoppingIn</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="recordTime">
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QCheckBox" name="autoStartStreamTimer">
<property name="text">
<string>OutputTimer.Stream.EnableEverytime</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QCheckBox" name="autoStartRecordTimer">
<property name="text">
<string>OutputTimer.Record.EnableEverytime</string>
</property>
</widget>
</item>
<item row="6" column="8">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources />
<connections />
<widget class="QDialog" name="OutputTimer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>697</width>
<height>240</height>
</rect>
</property>
<property name="windowTitle">
<string>OutputTimer</string>
</property>
<layout class="QGridLayout" name="timerLayout">
<item row="0" column="3">
<widget class="QLabel" name="hoursLabel">
<property name="text">
<string>Hours</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="recordingTimerHours">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>24</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QSpinBox" name="streamingTimerSeconds">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
<item row="0" column="8">
<widget class="QPushButton" name="outputTimerStream">
<property name="text">
<string>Start</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QSpinBox" name="recordingTimerMinutes">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="streamingLabel">
<property name="text">
<string>OutputTimer.Stream</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="streamingTimerMinutes">
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="3" column="8">
<widget class="QPushButton" name="outputTimerRecord">
<property name="text">
<string>Start</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="recordStoppingIn">
<property name="text">
<string>OutputTimer.Record.StoppingIn</string>
</property>
</widget>
</item>
<item row="3" column="7">
<widget class="QLabel" name="secondsLabel_2">
<property name="text">
<string>Seconds</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="streamTime">
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
<item row="3" column="5">
<widget class="QLabel" name="minutesLabel_2">
<property name="text">
<string>Minutes</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="streamingTimerHours">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>24</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="recordTime">
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLabel" name="minutesLabel">
<property name="text">
<string>Minutes</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="recordingLabel">
<property name="text">
<string>OutputTimer.Record</string>
</property>
</widget>
</item>
<item row="3" column="6">
<widget class="QSpinBox" name="recordingTimerSeconds">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>59</number>
</property>
<property name="value">
<number>30</number>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QCheckBox" name="autoStartStreamTimer">
<property name="text">
<string>OutputTimer.Stream.EnableEverytime</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="streamStoppingIn">
<property name="text">
<string>OutputTimer.Stream.StoppingIn</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QCheckBox" name="autoStartRecordTimer">
<property name="text">
<string>OutputTimer.Record.EnableEverytime</string>
</property>
</widget>
</item>
<item row="7" column="8">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="hoursLabel_2">
<property name="text">
<string>Hours</string>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="secondsLabel">
<property name="text">
<string>Seconds</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="3">
<widget class="QCheckBox" name="pauseRecordTimer">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>OutputTimer.Record.PauseTimer</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -13,19 +13,18 @@ using namespace std;
OutputTimer *ot;
OutputTimer::OutputTimer(QWidget *parent)
: QDialog(parent),
ui(new Ui_OutputTimer)
: QDialog(parent), ui(new Ui_OutputTimer)
{
ui->setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QObject::connect(ui->outputTimerStream, SIGNAL(clicked()), this,
SLOT(StreamingTimerButton()));
SLOT(StreamingTimerButton()));
QObject::connect(ui->outputTimerRecord, SIGNAL(clicked()), this,
SLOT(RecordingTimerButton()));
SLOT(RecordingTimerButton()));
QObject::connect(ui->buttonBox->button(QDialogButtonBox::Close),
SIGNAL(clicked()), this, SLOT(hide()));
SIGNAL(clicked()), this, SLOT(hide()));
streamingTimer = new QTimer(this);
streamingTimerDisplay = new QTimer(this);
@ -34,7 +33,7 @@ OutputTimer::OutputTimer(QWidget *parent)
recordingTimerDisplay = new QTimer(this);
}
void OutputTimer::closeEvent(QCloseEvent*)
void OutputTimer::closeEvent(QCloseEvent *)
{
obs_frontend_save();
}
@ -78,9 +77,7 @@ void OutputTimer::StreamTimerStart()
int minutes = ui->streamingTimerMinutes->value();
int seconds = ui->streamingTimerSeconds->value();
int total = (((hours * 3600) +
(minutes * 60)) +
seconds) * 1000;
int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
if (total == 0)
total = 1000;
@ -89,16 +86,18 @@ void OutputTimer::StreamTimerStart()
streamingTimer->setSingleShot(true);
QObject::connect(streamingTimer, SIGNAL(timeout()),
SLOT(EventStopStreaming()));
SLOT(EventStopStreaming()));
QObject::connect(streamingTimerDisplay, SIGNAL(timeout()), this,
SLOT(UpdateStreamTimerDisplay()));
SLOT(UpdateStreamTimerDisplay()));
streamingTimer->start();
streamingTimerDisplay->start(1000);
ui->outputTimerStream->setText(obs_module_text("Stop"));
UpdateStreamTimerDisplay();
ui->outputTimerStream->setChecked(true);
}
void OutputTimer::RecordTimerStart()
@ -112,9 +111,7 @@ void OutputTimer::RecordTimerStart()
int minutes = ui->recordingTimerMinutes->value();
int seconds = ui->recordingTimerSeconds->value();
int total = (((hours * 3600) +
(minutes * 60)) +
seconds) * 1000;
int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
if (total == 0)
total = 1000;
@ -123,16 +120,18 @@ void OutputTimer::RecordTimerStart()
recordingTimer->setSingleShot(true);
QObject::connect(recordingTimer, SIGNAL(timeout()),
SLOT(EventStopRecording()));
SLOT(EventStopRecording()));
QObject::connect(recordingTimerDisplay, SIGNAL(timeout()), this,
SLOT(UpdateRecordTimerDisplay()));
SLOT(UpdateRecordTimerDisplay()));
recordingTimer->start();
recordingTimerDisplay->start(1000);
ui->outputTimerRecord->setText(obs_module_text("Stop"));
UpdateRecordTimerDisplay();
ui->outputTimerRecord->setChecked(true);
}
void OutputTimer::StreamTimerStop()
@ -151,6 +150,7 @@ void OutputTimer::StreamTimerStop()
streamingTimerDisplay->stop();
ui->streamTime->setText("00:00:00");
ui->outputTimerStream->setChecked(false);
}
void OutputTimer::RecordTimerStop()
@ -169,6 +169,7 @@ void OutputTimer::RecordTimerStop()
recordingTimerDisplay->stop();
ui->recordTime->setText("00:00:00");
ui->outputTimerRecord->setChecked(false);
}
void OutputTimer::UpdateStreamTimerDisplay()
@ -186,7 +187,13 @@ void OutputTimer::UpdateStreamTimerDisplay()
void OutputTimer::UpdateRecordTimerDisplay()
{
int remainingTime = recordingTimer->remainingTime() / 1000;
int remainingTime = 0;
if (obs_frontend_recording_paused() &&
ui->pauseRecordTimer->isChecked())
remainingTime = recordingTimeLeft / 1000;
else
remainingTime = recordingTimer->remainingTime() / 1000;
int seconds = remainingTime % 60;
int minutes = (remainingTime % 3600) / 60;
@ -197,6 +204,26 @@ void OutputTimer::UpdateRecordTimerDisplay()
ui->recordTime->setText(text);
}
void OutputTimer::PauseRecordingTimer()
{
if (!ui->pauseRecordTimer->isChecked())
return;
if (recordingTimer->isActive()) {
recordingTimeLeft = recordingTimer->remainingTime();
recordingTimer->stop();
}
}
void OutputTimer::UnpauseRecordingTimer()
{
if (!ui->pauseRecordTimer->isChecked())
return;
if (!recordingTimer->isActive())
recordingTimer->start(recordingTimeLeft);
}
void OutputTimer::ShowHideDialog()
{
if (!isVisible()) {
@ -226,60 +253,63 @@ static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *)
obs_data_t *obj = obs_data_create();
obs_data_set_int(obj, "streamTimerHours",
ot->ui->streamingTimerHours->value());
ot->ui->streamingTimerHours->value());
obs_data_set_int(obj, "streamTimerMinutes",
ot->ui->streamingTimerMinutes->value());
ot->ui->streamingTimerMinutes->value());
obs_data_set_int(obj, "streamTimerSeconds",
ot->ui->streamingTimerSeconds->value());
ot->ui->streamingTimerSeconds->value());
obs_data_set_int(obj, "recordTimerHours",
ot->ui->recordingTimerHours->value());
ot->ui->recordingTimerHours->value());
obs_data_set_int(obj, "recordTimerMinutes",
ot->ui->recordingTimerMinutes->value());
ot->ui->recordingTimerMinutes->value());
obs_data_set_int(obj, "recordTimerSeconds",
ot->ui->recordingTimerSeconds->value());
ot->ui->recordingTimerSeconds->value());
obs_data_set_bool(obj, "autoStartStreamTimer",
ot->ui->autoStartStreamTimer->isChecked());
ot->ui->autoStartStreamTimer->isChecked());
obs_data_set_bool(obj, "autoStartRecordTimer",
ot->ui->autoStartRecordTimer->isChecked());
ot->ui->autoStartRecordTimer->isChecked());
obs_data_set_bool(obj, "pauseRecordTimer",
ot->ui->pauseRecordTimer->isChecked());
obs_data_set_obj(save_data, "output-timer", obj);
obs_data_release(obj);
} else {
obs_data_t *obj = obs_data_get_obj(save_data,
"output-timer");
obs_data_t *obj = obs_data_get_obj(save_data, "output-timer");
if (!obj)
obj = obs_data_create();
ot->ui->streamingTimerHours->setValue(
obs_data_get_int(obj, "streamTimerHours"));
obs_data_get_int(obj, "streamTimerHours"));
ot->ui->streamingTimerMinutes->setValue(
obs_data_get_int(obj, "streamTimerMinutes"));
obs_data_get_int(obj, "streamTimerMinutes"));
ot->ui->streamingTimerSeconds->setValue(
obs_data_get_int(obj, "streamTimerSeconds"));
obs_data_get_int(obj, "streamTimerSeconds"));
ot->ui->recordingTimerHours->setValue(
obs_data_get_int(obj, "recordTimerHours"));
obs_data_get_int(obj, "recordTimerHours"));
ot->ui->recordingTimerMinutes->setValue(
obs_data_get_int(obj, "recordTimerMinutes"));
obs_data_get_int(obj, "recordTimerMinutes"));
ot->ui->recordingTimerSeconds->setValue(
obs_data_get_int(obj, "recordTimerSeconds"));
obs_data_get_int(obj, "recordTimerSeconds"));
ot->ui->autoStartStreamTimer->setChecked(
obs_data_get_bool(obj, "autoStartStreamTimer"));
obs_data_get_bool(obj, "autoStartStreamTimer"));
ot->ui->autoStartRecordTimer->setChecked(
obs_data_get_bool(obj, "autoStartRecordTimer"));
obs_data_get_bool(obj, "autoStartRecordTimer"));
ot->ui->pauseRecordTimer->setChecked(
obs_data_get_bool(obj, "pauseRecordTimer"));
obs_data_release(obj);
}
}
extern "C" void FreeOutputTimer()
{
}
extern "C" void FreeOutputTimer() {}
static void OBSEvent(enum obs_frontend_event event, void *)
{
@ -294,24 +324,25 @@ static void OBSEvent(enum obs_frontend_event event, void *)
ot->RecordTimerStart();
} else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING) {
ot->RecordTimerStop();
} else if (event == OBS_FRONTEND_EVENT_RECORDING_PAUSED) {
ot->PauseRecordingTimer();
} else if (event == OBS_FRONTEND_EVENT_RECORDING_UNPAUSED) {
ot->UnpauseRecordingTimer();
}
}
extern "C" void InitOutputTimer()
{
QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
obs_module_text("OutputTimer"));
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
obs_module_text("OutputTimer"));
obs_frontend_push_ui_translation(obs_module_get_string);
QMainWindow *window = (QMainWindow*)obs_frontend_get_main_window();
QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window();
ot = new OutputTimer(window);
auto cb = [] ()
{
ot->ShowHideDialog();
};
auto cb = []() { ot->ShowHideDialog(); };
obs_frontend_pop_ui_translation();

View file

@ -15,6 +15,8 @@ public:
OutputTimer(QWidget *parent);
void closeEvent(QCloseEvent *event) override;
void PauseRecordingTimer();
void UnpauseRecordingTimer();
public slots:
void StreamingTimerButton();
@ -37,4 +39,6 @@ private:
QTimer *recordingTimer;
QTimer *streamingTimerDisplay;
QTimer *recordingTimerDisplay;
int recordingTimeLeft;
};

View file

@ -43,7 +43,7 @@
/* ----------------------------------------------------------------- */
using OBSScript = OBSObj<obs_script_t*, obs_script_destroy>;
using OBSScript = OBSObj<obs_script_t *, obs_script_destroy>;
struct ScriptData {
std::vector<OBSScript> scripts;
@ -92,11 +92,10 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(nullptr)
QHBoxLayout *buttonLayout = new QHBoxLayout();
QPushButton *clearButton = new QPushButton(tr("Clear"));
connect(clearButton, &QPushButton::clicked,
this, &ScriptLogWindow::ClearWindow);
connect(clearButton, &QPushButton::clicked, this,
&ScriptLogWindow::ClearWindow);
QPushButton *closeButton = new QPushButton(tr("Close"));
connect(closeButton, &QPushButton::clicked,
this, &QDialog::hide);
connect(closeButton, &QPushButton::clicked, this, &QDialog::hide);
buttonLayout->addStretch();
buttonLayout->addWidget(clearButton);
@ -112,8 +111,8 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(nullptr)
resize(600, 400);
config_t *global_config = obs_frontend_get_global_config();
const char *geom = config_get_string(global_config,
"ScriptLogWindow", "geometry");
const char *geom =
config_get_string(global_config, "ScriptLogWindow", "geometry");
if (geom != nullptr) {
QByteArray ba = QByteArray::fromBase64(QByteArray(geom));
restoreGeometry(ba);
@ -121,16 +120,15 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(nullptr)
setWindowTitle(obs_module_text("ScriptLogWindow"));
connect(edit->verticalScrollBar(), &QAbstractSlider::sliderMoved,
this, &ScriptLogWindow::ScrollChanged);
connect(edit->verticalScrollBar(), &QAbstractSlider::sliderMoved, this,
&ScriptLogWindow::ScrollChanged);
}
ScriptLogWindow::~ScriptLogWindow()
{
config_t *global_config = obs_frontend_get_global_config();
config_set_string(global_config,
"ScriptLogWindow", "geometry",
saveGeometry().toBase64().constData());
config_set_string(global_config, "ScriptLogWindow", "geometry",
saveGeometry().toBase64().constData());
}
void ScriptLogWindow::ScrollChanged(int val)
@ -180,17 +178,15 @@ void ScriptLogWindow::Clear()
/* ----------------------------------------------------------------- */
ScriptsTool::ScriptsTool()
: QWidget (nullptr),
ui (new Ui_ScriptsTool)
ScriptsTool::ScriptsTool() : QWidget(nullptr), ui(new Ui_ScriptsTool)
{
ui->setupUi(this);
RefreshLists();
#if PYTHON_UI
config_t *config = obs_frontend_get_global_config();
const char *path = config_get_string(config, "Python",
"Path" ARCH_NAME);
const char *path =
config_get_string(config, "Python", "Path" ARCH_NAME);
ui->pythonPath->setText(path);
ui->pythonPathLabel->setText(obs_module_text(PYTHONPATH_LABEL_TEXT));
#else
@ -201,7 +197,7 @@ ScriptsTool::ScriptsTool()
delete propertiesView;
propertiesView = new QWidget();
propertiesView->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
QSizePolicy::Expanding);
ui->propertiesLayout->addWidget(propertiesView);
}
@ -217,8 +213,8 @@ void ScriptsTool::RemoveScript(const char *path)
const char *script_path = obs_script_get_path(script);
if (strcmp(script_path, path) == 0) {
scriptData->scripts.erase(
scriptData->scripts.begin() + i);
scriptData->scripts.erase(scriptData->scripts.begin() +
i);
break;
}
}
@ -323,7 +319,8 @@ void ScriptsTool::on_addScripts_clicked()
scriptData->scripts.emplace_back(script);
QListWidgetItem *item = new QListWidgetItem(script_file);
QListWidgetItem *item =
new QListWidgetItem(script_file);
item->setData(Qt::UserRole, QString(file));
ui->scripts->addItem(item);
@ -343,8 +340,10 @@ void ScriptsTool::on_removeScripts_clicked()
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
for (QListWidgetItem *item : items)
RemoveScript(item->data(Qt::UserRole).toString()
.toUtf8().constData());
RemoveScript(item->data(Qt::UserRole)
.toString()
.toUtf8()
.constData());
RefreshLists();
}
@ -352,8 +351,10 @@ void ScriptsTool::on_reloadScripts_clicked()
{
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
for (QListWidgetItem *item : items)
ReloadScript(item->data(Qt::UserRole).toString()
.toUtf8().constData());
ReloadScript(item->data(Qt::UserRole)
.toString()
.toUtf8()
.constData());
on_scripts_currentRowChanged(ui->scripts->currentRow());
}
@ -368,9 +369,7 @@ void ScriptsTool::on_pythonPathBrowse_clicked()
{
QString curPath = ui->pythonPath->text();
QString newPath = QFileDialog::getExistingDirectory(
this,
ui->pythonPathLabel->text(),
curPath);
this, ui->pythonPathLabel->text(), curPath);
if (newPath.isEmpty())
return;
@ -406,14 +405,14 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
if (row == -1) {
propertiesView = new QWidget();
propertiesView->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
QSizePolicy::Expanding);
ui->propertiesLayout->addWidget(propertiesView);
ui->description->setText(QString());
return;
}
QByteArray array = ui->scripts->item(row)->data(Qt::UserRole)
.toString().toUtf8();
QByteArray array =
ui->scripts->item(row)->data(Qt::UserRole).toString().toUtf8();
const char *path = array.constData();
obs_script_t *script = scriptData->FindScript(path);
@ -425,9 +424,10 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
OBSData settings = obs_script_get_settings(script);
obs_data_release(settings);
propertiesView = new OBSPropertiesView(settings, script,
(PropertiesReloadCallback)obs_script_get_properties,
(PropertiesUpdateCallback)obs_script_update);
propertiesView = new OBSPropertiesView(
settings, script,
(PropertiesReloadCallback)obs_script_get_properties,
(PropertiesUpdateCallback)obs_script_update);
ui->propertiesLayout->addWidget(propertiesView);
ui->description->setText(obs_script_get_description(script));
}
@ -457,8 +457,7 @@ static void obs_event(enum obs_frontend_event event, void *)
static void load_script_data(obs_data_t *load_data, bool, void *)
{
obs_data_array_t *array = obs_data_get_array(load_data,
"scripts-tool");
obs_data_array_t *array = obs_data_get_array(load_data, "scripts-tool");
delete scriptData;
scriptData = new ScriptData;
@ -509,21 +508,19 @@ static void save_script_data(obs_data_t *save_data, bool saving, void *)
}
static void script_log(void *, obs_script_t *script, int log_level,
const char *message)
const char *message)
{
QString qmsg;
if (script) {
qmsg = QStringLiteral("[%1] %2").arg(
obs_script_get_file(script),
message);
obs_script_get_file(script), message);
} else {
qmsg = QStringLiteral("[Unknown Script] %1").arg(message);
}
QMetaObject::invokeMethod(scriptLogWindow, "AddLogMsg",
Q_ARG(int, log_level),
Q_ARG(QString, qmsg));
Q_ARG(int, log_level), Q_ARG(QString, qmsg));
}
extern "C" void InitScripts()
@ -533,13 +530,13 @@ extern "C" void InitScripts()
obs_scripting_load();
obs_scripting_set_log_callback(script_log, nullptr);
QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction(
obs_module_text("Scripts"));
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
obs_module_text("Scripts"));
#if PYTHON_UI
config_t *config = obs_frontend_get_global_config();
const char *python_path = config_get_string(config, "Python",
"Path" ARCH_NAME);
const char *python_path =
config_get_string(config, "Python", "Path" ARCH_NAME);
if (!obs_scripting_python_loaded() && python_path && *python_path)
obs_scripting_load_python(python_path);
@ -547,8 +544,7 @@ extern "C" void InitScripts()
scriptData = new ScriptData;
auto cb = [] ()
{
auto cb = []() {
obs_frontend_push_ui_translation(obs_module_get_string);
if (!scriptsWindow) {