Tusker/Tusker/Views/Attachments/GifvController.swift

93 lines
2.9 KiB
Swift
Raw Normal View History

//
2024-03-19 18:58:51 +00:00
// GifvController.swift
// Tusker
//
2024-03-19 18:58:51 +00:00
// Created by Shadowfacts on 3/18/24.
// Copyright © 2024 Shadowfacts. All rights reserved.
//
2024-03-19 18:58:51 +00:00
import Foundation
import AVKit
import Combine
2024-03-19 18:58:51 +00:00
@MainActor
class GifvController {
private let asset: AVAsset
2020-11-01 18:59:58 +00:00
private(set) var item: AVPlayerItem
let player: AVPlayer
2024-03-19 18:58:51 +00:00
2020-11-01 18:59:58 +00:00
private var isGrayscale = false
2024-03-19 18:58:51 +00:00
let presentationSizeSubject = PassthroughSubject<CGSize, Never>()
private var presentationSizeObservation: NSKeyValueObservation?
init(asset: AVAsset) {
2020-11-01 18:59:58 +00:00
self.asset = asset
2024-03-19 18:58:51 +00:00
self.item = AVPlayerItem(asset: asset)
self.player = AVPlayer(playerItem: item)
self.isGrayscale = Preferences.shared.grayscaleImages
player.isMuted = true
2024-03-19 18:58:51 +00:00
NotificationCenter.default.addObserver(self, selector: #selector(restartItem), name: .AVPlayerItemDidPlayToEndTime, object: item)
2020-11-01 18:59:58 +00:00
NotificationCenter.default.addObserver(self, selector: #selector(preferencesChanged), name: .preferencesChanged, object: nil)
2024-03-19 18:58:51 +00:00
updatePresentationSizeObservation()
}
func play() {
if player.rate == 0 {
player.play()
}
}
func pause() {
player.pause()
}
private func updatePresentationSizeObservation() {
presentationSizeObservation = item.observe(\.presentationSize, changeHandler: { [unowned self] item, _ in
self.presentationSizeSubject.send(item.presentationSize)
})
}
@objc private func restartItem() {
item.seek(to: .zero) { (success) in
guard success else { return }
self.player.play()
}
}
2024-03-19 18:58:51 +00:00
@objc private func preferencesChanged() {
if isGrayscale != Preferences.shared.grayscaleImages {
isGrayscale = Preferences.shared.grayscaleImages
item = GifvController.createItem(asset: asset)
player.replaceCurrentItem(with: item)
self.updatePresentationSizeObservation()
player.play()
}
}
2020-11-01 18:59:58 +00:00
private static func createItem(asset: AVAsset) -> AVPlayerItem {
let item = AVPlayerItem(asset: asset)
if Preferences.shared.grayscaleImages {
2023-10-20 02:50:20 +00:00
#if os(visionOS)
#warning("Use async AVVideoComposition CIFilter initializer")
#else
2020-11-01 18:59:58 +00:00
item.videoComposition = AVVideoComposition(asset: asset, applyingCIFiltersWithHandler: { (request) in
let filter = CIFilter(name: "CIColorMonochrome")!
filter.setValue(request.sourceImage, forKey: "inputImage")
filter.setValue(CIColor(red: 0.85, green: 0.85, blue: 0.85), forKey: "inputColor")
filter.setValue(1.0, forKey: "inputIntensity")
request.finish(with: filter.outputImage!, context: nil)
})
2023-10-20 02:50:20 +00:00
#endif
2020-11-01 18:59:58 +00:00
}
return item
}
}