Skip to content

Commit

Permalink
[LLC]Public interface cleanup (#372)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipavlidakis authored Apr 30, 2024
1 parent 785c66e commit 985e384
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 47 deletions.
2 changes: 1 addition & 1 deletion Sources/StreamVideo/StreamVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,6 @@ extension StreamVideo: WSEventsSubscriber {
}

/// Returns the current value for the `StreamVideo` instance.
internal struct StreamVideoProviderKey: InjectionKey {
struct StreamVideoProviderKey: InjectionKey {
static var currentValue: StreamVideo?
}
10 changes: 5 additions & 5 deletions Sources/StreamVideo/Utils/Atomic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import Foundation
/// itself from multiple threads can cause a crash.

@propertyWrapper
public class Atomic<T> {
public var wrappedValue: T {
final class Atomic<T> {
var wrappedValue: T {
get {
var currentValue: T!
mutate { currentValue = $0 }
Expand All @@ -41,19 +41,19 @@ public class Atomic<T> {

/// Update the value safely.
/// - Parameter changes: a block with changes. It should return a new value.
public func mutate(_ changes: (_ value: inout T) -> Void) {
func mutate(_ changes: (_ value: inout T) -> Void) {
lock.lock()
changes(&_wrappedValue)
lock.unlock()
}

/// Update the value safely.
/// - Parameter changes: a block with changes. It should return a new value.
public func callAsFunction(_ changes: (_ value: inout T) -> Void) {
func callAsFunction(_ changes: (_ value: inout T) -> Void) {
mutate(changes)
}

public init(wrappedValue: T) {
init(wrappedValue: T) {
_wrappedValue = wrappedValue
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ open class StreamCallAudioRecorder: @unchecked Sendable {
}

/// Provides the default value of the `StreamCallAudioRecorder` class.
public struct StreamCallAudioRecorderKey: InjectionKey {
public static var currentValue: StreamCallAudioRecorder = StreamCallAudioRecorder(
struct StreamCallAudioRecorderKey: InjectionKey {
static var currentValue: StreamCallAudioRecorder = StreamCallAudioRecorder(
filename: "recording.wav"
)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/StreamVideo/Utils/Sorting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public var dominantSpeaker: StreamSortComparator<CallParticipant> = { comparison
public var isSpeaking: StreamSortComparator<CallParticipant> = { comparison($0, $1, keyPath: \.isSpeaking) }

/// Comparator which prioritizes participants who are pinned.
/// - Note: Remote pins has higher priority than local.
/// - Note: Remote pins have higher priority than local.
public var pinned: StreamSortComparator<CallParticipant> = { a, b in
switch (a.pin, b.pin) {
case (nil, _?): return .orderedDescending
Expand Down
9 changes: 2 additions & 7 deletions Sources/StreamVideo/Utils/StreamRuntimeCheck.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
import Foundation

public enum StreamRuntimeCheck {
/// Enables assertions thrown by the Stream SDK.
/// Enables assertions thrown by the StreamVideo SDK.
///
/// When set to false, a message will be logged on console, but the assertion will not be thrown.
public static var assertionsEnabled = false

/// For *internal use* only
///
/// Enables lazy mapping of DB models
public static var _isLazyMappingEnabled = true
static var assertionsEnabled = false
}
4 changes: 2 additions & 2 deletions Sources/StreamVideo/Utils/ThermalStateObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ final class ThermalStateObserver: ObservableObject, ThermalStateObserving {
}

/// Provides the default value of the `Appearance` class.
public struct ThermalStateObserverKey: InjectionKey {
public static var currentValue: any ThermalStateObserving = ThermalStateObserver.shared
enum ThermalStateObserverKey: InjectionKey {
static var currentValue: any ThermalStateObserving = ThermalStateObserver.shared
}

extension InjectedValues {
Expand Down
25 changes: 18 additions & 7 deletions Sources/StreamVideo/WebRTC/Screensharing/BroadcastObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,33 @@
import Combine
import Foundation

/// Enum representing different states of a broadcast.
public enum BroadcastState {
case notStarted
case started
case finished
}

/// Class responsible for observing broadcast state changes.
public class BroadcastObserver: ObservableObject {


/// Published property to track the current state of the broadcast.
@Published public var broadcastState: BroadcastState = .notStarted


/// Initializes a new instance of `BroadcastObserver`.
public init() {}


/// Callback function triggered when the broadcast starts.
lazy var broadcastStarted: CFNotificationCallback = { _, _, _, _, _ in
postNotification(with: BroadcastConstants.broadcastStartedNotification)
}


/// Callback function triggered when the broadcast stops.
lazy var broadcastStopped: CFNotificationCallback = { _, _, _, _, _ in
postNotification(with: BroadcastConstants.broadcastStoppedNotification)
}


/// Initiates the observation of broadcast notifications.
public func observe() {
observe(
notification: BroadcastConstants.broadcastStartedNotification,
Expand All @@ -34,6 +41,7 @@ public class BroadcastObserver: ObservableObject {
notification: BroadcastConstants.broadcastStoppedNotification,
function: broadcastStopped
)

NotificationCenter.default.addObserver(
self,
selector: #selector(handleBroadcastStarted),
Expand All @@ -47,7 +55,8 @@ public class BroadcastObserver: ObservableObject {
object: nil
)
}


/// Registers a notification observer with a specific callback function.
private func observe(notification: String, function: CFNotificationCallback) {
let cfstr = notification as CFString
let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
Expand All @@ -61,10 +70,12 @@ public class BroadcastObserver: ObservableObject {
)
}

/// Method triggered when the broadcast starts to update the state to `.started`.
@objc func handleBroadcastStarted() {
broadcastState = .started
}


/// Method triggered when the broadcast stops to update the state to `.finished`.
@objc func handleBroadcastStopped() {
broadcastState = .finished
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,75 @@ import ReplayKit

/// Handler that can be used in broadcast upload extension to support screensharing from the background.
open class BroadcastSampleHandler: RPBroadcastSampleHandler {


/// Represents the client connection for uploading broadcast buffers.
private var clientConnection: BroadcastBufferUploadConnection?

/// Handles the uploading of broadcast buffers.
private var uploader: BroadcastBufferUploader?

/// Core Foundation notification center used for broadcasting notifications.
private let notificationCenter: CFNotificationCenter

/// File path for the socket used in broadcasting.
private var socketFilePath: String {
guard let appGroupIdentifier = infoPlistValue(for: BroadcastConstants.broadcastAppGroupIdentifier),
let sharedContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier)
else {
return ""
}

return sharedContainer.appendingPathComponent(
BroadcastConstants.broadcastSharePath
)
.path
}


/// Initializes the broadcast sample handler.
override public init() {
notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
super.init()

if let connection = BroadcastBufferUploadConnection(filePath: socketFilePath) {
clientConnection = connection
setupConnection()
uploader = BroadcastBufferUploader(connection: connection)
}
}


/// Handles the broadcast start event.
///
/// - Parameter setupInfo: Information passed during setup.
override public func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
postNotification(BroadcastConstants.broadcastStartedNotification)
openConnection()
}

override public func broadcastPaused() {}

override public func broadcastResumed() {}


/// Placeholder method for handling broadcast pause event.
override public func broadcastPaused() {
// No action required for broadcast pause
}

/// Placeholder method for handling broadcast resume event.
override public func broadcastResumed() {
// No action required for broadcast resume
}

/// Handles the broadcast end event.
override public func broadcastFinished() {
postNotification(BroadcastConstants.broadcastStoppedNotification)
clientConnection?.close()
}

override public func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {

/// Processes the sample buffer.
///
/// - Parameters:
/// - sampleBuffer: The sample buffer to process.
/// - sampleBufferType: The type of the sample buffer.
override public func processSampleBuffer(
_ sampleBuffer: CMSampleBuffer,
with sampleBufferType: RPSampleBufferType
) {
switch sampleBufferType {
case RPSampleBufferType.video:
Task {
Expand All @@ -58,9 +84,10 @@ open class BroadcastSampleHandler: RPBroadcastSampleHandler {
break
}
}

// MARK: - private


// MARK: - Private Helpers

/// Sets up the client connection and defines an `onClose` callback.
private func setupConnection() {
clientConnection?.onClose = { [weak self] error in
if let error = error {
Expand All @@ -75,7 +102,8 @@ open class BroadcastSampleHandler: RPBroadcastSampleHandler {
}
}
}


/// Opens the broadcast connection using a timer.
private func openConnection() {
let queue = DispatchQueue(label: "broadcast.connectTimer")
let timer = DispatchSource.makeTimerSource(queue: queue)
Expand All @@ -88,13 +116,16 @@ open class BroadcastSampleHandler: RPBroadcastSampleHandler {
guard self?.clientConnection?.open() == true else {
return
}

timer.cancel()
}

timer.resume()
}


/// Posts a notification using Core Foundation's notification center.
///
/// - Parameter name: The name of the notification to post.
private func postNotification(_ name: String) {
CFNotificationCenterPostNotification(
notificationCenter,
Expand All @@ -106,4 +137,7 @@ open class BroadcastSampleHandler: RPBroadcastSampleHandler {
}
}

// MARK: - Extensions

/// Extension to make `CMSampleBuffer` conform to `Sendable` without checked effects.
extension CMSampleBuffer: @unchecked Sendable {}
4 changes: 2 additions & 2 deletions Sources/StreamVideo/WebRTC/SimulatorScreenCapturer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ final class SimulatorScreenCapturer: RTCVideoCapturer {
}

/// Provides the default value of the `SimulatorStreamFile` class.
public struct SimulatorStreamFileKey: InjectionKey {
public static var currentValue: URL? = nil
enum SimulatorStreamFileKey: InjectionKey {
static var currentValue: URL?
}

extension InjectedValues {
Expand Down
2 changes: 1 addition & 1 deletion StreamVideoSwiftUITests/CallViewModel_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ final class CallViewModel_Tests: StreamVideoTestCase {
participant.sessionID = UUID().uuidString
participantJoined.participant = participant

let controller = callViewModel.call!.callController as! CallController_Mock
let controller = try XCTUnwrap(callViewModel.call?.callController as? CallController_Mock)
controller.webRTCClient.eventNotificationCenter.process(.sfuEvent(.participantJoined(participantJoined)))

let callParticipant = participant.toCallParticipant(showTrack: false)
Expand Down
1 change: 1 addition & 0 deletions StreamVideoTests/IntegrationTests/IntegrationTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class IntegrationTest: XCTestCase {
apiKey: tokenResponse.apiKey,
user: User(id: userId),
token: .init(rawValue: tokenResponse.token),
videoConfig: .dummy(),
pushNotificationsConfig: .init(
pushProviderInfo: .init(name: "ios-apn", pushProvider: .apn),
voipPushProviderInfo: .init(name: "ios-voip", pushProvider: .apn)
Expand Down

0 comments on commit 985e384

Please sign in to comment.