diff --git a/Aerial/Source/Controllers/CustomVideoController.swift b/Aerial/Source/Controllers/CustomVideoController.swift index c0edd1e2..50ec9c9e 100644 --- a/Aerial/Source/Controllers/CustomVideoController.swift +++ b/Aerial/Source/Controllers/CustomVideoController.swift @@ -29,10 +29,17 @@ class CustomVideoController: NSWindowController, NSWindowDelegate { @IBOutlet var addPoiPopover: NSPopover! @IBOutlet var timeTextField: NSTextField! + @IBOutlet var timeTextStepper: NSStepper! + @IBOutlet var timeTextFormatter: NumberFormatter! @IBOutlet var descriptionTextField: NSTextField! + @IBOutlet var durationLabel: NSTextField! + @IBOutlet var resolutionLabel: NSTextField! + var currentFolder: Folder? var currentAsset: Asset? + var currentAssetDuration: Int? + var hasAwokenAlready = false var sw: NSWindow? var controller: PreferencesWindowController? @@ -78,7 +85,7 @@ class CustomVideoController: NSWindowController, NSWindowDelegate { manifestInstance.addCallback { manifestVideos in if let contr = self.controller { - contr.loaded(manifestVideos: manifestVideos) + contr.loaded(manifestVideos: []) } } manifestInstance.loadManifestsFromLoadedFiles() @@ -219,6 +226,18 @@ class CustomVideoController: NSWindowController, NSWindowDelegate { } } + @IBAction func timeStepperChange(_ sender: NSStepper) { + if let player = editPlayerView.player { + player.seek(to: CMTime(seconds: Double(sender.intValue), preferredTimescale: 1)) + } + } + + @IBAction func timeTextChange(_ sender: NSTextField) { + if let player = editPlayerView.player { + player.seek(to: CMTime(seconds: Double(sender.intValue), preferredTimescale: 1)) + } + } + @IBAction func tableViewTimeField(_ sender: NSTextField) { if let asset = currentAsset { if poiTableView.selectedRow != -1 { @@ -338,6 +357,20 @@ extension CustomVideoController: NSOutlineViewDelegate { if let player = editPlayerView.player { let localitem = AVPlayerItem(url: URL(fileURLWithPath: file.url)) + currentAssetDuration = Int(localitem.asset.duration.convertScale(1, method: .default).value) + let currentResolution = getResolution(asset: localitem.asset) + let crString = String(Int(currentResolution.width)) + "x" + String(Int(currentResolution.height)) + + timeTextStepper.minValue = 0 + timeTextStepper.maxValue = Double(currentAssetDuration!) + timeTextFormatter.minimum = 0 + timeTextFormatter.maximum = NSNumber(value: currentAssetDuration!) + //timeTableFormatter.minimum = 0 + //timeTableFormatter.maximum = NSNumber(value: currentAssetDuration!) + + durationLabel.stringValue = String(currentAssetDuration!) + " seconds" + resolutionLabel.stringValue = crString + player.replaceCurrentItem(with: localitem) } @@ -350,6 +383,12 @@ extension CustomVideoController: NSOutlineViewDelegate { return true } + + func getResolution(asset: AVAsset) -> CGSize { + guard let track = asset.tracks(withMediaType: AVMediaType.video).first else { return CGSize.zero } + let size = track.naturalSize.applying(track.preferredTransform) + return CGSize(width: abs(size.width), height: abs(size.height)) + } } // MARK: - Extension for poi table view diff --git a/Aerial/Source/Controllers/PreferencesWindowController.swift b/Aerial/Source/Controllers/PreferencesWindowController.swift index ed14f0cb..2be22d43 100644 --- a/Aerial/Source/Controllers/PreferencesWindowController.swift +++ b/Aerial/Source/Controllers/PreferencesWindowController.swift @@ -1971,8 +1971,12 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo var videos = [AerialVideo]() var cities = [String: City]() + // Grab a fresh version, because our callback can be feeding us wrong data in CVC + let freshManifestVideos = ManifestLoader.instance.loadedManifest + //debugLog("freshManifestVideos count : \(freshManifestVideos.count)") + // First day, then night - for video in manifestVideos { + for video in freshManifestVideos { let name = video.name if cities.keys.contains(name) == false { @@ -2183,6 +2187,7 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo case let video as AerialVideo: player = AVPlayer() playerView.player = player + player.isMuted = true debugLog("Playing this preview \(video)") // Workaround for cached videos generating online traffic diff --git a/Aerial/Source/Models/CustomVideoFolders.swift b/Aerial/Source/Models/CustomVideoFolders.swift index e9a36ef7..0ae7a27a 100644 --- a/Aerial/Source/Models/CustomVideoFolders.swift +++ b/Aerial/Source/Models/CustomVideoFolders.swift @@ -194,6 +194,7 @@ func newJSONDecoder() -> JSONDecoder { func newJSONEncoder() -> JSONEncoder { let encoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) { encoder.dateEncodingStrategy = .iso8601 } diff --git a/Aerial/Source/Models/ManifestLoader.swift b/Aerial/Source/Models/ManifestLoader.swift index 2a812aab..6741c284 100644 --- a/Aerial/Source/Models/ManifestLoader.swift +++ b/Aerial/Source/Models/ManifestLoader.swift @@ -9,6 +9,7 @@ import Foundation import ScreenSaver import GameplayKit +import AVFoundation typealias ManifestLoadCallback = ([AerialVideo]) -> Void @@ -410,6 +411,7 @@ class ManifestLoader { if let encodedData = try? cvf.jsonData() { try encodedData.write(to: cacheFileUrl) debugLog("customvideos.json saved successfully!") + loadedManifest.removeAll() // we remove our previously loaded manifest, it's invalid } } catch let error as NSError { errorLog("customvideos.json could not be saved: \(error.localizedDescription)") @@ -422,14 +424,24 @@ class ManifestLoader { if let cvf = customVideoFolders { for folder in cvf.folders { for asset in folder.assets { + let avResolution = getResolution(asset: AVAsset(url: URL(fileURLWithPath: asset.url))) + var url1080p = "" + var url4K = "" + + if avResolution.height > 1080 { + url4K = URL(fileURLWithPath: asset.url).absoluteString + } else { + url1080p = URL(fileURLWithPath: asset.url).absoluteString + } + let video = AerialVideo(id: asset.id, name: folder.label, secondaryName: asset.accessibilityLabel, type: "video", timeOfDay: asset.time, - url1080pH264: URL(fileURLWithPath: asset.url).absoluteString, + url1080pH264: url1080p, url1080pHEVC: "", - url4KHEVC: "", + url4KHEVC: url4K, manifest: .customVideos, poi: [:], communityPoi: asset.pointsOfInterest) @@ -439,6 +451,12 @@ class ManifestLoader { } } + func getResolution(asset: AVAsset) -> CGSize { + guard let track = asset.tracks(withMediaType: AVMediaType.video).first else { return CGSize.zero } + let size = track.naturalSize.applying(track.preferredTransform) + return CGSize(width: abs(size.width), height: abs(size.height)) + } + // MARK: - Periodically check for new videos func checkIfShouldRedownloadFiles() { let dateFormatter = DateFormatter() @@ -641,7 +659,7 @@ class ManifestLoader { } }*/ - debugLog("Total videos processed : \(processedVideos.count)") + debugLog("Total videos processed : \(processedVideos.count) callbacks : \(callbacks.count)") // callbacks for callback in self.callbacks { callback(self.loadedManifest) diff --git a/Aerial/Source/Views/AerialView.swift b/Aerial/Source/Views/AerialView.swift index 08eb4edd..f332dd71 100644 --- a/Aerial/Source/Views/AerialView.swift +++ b/Aerial/Source/Views/AerialView.swift @@ -549,6 +549,7 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { // play another video let oldPlayer = self.player self.player = player + player.isMuted = true player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil) self.playerLayer.player = self.player diff --git a/Resources/CustomVideos.xib b/Resources/CustomVideos.xib index 4a2ccdd1..a0af20bb 100644 --- a/Resources/CustomVideos.xib +++ b/Resources/CustomVideos.xib @@ -12,6 +12,7 @@ + @@ -20,8 +21,11 @@ + + + @@ -221,7 +225,6 @@ - @@ -294,10 +297,6 @@ - - - - + + + + + + + + + + diff --git a/Resources/Info.plist b/Resources/Info.plist index 35b27f35..5097b15a 100644 --- a/Resources/Info.plist +++ b/Resources/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.4.99beta6 + 1.4.99beta7 CFBundleSignature ???? CFBundleVersion - 1.4.99beta6 + 1.4.99beta7 LSApplicationCategoryType LSMinimumSystemVersion