CocoaSpice: update USB manager to support async

This commit is contained in:
osy 2023-09-04 19:39:33 -07:00
parent 8e820293bd
commit d1e547eec1
3 changed files with 47 additions and 46 deletions

View File

@ -293,17 +293,24 @@ extension VMSessionState: CSUSBManagerDelegate {
} }
} }
private func withUsbManagerSerialized<T>(_ task: @escaping () async -> T, onComplete: @escaping @MainActor (T) -> Void) { private func withUsbManagerSerialized<T>(_ task: @escaping () async throws -> T, onSuccess: @escaping @MainActor (T) -> Void = { _ in }, onError: @escaping @MainActor (Error) -> Void = { _ in }) {
usbManagerQueue.async { usbManagerQueue.async {
let event = DispatchSemaphore(value: 0) let event = DispatchSemaphore(value: 0)
Task.detached { [self] in Task.detached { [self] in
await MainActor.run { await MainActor.run {
isUsbBusy = true isUsbBusy = true
} }
let result = await task() do {
let result = try await task()
await MainActor.run { await MainActor.run {
isUsbBusy = false isUsbBusy = false
onComplete(result) onSuccess(result)
}
} catch {
await MainActor.run {
isUsbBusy = false
onError(error)
}
} }
event.signal() event.signal()
} }
@ -323,7 +330,7 @@ extension VMSessionState: CSUSBManagerDelegate {
logger.debug("found device: \(name ?? "(unknown)")") logger.debug("found device: \(name ?? "(unknown)")")
} }
return devices return devices
} onComplete: { devices in } onSuccess: { devices in
self.allUsbDevices = devices self.allUsbDevices = devices
} }
} }
@ -338,13 +345,11 @@ extension VMSessionState: CSUSBManagerDelegate {
return return
} }
withUsbManagerSerialized { withUsbManagerSerialized {
await usbManager.connectUsbDevice(usbDevice) try await usbManager.connectUsbDevice(usbDevice)
} onComplete: { success, message in } onSuccess: {
if success {
self.connectedUsbDevices.append(usbDevice) self.connectedUsbDevices.append(usbDevice)
} else { } onError: { error in
self.nonfatalError = message self.nonfatalError = error.localizedDescription
}
} }
} }
@ -358,12 +363,10 @@ extension VMSessionState: CSUSBManagerDelegate {
return return
} }
withUsbManagerSerialized { withUsbManagerSerialized {
await usbManager.disconnectUsbDevice(usbDevice)
} onComplete: { success, message in
if !success {
self.nonfatalError = message
}
self.connectedUsbDevices.removeAll(where: { $0 == usbDevice }) self.connectedUsbDevices.removeAll(where: { $0 == usbDevice })
try await usbManager.disconnectUsbDevice(usbDevice)
} onError: { error in
self.nonfatalError = error.localizedDescription
} }
} }

View File

@ -352,15 +352,15 @@ extension VMDisplayQemuWindowController: CSUSBManagerDelegate {
guard response == .alertFirstButtonReturn else { guard response == .alertFirstButtonReturn else {
return return
} }
DispatchQueue.global(qos: .utility).async { Task.detached {
usbManager.connectUsbDevice(usbDevice) { (result, message) in do {
DispatchQueue.main.async { try await usbManager.connectUsbDevice(usbDevice)
if let msg = message { await MainActor.run {
self.showErrorAlert(msg)
}
if result {
self.connectedUsbDevices.append(usbDevice) self.connectedUsbDevices.append(usbDevice)
} }
} catch {
await MainActor.run {
self.showErrorAlert(error.localizedDescription)
} }
} }
} }
@ -434,15 +434,15 @@ extension VMDisplayQemuWindowController {
return return
} }
let device = allUsbDevices[menu.tag] let device = allUsbDevices[menu.tag]
DispatchQueue.global(qos: .utility).async { Task.detached {
usbManager.connectUsbDevice(device) { (result, message) in do {
DispatchQueue.main.async { try await usbManager.connectUsbDevice(device)
if let msg = message { await MainActor.run {
self.showErrorAlert(msg)
}
if result {
self.connectedUsbDevices.append(device) self.connectedUsbDevices.append(device)
} }
} catch {
await MainActor.run {
self.showErrorAlert(error.localizedDescription)
} }
} }
} }
@ -458,15 +458,13 @@ extension VMDisplayQemuWindowController {
return return
} }
let device = allUsbDevices[menu.tag] let device = allUsbDevices[menu.tag]
DispatchQueue.global(qos: .utility).async { connectedUsbDevices.removeAll(where: { $0 == device })
usbManager.disconnectUsbDevice(device) { (result, message) in Task.detached {
DispatchQueue.main.async { do {
if let msg = message { try await usbManager.disconnectUsbDevice(device)
self.showErrorAlert(msg) } catch {
} await MainActor.run {
if result { self.showErrorAlert(error.localizedDescription)
self.connectedUsbDevices.removeAll(where: { $0 == device })
}
} }
} }
} }

View File

@ -15,7 +15,7 @@
"location" : "https://github.com/utmapp/CocoaSpice.git", "location" : "https://github.com/utmapp/CocoaSpice.git",
"state" : { "state" : {
"branch" : "visionos", "branch" : "visionos",
"revision" : "5405e085b9bc45ab13a862ddea350fdf660db86d" "revision" : "4529c9686259e8d1e94d6253ad2e3a563fd1498d"
} }
}, },
{ {