Skip to content

Patch 1.0.9#119

Merged
hanatyan128 merged 78 commits into
masterfrom
dev
Apr 11, 2026
Merged

Patch 1.0.9#119
hanatyan128 merged 78 commits into
masterfrom
dev

Conversation

@hanatyan128 hanatyan128 added this to the 1.1.0 milestone Mar 14, 2026
@hanatyan128 hanatyan128 linked an issue Mar 14, 2026 that may be closed by this pull request
hanatyan128 and others added 29 commits March 30, 2026 04:31
… replay buffer

- Refactor startOutput/stopOutput into ensureInfrastructure/releaseInfrastructureIfIdle
  to support shared encoder lifecycle across independently managed outputs
- Add per-output start/stop methods (startStreamingIndividual, stopRecordingIndividual, etc.)
  with internal helpers to eliminate code duplication
- Add INTERLOCK_TYPE_INDIVIDUAL mode that maps OBS streaming/recording/replay buffer
  states to their Branch Output counterparts independently
- Add OutputCell widget to status dock with per-output enable/disable checkbox
  (works in all interlock modes), preserving folder-open click for recording/replay
- Persist per-output enable/disable state in filter settings via save callback
- Add audioMutex to protect audio capture pointers in audioFilterCallback against
  concurrent release in releaseInfrastructureIfIdle
- Add "Individual" locale key to all 10 locale files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix critical resource leak in ensureInfrastructure() on partial failure,
add Individual mode additional output start logic when some outputs are
already active, reset streamingIndividualStopping flag in stopOutput(),
make user-enabled flags thread-safe with std::atomic<bool>, remove unused
RecordingOutputCell/ReplayBufferOutputCell classes, hide checkbox for
ROW_OUTPUT_NONE, improve lock contract documentation, and update Japanese
translation from "インディビデュアル" to "個別連動".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…start

- Change createAndStartStreamingOutputs, createAndStartRecordingOutputChecked,
  createAndStartReplayBufferChecked to return bool (true if output is active)
- Release infrastructure in start*Individual() only when no output started
- Return true when output is already active to avoid false release
- Add filter setting check (isStreamingGroupEnabled, isRecordingEnabled,
  isReplayBufferEnabled) to Individual mode idle path to prevent unconfigured
  output types from blocking subsequent outputs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…s dock

Add RecordingToggleTooltip and ReplayBufferToggleTooltip locale keys
to all 10 locale files and set tooltips on the corresponding
checkboxes in the output status dock for consistency with streaming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Separate INDIVIDUAL stop conditions from user toggle (per-output
  checkbox) to clarify responsibility boundaries
- Move extern pluginMutex declaration to plugin-main.hpp to eliminate
  duplicate declarations and type mismatch risk
- Use getter methods in saveCallback for consistent memory_order_relaxed
  access on atomic user-intent flags
- Fix stopStreamingOutputsGracefully() comment to accurately reflect
  that only outputMutex is required
- Add audioMutex lock in setAudioCapturesActive() to prevent race
  condition with releaseInfrastructureIfIdle()
- Release infrastructure only when all outputs fail to start in
  startOutput(), making the cleanup intent explicit
- Add ensureInfrastructure() precondition to helper function doc comments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace single streamingUserEnabled flag with per-stream array so each
streaming slot can be independently toggled ON/OFF from the status dock.
Previously all streaming checkboxes controlled a shared flag; now each
checkbox controls its own slot with graceful stop support for
reconnecting streams. Includes backward-compatible settings migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hing, and safety

- Make locking consistent across all individual start/stop functions
  (pluginMutex -> outputMutex order) for streaming, recording, and
  replay buffer
- Document lock ordering (pluginMutex -> outputMutex -> audioMutex)
  in plugin-main.hpp
- Batch individual start/stop operations per tick instead of
  one-output-per-tick serialization, treating streaming slots as
  a single output group
- Change individual start/stop functions to return bool indicating
  whether an operation was performed
- Extract startEligibleStreamings lambda to deduplicate streaming
  start logic with streamingIndividualStopping guard
- Move streamingIndividualStopping retry after per-output toggle
  stops so recording/replay buffer stops are not blocked during
  streaming graceful stop
- Add checkbox update guard in OutputTableRow::update() to skip
  unnecessary setChecked() calls
- Add null-check in createAndStartStreamingOutputs() start loop
- Use OBSWeakSourceAutoRelease in OutputCell for lifetime safety

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Read recordingActive/recordingPending and replayBufferActive under
pluginMutex+outputMutex to eliminate data race on non-atomic booleans
in stopRecordingIndividual() and stopReplayBufferIndividual().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch all three mutexes (pluginMutex, outputMutex, audioMutex) to
PTHREAD_MUTEX_RECURSIVE via OBS's pthread_mutex_init_recursive() helper.
This allows the same thread to re-lock a mutex it already holds, removing
the need for separate stopRecordingOutputLocked() and
stopReplayBufferOutputLocked() methods. Callers no longer need to track
whether they already hold outputMutex before calling stop functions.

Also includes review-driven fixes: typo correction, unused function
removal, return-value comment, user-flag guard in startOutput(), and
lock ordering unification in stopOutputGracefully().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change outputStarting to std::atomic<bool> and reconnectAttemptingAt
  to std::atomic<uint64_t> to eliminate data races from OBS signal
  callbacks (starting, activate, reconnect, stop) that write these
  fields on OBS core threads.
- Add default member initializers to BranchOutputStreamingContext,
  removing the explicit zero-init loop in the constructor.
- Change createSreamingOutput() to populate streamings[index] in-place
  and return bool, eliminating the need for move constructor/assignment
  operator on the context struct.
- Cache atomic load in reconnectAttemptingTimedOut() to prevent
  inconsistent reads between the two uses of the value.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
isAnyStreamingUserEnabled() checked all MAX_SERVICES slots, but
unconfigured slots default to enabled and are not visible in the
status dock, so users cannot toggle them off. This caused ALWAYS_ON
mode to rebuild infrastructure every tick.

Add isAnyStreamingUserEnabled(settings) overload that only checks
slots within service_count that are actually configured. Move all
streaming user-enabled accessors from header inline to
plugin-streaming.cpp.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…y_buffer in loadRecently

The legacy streaming_output_enabled key (without index) was for
backward compatibility with an unreleased version, so migration is
unnecessary. Remove it from constructor loading, saveCallback, and
getDefaults. Only indexed streaming_output_enabled_N keys are used.

Also erase replay_buffer from recently settings so new filters do
not inherit the replay buffer enabled state from previous filters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nctions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…art-stop

feat: Add individual start/stop control for streaming, recording, and replay buffer
… recording, and replay buffer control

Register OBS hotkeys to individually enable/disable each output type:
- Enable/Disable All Streaming (independent hotkeys)
- Enable/Disable Streaming Service 1-8 (paired hotkeys per slot)
- Enable/Disable Recording (paired hotkey)
- Enable/Disable Replay Buffer (paired hotkey)

Hotkey callbacks set the userEnabled intent flags and call the
corresponding *Individual() methods. Per-slot streaming callbacks
resolve the slot index by matching obs_hotkey_pair_id against the
stored ID array.

Also refactor existing hotkey callbacks to their respective files:
streaming → plugin-streaming.cpp, recording → plugin-stream-recording.cpp,
replay buffer → plugin-replay-buffer.cpp.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…fixes

- Emit outputUserEnabledChanged signal from setters when value changes,
  connected to status dock for immediate checkbox sync on hotkey press
- Fix hotkey pair toggle logic: return false when already in desired state
  so OBS correctly alternates enable/disable callbacks
- Move setRecordingUserEnabled/setReplayBufferUserEnabled to cpp files
- Add serviceCount check inside isStreamingEnabled to prevent stale slots
- Register hotkeys conditionally based on enabled output types
- Translate hotkey locale strings for all supported languages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, fix thread safety

- Extract unregisterAllHotkeys() helper to eliminate duplicate hotkey
  unregistration code in registerHotkey() and removeCallback()
- Add obs_filter_get_parent() null check in registerHotkey()
- Initialize togglePauseRecordingHotkeyPairId and addChapterToRecordingHotkeyId
  in constructor initializer list to avoid undefined behavior
- Use Qt::QueuedConnection for outputUserEnabledChanged signal connection
  to ensure UI updates run on the UI thread when emitted from OBS core thread
- Remove trailing blank lines before closing braces in streaming hotkey functions
- Document OBS hotkey persistence mechanism (name-string-based keybinding
  restoration) in registerHotkey() comments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…art-stop-hotkeys

feat: Add per-output enable/disable hotkeys
@hanatyan128
hanatyan128 merged commit 61efacd into master Apr 11, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant