From 6fc36194732c85b528a5472376d6ce0270519c36 Mon Sep 17 00:00:00 2001 From: Vainock Date: Wed, 3 May 2023 09:17:23 +0200 Subject: [PATCH 01/93] UI: Fix case inconsistency in translation key [skip crowdin-sync] (cherry picked from commit e23b80151b37f1a7159ebc621c12ac9d38917aea) --- UI/data/locale/en-US.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 4c03aa7db..9b6436dc2 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -1147,7 +1147,7 @@ Basic.Settings.Audio.MeterDecayRate.Slow="Slow (Type II PPM)" Basic.Settings.Audio.PeakMeterType="Peak Meter Type" Basic.Settings.Audio.PeakMeterType.SamplePeak="Sample Peak" Basic.Settings.Audio.PeakMeterType.TruePeak="True Peak (Higher CPU usage)" -Basic.Settings.Audio.MultiChannelWarning.Enabled="WARNING: Surround sound audio is enabled." +Basic.Settings.Audio.MultichannelWarning.Enabled="WARNING: Surround sound audio is enabled." Basic.Settings.Audio.MultichannelWarning="If streaming, check to see if your streaming service supports both surround sound ingest and surround sound playback. Facebook 360 Live is one example where surround sound is fully supported. Although Facebook Live and YouTube Live both accept surround ingest, Facebook Live downmixes to stereo, and YouTube Live plays only two channels.\n\nOBS audio filters are compatible with surround sound, though VST plugin support isn't guaranteed." Basic.Settings.Audio.MultichannelWarning.Title="Enable surround sound audio?" Basic.Settings.Audio.MultichannelWarning.Confirm="Are you sure you want to enable surround sound audio?" From 2e04c3619b63a44be89d79c21a2f3faf4b89b84c Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Wed, 3 May 2023 01:50:47 +0200 Subject: [PATCH 02/93] UI: Relax mc_trans_video_imagescaler.dll DLL block This is actually a MainConcept redistributable and not related to Adobe. Unfortunately Elgato Game Capture HD software relies on this dependency when presenting the DirectShow device to OBS, so we unintentionally blocked it from loading. Instead of outright blocking, we now block only older versions than the version shipped by Elgato, which has hopefully been patched to fix the random crashes. (cherry picked from commit 132f0b85fc92f785a3da3ee1be9aecfab219c64d) --- UI/win-dll-blocklist.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UI/win-dll-blocklist.c b/UI/win-dll-blocklist.c index 9ed19cab6..4cba6d932 100644 --- a/UI/win-dll-blocklist.c +++ b/UI/win-dll-blocklist.c @@ -124,8 +124,9 @@ static blocked_module_t blocked_modules[] = { // Wacom / Other tablet driver, locks up UI {L"\\wintab32.dll", 0, 0, TS_IGNORE}, - // Adobe Dynamic Link (Adobe CC), crashes in its own thread - {L"\\mc_trans_video_imagescaler.dll", 0, 0, TS_IGNORE}, + // MainConcept Image Scaler, crashes in its own thread. Block versions + // older than the one Elgato uses (2016-02-15). + {L"\\mc_trans_video_imagescaler.dll", 0, 1455495131, TS_LESS_THAN}, // Weird Polish banking "security" software, breaks UI {L"\\wslbscr64.dll", 0, 0, TS_IGNORE}, From a0f10048fa9f78ea5d113cfd6ef0f9a771d8cb85 Mon Sep 17 00:00:00 2001 From: derrod Date: Fri, 5 May 2023 12:51:24 +0200 Subject: [PATCH 03/93] UI: Fix FLAC missing from builtin codecs list (cherry picked from commit 0c0ec90eac804c99669d9ff835bbef3c843558e0) --- UI/window-basic-settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 643aa0eac..10aa5559b 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -4980,8 +4980,8 @@ void OBSBasicSettings::AdvOutSplitFileChanged() } static const unordered_set builtin_codecs = { - "h264", "hevc", "av1", "prores", "aac", - "opus", "alac", "pcm_s16le", "pcm_s24le", "pcm_f32le"}; + "h264", "hevc", "av1", "prores", "aac", "opus", + "alac", "flac", "pcm_s16le", "pcm_s24le", "pcm_f32le"}; static const unordered_map> codec_compat = { // Technically our muxer supports HEVC and AV1 as well, but nothing else does From b9a95b2f5fb9e156a0a6d4390e402bd7026861ea Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Thu, 4 May 2023 21:53:55 +0200 Subject: [PATCH 04/93] obs-ffmpeg: Show error if trying to use AV1 fallback (cherry picked from commit ba0c2738465c71326b7595083756d7decd3609b3) --- plugins/obs-ffmpeg/data/locale/en-US.ini | 1 + plugins/obs-ffmpeg/jim-nvenc.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/plugins/obs-ffmpeg/data/locale/en-US.ini b/plugins/obs-ffmpeg/data/locale/en-US.ini index 0646c5f10..b6b144c15 100644 --- a/plugins/obs-ffmpeg/data/locale/en-US.ini +++ b/plugins/obs-ffmpeg/data/locale/en-US.ini @@ -36,6 +36,7 @@ NVENC.I010Unsupported="NVENC does not support I010. Use P010 instead." NVENC.10bitUnsupported="Cannot perform 10-bit encode on this encoder." NVENC.16bitUnsupported="Cannot perform 16-bit encode on this encoder." NVENC.TooManyBFrames="Max B-frames setting (%d) is more than encoder supports (%d)." +NVENC.NoAV1FallbackPossible="AV1 encoding is not available with the current settings. Try disabling any re-scaling or GPU options that may be set. Check the log for more details." NVENC.Preset2.p1="P1: Fastest (Lowest Quality)" NVENC.Preset2.p2="P2: Faster (Lower Quality)" NVENC.Preset2.p3="P3: Fast (Low Quality)" diff --git a/plugins/obs-ffmpeg/jim-nvenc.c b/plugins/obs-ffmpeg/jim-nvenc.c index 10a7dd185..ff67ab7e7 100644 --- a/plugins/obs-ffmpeg/jim-nvenc.c +++ b/plugins/obs-ffmpeg/jim-nvenc.c @@ -1165,6 +1165,11 @@ reroute: case CODEC_HEVC: return obs_encoder_create_rerouted(encoder, "ffmpeg_hevc_nvenc"); + case CODEC_AV1: + obs_encoder_set_last_error( + encoder, + obs_module_text("NVENC.NoAV1FallbackPossible")); + break; } return NULL; From ea826adee1bca16f75d9b401f317c44f1a9526d2 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 4 May 2023 11:07:52 +0200 Subject: [PATCH 05/93] cmake: Enforce -Wmaybe-uninitialized to never turn into an error (cherry picked from commit 12ad59f31fc3512f05367b2ffba8b7826f6edb88) --- cmake/Modules/CompilerConfig.cmake | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cmake/Modules/CompilerConfig.cmake b/cmake/Modules/CompilerConfig.cmake index 41c56da8b..849d19de7 100644 --- a/cmake/Modules/CompilerConfig.cmake +++ b/cmake/Modules/CompilerConfig.cmake @@ -100,6 +100,13 @@ else() endif() option(CALM_DEPRECATION "Keep deprecated-declarations as warnings" OFF) + #[[ + Note about -Wmaybe-uninitialized on GCC, this warning seems to be subject of various regressions and false positives. This + warning is set to not turn into an error. + + - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562 for 12.1.0 + - https://github.com/obsproject/obs-studio/issues/8850 for 13.1.1 + ]] add_compile_options( -Werror -Wextra @@ -117,19 +124,13 @@ else() "$<$:-DDEBUG=1;-D_DEBUG=1>" "$<$:-Wnull-conversion;-fcolor-diagnostics;-Wno-error=shorten-64-to-32>" "$<$:-Wnull-conversion;-fcolor-diagnostics;-Wno-error=shorten-64-to-32>" - "$<$:-Wconversion-null>" + "$<$:-Wconversion-null;-Wno-error=maybe-uninitialized>" + "$<$:-Wno-error=maybe-uninitialized>" "$<$:-Wno-error=deprecated-declarations>") - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # GCC on aarch64 emits type-limits warnings that do not appear on x86_64 - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") - add_compile_options(-Wno-error=type-limits) - endif() - - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562 - if(CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "12.1.0") - add_compile_options(-Wno-error=maybe-uninitialized) - endif() + # GCC on aarch64 emits type-limits warnings that do not appear on x86_64 + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + add_compile_options(-Wno-error=type-limits) endif() if(OBS_CODESIGN_LINKER) From 81e614cc4dad70251bbfe6f1495ba6582c35e0d6 Mon Sep 17 00:00:00 2001 From: derrod Date: Wed, 3 May 2023 15:46:40 +0200 Subject: [PATCH 06/93] UI: Do not show unassigned icon for monitored sources (cherry picked from commit 982c424de3adb6c5aeec2d837c641c7265020d85) --- UI/volume-control.cpp | 33 ++++++++++++++++++++++----------- UI/volume-control.hpp | 4 ++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/UI/volume-control.cpp b/UI/volume-control.cpp index c4741ab0b..0ec2288b5 100644 --- a/UI/volume-control.cpp +++ b/UI/volume-control.cpp @@ -37,8 +37,11 @@ static inline Qt::CheckState GetCheckState(bool muted, bool unassigned) static inline bool IsSourceUnassigned(obs_source_t *source) { - return (obs_source_get_audio_mixers(source) & - ((1 << MAX_AUDIO_MIXES) - 1)) == 0; + uint32_t mixes = (obs_source_get_audio_mixers(source) & + ((1 << MAX_AUDIO_MIXES) - 1)); + obs_monitoring_type mt = obs_source_get_monitoring_type(source); + + return mixes == 0 && mt != OBS_MONITORING_TYPE_MONITOR_ONLY; } static void ShowUnassignedWarning(const char *name) @@ -116,19 +119,19 @@ void VolControl::VolumeMuted(bool muted) volMeter->muted = muted || unassigned; } -void VolControl::OBSMixersChanged(void *data, calldata_t *calldata) +void VolControl::OBSMixersOrMonitoringChanged(void *data, calldata_t *) { - VolControl *volControl = static_cast(data); - bool unassigned = (calldata_int(calldata, "mixers") & - ((1 << MAX_AUDIO_MIXES) - 1)) == 0; - QMetaObject::invokeMethod(volControl, "AssignmentChanged", - Q_ARG(bool, unassigned)); + VolControl *volControl = static_cast(data); + QMetaObject::invokeMethod(volControl, "MixersOrMonitoringChanged", + Qt::QueuedConnection); } -void VolControl::AssignmentChanged(bool unassigned) +void VolControl::MixersOrMonitoringChanged() { bool muted = obs_source_muted(source); + bool unassigned = IsSourceUnassigned(source); + auto newState = GetCheckState(muted, unassigned); if (mute->checkState() != newState) mute->setCheckState(newState); @@ -377,7 +380,11 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical) signal_handler_connect(obs_source_get_signal_handler(source), "mute", OBSVolumeMuted, this); signal_handler_connect(obs_source_get_signal_handler(source), - "audio_mixers", OBSMixersChanged, this); + "audio_mixers", OBSMixersOrMonitoringChanged, + this); + signal_handler_connect(obs_source_get_signal_handler(source), + "audio_monitoring", OBSMixersOrMonitoringChanged, + this); QWidget::connect(slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChanged(int))); @@ -416,7 +423,11 @@ VolControl::~VolControl() signal_handler_disconnect(obs_source_get_signal_handler(source), "mute", OBSVolumeMuted, this); signal_handler_disconnect(obs_source_get_signal_handler(source), - "audio_mixers", OBSMixersChanged, this); + "audio_mixers", OBSMixersOrMonitoringChanged, + this); + signal_handler_disconnect(obs_source_get_signal_handler(source), + "audio_monitoring", + OBSMixersOrMonitoringChanged, this); obs_fader_destroy(obs_fader); obs_volmeter_destroy(obs_volmeter); diff --git a/UI/volume-control.hpp b/UI/volume-control.hpp index cb31bcb12..b8eaaac05 100644 --- a/UI/volume-control.hpp +++ b/UI/volume-control.hpp @@ -301,14 +301,14 @@ private: const float peak[MAX_AUDIO_CHANNELS], const float inputPeak[MAX_AUDIO_CHANNELS]); static void OBSVolumeMuted(void *data, calldata_t *calldata); - static void OBSMixersChanged(void *data, calldata_t *alldata); + static void OBSMixersOrMonitoringChanged(void *data, calldata_t *); void EmitConfigClicked(); private slots: void VolumeChanged(); void VolumeMuted(bool muted); - void AssignmentChanged(bool unassigned); + void MixersOrMonitoringChanged(); void SetMuted(bool checked); void SliderChanged(int vol); From a3c275c9da710813d0ef55f63b5f9a0be5dde3b0 Mon Sep 17 00:00:00 2001 From: PatTheMav Date: Mon, 1 May 2023 15:23:58 +0200 Subject: [PATCH 07/93] mac-capture: Fix possible division by zero error Possibility of `mChannelsPerFrame` being 0 is not properly covered by current code, which will result in a division-by-zero error. (cherry picked from commit f20f788d0b11f1938728d9c784ea030dc6ac0a3c) --- plugins/mac-capture/mac-screen-capture.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/mac-capture/mac-screen-capture.m b/plugins/mac-capture/mac-screen-capture.m index cc09437fa..cc3a5acc8 100644 --- a/plugins/mac-capture/mac-screen-capture.m +++ b/plugins/mac-capture/mac-screen-capture.m @@ -297,6 +297,13 @@ static inline void screen_stream_audio_update(struct screen_capture *sc, CMAudioFormatDescriptionGetStreamBasicDescription( format_description); + if (audio_description->mChannelsPerFrame < 1) { + MACCAP_ERR( + "screen_stream_audio_update: Received sample buffer has less than 1 channel per frame (mChannelsPerFrame set to '%d')\n", + audio_description->mChannelsPerFrame); + return; + } + char *_Nullable bytes = NULL; CMBlockBufferRef data_buffer = CMSampleBufferGetDataBuffer(sample_buffer); From cf2af3a5b4a0ee082ee24964334802194ed71297 Mon Sep 17 00:00:00 2001 From: PatTheMav Date: Mon, 1 May 2023 18:36:07 +0200 Subject: [PATCH 08/93] CI: Update ccache cache entries to enable restoration from master branch Current caching steps do not use a coarse restore key to enable cache restoration from a possible master cache. This is a forward-port of a future CI workflow update that uses the same cache key logic. Also fixes missing generator token for cache keys generated by master branch. (cherry picked from commit f1c7296ac25ed72c4758ae02c2da6a8d9842f196) --- .github/workflows/main.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 26da48b7e..dfccd902a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -106,10 +106,19 @@ jobs: - name: 'Check for GitHub Labels' id: github-check - if: github.event_name == 'pull_request' run: | - if test -n "$(curl -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')"; then - echo "generator=Xcode" >> $GITHUB_OUTPUT + if [[ "${GITHUB_EVENT_NAME}" == 'pull_request' ]]; then + if test -n "$(curl -H "Authorization: Bearer ${{ github.token }}" -s "${{ github.event.pull_request.url }}" | jq -e '.labels[] | select(.name == "Seeking Testers")')"; then + echo "generator=Xcode" >> $GITHUB_OUTPUT + else + echo "generator=Ninja" >> $GITHUB_OUTPUT + fi + elif [[ "${GITHUB_EVENT_NAME}" == 'push' ]]; then + if [[ ${GITHUB_REF_NAME} =~ [0-9]+.[0-9]+.[0-9]+(-(rc|beta).+)? ]]; then + echo "generator=Xcode" >> $GITHUB_OUTPUT + else + echo "generator=Ninja" >> $GITHUB_OUTPUT + fi else echo "generator=Ninja" >> $GITHUB_OUTPUT fi @@ -119,7 +128,9 @@ jobs: uses: actions/cache@v3 with: path: ${{ github.workspace }}/.ccache - key: ${{ runner.os }}-${{ github.ref_name }}-${{ steps.github-check.outputs.generator }}-ccache-${{ matrix.arch }}-${{ needs.config.outputs.cache_date }} + key: ${{ runner.os }}-ccache-${{ steps.github-check.outputs.generator }}-${{ matrix.arch }}-${{ github.event_name }}-${{ github.head_ref }} + restore-keys: | + ${{ runner.os }}-ccache-${{ steps.github-check.outputs.generator }}-${{ matrix.arch }}-push- - name: 'Setup build environment' id: setup @@ -215,7 +226,9 @@ jobs: CACHE_NAME: 'ccache-cache' with: path: ${{ github.workspace }}/.ccache - key: ${{ runner.os }}-pr-${{ env.CACHE_NAME }}-${{ matrix.ubuntu }}-${{ needs.config.outputs.cache_date }} + key: ${{ runner.os }}-ccache-${{ matrix.ubuntu }}-${{ github.event_name }}-${{ github.head_ref }} + restore-keys: | + ${{ runner.os }}-ccache-${{ matrix.ubuntu }}-push- - name: 'Restore Chromium Embedded Framework from cache' id: cef-cache From d775f5bdc115d20df23c2ce0523f3f80b8ceaa28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=83=E4=B8=8D=E7=94=9C?= <1633557643@qq.com> Date: Wed, 3 May 2023 18:57:21 +0800 Subject: [PATCH 09/93] UI: Make "Portable Mode" translateable (cherry picked from commit e1a202b370589e3b449831fa6256806b8171a71a) --- UI/data/locale/en-US.ini | 1 + UI/window-basic-main.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 9b6436dc2..84e804a4d 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -348,6 +348,7 @@ TransitionNameDlg.Text="Please enter the name of the transition" TransitionNameDlg.Title="Transition Name" # title bar strings +TitleBar.PortableMode="Portable Mode" TitleBar.Profile="Profile" TitleBar.Scenes="Scenes" diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 8b0714ad7..fc9104a08 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -9127,7 +9127,7 @@ void OBSBasic::UpdateTitleBar() name << App()->GetVersionString(false); if (App()->IsPortableMode()) - name << " - Portable Mode"; + name << " - " << Str("TitleBar.PortableMode"); name << " - " << Str("TitleBar.Profile") << ": " << profile; name << " - " << Str("TitleBar.Scenes") << ": " << sceneCollection; From e3ad8cb8786f2fbac6eb3cfb585c0cf9afcfa687 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 3 May 2023 12:34:49 +0200 Subject: [PATCH 10/93] docs: Add missing elements in Services API (cherry picked from commit 3a16a6c8361d4c55369726663df083780ba01929) --- docs/sphinx/reference-services.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sphinx/reference-services.rst b/docs/sphinx/reference-services.rst index 192022670..7085742cb 100644 --- a/docs/sphinx/reference-services.rst +++ b/docs/sphinx/reference-services.rst @@ -186,6 +186,8 @@ Service Definition Structure .. member:: bool (*obs_service_info.can_try_to_connect)(void *data) + (Optional) + :return: If the service has all the needed connection info to be able to connect. @@ -380,12 +382,16 @@ General Service Functions :return: The output type that should be preferred with this service +--------------------- + .. function:: const char *obs_service_get_connect_info(const obs_service_t *service, uint32_t type) :param type: Check :c:member:`obs_service_info.get_connect_info` for type values. :return: Connection info related to the type value. +--------------------- + .. function:: bool obs_service_can_try_to_connect(const obs_service_t *service) :return: If the service has all the needed connection info to be From fba8618675bd6edd36ecef9183c4f107f82bb5e7 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Thu, 4 May 2023 00:32:46 -0700 Subject: [PATCH 11/93] libobs: Fix luma sampling for packed 4:2:2 sources (cherry picked from commit 7ff5dd63b9f2edf31d155f2fda547d09489c0fc0) --- libobs/data/format_conversion.effect | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libobs/data/format_conversion.effect b/libobs/data/format_conversion.effect index 40284a7b3..734f14032 100644 --- a/libobs/data/format_conversion.effect +++ b/libobs/data/format_conversion.effect @@ -153,12 +153,12 @@ VertTexTexPos VSPacked422Left_Reverse(uint id : VERTEXID) float x = idHigh * 4. - 1.; float y = idLow * 4. - 1.; - float u = idHigh * 2. + width_x2_i; + float u = idHigh * 2.; float v = idLow * 2.; v = obs_glsl_compile ? v : (1. - v); VertTexTexPos vert_out; - vert_out.uvuv = float4(width_d2 * u, height * v, u, v); + vert_out.uvuv = float4(width_d2 * u, height * v, u + width_x2_i, v); vert_out.pos = float4(x, y, 0., 1.); return vert_out; } From 2128de7fdf014666fe6873165baa960c436ed024 Mon Sep 17 00:00:00 2001 From: derrod Date: Wed, 3 May 2023 14:59:48 +0200 Subject: [PATCH 12/93] UI: Exit and show error if clearing scene data fails (cherry picked from commit 4419786840567aa4140a2ab6c597ddeebfbf2fc9) --- UI/data/locale/en-US.ini | 4 +++ UI/window-basic-main.cpp | 55 ++++++++++++++++++++++++++++++++++++---- UI/window-basic-main.hpp | 2 ++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 84e804a4d..a651c619e 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -502,6 +502,10 @@ MacPermissions.Continue="Continue" UpdateAvailable="New Update Available" UpdateAvailable.Text="Version %1.%2.%3 is now available. Click here to download" +# Source leak error message +SourceLeak.Title="Source Cleanup Error" +SourceLeak.Text="There was a problem while changing scene collections and some sources could not be unloaded. This issue is typically caused by plugins that are not releasing resources properly. Please ensure that any plugins you are using are up to date.\n\nOBS Studio will now exit to prevent any potential data corruption." + # audio device names Basic.DesktopDevice1="Desktop Audio" Basic.DesktopDevice2="Desktop Audio 2" diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index fc9104a08..86a6e3b0f 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1065,9 +1065,18 @@ static inline void AddMissingFiles(void *data, obs_source_t *source) void OBSBasic::LoadData(obs_data_t *data, const char *file) { ClearSceneData(); - InitDefaultTransitions(); ClearContextBar(); + /* Exit OBS if clearing scene data failed for some reason. */ + if (clearingFailed) { + OBSMessageBox::critical(this, QTStr("SourceLeak.Title"), + QTStr("SourceLeak.Text")); + close(); + return; + } + + InitDefaultTransitions(); + if (devicePropertiesThread && devicePropertiesThread->isRunning()) { devicePropertiesThread->wait(); devicePropertiesThread.reset(); @@ -4880,10 +4889,45 @@ void OBSBasic::ClearSceneData() unsetCursor(); - disableSaving--; + /* If scene data wasn't actually cleared, e.g. faulty plugin holding a + * reference, they will still be in the hash table, enumerate them and + * store the names for logging purposes. */ + auto cb2 = [](void *param, obs_source_t *source) { + auto orphans = static_cast *>(param); + orphans->push_back(obs_source_get_name(source)); + return true; + }; - blog(LOG_INFO, "All scene data cleared"); - blog(LOG_INFO, "------------------------------------------------"); + vector orphan_sources; + obs_enum_sources(cb2, &orphan_sources); + + if (!orphan_sources.empty()) { + /* Avoid logging list twice in case it gets called after + * setting the flag the first time. */ + if (!clearingFailed) { + /* This ugly mess exists to join a vector of strings + * with a user-defined delimiter. */ + string orphan_names = std::accumulate( + orphan_sources.begin(), orphan_sources.end(), + string(""), [](string a, string b) { + return std::move(a) + "\n- " + b; + }); + + blog(LOG_ERROR, + "Not all sources were cleared when clearing scene data:\n%s\n", + orphan_names.c_str()); + } + + /* We do not decrement disableSaving here to avoid OBS + * overwriting user data with garbage. */ + clearingFailed = true; + } else { + disableSaving--; + + blog(LOG_INFO, "All scene data cleared"); + blog(LOG_INFO, + "------------------------------------------------"); + } } void OBSBasic::closeEvent(QCloseEvent *event) @@ -4914,7 +4958,8 @@ void OBSBasic::closeEvent(QCloseEvent *event) bool confirmOnExit = config_get_bool(GetGlobalConfig(), "General", "ConfirmOnExit"); - if (confirmOnExit && outputHandler && outputHandler->Active()) { + if (confirmOnExit && outputHandler && outputHandler->Active() && + !clearingFailed) { SetShowing(true); QMessageBox::StandardButton button = OBSMessageBox::question( diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index cbce69832..55abea8fe 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -245,6 +245,8 @@ private: OBSWeakSourceAutoRelease copySourceTransition; bool closing = false; + bool clearingFailed = false; + QScopedPointer devicePropertiesThread; QScopedPointer whatsNewInitThread; QScopedPointer updateCheckThread; From 00f1ec853859ebcf66c53fd8c4d35722b40fd494 Mon Sep 17 00:00:00 2001 From: gxalpha Date: Sun, 7 May 2023 14:37:06 +0200 Subject: [PATCH 13/93] obs-websocket: Update submodule to pull translations (cherry picked from commit d63ed016b43227bb775f27f673edbf63d86fe7f9) --- plugins/obs-websocket | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/obs-websocket b/plugins/obs-websocket index 6ef055a36..57a9c19f2 160000 --- a/plugins/obs-websocket +++ b/plugins/obs-websocket @@ -1 +1 @@ -Subproject commit 6ef055a369249f6d7b008914fe2bc360c96f23dc +Subproject commit 57a9c19f2ccf4e5452baeffd78014579622b9f3a From 40fdec218c588e9adaab34e0aba5cdc3e5ea919f Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 7 May 2023 01:52:23 +0200 Subject: [PATCH 14/93] UI: Avoid registering CEF OAuth integrations on Wayland (cherry picked from commit 169cd07c42ddf1d0693094badb75f6255c052fac) --- UI/auth-restream.cpp | 5 +++++ UI/auth-twitch.cpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/UI/auth-restream.cpp b/UI/auth-restream.cpp index ed4d39c88..9188da118 100644 --- a/UI/auth-restream.cpp +++ b/UI/auth-restream.cpp @@ -282,6 +282,11 @@ static void DeleteCookies() void RegisterRestreamAuth() { +#if !defined(__APPLE__) && !defined(_WIN32) + if (QApplication::platformName().contains("wayland")) + return; +#endif + OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth, RestreamAuth::Login, DeleteCookies); } diff --git a/UI/auth-twitch.cpp b/UI/auth-twitch.cpp index 034c3d82b..386a0e927 100644 --- a/UI/auth-twitch.cpp +++ b/UI/auth-twitch.cpp @@ -512,6 +512,11 @@ static void DeleteCookies() void RegisterTwitchAuth() { +#if !defined(__APPLE__) && !defined(_WIN32) + if (QApplication::platformName().contains("wayland")) + return; +#endif + OAuth::RegisterOAuth(twitchDef, CreateTwitchAuth, TwitchAuth::Login, DeleteCookies); } From 229616af1639ae3732a50bdfec1653b6d091c87b Mon Sep 17 00:00:00 2001 From: PatTheMav Date: Sun, 7 May 2023 23:23:52 +0200 Subject: [PATCH 15/93] UI: Fix crash on macOS when closing OAUTH browser panel Deleting the cefWidget in the panel's destructor can result in a crash on macOS because the underlying NSView might have been destroyed in memory between Qt closing the QDialog and the destructor call. Moving the browser destruction into the accept and reject calls ensures that CEF can clean up its state _before_ Qt tears down the view hierarchy. (cherry picked from commit efbae916fbbbdf76eecc67e2ebf5a351d2dfb43a) --- UI/auth-oauth.cpp | 23 +++++++++++++++++------ UI/auth-oauth.hpp | 2 ++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/UI/auth-oauth.cpp b/UI/auth-oauth.cpp index c19be67bd..d18923d9d 100644 --- a/UI/auth-oauth.cpp +++ b/UI/auth-oauth.cpp @@ -71,12 +71,7 @@ OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token) #endif } -OAuthLogin::~OAuthLogin() -{ -#ifdef BROWSER_AVAILABLE - delete cefWidget; -#endif -} +OAuthLogin::~OAuthLogin() {} int OAuthLogin::exec() { @@ -88,6 +83,22 @@ int OAuthLogin::exec() return QDialog::Rejected; } +void OAuthLogin::reject() +{ +#ifdef BROWSER_AVAILABLE + delete cefWidget; +#endif + QDialog::reject(); +} + +void OAuthLogin::accept() +{ +#ifdef BROWSER_AVAILABLE + delete cefWidget; +#endif + QDialog::accept(); +} + void OAuthLogin::urlChanged(const QString &url) { std::string uri = get_token ? "access_token=" : "code="; diff --git a/UI/auth-oauth.hpp b/UI/auth-oauth.hpp index b558692b2..364dccdc4 100644 --- a/UI/auth-oauth.hpp +++ b/UI/auth-oauth.hpp @@ -24,6 +24,8 @@ public: inline bool LoadFail() const { return fail; } virtual int exec() override; + virtual void reject() override; + virtual void accept() override; public slots: void urlChanged(const QString &url); From abb80571351438bebd018a45d896b26f95881fbe Mon Sep 17 00:00:00 2001 From: jp9000 Date: Mon, 8 May 2023 22:31:35 -0700 Subject: [PATCH 16/93] libobs: Update version to 29.1.1 --- libobs/obs-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-config.h b/libobs/obs-config.h index 63372a2af..9de519b1a 100644 --- a/libobs/obs-config.h +++ b/libobs/obs-config.h @@ -41,7 +41,7 @@ * * Reset to zero each major or minor version */ -#define LIBOBS_API_PATCH_VER 0 +#define LIBOBS_API_PATCH_VER 1 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | patch) From e55171f28c43277242d8b54184874de91ba2007d Mon Sep 17 00:00:00 2001 From: derrod Date: Mon, 22 May 2023 14:22:35 +0200 Subject: [PATCH 17/93] UI: Reset service selection to custom if name not found --- UI/window-basic-settings-stream.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp index f6e0817a0..110f64d17 100644 --- a/UI/window-basic-settings-stream.cpp +++ b/UI/window-basic-settings-stream.cpp @@ -140,11 +140,10 @@ void OBSBasicSettings::LoadStream1Settings() QTStr("Basic.Settings.Stream.Custom.Password.ToolTip")); } else { int idx = ui->service->findText(service); - if (idx == -1) { - if (service && *service) - ui->service->insertItem(1, service); - idx = 1; - } + /* 29.1 crash workaround: Fall back to "Custom" if service not found. */ + if (idx == -1) + idx = 0; + ui->service->setCurrentIndex(idx); lastServiceIdx = idx; From eb80be5bf94ca8638fec22e715da4ef4971e55c4 Mon Sep 17 00:00:00 2001 From: Florian Zwoch Date: Tue, 9 May 2023 11:39:28 +0200 Subject: [PATCH 18/93] obs-ffmpeg: Fix compilation when ENABLE_HEVC is not set When ENABLE_HEVC is not set the 'bool hevc' function parameter is not being used in this function causing a warning and aborting compilation. --- plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c index 79c7f3f4a..134efb5ec 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c @@ -287,6 +287,8 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) hevc_vaapi_video_info(enc, &info); } else +#else + UNUSED_PARAMETER(hevc); #endif { h264_vaapi_video_info(enc, &info); @@ -564,6 +566,8 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, &enc->header_size, &enc->sei, &enc->sei_size); } else +#else + UNUSED_PARAMETER(hevc); #endif { obs_extract_avc_headers( @@ -649,6 +653,8 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) FF_PROFILE_HEVC_MAIN); } else +#else + UNUSED_PARAMETER(hevc); #endif { obs_data_set_default_int(settings, "profile", From d2019b92d45655aecb8ab0a12a3640120c169c43 Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Thu, 11 May 2023 15:26:15 +0200 Subject: [PATCH 19/93] UI: Fix crash when double-clicking projector If "transition on double click" was enabled, OBS assumed all double clicks were going to multiview projectors, which isn't necessarily the case. --- UI/window-projector.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UI/window-projector.cpp b/UI/window-projector.cpp index 174967467..f2ec7ca99 100644 --- a/UI/window-projector.cpp +++ b/UI/window-projector.cpp @@ -229,6 +229,10 @@ void OBSProjector::mouseDoubleClickEvent(QMouseEvent *event) if (!transitionOnDoubleClick) return; + // Only MultiView projectors handle double click + if (this->type != ProjectorType::Multiview) + return; + OBSBasic *main = (OBSBasic *)obs_frontend_get_main_window(); if (!main->IsPreviewProgramMode()) return; From 6d01b0c63509790e6c050dc522a18b2e41e83389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=83=E4=B8=8D=E7=94=9C?= <1633557643@qq.com> Date: Thu, 11 May 2023 22:23:35 +0800 Subject: [PATCH 20/93] UI: Normalize theme qss files --- UI/data/themes/Acri.qss | 100 +++++++++++++++++------------------ UI/data/themes/Dark.qss | 40 +++++++------- UI/data/themes/Grey.qss | 80 ++++++++++++++-------------- UI/data/themes/Light.qss | 80 ++++++++++++++-------------- UI/data/themes/Rachni.qss | 106 +++++++++++++++++++------------------- UI/data/themes/System.qss | 36 ++++++------- UI/data/themes/Yami.qss | 80 ++++++++++++++-------------- 7 files changed, 261 insertions(+), 261 deletions(-) diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss index a525bbebe..b8114eefc 100644 --- a/UI/data/themes/Acri.qss +++ b/UI/data/themes/Acri.qss @@ -36,7 +36,7 @@ OBSTheme { alternateBase: rgb(11,10,11); text: rgb(255,254,255); - + button: rgb(22,36,88); buttonText: rgb(255,254,255); @@ -62,14 +62,14 @@ OBSTheme::disabled { windowText: rgb(153,153,153); text: rgb(153,153,153); button: rgb(27,29,34); - + buttonText: rgb(24,24,25); brightText: rgb(24,24,25); } OBSTheme::inactive { text: rgb(255,254,255); - + highlight: rgb(25,28,34); highlightText: rgb(255,255,255); } @@ -171,11 +171,11 @@ QMenu::right-arrow { /* Top Menu Bar Items */ QMenuBar::item { - background-color: transparent; + background-color: transparent; } QMenuBar::item:selected { - background: rgb(19,26,48); + background: rgb(19,26,48); } /* Item Lists */ @@ -212,7 +212,7 @@ SceneTree::item, SourceTree::item { border-radius: 4px; color: palette(text); - border: 0px solid transparent; + border: 0px solid transparent; } QMenu::item:selected, @@ -420,7 +420,7 @@ QScrollBar::handle:pressed { } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 20px; } QScrollBar::handle:horizontal { @@ -891,7 +891,7 @@ QSlider::handle:vertical:pressed { } QSlider::add-page:vertical { - background-color: palette(highlight); + background-color: palette(highlight); border-radius: 2px; } @@ -929,16 +929,16 @@ QSlider::handle:disabled { } VolumeMeter { - qproperty-backgroundNominalColor: rgb(66,116,12); - qproperty-backgroundWarningColor: rgb(152,143,15); - qproperty-backgroundErrorColor: rgb(128,32,4); - qproperty-foregroundNominalColor: rgb(132,216,43); - qproperty-foregroundWarningColor: rgb(228,215,23); - qproperty-foregroundErrorColor: rgb(215,65,22); - qproperty-magnitudeColor: rgb(49,54,59); - qproperty-majorTickColor: rgb(239,240,241); - qproperty-minorTickColor: rgb(118,121,124); - qproperty-peakDecayRate: 23.4; + qproperty-backgroundNominalColor: rgb(66,116,12); + qproperty-backgroundWarningColor: rgb(152,143,15); + qproperty-backgroundErrorColor: rgb(128,32,4); + qproperty-foregroundNominalColor: rgb(132,216,43); + qproperty-foregroundWarningColor: rgb(228,215,23); + qproperty-foregroundErrorColor: rgb(215,65,22); + qproperty-magnitudeColor: rgb(49,54,59); + qproperty-majorTickColor: rgb(239,240,241); + qproperty-minorTickColor: rgb(118,121,124); + qproperty-peakDecayRate: 23.4; } /* Status Bar */ @@ -1107,44 +1107,44 @@ QCheckBox { QCheckBox::indicator, QGroupBox::indicator { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } QGroupBox::indicator { - margin-left: 2px; + margin-left: 2px; } QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(./Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { - border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + border: none; + image: url(./Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(./Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { - border: none; - image: url(./Yami/checkbox_checked_focus.svg); + border: none; + image: url(./Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(./Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(./Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1212,7 +1212,7 @@ QPushButton#extraPanelDelete:pressed { /* Mute CheckBox */ MuteCheckBox { - outline: none; + outline: none; } MuteCheckBox::indicator { @@ -1221,35 +1221,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1266,7 +1266,7 @@ OBSHotkeyLabel { } OBSHotkeyLabel[hotkeyPairHover=true] { - color: rgb(53,82,222); + color: rgb(53,82,222); } OBSHotkeyWidget QPushButton { @@ -1356,25 +1356,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: palette(dark); + border: 1px solid #4c4c4c; + height: 5px; + background: palette(dark); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(dark); - border: 1px solid #4c4c4c; + background: palette(dark); + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: #d2d2d2; - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: #d2d2d2; + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ @@ -1487,7 +1487,7 @@ QCalendarWidget QToolButton:pressed { /* Month Dropdown Menu */ QCalendarWidget QMenu { - + } /* Year spinbox */ QCalendarWidget QSpinBox { diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss index 2b56359d3..fc4883759 100644 --- a/UI/data/themes/Dark.qss +++ b/UI/data/themes/Dark.qss @@ -132,8 +132,8 @@ QMainWindow::separator { /* Dock Widget */ QDockWidget { - 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 { @@ -262,8 +262,8 @@ QToolBar { QPushButton[toolButton="true"], QToolButton { - background: transparent; - border: none; + background: transparent; + border: none; padding: 1px; margin: 1px; } @@ -750,7 +750,7 @@ QLabel#errorLabel { /* Preview background color */ OBSQTDisplay { - qproperty-displayBackgroundColor: rgb(76,76,76); + qproperty-displayBackgroundColor: rgb(76,76,76); } /* Preview/Program labels */ @@ -826,7 +826,7 @@ QPushButton#extraPanelDelete:pressed { } OBSMissingFiles { - qproperty-warningIcon: url(./Dark/alert.svg); + qproperty-warningIcon: url(./Dark/alert.svg); } /* Source Icons */ @@ -854,7 +854,7 @@ OBSBasic { SceneTree { qproperty-gridItemWidth: 150; - qproperty-gridItemHeight: 27; + qproperty-gridItemHeight: 27; } *[gridMode="true"] SceneTree::item { @@ -863,9 +863,9 @@ SceneTree { border: none; border-radius: 3px; padding: 4px; - padding-left: 10px; - padding-right: 10px; - margin: 1px; + padding-left: 10px; + padding-right: 10px; + margin: 1px; } *[gridMode="true"] SceneTree::item:selected { @@ -893,25 +893,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid rgb(76,76,76); - height: 5px; - background: palette(base); + border: 1px solid rgb(76,76,76); + height: 5px; + background: palette(base); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(base);; - border: 1px solid rgb(76,76,76); + background: palette(base);; + border: 1px solid rgb(76,76,76); } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: rgb(210,210,210); - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: rgb(210,210,210); + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ diff --git a/UI/data/themes/Grey.qss b/UI/data/themes/Grey.qss index 6c4df993c..be3a9f517 100644 --- a/UI/data/themes/Grey.qss +++ b/UI/data/themes/Grey.qss @@ -36,7 +36,7 @@ OBSTheme { alternateBase: rgb(11,10,11); text: rgb(255,254,255); - + button: rgb(67,67,67); buttonText: rgb(255,254,255); @@ -62,14 +62,14 @@ OBSTheme::disabled { windowText: rgb(153,153,153); text: rgb(153,153,153); button: rgb(27,29,34); - + buttonText: rgb(43,46,56); brightText: rgb(43,46,56); } OBSTheme::inactive { text: rgb(255,254,255); - + highlight: rgb(25,28,34); highlightText: rgb(255,255,255); } @@ -171,11 +171,11 @@ QMenu::right-arrow { /* Top Menu Bar Items */ QMenuBar::item { - background-color: transparent; + background-color: transparent; } QMenuBar::item:selected { - background: rgb(40,76,184); + background: rgb(40,76,184); } /* Item Lists */ @@ -212,7 +212,7 @@ SceneTree::item, SourceTree::item { border-radius: 4px; color: palette(text); - border: 0px solid transparent; + border: 0px solid transparent; } QMenu::item:selected, @@ -420,7 +420,7 @@ QScrollBar::handle:pressed { } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 20px; } QScrollBar::handle:horizontal { @@ -880,7 +880,7 @@ QSlider::handle:vertical:pressed { } QSlider::add-page:vertical { - background-color: palette(highlight); + background-color: palette(highlight); border-radius: 2px; } @@ -1095,44 +1095,44 @@ QCheckBox { QCheckBox::indicator, QGroupBox::indicator { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } QGroupBox::indicator { - margin-left: 2px; + margin-left: 2px; } QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(./Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { - border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + border: none; + image: url(./Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(./Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { - border: none; - image: url(./Yami/checkbox_checked_focus.svg); + border: none; + image: url(./Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(./Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(./Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1200,7 +1200,7 @@ QPushButton#extraPanelDelete:pressed { /* Mute CheckBox */ MuteCheckBox { - outline: none; + outline: none; } MuteCheckBox::indicator { @@ -1209,35 +1209,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1254,7 +1254,7 @@ OBSHotkeyLabel { } OBSHotkeyLabel[hotkeyPairHover=true] { - color: rgb(53,82,222); + color: rgb(53,82,222); } OBSHotkeyWidget QPushButton { @@ -1344,25 +1344,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: palette(dark); + border: 1px solid #4c4c4c; + height: 5px; + background: palette(dark); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(dark); - border: 1px solid #4c4c4c; + background: palette(dark); + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: #d2d2d2; - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: #d2d2d2; + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ @@ -1475,7 +1475,7 @@ QCalendarWidget QToolButton:pressed { /* Month Dropdown Menu */ QCalendarWidget QMenu { - + } /* Year spinbox */ QCalendarWidget QSpinBox { diff --git a/UI/data/themes/Light.qss b/UI/data/themes/Light.qss index cb55f2c66..500c82249 100644 --- a/UI/data/themes/Light.qss +++ b/UI/data/themes/Light.qss @@ -36,7 +36,7 @@ OBSTheme { alternateBase: rgb(11,10,11); text: rgb(2,2,2); - + button: rgb(243,243,243); buttonText: rgb(2,2,2); @@ -62,14 +62,14 @@ OBSTheme::disabled { windowText: rgb(74,74,74); text: rgb(74,74,74); button: rgb(27,29,34); - + buttonText: rgb(43,46,56); brightText: rgb(43,46,56); } OBSTheme::inactive { text: rgb(255,254,255); - + highlight: rgb(25,28,34); highlightText: rgb(255,255,255); } @@ -171,11 +171,11 @@ QMenu::right-arrow { /* Top Menu Bar Items */ QMenuBar::item { - background-color: transparent; + background-color: transparent; } QMenuBar::item:selected { - background: rgb(140,181,255); + background: rgb(140,181,255); } /* Item Lists */ @@ -212,7 +212,7 @@ SceneTree::item, SourceTree::item { border-radius: 4px; color: palette(text); - border: 0px solid transparent; + border: 0px solid transparent; } QMenu::item:selected, @@ -420,7 +420,7 @@ QScrollBar::handle:pressed { } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 20px; } QScrollBar::handle:horizontal { @@ -880,7 +880,7 @@ QSlider::handle:vertical:pressed { } QSlider::add-page:vertical { - background-color: palette(highlight); + background-color: palette(highlight); border-radius: 2px; } @@ -1095,44 +1095,44 @@ QCheckBox { QCheckBox::indicator, QGroupBox::indicator { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } QGroupBox::indicator { - margin-left: 2px; + margin-left: 2px; } QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Light/checkbox_unchecked.svg); + image: url(./Light/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { - border: none; - image: url(./Light/checkbox_unchecked_focus.svg); + border: none; + image: url(./Light/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Light/checkbox_checked.svg); + image: url(./Light/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { - border: none; - image: url(./Light/checkbox_checked_focus.svg); + border: none; + image: url(./Light/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Light/checkbox_checked_disabled.svg); + image: url(./Light/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Light/checkbox_unchecked_disabled.svg); + image: url(./Light/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1200,7 +1200,7 @@ QPushButton#extraPanelDelete:pressed { /* Mute CheckBox */ MuteCheckBox { - outline: none; + outline: none; } MuteCheckBox::indicator { @@ -1209,35 +1209,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Light/mute.svg); + image: url(./Light/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Light/settings/audio.svg); + image: url(./Light/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Light/settings/audio.svg); + image: url(./Light/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Light/settings/audio.svg); + image: url(./Light/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Light/mute.svg); + image: url(./Light/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Light/mute.svg); + image: url(./Light/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Light/mute.svg); + image: url(./Light/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Light/settings/audio.svg); + image: url(./Light/settings/audio.svg); } #hotkeyFilterReset { @@ -1254,7 +1254,7 @@ OBSHotkeyLabel { } OBSHotkeyLabel[hotkeyPairHover=true] { - color: rgb(53,82,222); + color: rgb(53,82,222); } OBSHotkeyWidget QPushButton { @@ -1350,25 +1350,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: palette(dark); + border: 1px solid #4c4c4c; + height: 5px; + background: palette(dark); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(dark); - border: 1px solid #4c4c4c; + background: palette(dark); + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: palette(text); - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: palette(text); + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ @@ -1481,7 +1481,7 @@ QCalendarWidget QToolButton:pressed { /* Month Dropdown Menu */ QCalendarWidget QMenu { - + } /* Year spinbox */ QCalendarWidget QSpinBox { diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss index d376fb109..81f0c32d9 100644 --- a/UI/data/themes/Rachni.qss +++ b/UI/data/themes/Rachni.qss @@ -36,7 +36,7 @@ OBSTheme { alternateBase: rgb(11,10,11); text: rgb(255,254,255); - + button: rgb(0,187,210); buttonText: rgb(255,254,255); @@ -51,7 +51,7 @@ OBSTheme { primaryLight: rgb(0,188,212); primaryDark: rgb(25,27,38); - secondary: rgb(240,96,146); + secondary: rgb(240,96,146); highlight: rgb(42,130,218); highlightText: rgb(255,254,255); @@ -64,14 +64,14 @@ OBSTheme::disabled { windowText: rgb(153,153,153); text: rgb(153,153,153); button: rgb(27,29,34); - + buttonText: rgb(35,38,41); brightText: rgb(35,38,41); } OBSTheme::inactive { text: rgb(255,254,255); - + highlight: rgb(25,28,34); highlightText: rgb(255,255,255); } @@ -173,11 +173,11 @@ QMenu::right-arrow { /* Top Menu Bar Items */ QMenuBar::item { - background-color: transparent; + background-color: transparent; } QMenuBar::item:selected { - background: rgb(0,188,212); + background: rgb(0,188,212); } /* Item Lists */ @@ -214,7 +214,7 @@ SceneTree::item, SourceTree::item { border-radius: 4px; color: palette(text); - border: 0px solid transparent; + border: 0px solid transparent; } QMenu::item:selected, @@ -355,7 +355,7 @@ QGroupBox { } QGroupBox::title { - color: rgb(240,98,146); + color: rgb(240,98,146); subcontrol-origin: margin; left: 8px; top: 8px; @@ -423,7 +423,7 @@ QScrollBar::handle:pressed { } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 20px; } QScrollBar::handle:horizontal { @@ -470,7 +470,7 @@ QToolButton { QPushButton[toolButton="true"]:disabled, QToolButton:disabled { - background-color: transparent; + background-color: transparent; } QPushButton[toolButton="true"]:last-child, @@ -627,7 +627,7 @@ QComboBox:selected, QDateTimeEdit:hover, QDateTimeEdit:selected { background-color: palette(base); - border: 2px solid rgb(0,188,212); + border: 2px solid rgb(0,188,212); } QComboBox::drop-down, @@ -884,7 +884,7 @@ QSlider::handle:vertical:pressed { } QSlider::add-page:vertical { - background-color: palette(highlight); + background-color: palette(highlight); border-radius: 2px; } @@ -922,15 +922,15 @@ QSlider::handle:disabled { } VolumeMeter { - qproperty-backgroundNominalColor: rgb(0, 128, 79); - qproperty-backgroundWarningColor: rgb(128, 57, 0); - qproperty-backgroundErrorColor: rgb(128, 9, 0); - qproperty-foregroundNominalColor: rgb(119, 255, 143); - qproperty-foregroundWarningColor: rgb(255, 157, 76); - qproperty-foregroundErrorColor: rgb(255, 89, 76); - qproperty-magnitudeColor: palette(window); - qproperty-majorTickColor: palette(window-text); - qproperty-minorTickColor: palette(mid); + qproperty-backgroundNominalColor: rgb(0, 128, 79); + qproperty-backgroundWarningColor: rgb(128, 57, 0); + qproperty-backgroundErrorColor: rgb(128, 9, 0); + qproperty-foregroundNominalColor: rgb(119, 255, 143); + qproperty-foregroundWarningColor: rgb(255, 157, 76); + qproperty-foregroundErrorColor: rgb(255, 89, 76); + qproperty-magnitudeColor: palette(window); + qproperty-majorTickColor: palette(window-text); + qproperty-minorTickColor: palette(mid); } /* Status Bar */ @@ -1099,44 +1099,44 @@ QCheckBox { QCheckBox::indicator, QGroupBox::indicator { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } QGroupBox::indicator { - margin-left: 2px; + margin-left: 2px; } QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(./Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { - border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + border: none; + image: url(./Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(./Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { - border: none; - image: url(./Yami/checkbox_checked_focus.svg); + border: none; + image: url(./Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(./Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(./Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1204,7 +1204,7 @@ QPushButton#extraPanelDelete:pressed { /* Mute CheckBox */ MuteCheckBox { - outline: none; + outline: none; } MuteCheckBox::indicator { @@ -1213,35 +1213,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1258,7 +1258,7 @@ OBSHotkeyLabel { } OBSHotkeyLabel[hotkeyPairHover=true] { - color: rgb(240,98,146); + color: rgb(240,98,146); } OBSHotkeyWidget QPushButton { @@ -1348,25 +1348,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: palette(dark); + border: 1px solid #4c4c4c; + height: 5px; + background: palette(dark); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(dark); - border: 1px solid #4c4c4c; + background: palette(dark); + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: #d2d2d2; - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: #d2d2d2; + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ @@ -1479,7 +1479,7 @@ QCalendarWidget QToolButton:pressed { /* Month Dropdown Menu */ QCalendarWidget QMenu { - + } /* Year spinbox */ QCalendarWidget QSpinBox { diff --git a/UI/data/themes/System.qss b/UI/data/themes/System.qss index 2a96cacd4..76af193c6 100644 --- a/UI/data/themes/System.qss +++ b/UI/data/themes/System.qss @@ -174,13 +174,13 @@ QMainWindow::separator { } * [themeID="aboutHLayout"] { - background-color: #DCD9D7; + background-color: #DCD9D7; } /* Preview background color */ OBSQTDisplay { - qproperty-displayBackgroundColor: rgb(76, 76, 76); + qproperty-displayBackgroundColor: rgb(76, 76, 76); } /* Preview/Program labels */ @@ -244,7 +244,7 @@ VisibilityCheckBox::indicator:unchecked { } OBSMissingFiles { - qproperty-warningIcon: url(:res/images/alert.svg); + qproperty-warningIcon: url(:res/images/alert.svg); } /* Source Icons */ @@ -272,7 +272,7 @@ OBSBasic { SceneTree { qproperty-gridItemWidth: 150; - qproperty-gridItemHeight: 24; + qproperty-gridItemHeight: 24; } /* Save icon */ @@ -284,25 +284,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: #DCD9D7; + border: 1px solid #4c4c4c; + height: 5px; + background: #DCD9D7; } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: #DCD9D7; - border: 1px solid #4c4c4c; + background: #DCD9D7; + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: #4c4c4c; - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: #4c4c4c; + width: 12px; + height: 24px; + margin: -24px 0px; } /* Source Context */ @@ -358,18 +358,18 @@ OBSYoutubeActions { } #ytEventList QLabel { - background-color: #e1e1e1; - border: 1px solid #ddd; + background-color: #e1e1e1; + border: 1px solid #ddd; } #ytEventList QLabel:hover { background-color: #eee; - border: 1px solid #777; + border: 1px solid #777; } #ytEventList QLabel[isSelectedEvent=true] { background-color: #ccc; - border: 1px solid #444; + border: 1px solid #444; } /* Calendar Widget */ diff --git a/UI/data/themes/Yami.qss b/UI/data/themes/Yami.qss index 21eefbd34..98fb192e5 100644 --- a/UI/data/themes/Yami.qss +++ b/UI/data/themes/Yami.qss @@ -36,7 +36,7 @@ OBSTheme { alternateBase: rgb(11,10,11); text: rgb(255,254,255); - + button: rgb(60,64,75); buttonText: rgb(255,254,255); @@ -62,14 +62,14 @@ OBSTheme::disabled { windowText: rgb(153,153,153); text: rgb(153,153,153); button: rgb(27,29,34); - + buttonText: rgb(43,46,56); brightText: rgb(43,46,56); } OBSTheme::inactive { text: rgb(255,254,255); - + highlight: rgb(25,28,34); highlightText: rgb(255,255,255); } @@ -171,11 +171,11 @@ QMenu::right-arrow { /* Top Menu Bar Items */ QMenuBar::item { - background-color: transparent; + background-color: transparent; } QMenuBar::item:selected { - background: rgb(40,76,184); + background: rgb(40,76,184); } /* Item Lists */ @@ -212,7 +212,7 @@ SceneTree::item, SourceTree::item { border-radius: 4px; color: palette(text); - border: 0px solid transparent; + border: 0px solid transparent; } QMenu::item:selected, @@ -424,7 +424,7 @@ QScrollBar::handle:pressed { } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 20px; } QScrollBar::handle:horizontal { @@ -884,7 +884,7 @@ QSlider::handle:vertical:pressed { } QSlider::add-page:vertical { - background-color: palette(highlight); + background-color: palette(highlight); border-radius: 2px; } @@ -1099,44 +1099,44 @@ QCheckBox { QCheckBox::indicator, QGroupBox::indicator { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } QGroupBox::indicator { - margin-left: 2px; + margin-left: 2px; } QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(./Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { - border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + border: none; + image: url(./Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(./Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { - border: none; - image: url(./Yami/checkbox_checked_focus.svg); + border: none; + image: url(./Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(./Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(./Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1204,7 +1204,7 @@ QPushButton#extraPanelDelete:pressed { /* Mute CheckBox */ MuteCheckBox { - outline: none; + outline: none; } MuteCheckBox::indicator { @@ -1213,35 +1213,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(./Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(./Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1258,7 +1258,7 @@ OBSHotkeyLabel { } OBSHotkeyLabel[hotkeyPairHover=true] { - color: rgb(53,82,222); + color: rgb(53,82,222); } OBSHotkeyWidget QPushButton { @@ -1348,25 +1348,25 @@ SceneTree { /* Studio Mode T-Bar */ QSlider[themeID="tBarSlider"] { - height: 24px; + height: 24px; } QSlider::groove:horizontal[themeID="tBarSlider"] { - border: 1px solid #4c4c4c; - height: 5px; - background: palette(dark); + border: 1px solid #4c4c4c; + height: 5px; + background: palette(dark); } QSlider::sub-page:horizontal[themeID="tBarSlider"] { - background: palette(dark); - border: 1px solid #4c4c4c; + background: palette(dark); + border: 1px solid #4c4c4c; } QSlider::handle:horizontal[themeID="tBarSlider"] { - background-color: #d2d2d2; - width: 12px; - height: 24px; - margin: -24px 0px; + background-color: #d2d2d2; + width: 12px; + height: 24px; + margin: -24px 0px; } /* Media icons */ @@ -1479,7 +1479,7 @@ QCalendarWidget QToolButton:pressed { /* Month Dropdown Menu */ QCalendarWidget QMenu { - + } /* Year spinbox */ QCalendarWidget QSpinBox { From 96db6187adecdba813b1d3122ce56fe5bfaa8ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=83=E4=B8=8D=E7=94=9C?= <1633557643@qq.com> Date: Thu, 11 May 2023 22:25:15 +0800 Subject: [PATCH 21/93] UI: Fix scene grid mode button color --- UI/data/themes/Acri.qss | 8 ++++++-- UI/data/themes/Grey.qss | 8 ++++++-- UI/data/themes/Light.qss | 8 ++++++-- UI/data/themes/Rachni.qss | 8 ++++++-- UI/data/themes/Yami.qss | 8 ++++++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss index b8114eefc..3a47002d1 100644 --- a/UI/data/themes/Acri.qss +++ b/UI/data/themes/Acri.qss @@ -1336,17 +1336,21 @@ SceneTree { } *[gridMode="true"] SceneTree::item:selected { - background-color: rgb(51,69,163); + background-color: rgb(88,22,36); } *[gridMode="true"] SceneTree::item:checked { - background-color: rgb(51,69,163); + background-color: rgb(88,22,36); } *[gridMode="true"] SceneTree::item:hover { background-color: rgb(42,58,117); } +*[gridMode="true"] SceneTree::item:selected:hover { + background-color: rgb(116,32,49); +} + /* Save icon */ * [themeID="replayIconSmall"] { diff --git a/UI/data/themes/Grey.qss b/UI/data/themes/Grey.qss index be3a9f517..93733dd07 100644 --- a/UI/data/themes/Grey.qss +++ b/UI/data/themes/Grey.qss @@ -1324,17 +1324,21 @@ SceneTree { } *[gridMode="true"] SceneTree::item:selected { - background-color: rgb(51,69,163); + background-color: rgb(40,76,184); } *[gridMode="true"] SceneTree::item:checked { - background-color: rgb(51,69,163); + background-color: rgb(40,76,184); } *[gridMode="true"] SceneTree::item:hover { background-color: rgb(89,89,89); } +*[gridMode="true"] SceneTree::item:selected:hover { + background-color: rgb(54,92,192); +} + /* Save icon */ * [themeID="replayIconSmall"] { diff --git a/UI/data/themes/Light.qss b/UI/data/themes/Light.qss index 500c82249..3f8f81781 100644 --- a/UI/data/themes/Light.qss +++ b/UI/data/themes/Light.qss @@ -1324,17 +1324,21 @@ SceneTree { } *[gridMode="true"] SceneTree::item:selected { - background-color: rgb(51,69,163); + background-color: rgb(140,181,255); } *[gridMode="true"] SceneTree::item:checked { - background-color: rgb(51,69,163); + background-color: rgb(140,181,255); } *[gridMode="true"] SceneTree::item:hover { background-color: rgb(254,254,255); } +*[gridMode="true"] SceneTree::item:selected:hover { + background-color: rgb(178,207,255); +} + /* Save icon */ * [themeID="replayIconSmall"] { diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss index 81f0c32d9..351e9bef9 100644 --- a/UI/data/themes/Rachni.qss +++ b/UI/data/themes/Rachni.qss @@ -1328,17 +1328,21 @@ SceneTree { } *[gridMode="true"] SceneTree::item:selected { - background-color: rgb(51,69,163); + background-color: rgb(145,76,103); } *[gridMode="true"] SceneTree::item:checked { - background-color: rgb(51,69,163); + background-color: rgb(145,76,103); } *[gridMode="true"] SceneTree::item:hover { background-color: rgb(145,76,103); } +*[gridMode="true"] SceneTree::item:selected:hover { + background-color: rgb(145,76,103); +} + /* Save icon */ * [themeID="replayIconSmall"] { diff --git a/UI/data/themes/Yami.qss b/UI/data/themes/Yami.qss index 98fb192e5..54b3c2e6a 100644 --- a/UI/data/themes/Yami.qss +++ b/UI/data/themes/Yami.qss @@ -1328,17 +1328,21 @@ SceneTree { } *[gridMode="true"] SceneTree::item:selected { - background-color: rgb(51,69,163); + background-color: rgb(40,76,184); } *[gridMode="true"] SceneTree::item:checked { - background-color: rgb(51,69,163); + background-color: rgb(40,76,184); } *[gridMode="true"] SceneTree::item:hover { background-color: rgb(79,83,94); } +*[gridMode="true"] SceneTree::item:selected:hover { + background-color: rgb(54,92,192); +} + /* Save icon */ * [themeID="replayIconSmall"] { From 809feb3ddfcc1754d7501bbb298fdaa3ff70d2b3 Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 11 May 2023 22:17:10 +0200 Subject: [PATCH 22/93] deps/obs-scripting: Set file/chunk name when loading lua scripts --- deps/obs-scripting/obs-scripting-lua.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps/obs-scripting/obs-scripting-lua.c b/deps/obs-scripting/obs-scripting-lua.c index 6f0d7222c..e4cf186f2 100644 --- a/deps/obs-scripting/obs-scripting-lua.c +++ b/deps/obs-scripting/obs-scripting-lua.c @@ -129,7 +129,8 @@ static bool load_lua_script(struct obs_lua_script *data) goto fail; } - if (luaL_loadbuffer(script, file_data, strlen(file_data), NULL) != 0) { + if (luaL_loadbuffer(script, file_data, strlen(file_data), + data->base.path.array) != 0) { script_warn(&data->base, "Error loading file: %s", lua_tostring(script, -1)); bfree(file_data); From dfc35603cfd66ef280725fea41d76f5785ce27ec Mon Sep 17 00:00:00 2001 From: derrod Date: Sat, 13 May 2023 17:19:00 +0200 Subject: [PATCH 23/93] UI: Reset VCam when clearing scene data --- UI/window-basic-main-outputs.cpp | 10 ++++++++-- UI/window-basic-main-outputs.hpp | 1 + UI/window-basic-main.cpp | 10 +++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 737ab966d..5f88ea3a4 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -348,6 +348,7 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource() switch (main->vcamConfig.type) { case VCamOutputType::InternalOutput: + DestroyVirtualCameraScene(); switch (main->vcamConfig.internal) { case VCamInternalType::Default: source = obs_get_output_source(0); @@ -360,10 +361,11 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource() } break; case VCamOutputType::SceneOutput: + DestroyVirtualCameraScene(); source = obs_get_source_by_name(main->vcamConfig.scene.c_str()); break; case VCamOutputType::SourceOutput: - OBSSource s = + OBSSourceAutoRelease s = obs_get_source_by_name(main->vcamConfig.source.c_str()); if (!vCamSourceScene) @@ -380,7 +382,6 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource() if (!vCamSourceSceneItem) { vCamSourceSceneItem = obs_scene_add(vCamSourceScene, s); - obs_source_release(s); obs_sceneitem_set_bounds_type(vCamSourceSceneItem, OBS_BOUNDS_SCALE_INNER); @@ -410,6 +411,11 @@ void BasicOutputHandler::DestroyVirtualCamView() obs_view_destroy(virtualCamView); virtualCamView = nullptr; + DestroyVirtualCameraScene(); +} + +void BasicOutputHandler::DestroyVirtualCameraScene() +{ if (!vCamSourceScene) return; diff --git a/UI/window-basic-main-outputs.hpp b/UI/window-basic-main-outputs.hpp index a67a563e9..80d580e19 100644 --- a/UI/window-basic-main-outputs.hpp +++ b/UI/window-basic-main-outputs.hpp @@ -64,6 +64,7 @@ struct BasicOutputHandler { virtual void UpdateVirtualCamOutputSource(); virtual void DestroyVirtualCamView(); + virtual void DestroyVirtualCameraScene(); inline bool Active() const { diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 86a6e3b0f..6874aa111 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1280,7 +1280,7 @@ retryScene: disableSaving--; - if (vcamEnabled && vcamConfig.internal == VCamInternalType::Preview) + if (vcamEnabled) outputHandler->UpdateVirtualCamOutputSource(); if (api) { @@ -4857,6 +4857,14 @@ void OBSBasic::ClearSceneData() for (int i = 0; i < MAX_CHANNELS; i++) obs_set_output_source(i, nullptr); + /* Reset VCam to default to clear its private scene and any references + * it holds. It will be reconfigured during loading. */ + if (vcamEnabled) { + vcamConfig.type = VCamOutputType::InternalOutput; + vcamConfig.internal = VCamInternalType::Default; + outputHandler->UpdateVirtualCamOutputSource(); + } + lastScene = nullptr; swapScene = nullptr; programScene = nullptr; From c304480f1362ac0c075061e7f0ae5aa5784ec7dc Mon Sep 17 00:00:00 2001 From: derrod Date: Sat, 13 May 2023 17:53:47 +0200 Subject: [PATCH 24/93] UI: Only update vcam output if necessary --- UI/window-basic-main-transitions.cpp | 3 ++- UI/window-basic-main.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/UI/window-basic-main-transitions.cpp b/UI/window-basic-main-transitions.cpp index 9f2e1354e..beb5b1f60 100644 --- a/UI/window-basic-main-transitions.cpp +++ b/UI/window-basic-main-transitions.cpp @@ -426,7 +426,8 @@ void OBSBasic::SetTransition(OBSSource transition) ui->transitionRemove->setEnabled(configurable); ui->transitionProps->setEnabled(configurable); - if (vcamEnabled && vcamConfig.internal == VCamInternalType::Default) + if (vcamEnabled && vcamConfig.type == VCamOutputType::InternalOutput && + vcamConfig.internal == VCamInternalType::Default) outputHandler->UpdateVirtualCamOutputSource(); if (api) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 6874aa111..73764e06d 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -5282,7 +5282,8 @@ void OBSBasic::on_scenes_currentItemChanged(QListWidgetItem *current, SetCurrentScene(source); - if (vcamEnabled && vcamConfig.internal == VCamInternalType::Preview) + if (vcamEnabled && vcamConfig.type == VCamOutputType::InternalOutput && + vcamConfig.internal == VCamInternalType::Preview) outputHandler->UpdateVirtualCamOutputSource(); if (api) From 10fdafb9f1445faeef9fed36130b9bda25a2e794 Mon Sep 17 00:00:00 2001 From: derrod Date: Sun, 14 May 2023 00:25:10 +0200 Subject: [PATCH 25/93] UI: Process Qt events once after destroy queue finishes --- UI/window-basic-main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 73764e06d..517c34ae3 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -4895,6 +4895,11 @@ void OBSBasic::ClearSceneData() QApplication::sendPostedEvents(nullptr); } while (obs_wait_for_destroy_queue()); + /* Pump Qt events one final time to give remaining signals time to be + * processed (since this happens after the destroy thread finishes and + * the audio/video threads have processed their tasks). */ + QApplication::sendPostedEvents(nullptr); + unsetCursor(); /* If scene data wasn't actually cleared, e.g. faulty plugin holding a From 890f96ed34d383de220086746394abe124894102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E4=B8=83=E4=B8=8D=E7=94=9C?= <1633557643@qq.com> Date: Mon, 1 May 2023 23:56:02 +0800 Subject: [PATCH 26/93] UI: Remove tabs for About error statements And change error statements to translation key --- UI/data/locale/en-US.ini | 1 + UI/window-basic-about.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index a651c619e..d77475f47 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -1369,6 +1369,7 @@ About.Donate="Make a Contribution" About.GetInvolved="Get Involved" About.Authors="Authors" About.License="License" +About.Error="Error! File could not be read.\n\nGo to: %1" About.Contribute="Support the OBS Project" # Drag-drop URL diff --git a/UI/window-basic-about.cpp b/UI/window-basic-about.cpp index 2bbc216aa..90e146d34 100644 --- a/UI/window-basic-about.cpp +++ b/UI/window-basic-about.cpp @@ -133,8 +133,9 @@ void OBSAbout::ShowAbout() void OBSAbout::ShowAuthors() { std::string path; - QString error = "Error! File could not be read.\n\n \ - Go to: https://github.com/obsproject/obs-studio/blob/master/AUTHORS"; + QString error = + QTStr("About.Error") + .arg("https://github.com/obsproject/obs-studio/blob/master/AUTHORS"); #ifdef __APPLE__ if (!GetDataFilePath("AUTHORS", path)) { @@ -160,8 +161,9 @@ void OBSAbout::ShowAuthors() void OBSAbout::ShowLicense() { std::string path; - QString error = "Error! File could not be read.\n\n \ - Go to: https://github.com/obsproject/obs-studio/blob/master/COPYING"; + QString error = + QTStr("About.Error") + .arg("https://github.com/obsproject/obs-studio/blob/master/COPYING"); if (!GetDataFilePath("license/gplv2.txt", path)) { ui->textBrowser->setPlainText(error); From 8b48d8e867fa128f78c3bd7ed75523d643ae025f Mon Sep 17 00:00:00 2001 From: gxalpha Date: Mon, 1 May 2023 02:39:57 +0200 Subject: [PATCH 27/93] UI: Re-raise missing files dialog on macOS after file is selected --- UI/window-missing-files.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/UI/window-missing-files.cpp b/UI/window-missing-files.cpp index b676b507e..f42dc07a6 100644 --- a/UI/window-missing-files.cpp +++ b/UI/window-missing-files.cpp @@ -164,6 +164,11 @@ void MissingFilesPathItemDelegate::handleBrowse(QWidget *container) container, QTStr("MissingFiles.SelectFile"), currentPath, nullptr); +#ifdef __APPLE__ + // TODO: Revisit when QTBUG-42661 is fixed + container->window()->raise(); +#endif + if (!newPath.isEmpty()) { container->setProperty(PATH_LIST_PROP, QStringList() << newPath); From 2b6bdbafb2befbdc5c1dae1dee42da963f591771 Mon Sep 17 00:00:00 2001 From: gxalpha Date: Sun, 14 May 2023 15:00:49 +0200 Subject: [PATCH 28/93] mac-videotoolbox: Fix incorrect keyframe interval calculation --- plugins/mac-videotoolbox/encoder.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/mac-videotoolbox/encoder.c b/plugins/mac-videotoolbox/encoder.c index 9aa3e2b05..628408554 100644 --- a/plugins/mac-videotoolbox/encoder.c +++ b/plugins/mac-videotoolbox/encoder.c @@ -626,8 +626,9 @@ static bool create_encoder(struct vt_encoder *enc) kVTCompressionPropertyKey_AllowFrameReordering, kVTCompressionPropertyKey_ProfileLevel}; - float key_frame_interval = - enc->keyint * ((float)enc->fps_num / enc->fps_den); + SInt32 key_frame_interval = + (SInt32)(enc->keyint * + ((float)enc->fps_num / enc->fps_den)); float expected_framerate = (float)enc->fps_num / enc->fps_den; CFNumberRef MaxKeyFrameInterval = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, From cfc65650f961f452626ab4e19a7510e2c7f79757 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 10 May 2023 17:46:28 -0500 Subject: [PATCH 29/93] libobs: Fix PulseAudio monitoring when device is set to default When the monitoring device is set to default, this bit of code was appending the no-longer-needed ".monitor" to the device name. Fixes #8877 --- libobs/audio-monitoring/pulse/pulseaudio-wrapper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c b/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c index c70ef468f..8fabe5c0f 100644 --- a/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c +++ b/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c @@ -54,7 +54,6 @@ void get_default_id(char **id) } else { *id = bzalloc(strlen(pdo->default_sink_name) + 9); strcat(*id, pdo->default_sink_name); - strcat(*id, ".monitor"); bfree(pdo->default_sink_name); } From 8110211a201f6aa642542a3117cebb2f7a93252a Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 14 May 2023 22:58:23 -0500 Subject: [PATCH 30/93] libobs: Rework logic for detecting monitoring feedback in PulseAudio The option of default device or specified device for audio input and monitoring device made for a matrix of four possible combinations. Not all combinations were properly detecting feedback potential. This reworks the logic so we properly detect in all four cases. --- .../pulse/pulseaudio-wrapper.c | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c b/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c index 8fabe5c0f..5293ea142 100644 --- a/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c +++ b/libobs/audio-monitoring/pulse/pulseaudio-wrapper.c @@ -61,9 +61,14 @@ void get_default_id(char **id) pulseaudio_unref(); } +/** + * Checks whether a sound source (id1) is the .monitor device for the + * selected monitoring output (id2). + */ bool devices_match(const char *id1, const char *id2) { bool match; + char *name_default = NULL; char *name1 = NULL; char *name2 = NULL; @@ -71,18 +76,28 @@ bool devices_match(const char *id1, const char *id2) return false; if (strcmp(id1, "default") == 0) { - get_default_id(&name1); - id1 = name1; + get_default_id(&name_default); + name1 = bzalloc(strlen(name_default) + 9); + strcat(name1, name_default); + strcat(name1, ".monitor"); + } else { + name1 = bstrdup(id1); } + if (strcmp(id2, "default") == 0) { - get_default_id(&name2); + if (!name_default) + get_default_id(&name_default); + name2 = bzalloc(strlen(name_default) + 9); + strcat(name2, name_default); + strcat(name2, ".monitor"); } else { name2 = bzalloc(strlen(id2) + 9); strcat(name2, id2); strcat(name2, ".monitor"); } - match = strcmp(id1, name2) == 0; + match = strcmp(name1, name2) == 0; + bfree(name_default); bfree(name1); bfree(name2); return match; From 40f7c7923c7f51360f82af7b1560009646cbfbd4 Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 19 May 2023 16:34:59 -0700 Subject: [PATCH 31/93] libobs: Prevent setting invalid scene item scale values Fixes obsproject/obs-studio#7962 --- libobs/obs-scene.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index 0744374cc..530c2f04a 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -2732,7 +2732,9 @@ void obs_sceneitem_set_info(obs_sceneitem_t *item, if (item && info) { item->pos = info->pos; item->rot = info->rot; - item->scale = info->scale; + if (isfinite(info->scale.x) && isfinite(info->scale.y)) { + item->scale = info->scale; + } item->align = info->alignment; item->bounds_type = info->bounds_type; item->bounds_align = info->bounds_alignment; From 22e5d98d6ee0bd4ddac378fb76543e67512d5e3c Mon Sep 17 00:00:00 2001 From: Jim Date: Fri, 19 May 2023 15:46:45 -0700 Subject: [PATCH 32/93] UI: Fix 0,0 size transform bug when resizing sources Fix a bug where if a source's width or height becomes 0 while you're stretching the size of a source or modifying it from the transform dialog, it would become permanently invisible Closes obsproject/obs-studio#7962 --- UI/window-basic-preview.cpp | 12 ++++++++++-- UI/window-basic-transform.cpp | 26 ++++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/UI/window-basic-preview.cpp b/UI/window-basic-preview.cpp index 7a03f6314..64104c729 100644 --- a/UI/window-basic-preview.cpp +++ b/UI/window-basic-preview.cpp @@ -1492,9 +1492,17 @@ void OBSBasicPreview::StretchItem(const vec2 &pos) obs_source_t *source = obs_sceneitem_get_source(stretchItem); + uint32_t source_cx = obs_source_get_width(source); + uint32_t source_cy = obs_source_get_height(source); + + /* if the source's internal size has been set to 0 for whatever reason + * while resizing, do not update transform, otherwise source will be + * stuck invisible until a complete transform reset */ + if (!source_cx || !source_cy) + return; + vec2 baseSize; - vec2_set(&baseSize, float(obs_source_get_width(source)), - float(obs_source_get_height(source))); + vec2_set(&baseSize, float(source_cx), float(source_cy)); vec2 size; vec2_set(&size, br.x - tl.x, br.y - tl.y); diff --git a/UI/window-basic-transform.cpp b/UI/window-basic-transform.cpp index c77b93b73..7449e8475 100644 --- a/UI/window-basic-transform.cpp +++ b/UI/window-basic-transform.cpp @@ -246,8 +246,10 @@ void OBSBasicTransform::RefreshControls() obs_sceneitem_get_crop(item, &crop); obs_source_t *source = obs_sceneitem_get_source(item); - float width = float(obs_source_get_width(source)); - float height = float(obs_source_get_height(source)); + uint32_t source_cx = obs_source_get_width(source); + uint32_t source_cy = obs_source_get_height(source); + float width = float(source_cx); + float height = float(source_cy); int alignIndex = AlignToList(osi.alignment); int boundsAlignIndex = AlignToList(osi.bounds_alignment); @@ -260,6 +262,10 @@ void OBSBasicTransform::RefreshControls() ui->sizeY->setValue(osi.scale.y * height); ui->align->setCurrentIndex(alignIndex); + bool valid_size = source_cx != 0 && source_cy != 0; + ui->sizeX->setEnabled(valid_size); + ui->sizeY->setEnabled(valid_size); + ui->boundsType->setCurrentIndex(int(osi.bounds_type)); ui->boundsAlign->setCurrentIndex(boundsAlignIndex); ui->boundsWidth->setValue(osi.bounds.x); @@ -308,15 +314,23 @@ void OBSBasicTransform::OnControlChanged() return; obs_source_t *source = obs_sceneitem_get_source(item); - double width = double(obs_source_get_width(source)); - double height = double(obs_source_get_height(source)); + uint32_t source_cx = obs_source_get_width(source); + uint32_t source_cy = obs_source_get_height(source); + double width = double(source_cx); + double height = double(source_cy); obs_transform_info oti; + obs_sceneitem_get_info(item, &oti); + + /* do not scale a source if it has 0 width/height */ + if (source_cx != 0 && source_cy != 0) { + oti.scale.x = float(ui->sizeX->value() / width); + oti.scale.y = float(ui->sizeY->value() / height); + } + oti.pos.x = float(ui->positionX->value()); oti.pos.y = float(ui->positionY->value()); oti.rot = float(ui->rotation->value()); - oti.scale.x = float(ui->sizeX->value() / width); - oti.scale.y = float(ui->sizeY->value() / height); oti.alignment = listToAlign[ui->align->currentIndex()]; oti.bounds_type = (obs_bounds_type)ui->boundsType->currentIndex(); From ecb26b18f35bc6b440cbf9818b93f8a0f8a7f891 Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 18 May 2023 16:37:15 +0200 Subject: [PATCH 33/93] libobs-d3d11: Log HAGS status --- libobs-d3d11/d3d11-subsystem.cpp | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 6e7e0e334..2352ed163 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -26,6 +26,7 @@ #include #include "d3d11-subsystem.hpp" #include +#include struct UnsupportedHWError : HRError { inline UnsupportedHWError(const char *str, HRESULT hr) @@ -524,6 +525,44 @@ static bool set_priority(ID3D11Device *device) #endif + +static bool adapter_hags_enabled(DXGI_ADAPTER_DESC *desc) +{ + D3DKMT_OPENADAPTERFROMLUID d3dkmt_openluid{}; + bool hags_enabled = false; + NTSTATUS res; + + d3dkmt_openluid.AdapterLuid = desc->AdapterLuid; + + res = D3DKMTOpenAdapterFromLuid(&d3dkmt_openluid); + if (FAILED(res)) { + blog(LOG_DEBUG, "Failed opening D3DKMT adapter: %x", res); + return hags_enabled; + } + + D3DKMT_WDDM_2_7_CAPS caps = {}; + D3DKMT_QUERYADAPTERINFO args = {}; + args.hAdapter = d3dkmt_openluid.hAdapter; + args.Type = KMTQAITYPE_WDDM_2_7_CAPS; + args.pPrivateDriverData = ∩︀ + args.PrivateDriverDataSize = sizeof(caps); + res = D3DKMTQueryAdapterInfo(&args); + + /* On Windows 10 pre-2004 this will fail, but HAGS isn't supported + * there anyway. */ + if (SUCCEEDED(res)) + hags_enabled = caps.HwSchEnabled; + + D3DKMT_CLOSEADAPTER d3dkmt_close = {d3dkmt_openluid.hAdapter}; + res = D3DKMTCloseAdapter(&d3dkmt_close); + if (FAILED(res)) { + blog(LOG_DEBUG, "Failed closing D3DKMT adapter %x: %x", + d3dkmt_openluid.hAdapter, res); + } + + return hags_enabled; +} + static bool CheckFormat(ID3D11Device *device, DXGI_FORMAT format) { constexpr UINT required = D3D11_FORMAT_SUPPORT_TEXTURE2D | @@ -573,6 +612,13 @@ void gs_device::InitDevice(uint32_t adapterIdx) blog(LOG_INFO, "DXGI increase maximum frame latency failed"); } + /* Log HAGS status */ + bool hags_enabled = adapter_hags_enabled(&desc); + if (hags_enabled) { + blog(LOG_WARNING, + "Hardware-Accelerated GPU Scheduling enabled on adapter!"); + } + /* adjust gpu thread priority on non-intel GPUs */ #if USE_GPU_PRIORITY if (desc.VendorId != 0x8086 && !set_priority(device)) { From 347fc668c6fc74e883daff9b89eeea7a3315e1bf Mon Sep 17 00:00:00 2001 From: derrod Date: Sat, 15 Apr 2023 18:43:25 +0200 Subject: [PATCH 34/93] libobs: Remove registry-based HAGS logging --- libobs/obs-windows.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libobs/obs-windows.c b/libobs/obs-windows.c index 4d16b011c..373f09dc3 100644 --- a/libobs/obs-windows.c +++ b/libobs/obs-windows.c @@ -180,8 +180,6 @@ static void log_admin_status(void) L"SOFTWARE\\Policies\\Microsoft\\Windows\\GameDVR" #define WIN10_GAME_DVR_REG_KEY L"System\\GameConfigStore" #define WIN10_GAME_MODE_REG_KEY L"Software\\Microsoft\\GameBar" -#define WIN10_HAGS_REG_KEY \ - L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers" static void log_gaming_features(void) { @@ -193,7 +191,6 @@ static void log_gaming_features(void) struct reg_dword game_dvr_enabled; struct reg_dword game_dvr_bg_recording; struct reg_dword game_mode_enabled; - struct reg_dword hags_enabled; get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_BAR_REG_KEY, L"AppCaptureEnabled", &game_bar_enabled); @@ -205,8 +202,6 @@ static void log_gaming_features(void) L"HistoricalCaptureEnabled", &game_dvr_bg_recording); get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_MODE_REG_KEY, L"AutoGameModeEnabled", &game_mode_enabled); - get_reg_dword(HKEY_LOCAL_MACHINE, WIN10_HAGS_REG_KEY, L"HwSchMode", - &hags_enabled); if (game_mode_enabled.status != ERROR_SUCCESS) { get_reg_dword(HKEY_CURRENT_USER, WIN10_GAME_MODE_REG_KEY, @@ -241,15 +236,6 @@ static void log_gaming_features(void) // On by default in newer Windows 10 builds (no registry key set) blog(LOG_INFO, "\tGame Mode: Probably On (no reg key set)"); } - - if (hags_enabled.status == ERROR_SUCCESS) { - blog(LOG_INFO, "\tHardware GPU Scheduler: %s", - (hags_enabled.return_value == 2) ? "On" : "Off"); - } else if (win_build >= 22000) { - // On by default in Windows 11 (no registry key set) - blog(LOG_INFO, - "\tHardware GPU Scheduler: Probably On (no reg key set)"); - } } static const char *get_str_for_state(int state) From 80318c5577d7b3809c8148956ebf596d3deb8c52 Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 18 May 2023 16:39:07 +0200 Subject: [PATCH 35/93] libobs-d3d11: Refactor set_priority to use included header --- libobs-d3d11/d3d11-subsystem.cpp | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 2352ed163..87afe62e2 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -475,37 +475,14 @@ static bool increase_maximum_frame_latency(ID3D11Device *device) #if USE_GPU_PRIORITY static bool set_priority(ID3D11Device *device) { - typedef enum _D3DKMT_SCHEDULINGPRIORITYCLASS { - D3DKMT_SCHEDULINGPRIORITYCLASS_IDLE, - D3DKMT_SCHEDULINGPRIORITYCLASS_BELOW_NORMAL, - D3DKMT_SCHEDULINGPRIORITYCLASS_NORMAL, - D3DKMT_SCHEDULINGPRIORITYCLASS_ABOVE_NORMAL, - D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH, - D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME - } D3DKMT_SCHEDULINGPRIORITYCLASS; - ComQIPtr dxgiDevice(device); if (!dxgiDevice) { blog(LOG_DEBUG, "%s: Failed to get IDXGIDevice", __FUNCTION__); return false; } - HMODULE gdi32 = GetModuleHandleW(L"GDI32"); - if (!gdi32) { - blog(LOG_DEBUG, "%s: Failed to get GDI32", __FUNCTION__); - return false; - } - - NTSTATUS(WINAPI * d3dkmt_spspc)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS); - d3dkmt_spspc = (decltype(d3dkmt_spspc))GetProcAddress( - gdi32, "D3DKMTSetProcessSchedulingPriorityClass"); - if (!d3dkmt_spspc) { - blog(LOG_DEBUG, "%s: Failed to get d3dkmt_spspc", __FUNCTION__); - return false; - } - - NTSTATUS status = d3dkmt_spspc(GetCurrentProcess(), - D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME); + NTSTATUS status = D3DKMTSetProcessSchedulingPriorityClass( + GetCurrentProcess(), D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME); if (status != 0) { blog(LOG_DEBUG, "%s: Failed to set process priority class: %d", __FUNCTION__, (int)status); @@ -522,10 +499,8 @@ static bool set_priority(ID3D11Device *device) blog(LOG_INFO, "D3D11 GPU priority setup success"); return true; } - #endif - static bool adapter_hags_enabled(DXGI_ADAPTER_DESC *desc) { D3DKMT_OPENADAPTERFROMLUID d3dkmt_openluid{}; From 9768f311bea107c1ae957842e0422cd6b30678cf Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 18 May 2023 16:40:02 +0200 Subject: [PATCH 36/93] libobs-d3d11: Set priority to high instead of realtime if HAGS enabled --- libobs-d3d11/d3d11-subsystem.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 87afe62e2..52518a7f7 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -473,7 +473,7 @@ static bool increase_maximum_frame_latency(ID3D11Device *device) } #if USE_GPU_PRIORITY -static bool set_priority(ID3D11Device *device) +static bool set_priority(ID3D11Device *device, bool hags_enabled) { ComQIPtr dxgiDevice(device); if (!dxgiDevice) { @@ -482,7 +482,9 @@ static bool set_priority(ID3D11Device *device) } NTSTATUS status = D3DKMTSetProcessSchedulingPriorityClass( - GetCurrentProcess(), D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME); + GetCurrentProcess(), + hags_enabled ? D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH + : D3DKMT_SCHEDULINGPRIORITYCLASS_REALTIME); if (status != 0) { blog(LOG_DEBUG, "%s: Failed to set process priority class: %d", __FUNCTION__, (int)status); @@ -596,7 +598,7 @@ void gs_device::InitDevice(uint32_t adapterIdx) /* adjust gpu thread priority on non-intel GPUs */ #if USE_GPU_PRIORITY - if (desc.VendorId != 0x8086 && !set_priority(device)) { + if (desc.VendorId != 0x8086 && !set_priority(device, hags_enabled)) { blog(LOG_INFO, "D3D11 GPU priority setup " "failed (not admin?)"); } From 45d06dbbc1878af4c8ed0982f19c9c5536dc8fab Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 18 May 2023 21:23:56 +0200 Subject: [PATCH 37/93] CI: Enable GPU priority setting for Windows builds --- .github/workflows/main.yml | 1 + CI/windows/02_build_obs.ps1 | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dfccd902a..80d551535 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,6 +29,7 @@ env: YOUTUBE_CLIENTID_HASH: ${{ secrets.YOUTUBE_CLIENTID_HASH }} YOUTUBE_SECRET: ${{ secrets.YOUTUBE_SECRET }} YOUTUBE_SECRET_HASH: ${{ secrets.YOUTUBE_SECRET_HASH }} + GPU_PRIORITY_VAL: ${{ secrets.GPU_PRIORITY_VAL }} concurrency: group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' diff --git a/CI/windows/02_build_obs.ps1 b/CI/windows/02_build_obs.ps1 index b075e07ec..0114d2763 100644 --- a/CI/windows/02_build_obs.ps1 +++ b/CI/windows/02_build_obs.ps1 @@ -83,6 +83,7 @@ function Configure-OBS { "-DYOUTUBE_CLIENTID_HASH=${Env:YOUTUBE_CLIENTID_HASH}", "-DYOUTUBE_SECRET=${Env:YOUTUBE_SECRET}", "-DYOUTUBE_SECRET_HASH=${Env:YOUTUBE_SECRET_HASH}", + "-DGPU_PRIORITY_VAL=${Env:GPU_PRIORITY_VAL}", "-DCOPIED_DEPENDENCIES=OFF", "-DCOPY_DEPENDENCIES=ON", "-DBUILD_FOR_DISTRIBUTION=$(if (Test-Path Env:BUILD_FOR_DISTRIBUTION) { "ON" } else { "OFF" })", @@ -109,6 +110,7 @@ function Configure-OBS { "-DYOUTUBE_CLIENTID_HASH=`"${Env:YOUTUBE_CLIENTID_HASH}`"", "-DYOUTUBE_SECRET=`"${Env:YOUTUBE_SECRET}`"", "-DYOUTUBE_SECRET_HASH=`"${Env:YOUTUBE_SECRET_HASH}`"", + "-DGPU_PRIORITY_VAL=`"${Env:GPU_PRIORITY_VAL}`"", "-DCOPIED_DEPENDENCIES=OFF", "-DCOPY_DEPENDENCIES=ON", "-DBUILD_FOR_DISTRIBUTION=`"$(if (Test-Path Env:BUILD_FOR_DISTRIBUTION) { "ON" } else { "OFF" })`"", From 1c346639caa4d02dcd4514c26a47821a3a3d66b7 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Fri, 19 May 2023 11:18:00 +0900 Subject: [PATCH 38/93] UI: Fix missing translations This commit fixes a typo in a translation key, adds two missing translations, and also removes obsolete translations in the translation files. --- UI/data/locale/en-US.ini | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index d77475f47..6923315d0 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -102,7 +102,6 @@ LockVolume="Lock Volume" LogViewer="Log Viewer" ShowOnStartup="Show on startup" OpenFile="Open file" -AddValue="Add %1" AddSource="Add Source" RemoveScene="Remove Selected Scene" RemoveSource="Remove Selected Source(s)" @@ -206,7 +205,6 @@ Basic.AutoConfig.StreamPage.Service.Custom="Custom..." Basic.AutoConfig.StreamPage.Server="Server" Basic.AutoConfig.StreamPage.StreamKey="Stream Key" Basic.AutoConfig.StreamPage.StreamKey.ToolTip="RIST: enter the encryption passphrase.\nRTMP: enter the key provided by the service.\nSRT: enter the streamid if the service uses one." -Basic.AutoConfig.StreamPage.StreamKey.LinkToSite="(Link)" Basic.AutoConfig.StreamPage.EncoderKey="Encoder Key" Basic.AutoConfig.StreamPage.ConnectedAccount="Connected account" Basic.AutoConfig.StreamPage.PerformBandwidthTest="Estimate bitrate with bandwidth test (may take a few minutes)" @@ -264,8 +262,6 @@ Updater.Text="There is a new update available:" Updater.UpdateNow="Update Now" Updater.RemindMeLater="Remind me Later" Updater.Skip="Skip Version" -Updater.Running.Title="Program currently active" -Updater.Running.Text="Outputs are currently active, please shut down any active outputs before attempting to update" Updater.NoUpdatesAvailable.Title="No updates available" Updater.NoUpdatesAvailable.Text="No updates are currently available" Updater.BranchNotFound.Title="Update Channel Removed" @@ -275,8 +271,6 @@ Updater.RepairButUpdatesAvailable.Text="Checking file integrity is only possible Updater.RepairConfirm.Title="Confirm Integrity Check" Updater.RepairConfirm.Text="Starting the integrity check will scan your OBS installation for corruption and redownload broken/modified files. This may take a moment.\n\nDo you wish to proceed?" Updater.FailedToLaunch="Failed to launch updater" -Updater.GameCaptureActive.Title="Game capture active" -Updater.GameCaptureActive.Text="Game capture hook library is currently in use. Please close any games/programs being captured (or restart Windows) and try again." # quick transitions QuickTransitions.SwapScenes="Swap Preview/Program Scenes After Transitioning" @@ -460,6 +454,8 @@ Remux.FileExists="The following target files already exist. Do you want to repla Remux.ExitUnfinishedTitle="Remuxing in progress" Remux.ExitUnfinished="Remuxing is not finished, stopping now may render the target file unusable.\nAre you sure you want to stop remuxing?" Remux.HelpText="Drop files in this window to remux, or select an empty \"OBS Recording\" cell to browse for a file." +Remux.NoFilesAddedTitle="No remuxing file added" +Remux.NoFilesAdded="No file is added to remux. Drop a folder containing one or more video files." # missing file dialog MissingFiles="Missing Files" @@ -498,10 +494,6 @@ MacPermissions.Item.Accessibility="Accessibility" MacPermissions.Item.Accessibility.Details="For keyboard shortcuts (hotkeys) to work while other apps are focused, please enable this permission." MacPermissions.Continue="Continue" -# update dialog -UpdateAvailable="New Update Available" -UpdateAvailable.Text="Version %1.%2.%3 is now available. Click here to download" - # Source leak error message SourceLeak.Title="Source Cleanup Error" SourceLeak.Text="There was a problem while changing scene collections and some sources could not be unloaded. This issue is typically caused by plugins that are not releasing resources properly. Please ensure that any plugins you are using are up to date.\n\nOBS Studio will now exit to prevent any potential data corruption." @@ -796,7 +788,6 @@ Basic.MainMenu.View="&View" Basic.MainMenu.View.Toolbars="&Toolbars" Basic.MainMenu.View.ListboxToolbars="Scene/Source List Buttons" Basic.MainMenu.View.ContextBar="Source Toolbar" -Basic.MainMenu.View.SceneTransitions="S&cene Transitions" Basic.MainMenu.View.SourceIcons="Source &Icons" Basic.MainMenu.View.StatusBar="&Status Bar" Basic.MainMenu.View.Fullscreen.Interface="Fullscreen Interface" @@ -818,7 +809,6 @@ Basic.MainMenu.Profile.Export="Export Profile" Basic.MainMenu.SceneCollection.Import="Import Scene Collection" Basic.MainMenu.SceneCollection.Export="Export Scene Collection" Basic.MainMenu.Profile.Exists="The profile already exists" -Basic.MainMenu.SceneCollection.Exists="The scene collection already exists" # basic mode help menu Basic.MainMenu.Tools="&Tools" @@ -913,7 +903,6 @@ Basic.Settings.General.ChannelDescription.beta="Potentially unstable pre-release # basic mode 'stream' settings Basic.Settings.Stream="Stream" -Basic.Settings.Stream.StreamType="Stream Type" Basic.Settings.Stream.Custom.UseAuthentication="Use authentication" Basic.Settings.Stream.Custom.Username="Username" Basic.Settings.Stream.Custom.Password="Password" @@ -954,7 +943,6 @@ Basic.Settings.Output.Format.TT.fmp4="Fragmented MP4 writes the recording in chu Basic.Settings.Output.Encoder.Video="Video Encoder" Basic.Settings.Output.Encoder.Audio="Audio Encoder" Basic.Settings.Output.SelectDirectory="Select Recording Directory" -Basic.Settings.Output.SelectFile="Select Recording File" Basic.Settings.Output.DynamicBitrate="Dynamically change bitrate to manage congestion" Basic.Settings.Output.DynamicBitrate.Beta="Dynamically change bitrate to manage congestion (Beta)" Basic.Settings.Output.DynamicBitrate.TT="Instead of dropping frames to reduce congestion, dynamically changes bitrate on the fly.\n\nNote that this can increase delay to viewers if there is significant sudden congestion.\nWhen the bitrate drops, it can take up to a few minutes to restore.\n\nCurrently only supported for RTMP." @@ -1204,7 +1192,6 @@ Basic.Settings.Advanced.General.ProcessPriority.Idle="Idle" Basic.Settings.Advanced.FormatWarning="Warning: Color formats other than NV12/P010 are primarily intended for recording, and are not recommended when streaming. Streaming may incur increased CPU usage due to color format conversion." Basic.Settings.Advanced.FormatWarningPreciseSdr="Warning: High-precision formats are more commonly used with HDR color spaces." Basic.Settings.Advanced.FormatWarning2100="Warning: Rec. 2100 should use a format with more precision." -Basic.Settings.Advanced.Audio.BufferingTime="Audio Buffering Time" Basic.Settings.Advanced.Video.ColorFormat="Color Format" Basic.Settings.Advanced.Video.ColorFormat.NV12="NV12 (8-bit, 4:2:0, 2 planes)" Basic.Settings.Advanced.Video.ColorFormat.I420="I420 (8-bit, 4:2:0, 3 planes)" @@ -1408,7 +1395,6 @@ LoadProfileNeedsRestart="Profile contains settings that require restarting OBS:\ # Context Bar ContextBar.NoSelectedSource="No source selected" ContextBar.ResetTransform="Reset Transform" -ContextBar.FitToCanvas="Fit to Canvas" # Context Bar Media Controls ContextBar.MediaControls.PlayMedia="Play Media" @@ -1417,7 +1403,6 @@ ContextBar.MediaControls.StopMedia="Stop Media" ContextBar.MediaControls.RestartMedia="Restart Media" ContextBar.MediaControls.PlaylistNext="Next in Playlist" ContextBar.MediaControls.PlaylistPrevious="Previous in Playlist" -ContextBar.MediaControls.MediaProperties="Media Properties" ContextBar.MediaControls.BlindSeek="Media Seek Widget" # YouTube Actions and Auth From 226fcf371f84cd4ee7492f6e59fd4af842e12fbb Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 17:04:22 +0900 Subject: [PATCH 39/93] linux-alsa: Add missing translations --- plugins/linux-alsa/data/locale/en-US.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/linux-alsa/data/locale/en-US.ini b/plugins/linux-alsa/data/locale/en-US.ini index 45d864717..e8e45f87f 100644 --- a/plugins/linux-alsa/data/locale/en-US.ini +++ b/plugins/linux-alsa/data/locale/en-US.ini @@ -1,2 +1,4 @@ AlsaInput="Audio Capture Device (ALSA)" Device="Device" +PCM="PCM" +Rate="Rate" From 5701873337ee60f96d7a09e82e37d98f1bc7bf0f Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 17:08:52 +0900 Subject: [PATCH 40/93] linux-capture: Remove obsolete translation "LockX" was added by 15fb027647 and removed by later commit 1604400e4. --- plugins/linux-capture/data/locale/en-US.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/linux-capture/data/locale/en-US.ini b/plugins/linux-capture/data/locale/en-US.ini index 1872fdb9d..b4339ef4d 100644 --- a/plugins/linux-capture/data/locale/en-US.ini +++ b/plugins/linux-capture/data/locale/en-US.ini @@ -10,6 +10,5 @@ CropLeft="Crop Left" CropRight="Crop Right" CropBottom="Crop Bottom" SwapRedBlue="Swap red and blue" -LockX="Lock X server when capturing" IncludeXBorder="Include X Border" ExcludeAlpha="Use alpha-less texture format (Mesa workaround)" From d5846867c9c6e1c1a3b25e8df379744c5995fb3e Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 17:15:06 +0900 Subject: [PATCH 41/93] linux-pulseaudio: Add missing translation --- plugins/linux-pulseaudio/data/locale/en-US.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/linux-pulseaudio/data/locale/en-US.ini b/plugins/linux-pulseaudio/data/locale/en-US.ini index 8b3c57c3c..43718c057 100644 --- a/plugins/linux-pulseaudio/data/locale/en-US.ini +++ b/plugins/linux-pulseaudio/data/locale/en-US.ini @@ -1,3 +1,4 @@ PulseInput="Audio Input Capture (PulseAudio)" PulseOutput="Audio Output Capture (PulseAudio)" Device="Device" +Default="Default" From 1403691e7e6f7aef2769e75f793aed80d036d061 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 17:16:03 +0900 Subject: [PATCH 42/93] mac-avcapture: Add missing translation --- plugins/mac-avcapture/data/locale/en-US.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/mac-avcapture/data/locale/en-US.ini b/plugins/mac-avcapture/data/locale/en-US.ini index 2fafea676..d6bd4a419 100644 --- a/plugins/mac-avcapture/data/locale/en-US.ini +++ b/plugins/mac-avcapture/data/locale/en-US.ini @@ -12,3 +12,4 @@ VideoRange.Full="Full" Auto="Auto" Unknown="Unknown (%1)" EnableAudio="Enable audio if supported by device" +Resolution="Resolution" From 1b0d90544266b9fd3c05da3fe8412e951542d17f Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 18:13:20 +0900 Subject: [PATCH 43/93] mac-syphon: Remove obsolete translations A commit f9cf458c1 removed syphon-inject but translations were left. --- plugins/mac-syphon/data/locale/en-US.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/mac-syphon/data/locale/en-US.ini b/plugins/mac-syphon/data/locale/en-US.ini index 86550bea9..5ad5336ff 100644 --- a/plugins/mac-syphon/data/locale/en-US.ini +++ b/plugins/mac-syphon/data/locale/en-US.ini @@ -1,8 +1,5 @@ Syphon="Syphon Client" Source="Source" -LaunchSyphonInject="Launch SyphonInject" -Inject="Inject" -Application="Application" SyphonLicense="Syphon License" Crop="Crop" Crop.origin.x="Crop left" From 19731875d24c8e396bca81efd363f58cdb51389e Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 18:16:10 +0900 Subject: [PATCH 44/93] mac-videotoolbox: Remove obsolete translation A commit e461ec4be1 added a translation key "VTEncoder" but never used. --- plugins/mac-videotoolbox/data/locale/en-US.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/mac-videotoolbox/data/locale/en-US.ini b/plugins/mac-videotoolbox/data/locale/en-US.ini index 0610c325b..174865672 100644 --- a/plugins/mac-videotoolbox/data/locale/en-US.ini +++ b/plugins/mac-videotoolbox/data/locale/en-US.ini @@ -5,7 +5,6 @@ VTHEVCEncT2="Apple VT HEVC T2 Hardware Encoder" VTHEVCEncSW="Apple VT HEVC Software Encoder" VTProResEncHW="Apple VT ProRes Hardware Encoder" VTProResEncSW="Apple VT ProRes Software Encoder" -VTEncoder="VideoToolbox Encoder" Bitrate="Bitrate" Quality="Quality" UseMaxBitrate="Limit bitrate" From 4fd4792d96b6df639147c1603d7134a733aeac13 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 19:35:58 +0900 Subject: [PATCH 45/93] obs-ffmpeg: Remove obsolete translations A commit 4e140d2ff added AMF error messages but they were never used. A commit 45d029b1f removed some code but a translation key "Advanced" was left. A commit 77fbfbe5c removed code to translate NVENC.TooManyBFrames but the translation key was left. A commit 6cc7cf3d5 removed the code to select codecs but the translation was left. --- plugins/obs-ffmpeg/data/locale/en-US.ini | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/obs-ffmpeg/data/locale/en-US.ini b/plugins/obs-ffmpeg/data/locale/en-US.ini index b6b144c15..4f9e085c2 100644 --- a/plugins/obs-ffmpeg/data/locale/en-US.ini +++ b/plugins/obs-ffmpeg/data/locale/en-US.ini @@ -23,7 +23,6 @@ AMFOpts.ToolTip="Use to specify custom AMF or FFmpeg options. For example, \"lev BFrames="Max B-frames" -VAAPI.Codec="VAAPI Codec" VAAPI.Device="VAAPI Device" NVENC.LookAhead="Look-ahead" @@ -35,7 +34,6 @@ NVENC.8bitUnsupportedHdr="OBS does not support 8-bit output of Rec. 2100." NVENC.I010Unsupported="NVENC does not support I010. Use P010 instead." NVENC.10bitUnsupported="Cannot perform 10-bit encode on this encoder." NVENC.16bitUnsupported="Cannot perform 16-bit encode on this encoder." -NVENC.TooManyBFrames="Max B-frames setting (%d) is more than encoder supports (%d)." NVENC.NoAV1FallbackPossible="AV1 encoding is not available with the current settings. Try disabling any re-scaling or GPU options that may be set. Check the log for more details." NVENC.Preset2.p1="P1: Fastest (Lowest Quality)" NVENC.Preset2.p2="P2: Faster (Lower Quality)" @@ -65,7 +63,6 @@ InputFormat="Input Format" BufferingMB="Network Buffering" HardwareDecode="Use hardware decoding when available" ClearOnMediaEnd="Show nothing when playback ends" -Advanced="Advanced" RestartWhenActivated="Restart playback when source becomes active" CloseFileWhenInactive="Close file when inactive" CloseFileWhenInactive.ToolTip="Closes the file when the source is not being displayed on the stream or\nrecording. This allows the file to be changed when the source isn't active,\nbut there may be some startup delay when the source reactivates." @@ -96,8 +93,6 @@ WarnWindowsDefender="If Windows 10 Ransomware Protection is enabled it can also Encoder.Error="Failed to open %1: %2" Encoder.Timeout="Encoder %1 is taking too long to encode (timeout: %2 seconds)" -AMF.Error="Failed to open AMF codec: %1" -AMF.GenericError="Try installing the latest AMD driver and closing other recording software that might be using the AMD encoder such as the Radeon Software or Windows Game DVR." AMF.8bitUnsupportedHdr="OBS does not support 8-bit output of Rec. 2100." AMF.10bitUnsupportedAvc="Cannot perform 10-bit encode on AMD H.264 encoder." AMF.16bitUnsupported="Cannot perform 16-bit encode on this encoder." From 28d79464c2dd7c186145b9436b5bb397cdfb4e25 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 19:58:30 +0900 Subject: [PATCH 46/93] obs-ffmpeg: Add missing translations --- plugins/obs-ffmpeg/data/locale/en-US.ini | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/obs-ffmpeg/data/locale/en-US.ini b/plugins/obs-ffmpeg/data/locale/en-US.ini index 4f9e085c2..9a23d8663 100644 --- a/plugins/obs-ffmpeg/data/locale/en-US.ini +++ b/plugins/obs-ffmpeg/data/locale/en-US.ini @@ -21,6 +21,7 @@ Level="Level" AMFOpts="AMF/FFmpeg Options" AMFOpts.ToolTip="Use to specify custom AMF or FFmpeg options. For example, \"level=5.2 profile=main\". Check the AMF encoder docs for more details." +GPU="GPU" BFrames="Max B-frames" VAAPI.Device="VAAPI Device" @@ -42,6 +43,13 @@ NVENC.Preset2.p4="P4: Medium (Medium Quality)" NVENC.Preset2.p5="P5: Slow (Good Quality)" NVENC.Preset2.p6="P6: Slower (Better Quality)" NVENC.Preset2.p7="P7: Slowest (Best Quality)" +NVENC.Preset2.mq="MQ" +NVENC.Preset2.hq="HQ" +NVENC.Preset2.default="Default" +NVENC.Preset2.hp="HP" +NVENC.Preset2.ll="LL" +NVENC.Preset2.llhq="LLHQ" +NVENC.Preset2.llhp="LLHP" NVENC.Tuning.hq="High Quality" NVENC.Tuning.ll="Low Latency" NVENC.Tuning.ull="Ultra Low Latency" From 554518bc789b6369bd74216c7a7dc8360376e92a Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:03:38 +0900 Subject: [PATCH 47/93] obs-ffmpeg: Add missing translations The name of the obs_output_t won't appear in usual operation but some output types have the translation and others do not. Let's translate them. Also translate `FilePath` property name. --- plugins/obs-ffmpeg/data/locale/en-US.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/obs-ffmpeg/data/locale/en-US.ini b/plugins/obs-ffmpeg/data/locale/en-US.ini index 9a23d8663..9652be160 100644 --- a/plugins/obs-ffmpeg/data/locale/en-US.ini +++ b/plugins/obs-ffmpeg/data/locale/en-US.ini @@ -1,4 +1,8 @@ FFmpegOutput="FFmpeg Output" +FFmpegMuxer="FFmpeg Muxer" +FFmpegHlsMuxer="FFmpeg HLS Muxer" +FFmpegMpegts="FFmpeg MPEG-TS" +FFmpegMpegtsMuxer="FFmpeg MPEG-TS Muxer" FFmpegAAC="FFmpeg AAC" FFmpegOpus="FFmpeg Opus" FFmpegALAC="FFmpeg ALAC (24-bit)" @@ -17,6 +21,7 @@ RateControl="Rate Control" KeyframeIntervalSec="Keyframe Interval (0=auto)" Lossless="Lossless" Level="Level" +FilePath="File Path" AMFOpts="AMF/FFmpeg Options" AMFOpts.ToolTip="Use to specify custom AMF or FFmpeg options. For example, \"level=5.2 profile=main\". Check the AMF encoder docs for more details." From bce23262de76d4c664d7fc245d083f07de678f4b Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:07:53 +0900 Subject: [PATCH 48/93] obs-filters: Add missing translation in chroma-key-filter A selection Custom for a property key_color_type was not translated. Use the same translation key CustomColor as color-key-filter. --- plugins/obs-filters/chroma-key-filter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/obs-filters/chroma-key-filter.c b/plugins/obs-filters/chroma-key-filter.c index 598a617fd..2a5a6557a 100644 --- a/plugins/obs-filters/chroma-key-filter.c +++ b/plugins/obs-filters/chroma-key-filter.c @@ -447,7 +447,8 @@ static obs_properties_t *chroma_key_properties_v1(void *data) obs_property_list_add_string(p, obs_module_text("Green"), "green"); obs_property_list_add_string(p, obs_module_text("Blue"), "blue"); obs_property_list_add_string(p, obs_module_text("Magenta"), "magenta"); - obs_property_list_add_string(p, obs_module_text("Custom"), "custom"); + obs_property_list_add_string(p, obs_module_text("CustomColor"), + "custom"); obs_property_set_modified_callback(p, key_type_changed); @@ -486,7 +487,8 @@ static obs_properties_t *chroma_key_properties_v2(void *data) obs_property_list_add_string(p, obs_module_text("Green"), "green"); obs_property_list_add_string(p, obs_module_text("Blue"), "blue"); obs_property_list_add_string(p, obs_module_text("Magenta"), "magenta"); - obs_property_list_add_string(p, obs_module_text("Custom"), "custom"); + obs_property_list_add_string(p, obs_module_text("CustomColor"), + "custom"); obs_property_set_modified_callback(p, key_type_changed); From 43c419a8085d1686433e7b76fd0634f5aac5525e Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:11:20 +0900 Subject: [PATCH 49/93] obs-filters: Remove obsolete translation in expander-filter Expander.None was never used. --- plugins/obs-filters/data/locale/en-US.ini | 1 - plugins/obs-filters/expander-filter.c | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/obs-filters/data/locale/en-US.ini b/plugins/obs-filters/data/locale/en-US.ini index a3def5ff5..17ce57827 100644 --- a/plugins/obs-filters/data/locale/en-US.ini +++ b/plugins/obs-filters/data/locale/en-US.ini @@ -111,7 +111,6 @@ Expander.OutputGain="Output Gain" Expander.Detector="Detection" Expander.RMS="RMS" Expander.Peak="Peak" -Expander.None="None" Expander.Presets="Presets" Expander.Presets.Expander="Expander" Expander.Presets.Gate="Gate" diff --git a/plugins/obs-filters/expander-filter.c b/plugins/obs-filters/expander-filter.c index 07d69e6d0..ebfbbdc39 100644 --- a/plugins/obs-filters/expander-filter.c +++ b/plugins/obs-filters/expander-filter.c @@ -45,7 +45,6 @@ #define TEXT_DETECTOR MT_("Expander.Detector") #define TEXT_PEAK MT_("Expander.Peak") #define TEXT_RMS MT_("Expander.RMS") -#define TEXT_NONE MT_("Expander.None") #define TEXT_PRESETS MT_("Expander.Presets") #define TEXT_PRESETS_EXP MT_("Expander.Presets.Expander") #define TEXT_PRESETS_GATE MT_("Expander.Presets.Gate") From 8c551ad2a5f5a46251b848aeb5a3e6c4d4a08957 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:13:59 +0900 Subject: [PATCH 50/93] obs-outputs: Add missing translations --- plugins/obs-outputs/data/locale/en-US.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/obs-outputs/data/locale/en-US.ini b/plugins/obs-outputs/data/locale/en-US.ini index 2e1ec58e7..6ae4d16af 100644 --- a/plugins/obs-outputs/data/locale/en-US.ini +++ b/plugins/obs-outputs/data/locale/en-US.ini @@ -1,5 +1,8 @@ RTMPStream="RTMP Stream" RTMPStream.DropThreshold="Drop Threshold" +RTMPStream.BindIP="Bind IP" +RTMPStream.NewSocketLoop="New Socket Loop" +RTMPStream.LowLatencyMode="Low Latency Mode" FLVOutput="FLV File Output" FLVOutput.FilePath="File Path" Default="Default" @@ -12,3 +15,6 @@ HostNotFound="Hostname not found. Make sure you entered a valid streaming server NoData="Hostname found, but no data of the requested type. This can occur if you have bound to an IPv6 address and your streaming service only has IPv4 addresses (see Settings → Advanced)." AddressNotAvailable="Address not available. You may have tried to bind to an invalid IP address (see Settings → Advanced)." SSLCertVerifyFailed="The RTMP server sent an invalid SSL certificate." + +FTLStream="FTL Stream" +FTLStream.PeakBitrate="Peak Bitrate" From 0c061865a685bc469b032792ca6f785d0704659f Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:15:00 +0900 Subject: [PATCH 51/93] obs-qsv11: Add missing translation --- plugins/obs-qsv11/data/locale/en-US.ini | 1 + plugins/obs-qsv11/obs-qsv11.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/obs-qsv11/data/locale/en-US.ini b/plugins/obs-qsv11/data/locale/en-US.ini index dbd2f410f..30e70710f 100644 --- a/plugins/obs-qsv11/data/locale/en-US.ini +++ b/plugins/obs-qsv11/data/locale/en-US.ini @@ -13,3 +13,4 @@ SubjectiveVideoEnhancements="Subjective Video Enhancements" 8bitUnsupportedHdr="OBS does not support 8-bit output of Rec. 2100." 10bitUnsupportedAvc="Cannot perform 10-bit encode on Intel QSV H.264 encoder." 16bitUnsupported="Cannot perform 16-bit encode on this encoder." +BFrames="B Frames" diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c index 4077005ad..1c7d60dfc 100644 --- a/plugins/obs-qsv11/obs-qsv11.c +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -228,7 +228,7 @@ static inline void add_strings(obs_property_t *list, const char *const *strings) #define TEXT_CONVERGENCE obs_module_text("Convergence") #define TEXT_ICQ_QUALITY obs_module_text("ICQQuality") #define TEXT_KEYINT_SEC obs_module_text("KeyframeIntervalSec") -#define TEXT_BFRAMES obs_module_text("B Frames") +#define TEXT_BFRAMES obs_module_text("BFrames") #define TEXT_PERCEPTUAL_ENHANCEMENTS \ obs_module_text("SubjectiveVideoEnhancements") From 042f5bc13951d37c62df4ad1bff4f0749c2507ba Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:21:43 +0900 Subject: [PATCH 52/93] win-capture: Remove obsolete translation A commit 80b4a65cd2 added a translation `Method.Auto` but the source code uses `WindowCapture.Method.Auto` instead. --- plugins/win-capture/data/locale/en-US.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/win-capture/data/locale/en-US.ini b/plugins/win-capture/data/locale/en-US.ini index e91b57ba1..1943768d9 100644 --- a/plugins/win-capture/data/locale/en-US.ini +++ b/plugins/win-capture/data/locale/en-US.ini @@ -18,7 +18,6 @@ AllowTransparency="Allow Transparency" Monitor="Display" PrimaryMonitor="Primary Monitor" Method="Capture Method" -Method.Auto="Automatic" Method.DXGI="DXGI Desktop Duplication" Method.WindowsGraphicsCapture="Windows 10 (1903 and up)" GameCapture="Game Capture" From 45caa065b748d17929d634e9c8d09499d068cf1c Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 20 May 2023 20:36:18 +0900 Subject: [PATCH 53/93] win-dshow: Remove obsolete translation A commit f50aa5e01b added a translation ConfigureAudio but never used. --- plugins/win-dshow/data/locale/en-US.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/win-dshow/data/locale/en-US.ini b/plugins/win-dshow/data/locale/en-US.ini index ddc91acdf..22bc67bf4 100644 --- a/plugins/win-dshow/data/locale/en-US.ini +++ b/plugins/win-dshow/data/locale/en-US.ini @@ -11,7 +11,6 @@ ColorRange="Color Range" ColorRange.Default="Default" ColorRange.Partial="Limited" ColorRange.Full="Full" -ConfigureAudio="Configure Audio" ConfigureVideo="Configure Video" ConfigureCrossbar="Configure Crossbar" ResFPSType="Resolution/FPS Type" From 2fbd54958d0074aae5e17fb1aa009ff91294ddba Mon Sep 17 00:00:00 2001 From: gxalpha Date: Fri, 28 Apr 2023 13:33:18 +0200 Subject: [PATCH 54/93] UI: Only defer property updates for input and transition sources Deferring properties was only ever made for input and transition sources. As other property dialogs do not have an "Ok" button that would cause an update to happen, if the deferred flag was set the callback would never be called. Also clarifies the docs to reflect this. --- UI/properties-view.cpp | 22 ++++++++++++++++++---- docs/sphinx/reference-properties.rst | 4 +++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/UI/properties-view.cpp b/UI/properties-view.cpp index b69f31023..f82680426 100644 --- a/UI/properties-view.cpp +++ b/UI/properties-view.cpp @@ -88,19 +88,33 @@ Q_DECLARE_METATYPE(media_frames_per_second); void OBSPropertiesView::ReloadProperties() { + deferUpdate = false; if (weakObj || rawObj) { OBSObject strongObj = GetObject(); void *obj = strongObj ? strongObj.Get() : rawObj; - if (obj) + if (obj) { properties.reset(reloadCallback(obj)); + + if (obs_obj_get_type(obj) == OBS_OBJ_TYPE_SOURCE) { + enum obs_source_type type = obs_source_get_type( + (obs_source_t *)obj); + if (type == OBS_SOURCE_TYPE_INPUT || + type == OBS_SOURCE_TYPE_TRANSITION) { + uint32_t flags = + obs_properties_get_flags( + properties.get()); + deferUpdate = + (flags & + OBS_PROPERTIES_DEFER_UPDATE) != + 0; + } + } + } } else { properties.reset(reloadCallback((void *)type.c_str())); obs_properties_apply_settings(properties.get(), settings); } - uint32_t flags = obs_properties_get_flags(properties.get()); - deferUpdate = (flags & OBS_PROPERTIES_DEFER_UPDATE) != 0; - RefreshProperties(); } diff --git a/docs/sphinx/reference-properties.rst b/docs/sphinx/reference-properties.rst index fc3c3e43c..19a6d1d74 100644 --- a/docs/sphinx/reference-properties.rst +++ b/docs/sphinx/reference-properties.rst @@ -51,7 +51,9 @@ General Functions - OBS_PROPERTIES_DEFER_UPDATE - A hint that tells the front-end to defers updating the settings until the user has finished editing all properties rather than - immediately updating any settings + immediately updating any settings. Currently only + works for properties of input and transition sources, + this flag is a no-op for other properties at this time. --------------------- From 11dd933b8d270aa1e3dfad4a8c35a6529d7c4539 Mon Sep 17 00:00:00 2001 From: PatTheMav Date: Tue, 16 May 2023 14:42:28 +0200 Subject: [PATCH 55/93] libobs: Adds obs.hpp to exported header files Required for plugins built using C++ linking against libobs. --- libobs/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index c5c0aace0..d2e26710d 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -283,6 +283,7 @@ set(public_headers obs-source.h obs-ui.h obs.h + obs.hpp util/base.h util/bmem.h util/c99defs.h From cc667ad7d9e5e1b614cea8d98ef1817da801fb57 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 21 May 2023 19:29:49 +0900 Subject: [PATCH 56/93] UI: Fix crash when receiving multiple SIGINT When there are two or more SIGINT signals were sent to obs, obs crashes because the 2nd SIGINT calls `close` though the main window has been deleted. --- UI/obs-app.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp index e0b9d114a..3bf50798c 100644 --- a/UI/obs-app.cpp +++ b/UI/obs-app.cpp @@ -3238,7 +3238,8 @@ void OBSApp::ProcessSigInt(void) recv(sigintFd[1], &tmp, sizeof(tmp), 0); OBSBasic *main = reinterpret_cast(GetMainWindow()); - main->close(); + if (main) + main->close(); #endif } From 85d22f5ff5f8b1a3f74029437de31ca144ba43aa Mon Sep 17 00:00:00 2001 From: gxalpha Date: Fri, 12 May 2023 18:01:00 +0200 Subject: [PATCH 57/93] UI: Disallow exiting settings with no track in simple mode (cherry picked from commit 2bc368349f904633f2fbe1f8d77687ac7b06f6b5) --- UI/data/locale/en-US.ini | 2 ++ UI/window-basic-settings.cpp | 36 ++++++++++++++++++++++++++++-------- UI/window-basic-settings.hpp | 1 + 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 6923315d0..8f11efee1 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -1319,6 +1319,8 @@ SceneItemHide="Hide '%1'" # Output warnings OutputWarnings.NoTracksSelected="You must select at least one track" +OutputWarnings.NoTracksSelectedOnExit.Title="Output Settings Error" +OutputWarnings.NoTracksSelectedOnExit.Text="All outputs must have at least one audio track selected." OutputWarnings.MP4Recording="Warning: Recordings saved to MP4/MOV will be unrecoverable if the file cannot be finalized (e.g. as a result of BSODs, power losses, etc.). If you want to record multiple audio tracks consider using MKV and remux the recording to MP4/MOV after it is finished (File → Remux Recordings)" OutputWarnings.CannotPause="Warning: Recordings cannot be paused if the recording encoder is set to \"(Use stream encoder)\"" OutputWarnings.CodecIncompatible="The audio or video encoder selection was reset due to incompatibility. Please select a compatible encoder from the list." diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 10aa5559b..840813889 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -3853,14 +3853,8 @@ void OBSBasicSettings::SaveOutputSettings() SaveCheckBox(ui->simpleReplayBuf, "SimpleOutput", "RecRB"); SaveSpinBox(ui->simpleRBSecMax, "SimpleOutput", "RecRBTime"); SaveSpinBox(ui->simpleRBMegsMax, "SimpleOutput", "RecRBSize"); - config_set_int( - main->Config(), "SimpleOutput", "RecTracks", - (ui->simpleOutRecTrack1->isChecked() ? (1 << 0) : 0) | - (ui->simpleOutRecTrack2->isChecked() ? (1 << 1) : 0) | - (ui->simpleOutRecTrack3->isChecked() ? (1 << 2) : 0) | - (ui->simpleOutRecTrack4->isChecked() ? (1 << 3) : 0) | - (ui->simpleOutRecTrack5->isChecked() ? (1 << 4) : 0) | - (ui->simpleOutRecTrack6->isChecked() ? (1 << 5) : 0)); + config_set_int(main->Config(), "SimpleOutput", "RecTracks", + SimpleOutGetSelectedAudioTracks()); curAdvStreamEncoder = GetComboData(ui->advOutEncoder); @@ -4219,6 +4213,7 @@ bool OBSBasicSettings::QueryAllowedToClose() bool invalidEncoder = false; bool invalidFormat = false; + bool invalidTracks = false; if (simple) { if (ui->simpleOutRecEncoder->currentIndex() == -1 || ui->simpleOutStrEncoder->currentIndex() == -1 || @@ -4228,6 +4223,14 @@ bool OBSBasicSettings::QueryAllowedToClose() if (ui->simpleOutRecFormat->currentIndex() == -1) invalidFormat = true; + + QString qual = + ui->simpleOutRecQuality->currentData().toString(); + QString format = + ui->simpleOutRecFormat->currentData().toString(); + if (SimpleOutGetSelectedAudioTracks() == 0 && + qual != "Stream" && format != "flv") + invalidTracks = true; } else { if (ui->advOutRecEncoder->currentIndex() == -1 || ui->advOutEncoder->currentIndex() == -1 || @@ -4246,6 +4249,12 @@ bool OBSBasicSettings::QueryAllowedToClose() this, QTStr("CodecCompat.ContainerMissingOnExit.Title"), QTStr("CodecCompat.ContainerMissingOnExit.Text")); return false; + } else if (invalidTracks) { + OBSMessageBox::warning( + this, + QTStr("OutputWarnings.NoTracksSelectedOnExit.Title"), + QTStr("OutputWarnings.NoTracksSelectedOnExit.Text")); + return false; } return true; @@ -6159,6 +6168,17 @@ int OBSBasicSettings::CurrentFLVTrack() return 0; } +int OBSBasicSettings::SimpleOutGetSelectedAudioTracks() +{ + int tracks = (ui->simpleOutRecTrack1->isChecked() ? (1 << 0) : 0) | + (ui->simpleOutRecTrack2->isChecked() ? (1 << 1) : 0) | + (ui->simpleOutRecTrack3->isChecked() ? (1 << 2) : 0) | + (ui->simpleOutRecTrack4->isChecked() ? (1 << 3) : 0) | + (ui->simpleOutRecTrack5->isChecked() ? (1 << 4) : 0) | + (ui->simpleOutRecTrack6->isChecked() ? (1 << 5) : 0); + return tracks; +} + /* Using setEditable(true) on a QComboBox when there's a custom style in use * does not work properly, so instead completely recreate the widget, which * seems to work fine. */ diff --git a/UI/window-basic-settings.hpp b/UI/window-basic-settings.hpp index 6c91532ae..03c399830 100644 --- a/UI/window-basic-settings.hpp +++ b/UI/window-basic-settings.hpp @@ -375,6 +375,7 @@ private: QIcon GetAdvancedIcon() const; int CurrentFLVTrack(); + int SimpleOutGetSelectedAudioTracks(); OBSService GetStream1Service(); From 3f3ff4fd92be3db1a678df428ab5decac51ea339 Mon Sep 17 00:00:00 2001 From: gxalpha Date: Fri, 12 May 2023 18:16:27 +0200 Subject: [PATCH 58/93] UI: Disallow exiting settings with no track in advanced mode (cherry picked from commit 4b376929394044c5eb665484001c3d1d6c18c502) --- UI/window-basic-main-outputs.cpp | 4 ++++ UI/window-basic-settings.cpp | 25 +++++++++++++++++-------- UI/window-basic-settings.hpp | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 5f88ea3a4..877c559f9 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -1792,6 +1792,10 @@ inline void AdvancedOutput::SetupRecording() unsigned int cy = 0; int idx = 0; + /* Hack to allow recordings without any audio tracks selected. It is no + * longer possible to select such a configuration in settings, but legacy + * configurations might still have this configured and we don't want to + * just break them. */ if (tracks == 0) tracks = config_get_int(main->Config(), "AdvOut", "TrackIndex"); diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 840813889..6676a36c0 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -3886,14 +3886,8 @@ void OBSBasicSettings::SaveOutputSettings() SaveSpinBox(ui->advOutSplitFileTime, "AdvOut", "RecSplitFileTime"); SaveSpinBox(ui->advOutSplitFileSize, "AdvOut", "RecSplitFileSize"); - config_set_int( - main->Config(), "AdvOut", "RecTracks", - (ui->advOutRecTrack1->isChecked() ? (1 << 0) : 0) | - (ui->advOutRecTrack2->isChecked() ? (1 << 1) : 0) | - (ui->advOutRecTrack3->isChecked() ? (1 << 2) : 0) | - (ui->advOutRecTrack4->isChecked() ? (1 << 3) : 0) | - (ui->advOutRecTrack5->isChecked() ? (1 << 4) : 0) | - (ui->advOutRecTrack6->isChecked() ? (1 << 5) : 0)); + config_set_int(main->Config(), "AdvOut", "RecTracks", + AdvOutGetSelectedAudioTracks()); config_set_int(main->Config(), "AdvOut", "FLVTrack", CurrentFLVTrack()); @@ -4237,6 +4231,10 @@ bool OBSBasicSettings::QueryAllowedToClose() ui->advOutRecAEncoder->currentIndex() == -1 || ui->advOutAEncoder->currentIndex() == -1) invalidEncoder = true; + + QString format = ui->advOutRecFormat->currentData().toString(); + if (AdvOutGetSelectedAudioTracks() == 0 && format != "flv") + invalidTracks = true; } if (invalidEncoder) { @@ -6179,6 +6177,17 @@ int OBSBasicSettings::SimpleOutGetSelectedAudioTracks() return tracks; } +int OBSBasicSettings::AdvOutGetSelectedAudioTracks() +{ + int tracks = (ui->advOutRecTrack1->isChecked() ? (1 << 0) : 0) | + (ui->advOutRecTrack2->isChecked() ? (1 << 1) : 0) | + (ui->advOutRecTrack3->isChecked() ? (1 << 2) : 0) | + (ui->advOutRecTrack4->isChecked() ? (1 << 3) : 0) | + (ui->advOutRecTrack5->isChecked() ? (1 << 4) : 0) | + (ui->advOutRecTrack6->isChecked() ? (1 << 5) : 0); + return tracks; +} + /* Using setEditable(true) on a QComboBox when there's a custom style in use * does not work properly, so instead completely recreate the widget, which * seems to work fine. */ diff --git a/UI/window-basic-settings.hpp b/UI/window-basic-settings.hpp index 03c399830..dd466f373 100644 --- a/UI/window-basic-settings.hpp +++ b/UI/window-basic-settings.hpp @@ -376,6 +376,7 @@ private: int CurrentFLVTrack(); int SimpleOutGetSelectedAudioTracks(); + int AdvOutGetSelectedAudioTracks(); OBSService GetStream1Service(); From 6e5e36d55635bf177ef24c2d73968a89cd0e29c5 Mon Sep 17 00:00:00 2001 From: Lain Date: Thu, 25 May 2023 18:01:17 -0700 Subject: [PATCH 59/93] deps/media-playback: Fix crash when interrupting stingers The `mp_media::obsframe` varaible is a variable used to store the current frame, or the first frame on stop. However, it's never cleared, and while decoding a frame, it's invalid. The variable was added for delayed preloading of the first frame for stingers. Now, for more context, when media sources stop, it stores the first frame of the video so it can set the source's current async texture to that frame, effectively preloading the first frame into the backend, making it so that when you play back that media, it's able to start playback instantly without having to wait for the thread to play back that frame, causing seamless playback. Normally, preload happens right when first frame is finished decoding, thus it wasn't a problem before these variables and delayed preloading was added. However, with stingers, I delayed that preload further because stingers are kind of a special case because the stinger does not clear itself right away on stop. Because of that, it was causing it to flash the first frame at the end of the stinger. This is why `obsframe` and `request_preload` were added: it's a way of signaling the media source to preload the first frame when the stinger itself is fully completed. It was added to fix that stinger bug. However, if the user interrupts playback of the stinger (e.g. swaps to another scene while in the middle of the transition), that `request_preload` might still be queued and happen while the media source is still decoding, and thus, while `obsframe` is invalid. I realize that we should probably refactor and clean up the media-playback lib. (cherry picked from commit a12d5812af59197ed36dd068abadf9b50d0295d5) --- deps/media-playback/media-playback/media.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c index 1446643e6..4169824ca 100644 --- a/deps/media-playback/media-playback/media.c +++ b/deps/media-playback/media-playback/media.c @@ -293,6 +293,14 @@ bool mp_media_prepare_frames(mp_media_t *m) } } + /* kind of a cheap fix, but because a stinger might be + * interrupted and restart playback, the request_preload signal + * might happen when the current frame is invalid, so clear out + * these pointers to signify they're not valid. (the obsframe + * structure is only used in the media thread, so this isn't a + * threading issue) */ + memset(&m->obsframe, 0, sizeof(m->obsframe)); + if (m->has_video && !mp_decode_frame(&m->v)) return false; if (m->has_audio && !mp_decode_frame(&m->a)) @@ -840,8 +848,11 @@ static inline bool mp_media_thread(mp_media_t *m) if (pause) continue; - if (preload_frame) + /* see note in mp_media_prepare_frames() for context on the + * pointer check */ + if (preload_frame && m->obsframe.data[0]) { m->v_preload_cb(m->opaque, &m->obsframe); + } /* frames are ready */ if (is_active && !timeout) { From faf4fd5b40d71143fc0587c3ad4482fc0a455e97 Mon Sep 17 00:00:00 2001 From: Lain Date: Thu, 25 May 2023 18:09:46 -0700 Subject: [PATCH 60/93] deps/media-playback: Check `is_active` when frame preloading Adds a check to make sure that delayed preload is ignored if the stinger is restarted/interrupted. Just adds this check to the previous commit to make sure that it doesn't redundantly try to preload a frame when playback is restarted. (cherry picked from commit 40ce466f4dd6356d8a42a0cc20ea13c5833a41d3) --- deps/media-playback/media-playback/media.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c index 4169824ca..bbfa30830 100644 --- a/deps/media-playback/media-playback/media.c +++ b/deps/media-playback/media-playback/media.c @@ -850,7 +850,7 @@ static inline bool mp_media_thread(mp_media_t *m) /* see note in mp_media_prepare_frames() for context on the * pointer check */ - if (preload_frame && m->obsframe.data[0]) { + if (preload_frame && m->obsframe.data[0] && !is_active) { m->v_preload_cb(m->opaque, &m->obsframe); } From 8b6b18079ec6f47d8e30e9ee305bf8596ef8b8d9 Mon Sep 17 00:00:00 2001 From: Lain Date: Thu, 25 May 2023 18:34:27 -0700 Subject: [PATCH 61/93] deps/media-playback: Just null the first frame pointer on decode memset is a little excessive considering we only check the first pointer. (cherry picked from commit 192d33ce860aea1354d33282925200aeb21981fe) --- deps/media-playback/media-playback/media.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/media-playback/media-playback/media.c b/deps/media-playback/media-playback/media.c index bbfa30830..a0d8ebd8e 100644 --- a/deps/media-playback/media-playback/media.c +++ b/deps/media-playback/media-playback/media.c @@ -299,7 +299,7 @@ bool mp_media_prepare_frames(mp_media_t *m) * these pointers to signify they're not valid. (the obsframe * structure is only used in the media thread, so this isn't a * threading issue) */ - memset(&m->obsframe, 0, sizeof(m->obsframe)); + m->obsframe.data[0] = NULL; if (m->has_video && !mp_decode_frame(&m->v)) return false; From e4142c874045925af4d220872f5aedfdc129dd2f Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 27 May 2023 01:13:32 +0900 Subject: [PATCH 62/93] UI: Fix crash on patronJsonThread If a user exit obs while patronJsonThread is running, the thread crashed with the error below. QThread: Destroyed while thread is still running (cherry picked from commit b21edafe980c894456a9b699859814b9e8829d9d) --- UI/window-basic-main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 517c34ae3..36597308d 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -2793,6 +2793,9 @@ OBSBasic::~OBSBasic() if (updateCheckThread && updateCheckThread->isRunning()) updateCheckThread->wait(); + if (patronJsonThread && patronJsonThread->isRunning()) + patronJsonThread->wait(); + delete screenshotData; delete previewProjector; delete studioProgramProjector; From 0bab4adf921dc9936ab35fb745a8ca2a15e99268 Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Fri, 26 May 2023 20:55:48 +0200 Subject: [PATCH 63/93] obs-outputs: Remove support for "RTMP Go Away" feature (#8959) Meta have filed a patent application on the Go Away feature. This goes against the spirit of free software and puts the use of this feature in questionable legal status, so let's remove this code until the patent situation is resolved. This reverts commits a593fe6755b620e0613ccfe82ddf38908cdff559 and dada82fec1e6fabdf83fb402d068f80112e88439. (cherry picked from commit 48a0e7822a4a08c9a252a1d9015d43e023279cc5) --- plugins/obs-outputs/rtmp-stream.c | 118 ++++-------------------------- plugins/obs-outputs/rtmp-stream.h | 1 - 2 files changed, 16 insertions(+), 103 deletions(-) diff --git a/plugins/obs-outputs/rtmp-stream.c b/plugins/obs-outputs/rtmp-stream.c index 899881765..8b20d7904 100644 --- a/plugins/obs-outputs/rtmp-stream.c +++ b/plugins/obs-outputs/rtmp-stream.c @@ -98,11 +98,6 @@ static inline bool disconnected(struct rtmp_stream *stream) return os_atomic_load_bool(&stream->disconnected); } -static inline bool silently_reconnecting(struct rtmp_stream *stream) -{ - return os_atomic_load_bool(&stream->silent_reconnect); -} - static void rtmp_stream_destroy(void *data) { struct rtmp_stream *stream = data; @@ -262,27 +257,6 @@ static inline bool get_next_packet(struct rtmp_stream *stream, return new_packet; } -static inline void peek_next_packet(struct rtmp_stream *stream, - struct encoder_packet *packet) -{ - pthread_mutex_lock(&stream->packets_mutex); - circlebuf_peek_front(&stream->packets, packet, - sizeof(struct encoder_packet)); - pthread_mutex_unlock(&stream->packets_mutex); -} - -static void reinsert_packet_at_front(struct rtmp_stream *stream, - struct encoder_packet *packet) -{ - pthread_mutex_lock(&stream->packets_mutex); - circlebuf_push_front(&stream->packets, packet, - sizeof(struct encoder_packet)); - pthread_mutex_unlock(&stream->packets_mutex); - os_sem_post(stream->send_sem); -} - -#define RTMP_PACKET_TYPE_RECONNECT 0x20 - static bool process_recv_data(struct rtmp_stream *stream, size_t size) { UNUSED_PARAMETER(size); @@ -301,9 +275,7 @@ static bool process_recv_data(struct rtmp_stream *stream, size_t size) } if (packet.m_body) { - if (packet.m_packetType == RTMP_PACKET_TYPE_RECONNECT) { - os_atomic_set_bool(&stream->silent_reconnect, true); - } + /* do processing here */ RTMPPacket_Free(&packet); } return true; @@ -635,7 +607,6 @@ static void dbr_add_frame(struct rtmp_stream *stream, struct dbr_frame *back) } static void dbr_set_bitrate(struct rtmp_stream *stream); -static bool rtmp_stream_start(void *data); #ifdef _WIN32 #define socklen_t int @@ -687,14 +658,6 @@ static void *send_thread(void *data) } } - /* silent reconnect signal received from server, reconnect on - * next keyframe */ - if (silently_reconnecting(stream) && - packet.type == OBS_ENCODER_VIDEO && packet.keyframe) { - reinsert_packet_at_front(stream, &packet); - break; - } - if (stream->dbr_enabled) { dbr_frame.send_beg = os_gettime_ns(); dbr_frame.size = packet.size; @@ -730,8 +693,6 @@ static void *send_thread(void *data) } else if (encode_error) { info("Encoder error, disconnecting"); send_footers(stream); // Y2023 spec - } else if (silently_reconnecting(stream)) { - info("Silent reconnect signal received from server"); } else { info("User stopped the stream"); send_footers(stream); // Y2023 spec @@ -751,14 +712,6 @@ static void *send_thread(void *data) set_output_error(stream); - if (silently_reconnecting(stream)) { - /* manually close the socket to prevent librtmp from sending - * unpublish / deletestream messages when we call RTMP_Close, - * since we want to re-use this stream when we reconnect */ - RTMPSockBuf_Close(&stream->rtmp.m_sb); - stream->rtmp.m_sb.sb_socket = -1; - } - RTMP_Close(&stream->rtmp); /* reset bitrate on stop */ @@ -771,35 +724,18 @@ static void *send_thread(void *data) if (!stopping(stream)) { pthread_detach(stream->send_thread); - if (!silently_reconnecting(stream)) - obs_output_signal_stop(stream->output, - OBS_OUTPUT_DISCONNECTED); + obs_output_signal_stop(stream->output, OBS_OUTPUT_DISCONNECTED); } else if (encode_error) { obs_output_signal_stop(stream->output, OBS_OUTPUT_ENCODE_ERROR); } else { obs_output_end_data_capture(stream->output); } - if (!silently_reconnecting(stream)) { - free_packets(stream); - os_event_reset(stream->stop_event); - os_atomic_set_bool(&stream->active, false); - } - + free_packets(stream); + os_event_reset(stream->stop_event); + os_atomic_set_bool(&stream->active, false); stream->sent_headers = false; - /* reset bitrate on stop */ - if (stream->dbr_enabled) { - if (stream->dbr_cur_bitrate != stream->dbr_orig_bitrate) { - stream->dbr_cur_bitrate = stream->dbr_orig_bitrate; - dbr_set_bitrate(stream); - } - } - - if (silently_reconnecting(stream)) { - rtmp_stream_start(stream); - } - return NULL; } @@ -1020,8 +956,7 @@ static int init_send(struct rtmp_stream *stream) int ret; obs_output_t *context = stream->output; - if (!silently_reconnecting(stream)) - reset_semaphore(stream); + reset_semaphore(stream); ret = pthread_create(&stream->send_thread, NULL, send_thread, stream); if (ret != 0) { @@ -1136,8 +1071,7 @@ static int init_send(struct rtmp_stream *stream) return OBS_OUTPUT_DISCONNECTED; } - if (!silently_reconnecting(stream)) - obs_output_begin_data_capture(stream->output, 0); + obs_output_begin_data_capture(stream->output, 0); return OBS_OUTPUT_SUCCESS; } @@ -1219,12 +1153,6 @@ static void win32_log_interface_type(struct rtmp_stream *stream) } #endif -static void add_connect_data(char **penc, char *pend) -{ - const AVal val = AVC("supportsGoAway"); - *penc = AMF_EncodeNamedBoolean(*penc, pend, &val, true); -} - static int try_connect(struct rtmp_stream *stream) { if (dstr_is_empty(&stream->path)) { @@ -1250,7 +1178,6 @@ static int try_connect(struct rtmp_stream *stream) set_rtmp_dstr(&stream->rtmp.Link.pubPasswd, &stream->password); set_rtmp_dstr(&stream->rtmp.Link.flashVer, &stream->encoder_name); stream->rtmp.Link.swfUrl = stream->rtmp.Link.tcUrl; - stream->rtmp.Link.customConnectEncode = add_connect_data; if (dstr_is_empty(&stream->bind_ip) || dstr_cmp(&stream->bind_ip, "default") == 0) { @@ -1409,17 +1336,9 @@ static void *connect_thread(void *data) os_set_thread_name("rtmp-stream: connect_thread"); - if (!silently_reconnecting(stream)) { - if (!init_connect(stream)) { - obs_output_signal_stop(stream->output, - OBS_OUTPUT_BAD_PATH); - os_atomic_set_bool(&stream->silent_reconnect, false); - return NULL; - } - } else { - struct encoder_packet packet; - peek_next_packet(stream, &packet); - stream->start_dts_offset = get_ms_time(&packet, packet.dts); + if (!init_connect(stream)) { + obs_output_signal_stop(stream->output, OBS_OUTPUT_BAD_PATH); + return NULL; } // HDR streaming disabled for AV1 and HEVC @@ -1446,7 +1365,6 @@ static void *connect_thread(void *data) if (!stopping(stream)) pthread_detach(stream->connect_thread); - os_atomic_set_bool(&stream->silent_reconnect, false); os_atomic_set_bool(&stream->connecting, false); return NULL; } @@ -1455,12 +1373,10 @@ static bool rtmp_stream_start(void *data) { struct rtmp_stream *stream = data; - if (!silently_reconnecting(stream)) { - if (!obs_output_can_begin_data_capture(stream->output, 0)) - return false; - if (!obs_output_initialize_encoders(stream->output, 0)) - return false; - } + if (!obs_output_can_begin_data_capture(stream->output, 0)) + return false; + if (!obs_output_initialize_encoders(stream->output, 0)) + return false; os_atomic_set_bool(&stream->connecting, true); return pthread_create(&stream->connect_thread, NULL, connect_thread, @@ -1708,10 +1624,8 @@ static void check_to_drop_frames(struct rtmp_stream *stream, bool pframes) static bool add_video_packet(struct rtmp_stream *stream, struct encoder_packet *packet) { - if (!silently_reconnecting(stream)) { - check_to_drop_frames(stream, false); - check_to_drop_frames(stream, true); - } + check_to_drop_frames(stream, false); + check_to_drop_frames(stream, true); /* if currently dropping frames, drop packets until it reaches the * desired priority */ diff --git a/plugins/obs-outputs/rtmp-stream.h b/plugins/obs-outputs/rtmp-stream.h index 6a33ff9c9..dd6985468 100644 --- a/plugins/obs-outputs/rtmp-stream.h +++ b/plugins/obs-outputs/rtmp-stream.h @@ -68,7 +68,6 @@ struct rtmp_stream { volatile bool active; volatile bool disconnected; volatile bool encode_error; - volatile bool silent_reconnect; pthread_t send_thread; int max_shutdown_time_sec; From e15a92e16fc3827027a956f6d6a1223b41aced61 Mon Sep 17 00:00:00 2001 From: Lain Date: Sat, 27 May 2023 14:49:56 -0700 Subject: [PATCH 64/93] libobs: Update version to 29.1.2 --- libobs/obs-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-config.h b/libobs/obs-config.h index 9de519b1a..20ce99aab 100644 --- a/libobs/obs-config.h +++ b/libobs/obs-config.h @@ -41,7 +41,7 @@ * * Reset to zero each major or minor version */ -#define LIBOBS_API_PATCH_VER 1 +#define LIBOBS_API_PATCH_VER 2 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | patch) From fb5d03130a81203e48e5e9cd65a966d5e221f76c Mon Sep 17 00:00:00 2001 From: derrod Date: Fri, 2 Jun 2023 09:19:11 +0200 Subject: [PATCH 65/93] Revert "UI: Reset service selection to custom if name not found" This reverts commit e55171f28c43277242d8b54184874de91ba2007d. --- UI/window-basic-settings-stream.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp index 110f64d17..f6e0817a0 100644 --- a/UI/window-basic-settings-stream.cpp +++ b/UI/window-basic-settings-stream.cpp @@ -140,10 +140,11 @@ void OBSBasicSettings::LoadStream1Settings() QTStr("Basic.Settings.Stream.Custom.Password.ToolTip")); } else { int idx = ui->service->findText(service); - /* 29.1 crash workaround: Fall back to "Custom" if service not found. */ - if (idx == -1) - idx = 0; - + if (idx == -1) { + if (service && *service) + ui->service->insertItem(1, service); + idx = 1; + } ui->service->setCurrentIndex(idx); lastServiceIdx = idx; From e26a04fa444fc6caeda809118ebf1947f7fe41a4 Mon Sep 17 00:00:00 2001 From: derrod Date: Sat, 3 Jun 2023 15:20:43 +0200 Subject: [PATCH 66/93] UI: Assume RTMP if service has no protcol --- UI/window-basic-settings-stream.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp index f6e0817a0..e8bb33c5e 100644 --- a/UI/window-basic-settings-stream.cpp +++ b/UI/window-basic-settings-stream.cpp @@ -566,7 +566,10 @@ QString OBSBasicSettings::FindProtocol() obs_properties_destroy(props); - return QT_UTF8(obs_data_get_string(settings, "protocol")); + const char *protocol = + obs_data_get_string(settings, "protocol"); + if (protocol && *protocol) + return QT_UTF8(protocol); } return QString("RTMP"); From 447710ab2c81ada7096f8d1b943a9eaf6ee0fd49 Mon Sep 17 00:00:00 2001 From: derrod Date: Sun, 4 Jun 2023 18:48:25 +0200 Subject: [PATCH 67/93] libobs: Fix crash when properties are deleted in callback --- libobs/obs-properties.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libobs/obs-properties.c b/libobs/obs-properties.c index ab683ed1d..dc2653dc2 100644 --- a/libobs/obs-properties.c +++ b/libobs/obs-properties.c @@ -363,9 +363,9 @@ void obs_properties_apply_settings_internal(obs_properties_t *props, obs_data_t *settings, obs_properties_t *realprops) { - struct obs_property *p, *tmp; + struct obs_property *p = props->properties; - HASH_ITER (hh, props->properties, p, tmp) { + while (p) { if (p->type == OBS_PROPERTY_GROUP) { obs_properties_apply_settings_internal( obs_property_group_content(p), settings, @@ -375,6 +375,8 @@ void obs_properties_apply_settings_internal(obs_properties_t *props, p->modified(realprops, p, settings); else if (p->modified2) p->modified2(p->priv, realprops, p, settings); + + p = p->hh.next; } } From b281a74e259c825e8bfc05aa890284bf22bd0abb Mon Sep 17 00:00:00 2001 From: cg2121 Date: Sat, 27 May 2023 04:54:05 -0500 Subject: [PATCH 68/93] UI: Fix menu actions missing shortcuts The scene and source rename/remove actions were missing shortcuts in the context menu. (cherry picked from commit 016ce128b7a30791f56dfad7001b28d38902b670) --- UI/forms/OBSBasic.ui | 6 ++++++ UI/window-basic-main.cpp | 15 ++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index 55af294c6..9ec44e77a 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -1683,6 +1683,9 @@ Qt::WidgetWithChildrenShortcut + + false + removeIconSmall @@ -1704,6 +1707,9 @@ Qt::WidgetWithChildrenShortcut + + false + removeIconSmall diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 36597308d..c02f8f04f 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -392,12 +392,12 @@ OBSBasic::OBSBasic(QWidget *parent) connect(diskFullTimer, SIGNAL(timeout()), this, SLOT(CheckDiskSpaceRemaining())); - renameScene = new QAction(ui->scenesDock); + renameScene = new QAction(QTStr("Rename"), ui->scenesDock); renameScene->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(renameScene, SIGNAL(triggered()), this, SLOT(EditSceneName())); ui->scenesDock->addAction(renameScene); - renameSource = new QAction(ui->sourcesDock); + renameSource = new QAction(QTStr("Rename"), ui->sourcesDock); renameSource->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(renameSource, SIGNAL(triggered()), this, SLOT(EditSceneItemName())); @@ -5385,9 +5385,8 @@ void OBSBasic::on_scenes_customContextMenuRequested(const QPoint &pos) popup.addAction(copyFilters); popup.addAction(pasteFilters); popup.addSeparator(); - popup.addAction(QTStr("Rename"), this, SLOT(EditSceneName())); - popup.addAction(QTStr("Remove"), this, - SLOT(RemoveSelectedScene())); + popup.addAction(renameScene); + popup.addAction(ui->actionRemoveScene); popup.addSeparator(); order.addAction(QTStr("Basic.MainMenu.Edit.Order.MoveUp"), this, @@ -5893,10 +5892,8 @@ void OBSBasic::CreateSourcePopupMenu(int idx, bool preview) colorSelect = new ColorSelect(colorMenu); popup.addMenu(AddBackgroundColorMenu( colorMenu, colorWidgetAction, colorSelect, sceneItem)); - popup.addAction(QTStr("Rename"), this, - SLOT(EditSceneItemName())); - popup.addAction(QTStr("Remove"), this, - SLOT(on_actionRemoveSource_triggered())); + popup.addAction(renameSource); + popup.addAction(ui->actionRemoveSource); popup.addSeparator(); popup.addMenu(ui->orderMenu); From 28a8ed16a9a14d7632accf7a8ecf94076cad9316 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 28 May 2023 00:50:46 +0900 Subject: [PATCH 69/93] text-freetype2: Fix crash after reaching buffer size The texbuf has a fixed size that won't expand. When a lot of multi-byte characters has arrived, it overflow and src_glyph becomes NULL. (cherry picked from commit 4fb2bc38de4170d85b6327bd9e62f9f658007e86) --- plugins/text-freetype2/text-functionality.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/text-freetype2/text-functionality.c b/plugins/text-freetype2/text-functionality.c index 7b4839d33..25772c50a 100644 --- a/plugins/text-freetype2/text-functionality.c +++ b/plugins/text-freetype2/text-functionality.c @@ -140,7 +140,8 @@ void set_up_vertex_buffer(struct ft2_source *srcdata) next_char:; glyph_index = FT_Get_Char_Index(srcdata->font_face, srcdata->text[i]); - word_width += src_glyph->xadv; + if (src_glyph) + word_width += src_glyph->xadv; eos_skip:; } From a11a51182943f24f20fe2612f6081ccee4192469 Mon Sep 17 00:00:00 2001 From: cg2121 Date: Fri, 2 Jun 2023 20:53:53 -0500 Subject: [PATCH 70/93] UI: Fix filter shortcuts not showing in context menu This fixes the shortcuts not showing up in the filters context menu for rename and remove. This also has a code cleanup for the rename action, as now it is created in the ui file. (cherry picked from commit 4c9e1949ad4456c466385bab7cddf9206dc3da4d) --- UI/forms/OBSBasicFilters.ui | 8 ++++++++ UI/window-basic-filters.cpp | 37 +++++++++++++------------------------ UI/window-basic-filters.hpp | 2 ++ 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/UI/forms/OBSBasicFilters.ui b/UI/forms/OBSBasicFilters.ui index 8f3c157f6..3594ac174 100644 --- a/UI/forms/OBSBasicFilters.ui +++ b/UI/forms/OBSBasicFilters.ui @@ -597,6 +597,9 @@ Del + + false + @@ -622,6 +625,11 @@ Ctrl+Down + + + Rename + + diff --git a/UI/window-basic-filters.cpp b/UI/window-basic-filters.cpp index 5a9c023df..92fc385d4 100644 --- a/UI/window-basic-filters.cpp +++ b/UI/window-basic-filters.cpp @@ -81,6 +81,7 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_) QApplication::translate("OBSBasicFilters", "Del", nullptr)); #endif // QT_NO_SHORTCUT + addAction(ui->actionRenameFilter); addAction(ui->actionRemoveFilter); addAction(ui->actionMoveUp); addAction(ui->actionMoveDown); @@ -154,24 +155,10 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_) ui->preview->hide(); } - QAction *renameAsync = new QAction(ui->asyncWidget); - renameAsync->setShortcutContext(Qt::WidgetWithChildrenShortcut); - connect(renameAsync, SIGNAL(triggered()), this, - SLOT(RenameAsyncFilter())); - ui->asyncWidget->addAction(renameAsync); - - QAction *renameEffect = new QAction(ui->effectWidget); - renameEffect->setShortcutContext(Qt::WidgetWithChildrenShortcut); - connect(renameEffect, SIGNAL(triggered()), this, - SLOT(RenameEffectFilter())); - ui->effectWidget->addAction(renameEffect); - #ifdef __APPLE__ - renameAsync->setShortcut({Qt::Key_Return}); - renameEffect->setShortcut({Qt::Key_Return}); + ui->actionRenameFilter->setShortcut({Qt::Key_Return}); #else - renameAsync->setShortcut({Qt::Key_F2}); - renameEffect->setShortcut({Qt::Key_F2}); + ui->actionRenameFilter->setShortcut({Qt::Key_F2}); #endif UpdateFilters(); @@ -932,6 +919,14 @@ void OBSBasicFilters::on_actionMoveDown_triggered() on_moveEffectFilterDown_clicked(); } +void OBSBasicFilters::on_actionRenameFilter_triggered() +{ + if (ui->asyncFilters->hasFocus()) + RenameAsyncFilter(); + else if (ui->effectFilters->hasFocus()) + RenameEffectFilter(); +} + void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async) { QListWidget *list = async ? ui->asyncFilters : ui->effectFilters; @@ -948,17 +943,11 @@ void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async) async ? SLOT(DuplicateAsyncFilter()) : SLOT(DuplicateEffectFilter()); - const char *renameSlot = async ? SLOT(RenameAsyncFilter()) - : SLOT(RenameEffectFilter()); - const char *removeSlot = - async ? SLOT(on_removeAsyncFilter_clicked()) - : SLOT(on_removeEffectFilter_clicked()); - popup.addSeparator(); popup.addAction(QTStr("Duplicate"), this, dulpicateSlot); popup.addSeparator(); - popup.addAction(QTStr("Rename"), this, renameSlot); - popup.addAction(QTStr("Remove"), this, removeSlot); + popup.addAction(ui->actionRenameFilter); + popup.addAction(ui->actionRemoveFilter); popup.addSeparator(); QAction *copyAction = new QAction(QTStr("Copy")); diff --git a/UI/window-basic-filters.hpp b/UI/window-basic-filters.hpp index 2a14e7931..e2bc8fa2a 100644 --- a/UI/window-basic-filters.hpp +++ b/UI/window-basic-filters.hpp @@ -113,6 +113,8 @@ private slots: void on_actionMoveUp_triggered(); void on_actionMoveDown_triggered(); + void on_actionRenameFilter_triggered(); + void AsyncFilterNameEdited(QWidget *editor); void EffectFilterNameEdited(QWidget *editor); From 5b8f429c8e08bc70ac5817f8ef1d27f4f3c6ad5e Mon Sep 17 00:00:00 2001 From: "Huts, Roman" Date: Tue, 30 May 2023 13:10:05 -0400 Subject: [PATCH 71/93] obs-ffmpeg: Fix AMF encoder reconfiguration Must Flush() or Drain() before ReInit() (cherry picked from commit 275bb344d88e59e1af1af309343cfef6b388f53e) --- plugins/obs-ffmpeg/texture-amf.cpp | 34 +++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp index abd1d6f92..c683d1bdf 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -1254,13 +1254,17 @@ try { int64_t qp = obs_data_get_int(settings, "cqp"); const char *rc_str = obs_data_get_string(settings, "rate_control"); int rc = get_avc_rate_control(rc_str); - AMF_RESULT res; + AMF_RESULT res = AMF_OK; amf_avc_update_data(enc, rc, bitrate * 1000, qp); + res = enc->amf_encoder->Flush(); + if (res != AMF_OK) + throw amf_error("AMFComponent::Flush failed", res); + res = enc->amf_encoder->ReInit(enc->cx, enc->cy); if (res != AMF_OK) - throw amf_error("AMFComponent::Init failed", res); + throw amf_error("AMFComponent::ReInit failed", res); return true; @@ -1488,8 +1492,7 @@ static void register_avc() amf_encoder_info.get_name = amf_avc_get_name; amf_encoder_info.create = amf_avc_create_texencode; amf_encoder_info.destroy = amf_destroy; - /* FIXME: Figure out why encoder does not survive reconfiguration - amf_encoder_info.update = amf_avc_update; */ + amf_encoder_info.update = amf_avc_update; amf_encoder_info.encode_texture = amf_encode_tex; amf_encoder_info.get_defaults = amf_defaults; amf_encoder_info.get_properties = amf_avc_properties; @@ -1581,13 +1584,17 @@ try { int64_t qp = obs_data_get_int(settings, "cqp"); const char *rc_str = obs_data_get_string(settings, "rate_control"); int rc = get_hevc_rate_control(rc_str); - AMF_RESULT res; + AMF_RESULT res = AMF_OK; amf_hevc_update_data(enc, rc, bitrate * 1000, qp); + res = enc->amf_encoder->Flush(); + if (res != AMF_OK) + throw amf_error("AMFComponent::Flush failed", res); + res = enc->amf_encoder->ReInit(enc->cx, enc->cy); if (res != AMF_OK) - throw amf_error("AMFComponent::Init failed", res); + throw amf_error("AMFComponent::ReInit failed", res); return true; @@ -1835,8 +1842,7 @@ static void register_hevc() amf_encoder_info.get_name = amf_hevc_get_name; amf_encoder_info.create = amf_hevc_create_texencode; amf_encoder_info.destroy = amf_destroy; - /* FIXME: Figure out why encoder does not survive reconfiguration - amf_encoder_info.update = amf_hevc_update; */ + amf_encoder_info.update = amf_hevc_update; amf_encoder_info.encode_texture = amf_encode_tex; amf_encoder_info.get_defaults = amf_defaults; amf_encoder_info.get_properties = amf_hevc_properties; @@ -1947,12 +1953,17 @@ try { int64_t cq_level = obs_data_get_int(settings, "cqp"); const char *rc_str = obs_data_get_string(settings, "rate_control"); int rc = get_av1_rate_control(rc_str); + AMF_RESULT res = AMF_OK; amf_av1_update_data(enc, rc, bitrate * 1000, cq_level); - AMF_RESULT res = enc->amf_encoder->ReInit(enc->cx, enc->cy); + res = enc->amf_encoder->Flush(); if (res != AMF_OK) - throw amf_error("AMFComponent::Init failed", res); + throw amf_error("AMFComponent::Flush failed", res); + + res = enc->amf_encoder->ReInit(enc->cx, enc->cy); + if (res != AMF_OK) + throw amf_error("AMFComponent::ReInit failed", res); return true; @@ -2153,8 +2164,7 @@ static void register_av1() amf_encoder_info.get_name = amf_av1_get_name; amf_encoder_info.create = amf_av1_create_texencode; amf_encoder_info.destroy = amf_destroy; - /* FIXME: Figure out why encoder does not survive reconfiguration - amf_encoder_info.update = amf_av1_update; */ + amf_encoder_info.update = amf_av1_update; amf_encoder_info.encode_texture = amf_encode_tex; amf_encoder_info.get_defaults = amf_av1_defaults; amf_encoder_info.get_properties = amf_av1_properties; From 946b0167e9dcbbeb8b049321606ac3903f46f8c1 Mon Sep 17 00:00:00 2001 From: rhutsAMD <71274498+rhutsAMD@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:56:07 -0400 Subject: [PATCH 72/93] obs-ffmpeg: Consider requested throughput in AMF preset fallback (cherry picked from commit 4bfe29152064f7aaeebb388809805523c8878b1f) --- plugins/obs-ffmpeg/texture-amf.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp index c683d1bdf..4f90087c4 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -104,6 +104,7 @@ struct amf_base { AMF_SURFACE_FORMAT amf_format; amf_int64 max_throughput = 0; + amf_int64 requested_throughput = 0; amf_int64 throughput = 0; int64_t dts_offset = 0; uint32_t cx; @@ -440,6 +441,8 @@ static inline void refresh_throughput_caps(amf_base *enc, const char *&preset) if (res == AMF_OK) { caps->GetProperty(get_opt_name(CAP_MAX_THROUGHPUT), &enc->max_throughput); + caps->GetProperty(get_opt_name(CAP_REQUESTED_THROUGHPUT), + &enc->requested_throughput); } } @@ -451,7 +454,8 @@ static inline void check_preset_compatibility(amf_base *enc, * throughput, switch to a lower preset. */ if (astrcmpi(preset, "highQuality") == 0) { - if (!enc->max_throughput) { + if (enc->max_throughput - enc->requested_throughput < + enc->throughput) { preset = "quality"; set_opt(QUALITY_PRESET, get_preset(enc, preset)); } else { @@ -467,7 +471,8 @@ static inline void check_preset_compatibility(amf_base *enc, preset = "balanced"; set_opt(QUALITY_PRESET, get_preset(enc, preset)); } else { - if (enc->max_throughput < enc->throughput) { + if (enc->max_throughput - enc->requested_throughput < + enc->throughput) { preset = "balanced"; refresh_throughput_caps(enc, preset); } @@ -476,7 +481,8 @@ static inline void check_preset_compatibility(amf_base *enc, if (astrcmpi(preset, "balanced") == 0) { if (enc->max_throughput && - enc->max_throughput < enc->throughput) { + enc->max_throughput - enc->requested_throughput < + enc->throughput) { preset = "speed"; refresh_throughput_caps(enc, preset); } @@ -1368,6 +1374,8 @@ static void amf_avc_create_internal(amf_base *enc, obs_data_t *settings) &enc->bframes_supported); caps->GetProperty(AMF_VIDEO_ENCODER_CAP_MAX_THROUGHPUT, &enc->max_throughput); + caps->GetProperty(AMF_VIDEO_ENCODER_CAP_REQUESTED_THROUGHPUT, + &enc->requested_throughput); } const char *preset = obs_data_get_string(settings, "preset"); @@ -1700,6 +1708,9 @@ static void amf_hevc_create_internal(amf_base *enc, obs_data_t *settings) if (res == AMF_OK) { caps->GetProperty(AMF_VIDEO_ENCODER_HEVC_CAP_MAX_THROUGHPUT, &enc->max_throughput); + caps->GetProperty( + AMF_VIDEO_ENCODER_HEVC_CAP_REQUESTED_THROUGHPUT, + &enc->requested_throughput); } const bool is10bit = enc->amf_format == AMF_SURFACE_P010; @@ -2038,6 +2049,9 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) if (res == AMF_OK) { caps->GetProperty(AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT, &enc->max_throughput); + caps->GetProperty( + AMF_VIDEO_ENCODER_AV1_CAP_REQUESTED_THROUGHPUT, + &enc->requested_throughput); } const bool is10bit = enc->amf_format == AMF_SURFACE_P010; From 018bfe87e7206181a8129effe861cb5bf4427b8d Mon Sep 17 00:00:00 2001 From: tududweb Date: Wed, 7 Sep 2022 18:05:19 +0800 Subject: [PATCH 73/93] UI: Don't trigger a settings update when list is empty To avoid recursive call (cherry picked from commit 4871fd301afb9806e158e6b0ebad3ba74868602d) --- UI/properties-view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/properties-view.cpp b/UI/properties-view.cpp index f82680426..9a4f41538 100644 --- a/UI/properties-view.cpp +++ b/UI/properties-view.cpp @@ -647,7 +647,7 @@ QWidget *OBSPropertiesView::AddList(obs_property_t *prop, bool &warning) children.emplace_back(info); /* trigger a settings update if the index was not found */ - if (idx == -1) + if (count && idx == -1) info->ControlChanged(); return combo; From 6dbf45dce947aa2cfadcb39354552e22398483d8 Mon Sep 17 00:00:00 2001 From: Gol-D-Ace Date: Thu, 8 Jun 2023 16:36:27 +0200 Subject: [PATCH 74/93] win-capture: Add Honkai: Star Rail to compatibility list (cherry picked from commit d3df414603fe12848055153b3fc63565a53ce6be) --- plugins/win-capture/data/compatibility.json | 14 ++++++++++++++ plugins/win-capture/data/package.json | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/win-capture/data/compatibility.json b/plugins/win-capture/data/compatibility.json index 1a1347106..8f30dbc46 100644 --- a/plugins/win-capture/data/compatibility.json +++ b/plugins/win-capture/data/compatibility.json @@ -211,6 +211,20 @@ "window_capture_wgc": false, "message": "Edge may not be capturable using the selected Capture Method (BitBlt).", "url": "" + }, + { + "name": "Honkai: Star Rail", + "translation_key": "Compatibility.GameCapture.Admin", + "severity": 1, + "executable": "StarRail.exe", + "window_class": "", + "window_title": "", + "match_flags": 1, + "game_capture": true, + "window_capture": false, + "window_capture_wgc": false, + "message": "Honkai: Star Rail may require OBS to be run as admin to use Game Capture.", + "url": "https://obsproject.com/kb/game-capture-troubleshooting" } ] } diff --git a/plugins/win-capture/data/package.json b/plugins/win-capture/data/package.json index 4bc99d9db..7737647f9 100644 --- a/plugins/win-capture/data/package.json +++ b/plugins/win-capture/data/package.json @@ -1,11 +1,11 @@ { "$schema": "schema/package-schema.json", "url": "https://obsproject.com/obs2_update/win-capture/v1", - "version": 1, + "version": 2, "files": [ { "name": "compatibility.json", - "version": 1 + "version": 2 } ] } From a305137392b9d0b32ddbdf80fb9d49dbc24776d0 Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Wed, 7 Jun 2023 23:34:39 +0200 Subject: [PATCH 75/93] win-capture: Skip compat helper matching if properties are null Fixes compatibility messages appearing when no window is selected in window capture properties. (cherry picked from commit b756c78f44f1127d2d0c66ac0dcfeb0017a3a54e) --- plugins/win-capture/compat-helpers.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/win-capture/compat-helpers.c b/plugins/win-capture/compat-helpers.c index 2ba9ce5c5..f4d5565ec 100644 --- a/plugins/win-capture/compat-helpers.c +++ b/plugins/win-capture/compat-helpers.c @@ -145,16 +145,17 @@ struct compat_result *check_compatibility(const char *win_title, const char *j_title = get_string_val(entry, "window_title"); const char *j_class = get_string_val(entry, "window_class"); - if (win_class && (match_flags & MATCH_CLASS) && - strcmp(win_class, j_class) != 0) + if ((match_flags & MATCH_CLASS) && + (!win_class || strcmp(win_class, j_class) != 0)) continue; - if (exe && (match_flags & MATCH_EXE) && - astrcmpi(exe, j_exe) != 0) + if ((match_flags & MATCH_EXE) && + (!exe || astrcmpi(exe, j_exe) != 0)) continue; /* Title supports partial matches as some games append additional * information after the title, e.g., "Minecraft 1.18". */ - if (win_title && (match_flags & MATCH_TITLE) && - astrcmpi_n(win_title, j_title, strlen(j_title)) != 0) + if ((match_flags & MATCH_TITLE) && + (!win_title || + astrcmpi_n(win_title, j_title, strlen(j_title)) != 0)) continue; /* Attempt to translate and compile message */ From e1e0d944fc085fd6ec35448efdec8969a443f9c3 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 10 Jun 2023 02:02:51 +0900 Subject: [PATCH 76/93] libobs/util: Fix use-after-free in darray_insert_new After the array is allocated in `darray_ensure_capacity`, the pointer `item` is invalid. (cherry picked from commit d040de51bb098a1f72a70cbed850e0b99e999071) --- libobs/util/darray.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libobs/util/darray.h b/libobs/util/darray.h index 2b308eb22..553b2a95b 100644 --- a/libobs/util/darray.h +++ b/libobs/util/darray.h @@ -269,10 +269,11 @@ static inline void *darray_insert_new(const size_t element_size, if (idx == dst->num) return darray_push_back_new(element_size, dst); + darray_ensure_capacity(element_size, dst, ++dst->num); + item = darray_item(element_size, dst, idx); move_count = dst->num - idx; - darray_ensure_capacity(element_size, dst, ++dst->num); memmove(darray_item(element_size, dst, idx + 1), item, move_count * element_size); From 72ced7fa91665c3f119b320ead07995123a2354d Mon Sep 17 00:00:00 2001 From: Lain Date: Sat, 10 Jun 2023 12:27:16 -0700 Subject: [PATCH 77/93] libobs/util: Actually fix use-after-free in da_insert_new d040de51bb098a1f72a70cbed850e0b99e999071 was prematurely merged, this should actually do the job as requested. (cherry picked from commit 9178ec6a8d5bbe523f61be8c6092ff29817b0c15) --- libobs/util/darray.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libobs/util/darray.h b/libobs/util/darray.h index 553b2a95b..ed566332d 100644 --- a/libobs/util/darray.h +++ b/libobs/util/darray.h @@ -269,11 +269,10 @@ static inline void *darray_insert_new(const size_t element_size, if (idx == dst->num) return darray_push_back_new(element_size, dst); + move_count = dst->num - idx; darray_ensure_capacity(element_size, dst, ++dst->num); item = darray_item(element_size, dst, idx); - - move_count = dst->num - idx; memmove(darray_item(element_size, dst, idx + 1), item, move_count * element_size); From 59cb2c2185a38dc4019c38343b4f2456b70335cd Mon Sep 17 00:00:00 2001 From: Exeldro Date: Fri, 9 Jun 2023 08:51:45 +0200 Subject: [PATCH 78/93] libobs: Don't keep the sources mutex in tick_sources Allow other threads to use sources while the graphics thread does video_tick, update, activate and deactivate on sources (cherry picked from commit a77789b2667388485851605fc3ede805c9fa569f) --- libobs/obs-internal.h | 1 + libobs/obs-video.c | 29 ++++++++++++++++++----------- libobs/obs.c | 1 + 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 1ea555c3a..ebb56975f 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -419,6 +419,7 @@ struct obs_core_data { volatile bool valid; DARRAY(char *) protocols; + DARRAY(obs_source_t *) sources_to_tick; }; /* user hotkeys */ diff --git a/libobs/obs-video.c b/libobs/obs-video.c index 60acaaf6f..2ce3401e1 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -45,35 +45,42 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time) /* ------------------------------------- */ /* call tick callbacks */ - pthread_mutex_lock(&obs->data.draw_callbacks_mutex); + pthread_mutex_lock(&data->draw_callbacks_mutex); - for (size_t i = obs->data.tick_callbacks.num; i > 0; i--) { + for (size_t i = data->tick_callbacks.num; i > 0; i--) { struct tick_callback *callback; - callback = obs->data.tick_callbacks.array + (i - 1); + callback = data->tick_callbacks.array + (i - 1); callback->tick(callback->param, seconds); } - pthread_mutex_unlock(&obs->data.draw_callbacks_mutex); + pthread_mutex_unlock(&data->draw_callbacks_mutex); /* ------------------------------------- */ - /* call the tick function of each source */ + /* get an array of all sources to tick */ + + data->sources_to_tick.num = 0; pthread_mutex_lock(&data->sources_mutex); source = data->sources; while (source) { obs_source_t *s = obs_source_get_ref(source); - - if (s) { - obs_source_video_tick(s, seconds); - obs_source_release(s); - } - + if (s) + da_push_back(data->sources_to_tick, &s); source = (struct obs_source *)source->context.hh_uuid.next; } pthread_mutex_unlock(&data->sources_mutex); + /* ------------------------------------- */ + /* call the tick function of each source */ + + for (size_t i = 0; i < data->sources_to_tick.num; i++) { + obs_source_t *s = data->sources_to_tick.array[i]; + obs_source_video_tick(s, seconds); + obs_source_release(s); + } + return cur_time; } diff --git a/libobs/obs.c b/libobs/obs.c index 1850ecc75..01fa16537 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -1083,6 +1083,7 @@ static void obs_free_data(void) for (size_t i = 0; i < data->protocols.num; i++) bfree(data->protocols.array[i]); da_free(data->protocols); + da_free(data->sources_to_tick); } static const char *obs_signals[] = { From 3d64f339cfc98d005418fbd0923171cbbe038eee Mon Sep 17 00:00:00 2001 From: Lain Date: Sat, 10 Jun 2023 14:29:33 -0700 Subject: [PATCH 79/93] libobs/util: Add da_clear() Adds a bit more of an explicit function for clearing dynamic arrays (cherry picked from commit 85ca5a25bee99f5b64d4bdb484aecf77a3638e72) --- libobs/util/darray.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libobs/util/darray.h b/libobs/util/darray.h index ed566332d..dba5c5d15 100644 --- a/libobs/util/darray.h +++ b/libobs/util/darray.h @@ -121,6 +121,11 @@ static inline void darray_ensure_capacity(const size_t element_size, dst->capacity = new_cap; } +static inline void darray_clear(struct darray *dst) +{ + dst->num = 0; +} + static inline void darray_resize(const size_t element_size, struct darray *dst, const size_t size) { @@ -487,6 +492,8 @@ static inline void darray_swap(const size_t element_size, struct darray *dst, #define da_resize(v, size) darray_resize(sizeof(*v.array), &v.da, size) +#define da_clear(v) darray_clear(&v.da) + #define da_copy(dst, src) darray_copy(sizeof(*dst.array), &dst.da, &src.da) #define da_copy_array(dst, src_array, n) \ From 12110325b8e9a6055fb0e1fc171136b7ff2de922 Mon Sep 17 00:00:00 2001 From: Lain Date: Sat, 10 Jun 2023 14:30:44 -0700 Subject: [PATCH 80/93] libobs: Use da_clear() to clear obs_core_data::sources_to_tick Makes it a bit more clear what's going on (cherry picked from commit 1aed7ed1147fe5fcb34834e8e0966b8de27a29f4) --- libobs/obs-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-video.c b/libobs/obs-video.c index 2ce3401e1..4732d2d0f 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -58,7 +58,7 @@ static uint64_t tick_sources(uint64_t cur_time, uint64_t last_time) /* ------------------------------------- */ /* get an array of all sources to tick */ - data->sources_to_tick.num = 0; + da_clear(data->sources_to_tick); pthread_mutex_lock(&data->sources_mutex); From c67f78b1222a6ae91ace757ab9445ff51561f1dc Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Sat, 10 Jun 2023 15:30:33 +0700 Subject: [PATCH 81/93] deps/obs-scripting: Fix crash removing callbacks in script_unload Signed-off-by: Ilya Chernikov (cherry picked from commit a609cfb2f0f368cc4ebb5d83da33f2cb333d4c0a) --- deps/obs-scripting/obs-scripting-lua.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deps/obs-scripting/obs-scripting-lua.c b/deps/obs-scripting/obs-scripting-lua.c index e4cf186f2..042b9cd7d 100644 --- a/deps/obs-scripting/obs-scripting-lua.c +++ b/deps/obs-scripting/obs-scripting-lua.c @@ -1228,10 +1228,13 @@ void obs_lua_script_unload(obs_script_t *s) /* call script_unload */ pthread_mutex_lock(&data->mutex); + current_lua_script = data; lua_getglobal(script, "script_unload"); lua_pcall(script, 0, 0, 0); + current_lua_script = NULL; + /* ---------------------------- */ /* remove all callbacks */ From 850df1058f82e9d2ff4e780551fe2e6889a6d425 Mon Sep 17 00:00:00 2001 From: CodeYan01 <65320293+CodeYan01@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:00:05 +0800 Subject: [PATCH 82/93] docs: Clarify da_erase_range (cherry picked from commit 26003fdf796e09a872af6f44b00a11bd2d50f13e) --- docs/sphinx/reference-libobs-util-darray.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/reference-libobs-util-darray.rst b/docs/sphinx/reference-libobs-util-darray.rst index 09365b4d2..cebace95a 100644 --- a/docs/sphinx/reference-libobs-util-darray.rst +++ b/docs/sphinx/reference-libobs-util-darray.rst @@ -236,7 +236,8 @@ dynamic array value with a reference (&) operator. For example: .. function:: void da_erase_range(da, size_t start_idx, size_t end_idx) - Erases a range of values. + Erases a range of values, including the element at ``start_idx``, but + not the one at ``end_idx``. :param da: The dynamic array :param start_idx: The starting index From 0be3b3b8453a2eb636d92793efda7d61ec435885 Mon Sep 17 00:00:00 2001 From: Exeldro Date: Fri, 9 Jun 2023 09:15:19 +0200 Subject: [PATCH 83/93] UI: Don't update text source when nothing changed (cherry picked from commit e830043851a4dc39cd67f81bc9b25cf8666ef613) --- UI/context-bar-controls.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/UI/context-bar-controls.cpp b/UI/context-bar-controls.cpp index 55fe20495..73c37582e 100644 --- a/UI/context-bar-controls.cpp +++ b/UI/context-bar-controls.cpp @@ -728,12 +728,15 @@ void TextSourceToolbar::on_text_textChanged() if (!source) { return; } - + std::string newText = QT_TO_UTF8(ui->text->text()); + OBSDataAutoRelease settings = obs_source_get_settings(source); + if (newText == obs_data_get_string(settings, "text")) { + return; + } SaveOldProperties(source); - OBSDataAutoRelease settings = obs_data_create(); - obs_data_set_string(settings, "text", QT_TO_UTF8(ui->text->text())); - obs_source_update(source, settings); + obs_data_set_string(settings, "text", newText.c_str()); + obs_source_update(source, nullptr); SetUndoProperties(source, true); } From e0519ed1e8fc5e3b7e60fe038dc92e275a707dba Mon Sep 17 00:00:00 2001 From: gxalpha Date: Thu, 8 Jun 2023 21:52:20 +0200 Subject: [PATCH 84/93] mac-capture: Explicitly set clear background for SCK (cherry picked from commit 2ea47bb65adb896e23a50d553fd6f6866d89aa81) --- plugins/mac-capture/mac-screen-capture.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/mac-capture/mac-screen-capture.m b/plugins/mac-capture/mac-screen-capture.m index cc3a5acc8..615394824 100644 --- a/plugins/mac-capture/mac-screen-capture.m +++ b/plugins/mac-capture/mac-screen-capture.m @@ -455,9 +455,12 @@ static bool init_screen_stream(struct screen_capture *sc) } break; } os_sem_post(sc->shareable_content_available); + + CGColorRef background = CGColorGetConstantColor(kCGColorClear); [sc->stream_properties setQueueDepth:8]; [sc->stream_properties setShowsCursor:!sc->hide_cursor]; [sc->stream_properties setColorSpaceName:kCGColorSpaceDisplayP3]; + [sc->stream_properties setBackgroundColor:background]; FourCharCode l10r_type = 0; l10r_type = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; [sc->stream_properties setPixelFormat:l10r_type]; From c6ac31f7e135a22b898aa8348cf827c0205d5832 Mon Sep 17 00:00:00 2001 From: John Bradley Date: Wed, 14 Jun 2023 23:53:55 -0500 Subject: [PATCH 85/93] libobs: Set video thread qos class to user interactive on macOS (cherry picked from commit 8981afe5b49269ad3961e5fd5eb82b0118b6f20e) --- libobs/obs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libobs/obs.c b/libobs/obs.c index 01fa16537..a19b9331b 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -748,7 +748,10 @@ static int obs_init_video(struct obs_video_info *ovi) int errorcode; #ifdef __APPLE__ - errorcode = pthread_create(&video->video_thread, NULL, + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INTERACTIVE, 0); + errorcode = pthread_create(&video->video_thread, &attr, obs_graphics_thread_autorelease, obs); #else errorcode = pthread_create(&video->video_thread, NULL, From 2b7cca859591e9ed536bba2e66efc7e6576b6afb Mon Sep 17 00:00:00 2001 From: Ryan Foster Date: Thu, 15 Jun 2023 21:01:09 -0400 Subject: [PATCH 86/93] obs-websocket: Update version to 5.2.3 (cherry picked from commit ced135a68e6fd1992708ef7a82a38a44649d3aea) --- plugins/obs-websocket | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/obs-websocket b/plugins/obs-websocket index 57a9c19f2..6fd18a7ef 160000 --- a/plugins/obs-websocket +++ b/plugins/obs-websocket @@ -1 +1 @@ -Subproject commit 57a9c19f2ccf4e5452baeffd78014579622b9f3a +Subproject commit 6fd18a7ef1ecb149e8444154af1daab61d4241a9 From e3cccac6ba7616f54c1a532220c2f8c855a93e11 Mon Sep 17 00:00:00 2001 From: "Huts, Roman" <71274498+rhutsAMD@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:29:57 -0400 Subject: [PATCH 87/93] obs-ffmpeg: Fix logic in one of the AMF preset fallback checks (cherry picked from commit 94d0b654f0f8c11325e18424c7bf96f0b7f8d815) --- plugins/obs-ffmpeg/texture-amf.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp index 4f90087c4..694156e32 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -454,12 +454,12 @@ static inline void check_preset_compatibility(amf_base *enc, * throughput, switch to a lower preset. */ if (astrcmpi(preset, "highQuality") == 0) { - if (enc->max_throughput - enc->requested_throughput < - enc->throughput) { + if (!enc->max_throughput) { preset = "quality"; set_opt(QUALITY_PRESET, get_preset(enc, preset)); } else { - if (enc->max_throughput < enc->throughput) { + if (enc->max_throughput - enc->requested_throughput < + enc->throughput) { preset = "quality"; refresh_throughput_caps(enc, preset); } From 8915d7c3bd01a5dabc9029ba3a3508507f09540f Mon Sep 17 00:00:00 2001 From: Lain Date: Sat, 17 Jun 2023 00:44:00 -0700 Subject: [PATCH 88/93] libobs: Update version to 29.1.3 --- libobs/obs-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-config.h b/libobs/obs-config.h index 20ce99aab..4ea959779 100644 --- a/libobs/obs-config.h +++ b/libobs/obs-config.h @@ -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) From eae2affc09dc2a39474ddc81079e6f9409c95a13 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 17 Jun 2023 23:07:37 +0900 Subject: [PATCH 89/93] text-freetype2: Fix not updating chat log mode property (cherry picked from commit 43f7c8c928b63ddf7e39eebc86dcb41478591eaa) --- plugins/text-freetype2/text-freetype2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/text-freetype2/text-freetype2.c b/plugins/text-freetype2/text-freetype2.c index 31bd8f53a..4c7e06987 100644 --- a/plugins/text-freetype2/text-freetype2.c +++ b/plugins/text-freetype2/text-freetype2.c @@ -376,7 +376,10 @@ static void ft2_source_update(void *data, obs_data_t *settings) srcdata->log_lines = log_lines; vbuf_needs_update = true; } - srcdata->log_mode = chat_log_mode; + if (srcdata->log_mode != chat_log_mode) { + srcdata->log_mode = chat_log_mode; + vbuf_needs_update = true; + } if (ft2_lib == NULL) goto error; From e2c481cf9542abfaea39d28ad23022bfdab73d84 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 17 Jun 2023 23:32:26 +0900 Subject: [PATCH 90/93] UI: Fix checked state of source toolbar menu item After the source toolbar was hidden or shown by a hotkey, the checked state of the menu item was not updated. (cherry picked from commit a1c88d58fcc57a605fe249d1034a69906570d700) --- UI/window-basic-main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index c02f8f04f..ddd2a3983 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -9365,11 +9365,13 @@ void OBSBasic::on_toggleListboxToolbars_toggled(bool visible) void OBSBasic::ShowContextBar() { on_toggleContextBar_toggled(true); + ui->toggleContextBar->setChecked(true); } void OBSBasic::HideContextBar() { on_toggleContextBar_toggled(false); + ui->toggleContextBar->setChecked(false); } void OBSBasic::on_toggleContextBar_toggled(bool visible) From 4e1e9470950152bda7ff7a310c56a931abdb9a88 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 18 Jun 2023 01:24:00 +0900 Subject: [PATCH 91/93] UI: Fix changing quick transition to/from fade to black (cherry picked from commit 35463cb46449aa494a9deb5a2ce48521348abab7) --- UI/window-basic-main-transitions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UI/window-basic-main-transitions.cpp b/UI/window-basic-main-transitions.cpp index beb5b1f60..ffc19a7cc 100644 --- a/UI/window-basic-main-transitions.cpp +++ b/UI/window-basic-main-transitions.cpp @@ -1476,6 +1476,7 @@ void OBSBasic::QuickTransitionChange() trIdx); if (tr) { qt->source = tr; + qt->fadeToBlack = fadeToBlack; ResetQuickTransitionText(qt); } } From 0b7ac961574387a0e98ee6cf38c748bcfc56ee1f Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 18 Jun 2023 01:47:43 +0900 Subject: [PATCH 92/93] UI: Fix changed state of audio settings When changing audio channels, sample rate, or audio buffering settings multiple times by hitting `Apply` button, the internal `changed` state got corrupted. To avoid this, set the changed state when changed something, but do not clear the changed state. (cherry picked from commit 846cdafbed4a3e84f42a35cd0bfd38a2bf5e205d) --- UI/window-basic-settings.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 6676a36c0..581493978 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -4643,17 +4643,15 @@ void OBSBasicSettings::AudioChangedRestart() if (currentChannelIndex != channelIndex || currentSampleRateIndex != sampleRateIndex || currentLLAudioBufVal != llBufferingEnabled) { - audioChanged = true; ui->audioMsg->setText( QTStr("Basic.Settings.ProgramRestart")); - sender()->setProperty("changed", QVariant(true)); - EnableApplyButton(true); } else { - audioChanged = false; ui->audioMsg->setText(""); - sender()->setProperty("changed", QVariant(false)); - EnableApplyButton(false); } + + audioChanged = true; + sender()->setProperty("changed", QVariant(true)); + EnableApplyButton(true); } } From c58e511813c33e93da7637d50aa431ae0cddda0c Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 18 Jun 2023 02:18:06 +0900 Subject: [PATCH 93/93] UI: Translate place holder name for new group (cherry picked from commit 323f3957cdebcdf0b1326bd3bae0339adacb45c3) --- UI/window-basic-source-select.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UI/window-basic-source-select.cpp b/UI/window-basic-source-select.cpp index 38308b5be..85edea1e8 100644 --- a/UI/window-basic-source-select.cpp +++ b/UI/window-basic-source-select.cpp @@ -367,6 +367,8 @@ static inline const char *GetSourceDisplayName(const char *id) { if (strcmp(id, "scene") == 0) return Str("Basic.Scene"); + else if (strcmp(id, "group") == 0) + return Str("Group"); const char *v_id = obs_get_latest_input_type_id(id); return obs_source_get_display_name(v_id); }