Projects
Multimedia
obs-studio
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 97
View file
obs-studio.changes
Changed
@@ -1,4 +1,29 @@ ------------------------------------------------------------------- +Sat Oct 22 09:19:53 UTC 2022 - hpj@urpla.net + +- Update to version 28.0.3: + * win-wasapi: Fix Stop hang + * frontend-tools: Display dialog when changing Python version + * frontend-tools: Display Python version in UI + * UI: Fix AutoRemux not working when FFmpeg output configured + * win-wasapi: Don't reconnect when inactive + * libobs: Update version to 28.0.3 + * obs-scripting: Fix compile when python is not found + * obs-ffmpeg: Fix unpause causing certain encoders to fail + * libobs: Add function to get encoder pause offset + * UI: Don't reselect SceneTree items if tree is clearing + * UI: Remove executable bit from public key file + * obs-ffmpeg: Fix m3u8 recording in AMF + * linux-pipewire: Close sessions as we are done with them + * libobs/media-io: Restore color range conversion + * CI: Downgrade Sphinx to fix docs build error + * libobs/media-io: Avoid scaler for range diff + * linux-capture: Fixup window name/class checking + * obs-ffmpeg: Cap AMF encoder at 100 Mbps + * UI: Fix color of popout icon + * UI: Fix dock titlebar icons not loading + +------------------------------------------------------------------- Sat Sep 24 16:13:45 UTC 2022 - Hans-Peter Jansen <hpj@urpla.net> - Disable cef for other than x86_64 archs
View file
obs-studio.spec
Changed
@@ -8,7 +8,7 @@ %endif Name: obs-studio -Version: 28.0.2 +Version: 28.0.3 Release: 0 Summary: A recording/broadcasting program Group: Productivity/Multimedia/Video/Editors and Convertors
View file
_service
Changed
@@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> <param name="versionformat">@PARENT_TAG@</param> - <param name="revision">refs/tags/28.0.2</param> + <param name="revision">refs/tags/28.0.3</param> <param name="url">https://github.com/obsproject/obs-studio.git</param> <param name="scm">git</param> <param name="changesgenerate">enable</param>
View file
_servicedata
Changed
@@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/obsproject/obs-studio.git</param> - <param name="changesrevision">087ee39e2d8b9240b2ada1492fc7ad85102084ab</param> + <param name="changesrevision">d21891b3ca1a8607de479687cd2e12a4455525d7</param> </service> </servicedata> \ No newline at end of file
View file
obs-studio-28.0.2.tar.xz/.github/workflows/docs.yml -> obs-studio-28.0.3.tar.xz/.github/workflows/docs.yml
Changed
@@ -42,6 +42,7 @@ build_only: True target_branch: 'master' target_path: '../home/_build' + pre_build_commands: 'pip install -Iv sphinx==5.1.1' - uses: actions/upload-artifact@v3 with: name: OBS Studio Documentation (HTML)
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Acri.qss -> obs-studio-28.0.3.tar.xz/UI/data/themes/Acri.qss
Changed
@@ -300,8 +300,8 @@ font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/Close.svg'); - titlebar-normal-icon: url('./Dark/Popout.svg'); + titlebar-close-icon: url('./Dark/close.svg'); + titlebar-normal-icon: url('./Dark/popout.svg'); } QDockWidget::title {
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Grey.qss -> obs-studio-28.0.3.tar.xz/UI/data/themes/Grey.qss
Changed
@@ -300,8 +300,8 @@ font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/Close.svg'); - titlebar-normal-icon: url('./Dark/Popout.svg'); + titlebar-close-icon: url('./Dark/close.svg'); + titlebar-normal-icon: url('./Dark/popout.svg'); } QDockWidget::title {
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Light.qss -> obs-studio-28.0.3.tar.xz/UI/data/themes/Light.qss
Changed
@@ -300,8 +300,8 @@ font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Light/Close.svg'); - titlebar-normal-icon: url('./Light/Popout.svg'); + titlebar-close-icon: url('./Light/close.svg'); + titlebar-normal-icon: url('./Light/popout.svg'); } QDockWidget::title {
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Light/popout.svg -> obs-studio-28.0.3.tar.xz/UI/data/themes/Light/popout.svg
Changed
@@ -1,1 +1,1 @@ -<svg class="feather feather-plus" fill="none" stroke="#FFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="24" height="20" /><rect x="2" y="2" width="24" height="4" style="fill:#fff" /><rect x="14" y="18" width="24" height="20" /><rect x="14" y="18" width="24" height="4" style="fill:#fff" /></svg> +<svg class="feather feather-plus" fill="none" stroke="#202020" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" version="1.1" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="24" height="20" /><rect x="2" y="2" width="24" height="4" style="fill:#202020" /><rect x="14" y="18" width="24" height="20" /><rect x="14" y="18" width="24" height="4" style="fill:#202020" /></svg>
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Rachni.qss -> obs-studio-28.0.3.tar.xz/UI/data/themes/Rachni.qss
Changed
@@ -302,8 +302,8 @@ font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/Close.svg'); - titlebar-normal-icon: url('./Dark/Popout.svg'); + titlebar-close-icon: url('./Dark/close.svg'); + titlebar-normal-icon: url('./Dark/popout.svg'); } QDockWidget::title {
View file
obs-studio-28.0.2.tar.xz/UI/data/themes/Yami.qss -> obs-studio-28.0.3.tar.xz/UI/data/themes/Yami.qss
Changed
@@ -304,8 +304,8 @@ font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/Close.svg'); - titlebar-normal-icon: url('./Dark/Popout.svg'); + titlebar-close-icon: url('./Dark/close.svg'); + titlebar-normal-icon: url('./Dark/popout.svg'); } QDockWidget::title {
View file
obs-studio-28.0.2.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini -> obs-studio-28.0.3.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini
Changed
@@ -39,6 +39,10 @@ PythonSettings.PythonInstallPath32bit="Python Install Path (32bit)" PythonSettings.PythonInstallPath64bit="Python Install Path (64bit)" PythonSettings.BrowsePythonPath="Browse Python Path" +PythonSettings.PythonVersion="Loaded Python Version: %1" +PythonSettings.PythonNotLoaded="Python not currently loaded" +PythonSettings.AlreadyLoaded.Title="Python Already Loaded" +PythonSettings.AlreadyLoaded.Message="A copy of Python %1 is already loaded. To load the newly selected Python version, please restart OBS." ScriptLogWindow="Script Log" Description="Description" ScriptDescriptionLink.Text="Open this link in your default web browser?"
View file
obs-studio-28.0.2.tar.xz/UI/frontend-plugins/frontend-tools/forms/scripts.ui -> obs-studio-28.0.3.tar.xz/UI/frontend-plugins/frontend-tools/forms/scripts.ui
Changed
@@ -269,6 +269,13 @@ </layout> </item> <item> + <widget class="QLabel" name="pythonVersionLabel"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum>
View file
obs-studio-28.0.2.tar.xz/UI/frontend-plugins/frontend-tools/scripts.cpp -> obs-studio-28.0.3.tar.xz/UI/frontend-plugins/frontend-tools/scripts.cpp
Changed
@@ -194,6 +194,7 @@ config_get_string(config, "Python", "Path" ARCH_NAME); ui->pythonPath->setText(path); ui->pythonPathLabel->setText(obs_module_text(PYTHONPATH_LABEL_TEXT)); + updatePythonVersionLabel(); #else delete ui->pythonSettingsTab; ui->pythonSettingsTab = nullptr; @@ -219,6 +220,20 @@ ui->scripts->currentRow()); } +void ScriptsTool::updatePythonVersionLabel() +{ + QString label; + if (obs_scripting_python_loaded()) { + char version8; + obs_scripting_python_version(version, sizeof(version)); + label = QString(obs_module_text("PythonSettings.PythonVersion")) + .arg(version); + } else { + label = obs_module_text("PythonSettings.PythonNotLoaded"); + } + ui->pythonVersionLabel->setText(label); +} + void ScriptsTool::RemoveScript(const char *path) { for (size_t i = 0; i < scriptData->scripts.size(); i++) { @@ -455,11 +470,29 @@ ui->pythonPath->setText(newPath); - if (obs_scripting_python_loaded()) + bool loaded = obs_scripting_python_loaded(); + + if (loaded && !newPath.isEmpty() && curPath.compare(newPath) != 0) { + char version8; + obs_scripting_python_version(version, sizeof(version)); + QString message = + QString(obs_module_text( + "PythonSettings.AlreadyLoaded.Message")) + .arg(version); + OBSMessageBox::information( + this, + obs_module_text("PythonSettings.AlreadyLoaded.Title"), + message); return; + } else if (loaded) { + return; + } + if (!obs_scripting_load_python(path)) return; + updatePythonVersionLabel(); + for (OBSScript &script : scriptData->scripts) { enum obs_script_lang lang = obs_script_get_lang(script); if (lang == OBS_SCRIPT_LANG_PYTHON) {
View file
obs-studio-28.0.2.tar.xz/UI/frontend-plugins/frontend-tools/scripts.hpp -> obs-studio-28.0.3.tar.xz/UI/frontend-plugins/frontend-tools/scripts.hpp
Changed
@@ -31,6 +31,8 @@ std::unique_ptr<Ui_ScriptsTool> ui; QWidget *propertiesView = nullptr; + void updatePythonVersionLabel(); + public: ScriptsTool(); ~ScriptsTool();
View file
obs-studio-28.0.2.tar.xz/UI/item-widget-helpers.cpp -> obs-studio-28.0.3.tar.xz/UI/item-widget-helpers.cpp
Changed
@@ -37,10 +37,14 @@ void ClearListItems(QListWidget *widget) { + // Workaround for the SceneTree workaround for QTBUG-105870 + widget->setProperty("clearing", true); + widget->setCurrentItem(nullptr, QItemSelectionModel::Clear); for (int i = 0; i < widget->count(); i++) delete widget->itemWidget(widget->item(i)); widget->clear(); + widget->setProperty("clearing", false); }
View file
obs-studio-28.0.2.tar.xz/UI/scene-tree.cpp -> obs-studio-28.0.3.tar.xz/UI/scene-tree.cpp
Changed
@@ -252,6 +252,7 @@ void SceneTree::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { - if (selected.count() == 0 && deselected.count() > 0) + if (selected.count() == 0 && deselected.count() > 0 && + !property("clearing").toBool()) setCurrentRow(deselected.indexes().front().row()); }
View file
obs-studio-28.0.2.tar.xz/UI/window-basic-main.cpp -> obs-studio-28.0.3.tar.xz/UI/window-basic-main.cpp
Changed
@@ -7122,17 +7122,31 @@ void OBSBasic::AutoRemux(QString input, bool no_show) { - bool autoRemux = config_get_bool(Config(), "Video", "AutoRemux"); + auto config = Config(); + + bool autoRemux = config_get_bool(config, "Video", "AutoRemux"); if (!autoRemux) return; - const char *recType = config_get_string(Config(), "AdvOut", "RecType"); - - bool ffmpegOutput = astrcmpi(recType, "FFmpeg") == 0; + bool isSimpleMode = false; - if (ffmpegOutput) - return; + const char *mode = config_get_string(config, "Output", "Mode"); + if (!mode) { + isSimpleMode = true; + } else { + isSimpleMode = strcmp(mode, "Simple") == 0; + } + + if (!isSimpleMode) { + const char *recType = + config_get_string(config, "AdvOut", "RecType"); + + bool ffmpegOutput = astrcmpi(recType, "FFmpeg") == 0; + + if (ffmpegOutput) + return; + } if (input.isEmpty()) return;
View file
obs-studio-28.0.2.tar.xz/deps/obs-scripting/obs-scripting-python.c -> obs-studio-28.0.3.tar.xz/deps/obs-scripting/obs-scripting-python.c
Changed
@@ -1590,6 +1590,17 @@ return (bool)RUNTIME_LINK; } +void obs_scripting_python_version(char *version, size_t version_length) +{ +#if RUNTIME_LINK + snprintf(version, version_length, "%d.%d", python_version.major, + python_version.minor); +#else + snprintf(version, version_length, "%d.%d", PY_MAJOR_VERSION, + PY_MINOR_VERSION); +#endif +} + bool obs_scripting_python_loaded(void) { return python_loaded;
View file
obs-studio-28.0.2.tar.xz/deps/obs-scripting/obs-scripting.c -> obs-studio-28.0.3.tar.xz/deps/obs-scripting/obs-scripting.c
Changed
@@ -458,4 +458,9 @@ { return (bool)true; } + +void obs_scripting_python_version(char *version, size_t version_length) +{ + version0 = 0; +} #endif
View file
obs-studio-28.0.2.tar.xz/deps/obs-scripting/obs-scripting.h -> obs-studio-28.0.3.tar.xz/deps/obs-scripting/obs-scripting.h
Changed
@@ -46,6 +46,7 @@ void *param); EXPORT bool obs_scripting_python_runtime_linked(void); +EXPORT void obs_scripting_python_version(char *version, size_t version_length); EXPORT bool obs_scripting_python_loaded(void); EXPORT bool obs_scripting_load_python(const char *python_path);
View file
obs-studio-28.0.2.tar.xz/libobs/media-io/video-scaler-ffmpeg.c -> obs-studio-28.0.3.tar.xz/libobs/media-io/video-scaler-ffmpeg.c
Changed
@@ -19,6 +19,7 @@ #include "video-scaler.h" #include <libavutil/imgutils.h> +#include <libavutil/opt.h> #include <libswscale/swscale.h> struct video_scaler { @@ -188,16 +189,27 @@ goto fail; } - scaler->swscale = sws_getCachedContext(NULL, src->width, src->height, - format_src, dst->width, - dst->height, format_dst, - scale_type, NULL, NULL, NULL); + scaler->swscale = sws_alloc_context(); if (!scaler->swscale) { blog(LOG_ERROR, "video_scaler_create: Could not create " "swscale"); goto fail; } + av_opt_set_int(scaler->swscale, "sws_flags", scale_type, 0); + av_opt_set_int(scaler->swscale, "srcw", src->width, 0); + av_opt_set_int(scaler->swscale, "srch", src->height, 0); + av_opt_set_int(scaler->swscale, "dstw", dst->width, 0); + av_opt_set_int(scaler->swscale, "dsth", dst->height, 0); + av_opt_set_int(scaler->swscale, "src_format", format_src, 0); + av_opt_set_int(scaler->swscale, "dst_format", format_dst, 0); + av_opt_set_int(scaler->swscale, "src_range", range_src, 0); + av_opt_set_int(scaler->swscale, "dst_range", range_dst, 0); + if (sws_init_context(scaler->swscale, NULL, NULL) < 0) { + blog(LOG_ERROR, "video_scaler_create: sws_init_context failed"); + goto fail; + } + ret = sws_setColorspaceDetails(scaler->swscale, coeff_src, range_src, coeff_dst, range_dst, 0, FIXED_1_0, FIXED_1_0);
View file
obs-studio-28.0.2.tar.xz/libobs/obs-config.h -> obs-studio-28.0.3.tar.xz/libobs/obs-config.h
Changed
@@ -41,7 +41,7 @@ * * Reset to zero each major or minor version */ -#define LIBOBS_API_PATCH_VER 2 +#define LIBOBS_API_PATCH_VER 3 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | patch)
View file
obs-studio-28.0.2.tar.xz/libobs/obs-encoder.c -> obs-studio-28.0.3.tar.xz/libobs/obs-encoder.c
Changed
@@ -1534,3 +1534,8 @@ else encoder->last_error_message = NULL; } + +uint64_t obs_encoder_get_pause_offset(const obs_encoder_t *encoder) +{ + return encoder ? encoder->pause.ts_offset : 0; +}
View file
obs-studio-28.0.2.tar.xz/libobs/obs.h -> obs-studio-28.0.3.tar.xz/libobs/obs.h
Changed
@@ -2413,6 +2413,8 @@ EXPORT void obs_encoder_set_last_error(obs_encoder_t *encoder, const char *message); +EXPORT uint64_t obs_encoder_get_pause_offset(const obs_encoder_t *encoder); + /* ------------------------------------------------------------------------- */ /* Stream Services */
View file
obs-studio-28.0.2.tar.xz/plugins/linux-capture/xcomposite-input.c -> obs-studio-28.0.3.tar.xz/plugins/linux-capture/xcomposite-input.c
Changed
@@ -310,11 +310,10 @@ char *wcls = bzalloc(strEnd - thirdStr + 1); memcpy(wname, secondStr, secondMark - secondStr); memcpy(wcls, thirdStr, strEnd - thirdStr); - xcb_window_t wid = (xcb_window_t)strtol(str, NULL, 10); + ret = (xcb_window_t)strtol(str, NULL, 10); // first try to find a match by the window-id - if (da_find(tlw, &wid, 0) != DARRAY_INVALID) { - ret = wid; + if (da_find(tlw, &ret, 0) != DARRAY_INVALID) { goto cleanup2; } @@ -325,8 +324,8 @@ struct dstr cwname = xcomp_window_name(conn, disp, cwin); struct dstr cwcls = xcomp_window_class(conn, cwin); - bool found = (strcmp(wname, cwname.array) == 0 && - strcmp(wcls, cwcls.array)); + bool found = strcmp(wname, cwname.array) == 0 && + strcmp(wcls, cwcls.array) == 0; dstr_free(&cwname); dstr_free(&cwcls); @@ -345,7 +344,7 @@ bfree(wcls); cleanup1: da_free(tlw); - return wid; + return ret; } void xcomp_cleanup_pixmap(Display *disp, struct xcompcap *s)
View file
obs-studio-28.0.2.tar.xz/plugins/linux-pipewire/screencast-portal.c -> obs-studio-28.0.3.tar.xz/plugins/linux-pipewire/screencast-portal.c
Changed
@@ -627,6 +627,20 @@ g_clear_pointer(&capture->restore_token, bfree); g_clear_pointer(&capture->obs_pw, obs_pipewire_destroy); + if (capture->session_handle) { + blog(LOG_DEBUG, "pipewire Cleaning previous session %s", + capture->session_handle); + g_dbus_connection_call(portal_get_dbus_connection(), + "org.freedesktop.portal.Desktop", + capture->session_handle, + "org.freedesktop.portal.Session", + "Close", NULL, NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, + NULL); + + g_clear_pointer(&capture->session_handle, g_free); + } + init_screencast_capture(capture); return false;
View file
obs-studio-28.0.2.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c -> obs-studio-28.0.3.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c
Changed
@@ -375,18 +375,33 @@ stream->found_audiopacket->track_idx = true; } -static bool ffmpeg_mux_start(void *data) +static inline void update_encoder_settings(struct ffmpeg_muxer *stream, + const char *path) { - struct ffmpeg_muxer *stream = data; - obs_data_t *settings; - const char *path; + obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output); + const char *ext = strrchr(path, '.'); + + /* if using m3u8, repeat headers */ + if (ext && strcmp(ext, ".m3u8") == 0) { + obs_data_t *settings = obs_encoder_get_settings(vencoder); + obs_data_set_bool(settings, "repeat_headers", true); + obs_encoder_update(vencoder, settings); + obs_data_release(settings); + } +} + +static inline bool ffmpeg_mux_start_internal(struct ffmpeg_muxer *stream, + obs_data_t *settings) +{ + const char *path = obs_data_get_string(settings, "path"); + + update_encoder_settings(stream, path); if (!obs_output_can_begin_data_capture(stream->output, 0)) return false; if (!obs_output_initialize_encoders(stream->output, 0)) return false; - settings = obs_output_get_settings(stream->output); if (stream->is_network) { obs_service_t *service; service = obs_output_get_service(stream->output); @@ -395,7 +410,6 @@ path = obs_service_get_url(service); stream->split_file = false; } else { - path = obs_data_get_string(settings, "path"); stream->max_time = obs_data_get_int(settings, "max_time_sec") * 1000000LL; @@ -427,7 +441,6 @@ } start_pipe(stream, path); - obs_data_release(settings); if (!stream->pipe) { obs_output_set_last_error( @@ -446,6 +459,17 @@ return true; } +static bool ffmpeg_mux_start(void *data) +{ + struct ffmpeg_muxer *stream = data; + + obs_data_t *settings = obs_output_get_settings(stream->output); + bool success = ffmpeg_mux_start_internal(stream, settings); + obs_data_release(settings); + + return success; +} + int deactivate(struct ffmpeg_muxer *stream, int code) { int ret = -1;
View file
obs-studio-28.0.2.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-video-encoders.c -> obs-studio-28.0.3.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-video-encoders.c
Changed
@@ -221,6 +221,8 @@ AVPacket av_pkt = {0}; bool timeout = false; const int64_t cur_ts = (int64_t)os_gettime_ns(); + const int64_t pause_offset = + (int64_t)obs_encoder_get_pause_offset(enc->encoder); int got_packet; int ret; @@ -270,7 +272,7 @@ debug("cur: %lld, packet: %lld, diff: %lld", cur_ts, recv_ts_nsec, cur_ts - recv_ts_nsec); #endif - if ((cur_ts - recv_ts_nsec) > TIMEOUT_MAX_NSEC) { + if ((cur_ts - recv_ts_nsec - pause_offset) > TIMEOUT_MAX_NSEC) { char timeout_str16; snprintf(timeout_str, sizeof(timeout_str), "%d", TIMEOUT_MAX_SEC);
View file
obs-studio-28.0.2.tar.xz/plugins/obs-ffmpeg/texture-amf.cpp -> obs-studio-28.0.3.tar.xz/plugins/obs-ffmpeg/texture-amf.cpp
Changed
@@ -964,7 +964,7 @@ obs_property_set_modified_callback(p, rate_control_modified); p = obs_properties_add_int(props, "bitrate", obs_module_text("Bitrate"), - 50, 300000, 50); + 50, 100000, 50); obs_property_int_set_suffix(p, " Kbps"); obs_properties_add_int(props, "cqp", obs_module_text("NVENC.CQLevel"), @@ -1158,6 +1158,11 @@ : 250; set_avc_property(enc, IDR_PERIOD, gop_size); + + bool repeat_headers = obs_data_get_bool(settings, "repeat_headers"); + if (repeat_headers) + set_avc_property(enc, HEADER_INSERTION_SPACING, gop_size); + set_avc_property(enc, DE_BLOCKING_FILTER, true); const char *ffmpeg_opts = obs_data_get_string(settings, "ffmpeg_opts");
View file
obs-studio-28.0.2.tar.xz/plugins/win-wasapi/win-wasapi.cpp -> obs-studio-28.0.3.tar.xz/plugins/win-wasapi/win-wasapi.cpp
Changed
@@ -182,7 +182,7 @@ std::atomic<bool> isDefaultDevice = false; bool previouslyFailed = false; - WinHandle reconnectThread; + WinHandle reconnectThread = NULL; class CallbackStartCapture : public ARtwqAsyncCallback { public: @@ -238,6 +238,7 @@ WinHandle stopSignal; WinHandle receiveSignal; WinHandle restartSignal; + WinHandle reconnectExitSignal; WinHandle exitSignal; WinHandle initSignal; DWORD reconnectDuration = 0; @@ -298,6 +299,9 @@ void Update(obs_data_t *settings); void OnWindowChanged(obs_data_t *settings); + void Activate(); + void Deactivate(); + void SetDefaultDevice(EDataFlow flow, ERole role, LPCWSTR id); void OnStartCapture(); @@ -390,6 +394,10 @@ if (!restartSignal.Valid()) throw "Could not create restart signal"; + reconnectExitSignal = CreateEvent(nullptr, true, false, nullptr); + if (!reconnectExitSignal.Valid()) + throw "Could not create reconnect exit signal"; + exitSignal = CreateEvent(nullptr, true, false, nullptr); if (!exitSignal.Valid()) throw "Could not create exit signal"; @@ -402,11 +410,6 @@ if (!reconnectSignal.Valid()) throw "Could not create reconnect signal"; - reconnectThread = CreateThread( - nullptr, 0, WASAPISource::ReconnectThread, this, 0, nullptr); - if (!reconnectThread.Valid()) - throw "Failed to create reconnect thread"; - notify = new WASAPINotify(this); if (!notify) throw "Could not create WASAPINotify"; @@ -532,11 +535,19 @@ if (rtwq_supported) SetEvent(receiveSignal); - WaitForSingleObject(idleSignal, INFINITE); + if (reconnectThread.Valid()) { + WaitForSingleObject(idleSignal, INFINITE); + } else { + const HANDLE sigs = {reconnectSignal, idleSignal}; + WaitForMultipleObjects(_countof(sigs), sigs, false, INFINITE); + } SetEvent(exitSignal); - WaitForSingleObject(reconnectThread, INFINITE); + if (reconnectThread.Valid()) { + SetEvent(reconnectExitSignal); + WaitForSingleObject(reconnectThread, INFINITE); + } if (rtwq_supported) rtwq_unlock_work_queue(sampleReady.GetQueueId()); @@ -657,6 +668,25 @@ SetEvent(restartSignal); } +void WASAPISource::Activate() +{ + if (!reconnectThread.Valid()) { + ResetEvent(reconnectExitSignal); + reconnectThread = CreateThread(nullptr, 0, + WASAPISource::ReconnectThread, + this, 0, nullptr); + } +} + +void WASAPISource::Deactivate() +{ + if (reconnectThread.Valid()) { + SetEvent(reconnectExitSignal); + WaitForSingleObject(reconnectThread, INFINITE); + reconnectThread = NULL; + } +} + ComPtr<IMMDevice> WASAPISource::InitDevice(IMMDeviceEnumerator *enumerator, bool isDefaultDevice, SourceType type, @@ -1005,10 +1035,15 @@ WASAPISource *source = (WASAPISource *)param; const HANDLE sigs = { - source->exitSignal, + source->reconnectExitSignal, source->reconnectSignal, }; + const HANDLE reconnect_sigs = { + source->reconnectExitSignal, + source->stopSignal, + }; + bool exit = false; while (!exit) { const DWORD ret = WaitForMultipleObjects(_countof(sigs), sigs, @@ -1020,8 +1055,10 @@ default: assert(ret == (WAIT_OBJECT_0 + 1)); if (source->reconnectDuration > 0) { - WaitForSingleObject(source->stopSignal, - source->reconnectDuration); + WaitForMultipleObjects( + _countof(reconnect_sigs), + reconnect_sigs, false, + source->reconnectDuration); } source->Start(); } @@ -1426,6 +1463,16 @@ static_cast<WASAPISource *>(obj)->Update(settings); } +static void ActivateWASAPISource(void *obj) +{ + static_cast<WASAPISource *>(obj)->Activate(); +} + +static void DeactivateWASAPISource(void *obj) +{ + static_cast<WASAPISource *>(obj)->Deactivate(); +} + static bool UpdateWASAPIMethod(obs_properties_t *props, obs_property_t *, obs_data_t *settings) { @@ -1542,6 +1589,8 @@ info.create = CreateWASAPIInput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsInput; info.get_properties = GetWASAPIPropertiesInput; info.icon_type = OBS_ICON_TYPE_AUDIO_INPUT; @@ -1559,6 +1608,8 @@ info.create = CreateWASAPIDeviceOutput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsDeviceOutput; info.get_properties = GetWASAPIPropertiesDeviceOutput; info.icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT; @@ -1576,6 +1627,8 @@ info.create = CreateWASAPIProcessOutput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsProcessOutput; info.get_properties = GetWASAPIPropertiesProcessOutput; info.icon_type = OBS_ICON_TYPE_PROCESS_AUDIO_OUTPUT;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.