Files
SwiftAudioPlayer/Source/LockScreenViewProtocol.swift
2021-08-12 15:55:04 -07:00

179 lines
7.3 KiB
Swift

//
// LockScreenViewProtocol.swift
// SwiftAudioPlayer
//
// Created by Tanha Kabir on 2019-01-29.
// Copyright © 2019 Tanha Kabir, Jon Mercer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import MediaPlayer
import UIKit
// MARK: - Set up lockscreen audio controls
// Documentation: https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/creating_a_basic_video_player_ios_and_tvos/controlling_background_audio
protocol LockScreenViewProtocol {
var skipForwardSeconds: Double { get set }
var skipBackwardSeconds: Double { get set }
}
extension LockScreenViewProtocol {
func clearLockScreenInfo() {
MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
}
@available(iOS 10.0, tvOS 10.0, *)
func setLockScreenInfo(withMediaInfo info: SALockScreenInfo?, duration: Duration) {
var nowPlayingInfo:[String : Any] = [:]
guard let info = info else {
MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
return
}
let title = info.title
let artist = info.artist
let albumTitle = info.albumTitle ?? artist
let releaseDate = info.releaseDate
// For some reason we need to set a duration here for the needle?
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = NSNumber(floatLiteral: duration)
nowPlayingInfo[MPMediaItemPropertyTitle] = title
nowPlayingInfo[MPMediaItemPropertyArtist] = artist
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = albumTitle
//nowPlayingInfo[MPMediaItemPropertyGenre] = //maybe later when we have it
//nowPlayingInfo[MPMediaItemPropertyIsExplicit] = //maybe later when we have it
nowPlayingInfo[MPMediaItemPropertyAlbumArtist] = artist
nowPlayingInfo[MPMediaItemPropertyMediaType] = MPMediaType.podcast.rawValue
nowPlayingInfo[MPMediaItemPropertyPodcastTitle] = title
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 0.0 //because default is 1.0. If we pause audio then it keeps ticking
nowPlayingInfo[MPMediaItemPropertyReleaseDate] = Date(timeIntervalSince1970: TimeInterval(releaseDate))
if let artwork = info.artwork {
nowPlayingInfo[MPMediaItemPropertyArtwork] =
MPMediaItemArtwork(boundsSize: artwork.size) { size in
return artwork
}
} else {
nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: UIImage().size) { size in
return UIImage()
}
}
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
// https://stackoverflow.com/questions/36754934/update-mpremotecommandcenter-play-pause-button
func setLockScreenControls(presenter: SAPlayerPresenter) { //FIXME: this is weird
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [weak presenter] event in
guard let presenter = presenter else {
return .commandFailed
}
if !presenter.getIsPlaying() {
presenter.handlePlay()
return .success
}
return .commandFailed
}
// Add handler for Pause Command
commandCenter.pauseCommand.addTarget { [weak presenter] event in
guard let presenter = presenter else {
return .commandFailed
}
if presenter.getIsPlaying() {
presenter.handlePause()
return .success
}
return .commandFailed
}
commandCenter.skipBackwardCommand.preferredIntervals = [skipBackwardSeconds] as [NSNumber]
commandCenter.skipForwardCommand.preferredIntervals = [skipForwardSeconds] as [NSNumber]
commandCenter.skipBackwardCommand.addTarget { [weak presenter] event in
guard let presenter = presenter else {
return .commandFailed
}
presenter.handleSkipBackward()
return .success
}
commandCenter.skipForwardCommand.addTarget { [weak presenter] event in
guard let presenter = presenter else {
return .commandFailed
}
presenter.handleSkipForward()
return .success
}
commandCenter.changePlaybackPositionCommand.addTarget { [weak presenter] event in
guard let presenter = presenter else {
return .commandFailed
}
if let positionEvent = event as? MPChangePlaybackPositionCommandEvent {
presenter.handleSeek(toNeedle: Needle(positionEvent.positionTime))
return .success
}
return .commandFailed
}
}
func updateLockscreenElapsedTime(needle: Needle) {
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = NSNumber(value: Double(needle))
}
func updateLockscreenPlaybackDuration(duration: Duration) {
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyPlaybackDuration] = NSNumber(value: duration)
}
func updateLockscreenPaused(){
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
}
func updateLockscreenPlaying(){
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
}
func updateLockscreenChangePlaybackRate(speed: Float){
if speed > 0.0{
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = speed
}
}
func updateLockscreenSkipIntervals() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.skipBackwardCommand.isEnabled = skipBackwardSeconds > 0
commandCenter.skipBackwardCommand.preferredIntervals = [skipBackwardSeconds] as [NSNumber]
commandCenter.skipForwardCommand.isEnabled = skipForwardSeconds > 0
commandCenter.skipForwardCommand.preferredIntervals = [skipForwardSeconds] as [NSNumber]
}
}