diff --git a/Aerial.xcodeproj/project.pbxproj b/Aerial.xcodeproj/project.pbxproj index eaf3dd6a..47c3919d 100644 --- a/Aerial.xcodeproj/project.pbxproj +++ b/Aerial.xcodeproj/project.pbxproj @@ -1367,7 +1367,7 @@ CODE_SIGN_IDENTITY = "Developer ID Application: Guillaume Louel (3L54M5L5KK)"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.7.0; + CURRENT_PROJECT_VERSION = 1.7.1beta1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_HARDENED_RUNTIME = YES; @@ -1375,7 +1375,7 @@ INSTALL_PATH = "$(HOME)/Library/Screen Savers"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1beta1; PRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1396,7 +1396,7 @@ CODE_SIGN_IDENTITY = "Developer ID Application: Guillaume Louel (3L54M5L5KK)"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.7.0; + CURRENT_PROJECT_VERSION = 1.7.1beta1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_HARDENED_RUNTIME = YES; @@ -1404,7 +1404,7 @@ INSTALL_PATH = "$(HOME)/Library/Screen Savers"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.7.0; + MARKETING_VERSION = 1.7.1beta1; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Aerial/Source/Models/ManifestLoader.swift b/Aerial/Source/Models/ManifestLoader.swift index 2cb2ef1d..29f3c959 100644 --- a/Aerial/Source/Models/ManifestLoader.swift +++ b/Aerial/Source/Models/ManifestLoader.swift @@ -149,6 +149,7 @@ class ManifestLoader { // MARK: - Playlist generation func generatePlaylist(isRestricted: Bool, restrictedTo: String) { + print("genplaylist") // Start fresh playlist = [AerialVideo]() playlistIsRestricted = isRestricted @@ -206,22 +207,27 @@ class ManifestLoader { } } - func randomVideo(excluding: [AerialVideo]) -> AerialVideo? { + func randomVideo(excluding: [AerialVideo]) -> (AerialVideo?, Bool) { + var shouldLoop = false let timeManagement = TimeManagement.sharedInstance let (shouldRestrictByDayNight, restrictTo) = timeManagement.shouldRestrictPlaybackToDayNightVideo() // We may need to regenerate a playlist! if playlist.isEmpty || restrictTo != playlistRestrictedTo || shouldRestrictByDayNight != playlistIsRestricted { generatePlaylist(isRestricted: shouldRestrictByDayNight, restrictedTo: restrictTo) + if playlist.count == 1 { + debugLog("playlist only has one element, looping!") + shouldLoop = true + } } // If not pluck one from current playlist and return that if !playlist.isEmpty { lastPluckedFromPlaylist = playlist.removeFirst() - return lastPluckedFromPlaylist + return (lastPluckedFromPlaylist, shouldLoop) } else { // If we don't have any playlist, something's got awfully wrong so deal with that! - return findBestEffortVideo() + return (findBestEffortVideo(), shouldLoop) } } diff --git a/Aerial/Source/Views/AerialView+Player.swift b/Aerial/Source/Views/AerialView+Player.swift index ee9a601b..496d7640 100644 --- a/Aerial/Source/Views/AerialView+Player.swift +++ b/Aerial/Source/Views/AerialView+Player.swift @@ -88,8 +88,17 @@ extension AerialView { @objc func playerItemDidReachEnd(_ aNotification: Notification) { debugLog("\(self.description) played did reach end") debugLog("\(self.description) notification: \(aNotification)") - playNextVideo() - debugLog("\(self.description) playing next video for player \(String(describing: player))") + + if shouldLoop { + debugLog("Rewinding video!") + if let playerItem = aNotification.object as? AVPlayerItem { + playerItem.seek(to: CMTime.zero, completionHandler: nil) + } + } else { + playNextVideo() + debugLog("\(self.description) playing next video for player \(String(describing: player))") + } + } // Video fade-in/out diff --git a/Aerial/Source/Views/AerialView.swift b/Aerial/Source/Views/AerialView.swift index acb7ce2e..7c0a32ff 100644 --- a/Aerial/Source/Views/AerialView.swift +++ b/Aerial/Source/Views/AerialView.swift @@ -38,6 +38,9 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { // We use this for tentative Catalina bug workaround var originalWidth, originalHeight: CGFloat + // Tentative improvement when only one video in playlist + var shouldLoop = false + static var shouldFade: Bool { return (PrefsVideos.fadeMode != .disabled) } @@ -365,6 +368,7 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { // MARK: - playNextVideo() func playNextVideo() { + print("playnext") let notificationCenter = NotificationCenter.default // Clear everything layerManager.clearLayerAnimations(player: self.player!) @@ -406,7 +410,10 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { (player.currentItem as? AerialPlayerItem)?.video } - let randomVideo = ManifestLoader.instance.randomVideo(excluding: currentVideos) + let (randomVideo, pshouldLoop) = ManifestLoader.instance.randomVideo(excluding: currentVideos) + + // If we only have one video in the playlist, we can rewind it for seamless transitions + self.shouldLoop = pshouldLoop guard let video = randomVideo else { errorLog("\(self.description) Error grabbing random video!") @@ -457,12 +464,11 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { object: currentItem) player.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none } -/* + override func keyDown(with event: NSEvent) { debugLog("keyDown") - let preferences = Preferences.sharedInstance - if preferences.allowSkips { + if PrefsVideos.allowSkips { if event.keyCode == 124 { if !isQuickFading { // If we share, just call this on our main view @@ -497,7 +503,6 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { return true } } - */ // MARK: - Extra Animations private func fastFadeOut(andPlayNext: Bool) {