Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,12 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install SwiftLint
run: brew install swiftlint
- name: SwiftLint
run: swiftlint lint --strict --reporter github-actions-logging
- name: SwiftFormat Lint
if: always()
run: swiftformat --lint . --reporter github-actions-log
# Comes pre-installed on macOS runners
build-docs:
Expand Down
17 changes: 17 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
excluded:
- Sources/LiveKit/Protos

disabled_rules:
- todo
- nesting
- identifier_name
Copy link
Contributor Author

@pblazej pblazej Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly for _privateFields, not sure if that's worth fixing.

Found 231 violations, 231 serious in 321 files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in a separate PR

- multiple_closures_with_trailing_closure
# SwiftFormat conflicts
- trailing_comma
- line_length
- opening_brace

type_name:
excluded:
- ID
- OS
2 changes: 2 additions & 0 deletions Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ class AudioDeviceModuleDelegateAdapter: NSObject, LKRTCAudioDeviceModuleDelegate
return entryPoint?.engineWillRelease(engine) ?? 0
}

// swiftlint:disable:next function_parameter_count
func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureInputFromSource src: AVAudioNode?, toDestination dst: AVAudioNode, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillConnectInput(engine, src: src, dst: dst, format: format, context: context) ?? 0
}

// swiftlint:disable:next function_parameter_count
func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureOutputFromSource src: AVAudioNode, toDestination dst: AVAudioNode?, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
Expand Down
2 changes: 2 additions & 0 deletions Sources/LiveKit/Audio/Manager/AudioManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

// swiftlint:disable file_length

import Accelerate
import AVFoundation
import Combine
Expand Down
10 changes: 7 additions & 3 deletions Sources/LiveKit/Broadcast/IPC/IPCChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ final class IPCChannel: Sendable {
guard let rawMessage = try await upstream.next() else {
return nil
}
let (data, context, isComplete) = rawMessage
let (data, context, isComplete) = (rawMessage.data, rawMessage.context, rawMessage.isComplete)
guard let data, isComplete else { return nil }

guard let payloadSize = context?.ipcMessagePayloadSize,
Expand Down Expand Up @@ -223,7 +223,11 @@ private extension NWConnection {
AsyncMessageSequence(connection: self)
}

typealias IncomingMessage = (Data?, NWConnection.ContentContext?, Bool)
struct IncomingMessage {
let data: Data?
let context: NWConnection.ContentContext?
let isComplete: Bool
}

struct AsyncMessageSequence: AsyncSequence, AsyncIteratorProtocol {
let connection: NWConnection
Expand All @@ -243,7 +247,7 @@ private extension NWConnection {
try await withCheckedThrowingContinuation { [weak self] continuation in
self?.receiveMessage { data, context, isComplete, error in
guard let error else {
continuation.resume(returning: (data, context, isComplete))
continuation.resume(returning: IncomingMessage(data: data, context: context, isComplete: isComplete))
return
}
continuation.resume(throwing: error)
Expand Down
2 changes: 1 addition & 1 deletion Sources/LiveKit/Broadcast/IPC/IPCProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ final class IPCProtocol: NWProtocolFramerImplementation, Loggable {

func handleInput(framer: NWProtocolFramer.Instance) -> Int {
while true {
var tempHeader: Header? = nil
var tempHeader: Header?
let parsed = framer.parseInput(
minimumIncompleteLength: Header.encodedSize,
maximumLength: Header.encodedSize
Expand Down
8 changes: 6 additions & 2 deletions Sources/LiveKit/Core/DataChannelPair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@
* limitations under the License.
*/

// swiftlint:disable file_length

import DequeModule
import Foundation

internal import LiveKitWebRTC

// MARK: - Internal delegate

protocol DataChannelDelegate: Sendable {
protocol DataChannelDelegate: AnyObject, Sendable {
func dataChannel(_ dataChannelPair: DataChannelPair, didReceiveDataPacket dataPacket: Livekit_DataPacket)
func dataChannel(_ dataChannelPair: DataChannelPair, didFailToDecryptDataPacket dataPacket: Livekit_DataPacket, error: LiveKitError)
}

// swiftlint:disable:next type_body_length
class DataChannelPair: NSObject, @unchecked Sendable, Loggable {
// MARK: - Public

Expand Down Expand Up @@ -133,6 +136,7 @@ class DataChannelPair: NSObject, @unchecked Sendable, Loggable {

// MARK: - Event handling

// swiftlint:disable:next cyclomatic_complexity
private func handleEvents(
events: AsyncStream<ChannelEvent>
) async {
Expand Down Expand Up @@ -476,7 +480,7 @@ private extension DataChannelPair.ChannelKind {

private extension LKRTCDataChannel {
var kind: DataChannelPair.ChannelKind {
guard label == LKRTCDataChannel.labels.lossy else {
guard label == LKRTCDataChannel.Labels.lossy else {
return .reliable
}
return .lossy
Expand Down
6 changes: 2 additions & 4 deletions Sources/LiveKit/Core/Room+DataStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ public extension Room {
onError: (@Sendable (Error) -> Void)?
) {
Task {
do { try await registerByteStreamHandler(for: topic, onNewStream: onNewStream) }
catch { onError?(error) }
do { try await registerByteStreamHandler(for: topic, onNewStream: onNewStream) } catch { onError?(error) }
}
}

Expand All @@ -82,8 +81,7 @@ public extension Room {
onError: (@Sendable (Error) -> Void)?
) {
Task {
do { try await registerTextStreamHandler(for: topic, onNewStream: onNewStream) }
catch { onError?(error) }
do { try await registerTextStreamHandler(for: topic, onNewStream: onNewStream) } catch { onError?(error) }
}
}
}
8 changes: 6 additions & 2 deletions Sources/LiveKit/Core/Room+Engine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

// swiftlint:disable file_length

import Foundation

#if canImport(Network)
Expand Down Expand Up @@ -113,6 +115,7 @@ extension Room {
// MARK: - Internal

extension Room {
// swiftlint:disable:next function_body_length
func configureTransports(connectResponse: SignalClient.ConnectResponse) async throws {
func makeConfiguration() -> LKRTCConfiguration {
let connectOptions = _state.connectOptions
Expand Down Expand Up @@ -169,10 +172,10 @@ extension Room {

// data over pub channel for backwards compatibility

let reliableDataChannel = await publisher.dataChannel(for: LKRTCDataChannel.labels.reliable,
let reliableDataChannel = await publisher.dataChannel(for: LKRTCDataChannel.Labels.reliable,
configuration: RTC.createDataChannelConfiguration())

let lossyDataChannel = await publisher.dataChannel(for: LKRTCDataChannel.labels.lossy,
let lossyDataChannel = await publisher.dataChannel(for: LKRTCDataChannel.Labels.lossy,
configuration: RTC.createDataChannelConfiguration(ordered: false, maxRetransmits: 0))

publisherDataChannel.set(reliable: reliableDataChannel)
Expand Down Expand Up @@ -268,6 +271,7 @@ extension Room {
log("\(_state.connectStopwatch)")
}

// swiftlint:disable:next cyclomatic_complexity function_body_length
func startReconnect(reason: StartReconnectReason, nextReconnectMode: ReconnectMode? = nil) async throws {
log("[Connect] Starting, reason: \(reason)")

Expand Down
1 change: 1 addition & 0 deletions Sources/LiveKit/Core/Room+EngineDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Foundation
internal import LiveKitWebRTC

extension Room {
// swiftlint:disable:next cyclomatic_complexity function_body_length
func engine(_: Room, didMutateState state: Room.State, oldState: Room.State) {
if state.connectionState != oldState.connectionState {
// connectionState did update
Expand Down
4 changes: 2 additions & 2 deletions Sources/LiveKit/Core/Room+TransportDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ extension Room: TransportDelegate {

if _state.isSubscriberPrimary, transport.target == .subscriber {
switch dataChannel.label {
case LKRTCDataChannel.labels.reliable: subscriberDataChannel.set(reliable: dataChannel)
case LKRTCDataChannel.labels.lossy: subscriberDataChannel.set(lossy: dataChannel)
case LKRTCDataChannel.Labels.reliable: subscriberDataChannel.set(reliable: dataChannel)
case LKRTCDataChannel.Labels.lossy: subscriberDataChannel.set(lossy: dataChannel)
default: log("Unknown data channel label \(dataChannel.label)", .warning)
}
}
Expand Down
5 changes: 5 additions & 0 deletions Sources/LiveKit/Core/Room.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

// swiftlint:disable file_length

import Combine
import Foundation

Expand All @@ -22,6 +24,7 @@ import Network
#endif

@objc
// swiftlint:disable:next type_body_length
public class Room: NSObject, @unchecked Sendable, ObservableObject, Loggable {
// MARK: - MulticastDelegate

Expand Down Expand Up @@ -213,6 +216,7 @@ public class Room: NSObject, @unchecked Sendable, ObservableObject, Loggable {
}

@objc
// swiftlint:disable:next cyclomatic_complexity function_body_length
public init(delegate: RoomDelegate? = nil,
connectOptions: ConnectOptions? = nil,
roomOptions: RoomOptions? = nil)
Expand Down Expand Up @@ -312,6 +316,7 @@ public class Room: NSObject, @unchecked Sendable, ObservableObject, Loggable {
}

@objc
// swiftlint:disable:next function_body_length
public func connect(url: String,
token: String,
connectOptions: ConnectOptions? = nil,
Expand Down
4 changes: 4 additions & 0 deletions Sources/LiveKit/Core/SignalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

// swiftlint:disable file_length

import Foundation

internal import LiveKitWebRTC
Expand Down Expand Up @@ -107,6 +109,7 @@ actor SignalClient: Loggable {
}

@discardableResult
// swiftlint:disable:next function_body_length
func connect(_ url: URL,
_ token: String,
connectOptions: ConnectOptions? = nil,
Expand Down Expand Up @@ -269,6 +272,7 @@ private extension SignalClient {
}
}

// swiftlint:disable:next cyclomatic_complexity function_body_length
func _process(signalResponse: Livekit_SignalResponse) async {
guard connectionState != .disconnected else {
log("connectionState is .disconnected", .error)
Expand Down
6 changes: 2 additions & 4 deletions Sources/LiveKit/DataStream/Outgoing/ByteStreamWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,15 @@ public extension ByteStreamWriter {
@available(*, unavailable, message: "Use async write(_:) method instead.")
func write(_ data: Data, completion: @Sendable @escaping (Error?) -> Void) {
Task {
do { try await write(data) }
catch { completion(error) }
do { try await write(data) } catch { completion(error) }
}
}

@objc
@available(*, unavailable, message: "Use async close(reason:) method instead.")
func close(reason: String?, completion: @Sendable @escaping (Error?) -> Void) {
Task {
do { try await close(reason: reason) }
catch { completion(error) }
do { try await close(reason: reason) } catch { completion(error) }
}
}
}
6 changes: 2 additions & 4 deletions Sources/LiveKit/DataStream/Outgoing/TextStreamWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,15 @@ public extension TextStreamWriter {
@available(*, unavailable, message: "Use async write(_:) method instead.")
func write(_ text: String, onCompletion: @Sendable @escaping (Error?) -> Void) {
Task {
do { try await write(text) }
catch { onCompletion(error) }
do { try await write(text) } catch { onCompletion(error) }
}
}

@objc
@available(*, unavailable, message: "Use async close(reason:) method instead.")
func close(reason: String?, onCompletion: @Sendable @escaping (Error?) -> Void) {
Task {
do { try await close(reason: reason) }
catch { onCompletion(error) }
do { try await close(reason: reason) } catch { onCompletion(error) }
}
}
}
2 changes: 1 addition & 1 deletion Sources/LiveKit/Extensions/LKRTCRtpSender.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extension LKRTCRtpSender: Loggable {

// For SVC mode...
if let firstEncoding = encodings.first,
let _ = ScalabilityMode.fromString(firstEncoding.scalabilityMode)
ScalabilityMode.fromString(firstEncoding.scalabilityMode) != nil
{
let _enabled = qualities.highest != .off
if firstEncoding.isActive != _enabled {
Expand Down
2 changes: 2 additions & 0 deletions Sources/LiveKit/Extensions/PixelBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public extension CVPixelBuffer {
}

public extension CMSampleBuffer {
// swiftlint:disable:next cyclomatic_complexity function_body_length
static func from(_ pixelBuffer: CVPixelBuffer) -> CMSampleBuffer? {
var sampleBuffer: CMSampleBuffer?

Expand Down Expand Up @@ -179,6 +180,7 @@ public extension Data {

extension OSType {
// Get string representation of CVPixelFormatType
// swiftlint:disable:next function_body_length
func toString() -> String {
let types = [
kCVPixelFormatType_TwoComponent8: "kCVPixelFormatType_TwoComponent8",
Expand Down
2 changes: 1 addition & 1 deletion Sources/LiveKit/Extensions/RTCDataChannel+Util.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Foundation
internal import LiveKitWebRTC

extension LKRTCDataChannel {
enum labels {
enum Labels {
static let reliable = "_reliable"
static let lossy = "_lossy"
}
Expand Down
1 change: 1 addition & 0 deletions Sources/LiveKit/Extensions/RTCI420Buffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Foundation
internal import LiveKitWebRTC

extension LKRTCI420Buffer {
// swiftlint:disable:next function_body_length
func toPixelBuffer() -> CVPixelBuffer? {
// default options
let options = [
Expand Down
6 changes: 5 additions & 1 deletion Sources/LiveKit/LiveKit+DeviceHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ public extension LiveKitSDK {
/// Blocking version of ensureDeviceAccess that uses DispatchGroup to wait for permissions.
static func ensureDeviceAccessSync(for types: Set<AVMediaType>) -> Bool {
let group = DispatchGroup()
var result = true
#if swift(>=6.0)
nonisolated(unsafe) var result = false
#else
var result = false
#endif

for type in types {
if ![.video, .audio].contains(type) {
Expand Down
Loading
Loading