feat(ios): refactor plugin and add DSCP, stats, and codec support

This commit is contained in:
Andrew 2026-05-06 21:11:49 +07:00
parent 057020864a
commit a02b76c360
2 changed files with 200 additions and 155 deletions

View file

@ -80,35 +80,21 @@ public class LiblinphoneFlutterPlugin: NSObject, FlutterPlugin {
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "checkPermissions":
let hasPermissions = linphoneBridge.checkPermissions()
result(hasPermissions)
result(linphoneBridge.checkPermissions())
case "initialize":
do {
linphoneBridge = LinphoneBridge(
remoteViewAcquisitor: { [weak self] in
return self?.acquireRemoteView()
},
localViewAcquisitor: { [weak self] in
return self?.acquireLocalView()
},
onRegistrationStateChanged: { [weak self] state in
self?.registrationEventsChannel?(state)
},
onCallStateChanged: { [weak self] state in
self?.callEventsChannel?(state)
}
)
linphoneBridge.initializeLinphone()
result(true)
} catch {
print("[\(LiblinphoneFlutterPlugin.TAG)] initialize error: \(error.localizedDescription)")
result(FlutterError(
code: "ERROR",
message: error.localizedDescription,
details: nil
))
}
linphoneBridge = LinphoneBridge(
remoteViewAcquisitor: { [weak self] in self?.acquireRemoteView() },
localViewAcquisitor: { [weak self] in self?.acquireLocalView() },
onRegistrationStateChanged: { [weak self] state in
self?.registrationEventsChannel?(state)
},
onCallStateChanged: { [weak self] state in
self?.callEventsChannel?(state)
}
)
linphoneBridge.initializeLinphone()
result(true)
case "register":
guard let args = call.arguments as? [String: Any],
@ -116,30 +102,11 @@ public class LiblinphoneFlutterPlugin: NSObject, FlutterPlugin {
let password = args["password"] as? String,
let serverIp = args["serverIp"] as? String,
let serverPort = args["serverPort"] as? Int else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Missing required arguments",
details: nil
))
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing required arguments", details: nil))
return
}
do {
linphoneBridge.register(
username: username,
password: password,
serverIp: serverIp,
serverPort: serverPort
)
result(true)
} catch {
print("[\(LiblinphoneFlutterPlugin.TAG)] register error: \(error.localizedDescription)")
result(FlutterError(
code: "ERROR",
message: error.localizedDescription,
details: nil
))
}
linphoneBridge.register(username: username, password: password, serverIp: serverIp, serverPort: serverPort)
result(true)
case "unregister":
linphoneBridge.unregister()
@ -149,118 +116,114 @@ public class LiblinphoneFlutterPlugin: NSObject, FlutterPlugin {
guard let args = call.arguments as? [String: Any],
let callTo = args["callTo"] as? String,
let isVideoEnabled = args["isVideoEnabled"] as? Bool else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Missing required arguments",
details: nil
))
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing required arguments", details: nil))
return
}
do {
try linphoneBridge.makeCall(callTo: callTo, isVideoEnabled: isVideoEnabled)
result(true)
} catch {
print("[\(LiblinphoneFlutterPlugin.TAG)] makeCall error: \(error.localizedDescription)")
result(FlutterError(
code: "ERROR",
message: error.localizedDescription,
details: nil
))
result(FlutterError(code: "ERROR", message: error.localizedDescription, details: nil))
}
case "answerCall":
let success = linphoneBridge.answerCall()
result(success)
result(linphoneBridge.answerCall())
case "hangupCall":
let success = linphoneBridge.hangupCall()
result(success)
result(linphoneBridge.hangupCall())
case "inCall":
let inCall = linphoneBridge.inCall()
result(inCall)
result(linphoneBridge.inCall())
case "callType":
let callType = linphoneBridge.callType()
let ordinal: Int
switch callType {
case .audio:
ordinal = 0
case .video:
ordinal = 1
case .unknown:
ordinal = 2
switch linphoneBridge.callType() {
case .audio: result(0)
case .video: result(1)
case .unknown: result(2)
}
result(ordinal)
case "toggleVideo":
let enabled = linphoneBridge.toggleVideo()
result(enabled)
result(linphoneBridge.toggleVideo())
case "toggleMicrophone":
let enabled = linphoneBridge.toggleMicrophone()
result(enabled)
result(linphoneBridge.toggleMicrophone())
case "stop":
linphoneBridge.stop()
result(true)
case "syncCurrentState" :
case "syncCurrentState":
linphoneBridge.syncCurrentState()
result(true)
case "sendDtmf":
guard let args = call.arguments as? [String: Any],
let tone = args["tone"] as? String else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Missing required arguments",
details: nil
))
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing required arguments", details: nil))
return
}
let success = linphoneBridge.sendDtmf(tone: tone)
result(success)
result(linphoneBridge.sendDtmf(tone: tone))
case "stopCallService":
// Android-only; no-op on iOS
result(true)
case "setMicGain":
guard let args = call.arguments as? [String: Any],
let level = args["level"] as? String else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Missing required arguments",
details: nil
))
let levelStr = args["level"] as? String,
let level = Float(levelStr) else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing or invalid 'level'", details: nil))
return
}
linphoneBridge.setMicGain(level: level)
result(success)
result(true)
case "getMicGain":
result(linphoneBridge.getMicGain())
result(String(linphoneBridge.getMicGain()))
case "setPlaybackGain":
guard let args = call.arguments as? [String: Any],
let level = args["level"] as? String else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Missing required arguments",
details: nil
))
let levelStr = args["level"] as? String,
let level = Float(levelStr) else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing or invalid 'level'", details: nil))
return
}
linphoneBridge.setPlaybackGain(level: level)
result(success)
result(true)
case "getPlaybackGain":
result(linphoneBridge.getPlaybackGain())
case "setDscp":
guard let args = call.arguments as? [String: Any] else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing arguments", details: nil))
return
}
// All three are optional only present keys are applied
let sipDscp = args["sipDscp"] as? Int
let audioDscp = args["audioDscp"] as? Int
let videoDscp = args["videoDscp"] as? Int
linphoneBridge.setDscp(sipDscp: sipDscp, audioDscp: audioDscp, videoDscp: videoDscp)
result(true)
case "getDscp":
result(linphoneBridge.getDscp())
case "getCurrentCallStats":
result(linphoneBridge.getCurrentCallStats())
case "getAvailableAudioCodecs":
result(linphoneBridge.getAvailableAudioCodecs())
case "setAudioCodec":
guard let args = call.arguments as? [String: Any],
let mime = args["mime"] as? String,
let clockRate = args["clockRate"] as? Int else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing required arguments", details: nil))
return
}
result(linphoneBridge.setAudioCodec(mime: mime, clockRate: clockRate))
default:
result(FlutterMethodNotImplemented)
}