import Intents /// "Hey Siri, play … on Stemify". Handled in the app process, so it can start playback directly. final class PlayMediaHandler: NSObject, INPlayMediaIntentHandling { func resolveMediaItems(for intent: INPlayMediaIntent) async -> [INPlayMediaMediaItemResolutionResult] { let q = intent.mediaSearch?.mediaName ?? intent.mediaSearch?.artistName ?? intent.mediaSearch?.albumName ?? "" let item = INMediaItem(identifier: "search:\(q)", title: q.isEmpty ? "Downloads" : q, type: .music, artwork: nil) return INPlayMediaMediaItemResolutionResult.successes(with: [item]) } func handle(intent: INPlayMediaIntent) async -> INPlayMediaIntentResponse { let s = intent.mediaSearch let q = s?.mediaName ?? s?.artistName ?? s?.albumName ?? intent.mediaItems?.first?.title ?? "" let shuffle = intent.playShuffled == true let ok = await Self.play(q, shuffle) return INPlayMediaIntentResponse(code: ok ? .success : .failure, userActivity: nil) } @MainActor static func play(_ query: String, _ shuffle: Bool) async -> Bool { let g = AppGraph.shared do { guard let r = try await g.car.resolveSearch(query) else { g.playback.report(query.isEmpty ? "Nothing downloaded yet" : "Nothing found for “\(query)”") return false } g.playback.playTracks(r.tracks, start: r.start, shuffle: r.shuffle || shuffle) return true } catch { g.playback.report(error is NotSignedIn ? "Sign in to Plex on your phone" : "Couldn't load that: \(error.localizedDescription)") return false } } }