forked from livekit/client-sdk-swift
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
commit aa0a21d Author: Jacob Gelman <3182119+ladvoc@users.noreply.github.com> Date: Thu Feb 13 06:28:21 2025 -0800 Simplify broadcast extension setup with standard format for identifiers (livekit#573) When configuring a broadcast extension, manually setting the info keys `RTCAppGroupIdentifier` and `RTCScreenSharingExtension` is no longer required when using the standard format. The standard format is as follows: - App group: `group.<main-app-bundle-id>` - Broadcast extension: `<main-app-bundle-id>.broadcast` --------- Co-authored-by: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> commit c3ee701 Author: Jacob Gelman <3182119+ladvoc@users.noreply.github.com> Date: Thu Feb 13 06:05:00 2025 -0800 Deprecate public broadcast picker extension (livekit#586) Public show method defined as an extension to `RPSystemBroadcastPickerView` has been deprecated in favor of `BroadcastManager.shared.requestActivation()`. --------- Co-authored-by: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> commit 0da6660 Author: Jacob Gelman <3182119+ladvoc@users.noreply.github.com> Date: Thu Feb 13 05:55:25 2025 -0800 Release automation (livekit#579) - Add version and platform compatibility badges from [Swift Package Index](https://swiftpackageindex.com/) to README - Automatically updated on each release - Add [nanpa](https://github.com/nbsp/nanpa) configuration - Custom script bumps version across repo (currently Podspec, README, and LiveKitSDK class) - GitHub publish workflow (based on workflow from livekit/rust-sdks) - Create workflow to push new releases to Cocopods when a release is published on GitHub I have also added changeset files to my currently open PRs (livekit#565, livekit#576, and livekit#573) that can be used to test this configuration. --------- Co-authored-by: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> commit 5b031c8 Author: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Thu Feb 13 22:36:35 2025 +0900 Update Podspec (livekit#587) Fixes: livekit#566 commit 485e76d Author: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed Feb 12 14:36:48 2025 +0900 macOS screen share audio (livekit#561)
- Loading branch information
1 parent
4a44ee9
commit 3b4e327
Showing
20 changed files
with
380 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: Bump version | ||
on: | ||
workflow_dispatch: | ||
env: | ||
PACKAGE_NAME: client-sdk-swift | ||
jobs: | ||
bump: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
ssh-key: ${{ secrets.NANPA_KEY }} | ||
- uses: nbsp/ilo@v1 | ||
with: | ||
packages: ${{ env.PACKAGE_NAME }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: Push to Cocoapods | ||
on: | ||
workflow_dispatch: | ||
release: | ||
types: [published] | ||
env: | ||
PODSPEC_FILE: LiveKitClient.podspec | ||
jobs: | ||
build: | ||
runs-on: macos-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Install Cocoapods | ||
run: gem install cocoapods | ||
- name: Validate Podspec | ||
run: pod lib lint --allow-warnings | ||
- name: Publish to CocoaPods | ||
run: pod trunk push ${{ env.PODSPEC_FILE }} --allow-warnings --verbose | ||
env: | ||
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Add changeset files in this directory. | ||
|
||
See nanpa documentation for more info: | ||
https://github.com/nbsp/nanpa/blob/trunk/doc/nanpa-changeset.5.scd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
patch type="change" "Simplify broadcast extension setup with standard format for identifiers" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
patch type="deprecated" "Deprecated public method to show broadcast picker" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
version 2.1.1 | ||
name client-sdk-swift | ||
custom ./scripts/replace_version.sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* Copyright 2025 LiveKit | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
@preconcurrency import AVFoundation | ||
|
||
#if swift(>=5.9) | ||
internal import LiveKitWebRTC | ||
#else | ||
@_implementationOnly import LiveKitWebRTC | ||
#endif | ||
|
||
public final class DefaultMixerAudioObserver: AudioEngineObserver, Loggable { | ||
public var next: (any AudioEngineObserver)? { | ||
get { _state.next } | ||
set { _state.mutate { $0.next = newValue } } | ||
} | ||
|
||
/// Adjust the volume of captured app audio. Range is 0.0 ~ 1.0. | ||
public var appVolume: Float { | ||
get { _state.read { $0.appMixerNode.outputVolume } } | ||
set { _state.mutate { $0.appMixerNode.outputVolume = newValue } } | ||
} | ||
|
||
/// Adjust the volume of microphone audio. Range is 0.0 ~ 1.0. | ||
public var micVolume: Float { | ||
get { _state.read { $0.micMixerNode.outputVolume } } | ||
set { _state.mutate { $0.micMixerNode.outputVolume = newValue } } | ||
} | ||
|
||
// MARK: - Internal | ||
|
||
var appAudioNode: AVAudioPlayerNode { | ||
_state.read { $0.appNode } | ||
} | ||
|
||
var micAudioNode: AVAudioPlayerNode { | ||
_state.read { $0.micNode } | ||
} | ||
|
||
var isConnected: Bool { | ||
_state.read { $0.isConnected } | ||
} | ||
|
||
struct State { | ||
var next: (any AudioEngineObserver)? | ||
|
||
// AppAudio | ||
public let appNode = AVAudioPlayerNode() | ||
public let appMixerNode = AVAudioMixerNode() | ||
|
||
// Not connected for device rendering mode. | ||
public let micNode = AVAudioPlayerNode() | ||
public let micMixerNode = AVAudioMixerNode() | ||
|
||
public var isConnected: Bool = false | ||
} | ||
|
||
let _state = StateSync(State()) | ||
|
||
public init() {} | ||
|
||
public func setNext(_ handler: any AudioEngineObserver) { | ||
next = handler | ||
} | ||
|
||
public func engineDidCreate(_ engine: AVAudioEngine) { | ||
let (appNode, appMixerNode, micNode, micMixerNode) = _state.read { | ||
($0.appNode, $0.appMixerNode, $0.micNode, $0.micMixerNode) | ||
} | ||
|
||
engine.attach(appNode) | ||
engine.attach(appMixerNode) | ||
engine.attach(micNode) | ||
engine.attach(micMixerNode) | ||
|
||
// Invoke next | ||
next?.engineDidCreate(engine) | ||
} | ||
|
||
public func engineWillRelease(_ engine: AVAudioEngine) { | ||
// Invoke next | ||
next?.engineWillRelease(engine) | ||
|
||
let (appNode, appMixerNode, micNode, micMixerNode) = _state.read { | ||
($0.appNode, $0.appMixerNode, $0.micNode, $0.micMixerNode) | ||
} | ||
|
||
engine.detach(appNode) | ||
engine.detach(appMixerNode) | ||
engine.detach(micNode) | ||
engine.detach(micMixerNode) | ||
} | ||
|
||
public func engineWillConnectInput(_ engine: AVAudioEngine, src: AVAudioNode?, dst: AVAudioNode, format: AVAudioFormat, context: [AnyHashable: Any]) { | ||
// Get the main mixer | ||
guard let mainMixerNode = context[kRTCAudioEngineInputMixerNodeKey] as? AVAudioMixerNode else { | ||
// If failed to get main mixer, call next and return. | ||
next?.engineWillConnectInput(engine, src: src, dst: dst, format: format, context: context) | ||
return | ||
} | ||
|
||
// Read nodes from state lock. | ||
let (appNode, appMixerNode, micNode, micMixerNode) = _state.read { | ||
($0.appNode, $0.appMixerNode, $0.micNode, $0.micMixerNode) | ||
} | ||
|
||
// TODO: Investigate if possible to get this format prior to starting screen capture. | ||
// <AVAudioFormat 0x600003055180: 2 ch, 48000 Hz, Float32, deinterleaved> | ||
let appAudioNodeFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, | ||
sampleRate: format.sampleRate, // Assume same sample rate | ||
channels: 2, | ||
interleaved: false) | ||
|
||
log("Connecting app -> appMixer -> mainMixer") | ||
// appAudio -> appAudioMixer -> mainMixer | ||
engine.connect(appNode, to: appMixerNode, format: appAudioNodeFormat) | ||
engine.connect(appMixerNode, to: mainMixerNode, format: format) | ||
|
||
// src is not null if device rendering mode. | ||
if let src { | ||
log("Connecting src (device) to micMixer -> mainMixer") | ||
// mic (device) -> micMixer -> mainMixer | ||
engine.connect(src, to: micMixerNode, format: format) | ||
} | ||
|
||
// TODO: Investigate if possible to get this format prior to starting screen capture. | ||
let micNodeFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, | ||
sampleRate: format.sampleRate, // Assume same sample rate | ||
channels: 1, // Mono | ||
interleaved: false) | ||
|
||
log("Connecting micAudio (player) to micMixer -> mainMixer") | ||
// mic (player) -> micMixer -> mainMixer | ||
engine.connect(micNode, to: micMixerNode, format: micNodeFormat) | ||
// Always connect micMixer to mainMixer | ||
engine.connect(micMixerNode, to: mainMixerNode, format: format) | ||
|
||
_state.mutate { $0.isConnected = true } | ||
|
||
// Invoke next | ||
next?.engineWillConnectInput(engine, src: src, dst: dst, format: format, context: context) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.