feat: add support for os media control
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
F12B73482C55C0C40064A230 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = SOURCE_ROOT; };
|
||||
F12B734A2C56AEB00064A230 /* LiveStatusManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveStatusManager.swift; sourceTree = "<group>"; };
|
||||
F12B734C2C5702EC0064A230 /* LiveListenerCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveListenerCounter.swift; sourceTree = "<group>"; };
|
||||
F12B734E2C57B0230064A230 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
F138396C2C51BABD00B4814F /* InfinifiIOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InfinifiIOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F138396F2C51BABD00B4814F /* InfinifiIOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfinifiIOSApp.swift; sourceTree = "<group>"; };
|
||||
F13839712C51BABD00B4814F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
@@ -61,6 +62,7 @@
|
||||
F138396E2C51BABD00B4814F /* InfinifiIOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F12B734E2C57B0230064A230 /* Info.plist */,
|
||||
F138396F2C51BABD00B4814F /* InfinifiIOSApp.swift */,
|
||||
F13839712C51BABD00B4814F /* ContentView.swift */,
|
||||
F13839732C51BABE00B4814F /* Assets.xcassets */,
|
||||
@@ -295,6 +297,7 @@
|
||||
DEVELOPMENT_TEAM = 5FG7YZ49ZA;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = InfinifiIOS/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = infinifi;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
@@ -326,6 +329,7 @@
|
||||
DEVELOPMENT_TEAM = 5FG7YZ49ZA;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = InfinifiIOS/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = infinifi;
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
|
@@ -10,6 +10,12 @@ struct ContentView: View {
|
||||
playbackManager.stop()
|
||||
case .paused:
|
||||
playbackManager.nextTrack()
|
||||
Task {
|
||||
// sleep for 100ms before configuring audio session and control
|
||||
// to prevent UI stutter
|
||||
try await Task.sleep(nanoseconds: 100_000_000)
|
||||
playbackManager.confiugureAudioSessionAndControls()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
10
InfinifiIOS/Info.plist
Normal file
10
InfinifiIOS/Info.plist
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@@ -1,5 +1,6 @@
|
||||
import AVKit
|
||||
import Foundation
|
||||
import MediaPlayer
|
||||
|
||||
enum PlaybackState {
|
||||
case playing
|
||||
@@ -21,6 +22,35 @@ class PlaybackManager: ObservableObject {
|
||||
Task { try await initialize() }
|
||||
}
|
||||
|
||||
func confiugureAudioSessionAndControls() {
|
||||
let audioSession = AVAudioSession.sharedInstance()
|
||||
do {
|
||||
try audioSession.setCategory(.playback, mode: .default)
|
||||
try audioSession.setActive(true)
|
||||
} catch {}
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(onAudioInterrupted), name: AVAudioSession.interruptionNotification, object: audioSession)
|
||||
|
||||
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
|
||||
MPMediaItemPropertyTitle: "infinite lo-fi music",
|
||||
MPMediaItemPropertyArtist: "infinifi"
|
||||
]
|
||||
|
||||
let cmdCenter = MPRemoteCommandCenter.shared()
|
||||
|
||||
cmdCenter.playCommand.isEnabled = true
|
||||
cmdCenter.playCommand.addTarget { _ in
|
||||
self.nextTrack()
|
||||
return .success
|
||||
}
|
||||
|
||||
cmdCenter.pauseCommand.isEnabled = true
|
||||
cmdCenter.pauseCommand.addTarget { _ in
|
||||
self.stop()
|
||||
return .success
|
||||
}
|
||||
}
|
||||
|
||||
func nextTrack() {
|
||||
playbackState = .loading
|
||||
Task {
|
||||
@@ -82,6 +112,38 @@ class PlaybackManager: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
private func onAudioInterrupted(notification: Notification) {
|
||||
guard let userInfo = notification.userInfo,
|
||||
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
|
||||
let interruptionType = AVAudioSession.InterruptionType(rawValue: typeValue)
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
switch interruptionType {
|
||||
case .began:
|
||||
DispatchQueue.main.async {
|
||||
self.stop()
|
||||
}
|
||||
|
||||
case .ended:
|
||||
guard let optionValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
|
||||
return
|
||||
}
|
||||
|
||||
let options = AVAudioSession.InterruptionOptions(rawValue: optionValue)
|
||||
if options.contains(.shouldResume) {
|
||||
DispatchQueue.main.async {
|
||||
self.nextTrack()
|
||||
}
|
||||
}
|
||||
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
private func playbackFinished() {
|
||||
NotificationCenter.default.removeObserver(self, name: AVPlayerItem.didPlayToEndTimeNotification, object: audioPlayer.currentItem)
|
||||
|
Reference in New Issue
Block a user