137 lines
5.3 KiB
Swift
137 lines
5.3 KiB
Swift
//
|
|
// FullAudioService.swift
|
|
// bigbluebutton-mobile-sdk
|
|
//
|
|
// Created by Tiago Daniel Jacobs on 20/04/22.
|
|
//
|
|
import os
|
|
import bigbluebutton_tablet_sdk_common
|
|
import WebRTC
|
|
|
|
open class FullAudioService {
|
|
// Logger (these messages are displayed in the console application)
|
|
private var logger = os.Logger(subsystem: "BigBlueButtonTabletSDK", category: "FullAudioService")
|
|
private var webRTCClient:AudioWebRTCClient?
|
|
private let encoder = JSONEncoder()
|
|
|
|
public func createOffer() async -> String? {
|
|
do{
|
|
webRTCClient = AudioWebRTCClient(iceServers: ["stun:stun.l.google.com:19302",
|
|
"stun:stun1.l.google.com:19302",
|
|
"stun:stun2.l.google.com:19302",
|
|
"stun:stun3.l.google.com:19302",
|
|
"stun:stun4.l.google.com:19302"])
|
|
webRTCClient!.delegate = self
|
|
|
|
var createOfferIterations = 0
|
|
while(true) {
|
|
createOfferIterations += 1;
|
|
|
|
let rtcSessionDescription = try await self.webRTCClient!.offer()
|
|
|
|
// Immediately connect when ice gathering is complete or after 5 iterations (5 seconds)
|
|
if(webRTCClient!.isIceGatheringComplete()) {
|
|
logger.debug("Ice gathering complete!");
|
|
return rtcSessionDescription.sdp
|
|
} else if ( createOfferIterations > 5 ) {
|
|
logger.debug("Ice iterations exceeded, sending what we have");
|
|
return rtcSessionDescription.sdp
|
|
} else {
|
|
logger.debug("Ice gathering not yet complete, waiting 1s");
|
|
try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
|
|
}
|
|
}
|
|
} catch {
|
|
logger.error("Error on webRTCClient.offer")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public func setRemoteSDP(remoteSDP:String) async -> Bool {
|
|
do {
|
|
try await self.webRTCClient!.setRemoteSDP(remoteSDP: remoteSDP)
|
|
return true
|
|
}
|
|
catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension FullAudioService: AudioWebRTCClientDelegate {
|
|
|
|
public func webRTCClient(_ client: AudioWebRTCClient, didDiscoverLocalCandidate rtcIceCandidate: RTCIceCandidate) {
|
|
do {
|
|
let iceCandidate = IceCandidate(from: rtcIceCandidate)
|
|
let iceCandidateAsJsonData = try self.encoder.encode(iceCandidate)
|
|
let iceCandidateAsJsonString = String(decoding: iceCandidateAsJsonData, as: UTF8.self)
|
|
|
|
print("---- ICE CANDIDATE \(iceCandidateAsJsonString) ")
|
|
} catch {
|
|
self.logger.error("Error handling ICE candidate")
|
|
}
|
|
}
|
|
|
|
public func webRTCClient(_ client: AudioWebRTCClient, didChangeIceConnectionState state: RTCIceConnectionState) {
|
|
switch state {
|
|
case .connected:
|
|
self.logger.info("didChangeConnectionState -> connected")
|
|
case .completed:
|
|
self.logger.info("didChangeConnectionState -> completed")
|
|
case .disconnected:
|
|
self.logger.info("didChangeConnectionState -> disconnected")
|
|
case .failed:
|
|
self.logger.info("didChangeConnectionState -> failed")
|
|
case .closed:
|
|
self.logger.info("didChangeConnectionState -> closed")
|
|
case .new, .checking, .count:
|
|
break
|
|
@unknown default:
|
|
print("Unknown connection state.")
|
|
}
|
|
}
|
|
|
|
public func webRTCClient(_ client: AudioWebRTCClient, didChangeIceGatheringState state: RTCIceGatheringState) {
|
|
switch state {
|
|
case .new:
|
|
self.logger.info("didChangeGatheringState -> new")
|
|
case .gathering:
|
|
self.logger.info("didChangeGatheringState -> gathering")
|
|
case .complete:
|
|
self.logger.info("didChangeGatheringState -> complete")
|
|
@unknown default:
|
|
self.logger.error("Unknown gathering state: \(state.rawValue)")
|
|
}
|
|
}
|
|
|
|
public func webRTCClient(_ client: AudioWebRTCClient, didChangeSignalingState state: RTCSignalingState) {
|
|
var stateString = ""
|
|
switch(state) {
|
|
case .haveLocalOffer:
|
|
self.logger.info("peerConnection new signaling state -> haveLocalOffer")
|
|
stateString = "have-local-offer"
|
|
case .haveLocalPrAnswer:
|
|
self.logger.info("peerConnection new signaling state -> haveLocalPrAnswer")
|
|
stateString = "have-local-pranswer"
|
|
case .haveRemoteOffer:
|
|
self.logger.info("peerConnection new signaling state -> haveRemoteOffer")
|
|
stateString = "have-remote-offer"
|
|
case .haveRemotePrAnswer:
|
|
self.logger.info("peerConnection new signaling state -> haveRemotePrAnswer")
|
|
stateString = "have-remote-pranswer"
|
|
case .stable:
|
|
self.logger.info("peerConnection new signaling state -> stable")
|
|
stateString = "stable"
|
|
case .closed:
|
|
self.logger.info("peerConnection new signaling state -> closed")
|
|
stateString = "closed"
|
|
default:
|
|
self.logger.error("peerConnection new signaling state -> UNKNOWN")
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|