From 8bca48f58bf03cd4b6c487053c7112080812abe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20D=C3=A9glon?= Date: Thu, 3 Oct 2024 08:54:49 +0200 Subject: [PATCH] feat: Add mini player info --- kDrive/Resources/de.lproj/Localizable.strings | 12 +++- kDrive/Resources/en.lproj/Localizable.strings | 6 ++ kDrive/Resources/es.lproj/Localizable.strings | 12 +++- kDrive/Resources/fr.lproj/Localizable.strings | 12 +++- kDrive/Resources/it.lproj/Localizable.strings | 12 +++- .../AudioPlayer/SingleTrackPlayer.swift | 56 +++++++++++++++---- kDriveCore/AudioPlayer/TrackMetadata.swift | 26 +++++++++ 7 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 kDriveCore/AudioPlayer/TrackMetadata.swift diff --git a/kDrive/Resources/de.lproj/Localizable.strings b/kDrive/Resources/de.lproj/Localizable.strings index 31aa143cbd..a1aa2fc8e8 100644 --- a/kDrive/Resources/de.lproj/Localizable.strings +++ b/kDrive/Resources/de.lproj/Localizable.strings @@ -1,10 +1,10 @@ /* - * Loco ios export: iOS Localizable.strings + * Loco ios export: Xcode Strings (legacy) * Project: kDrive * Locale: de, German * Tagged: ios - * Exported by: Valentin Perignon - * Exported at: Fri, 26 Jul 2024 13:09:12 +0200 + * Exported by: Matthieu Déglon + * Exported at: Thu, 03 Oct 2024 08:22:20 +0200 */ /* loco:610a8791fa12ab20713c09e4 */ @@ -2053,6 +2053,12 @@ /* loco:62344c023cb45e6fcb219b43 */ "trashedFileRestoreFileToOriginalPlaceSuccess-plural" = "%d Elemente am ursprünglichen Ort wiederhergestellt"; +/* loco:66fe3560501931dbfb04f0c8 */ +"unknownArtist" = "Unbekannter Künstler"; + +/* loco:66fe3634a0cfdc15cf0c1a94 */ +"unknownTitle" = "Unbekannter Titel"; + /* loco:6049df4d5c2c3a04bc397a7d */ "updateAvailableDescription" = "Mit Blick auf ein optimales kDrive-Benutzererlebnis empfehlen wir Ihnen, Ihre Anwendung zu aktualisieren."; diff --git a/kDrive/Resources/en.lproj/Localizable.strings b/kDrive/Resources/en.lproj/Localizable.strings index f7d83aab8d..ff54c19543 100644 --- a/kDrive/Resources/en.lproj/Localizable.strings +++ b/kDrive/Resources/en.lproj/Localizable.strings @@ -2053,6 +2053,12 @@ /* loco:62344c023cb45e6fcb219b43 */ "trashedFileRestoreFileToOriginalPlaceSuccess-plural" = "%d items recovered to their original location"; +/* loco:66fe3560501931dbfb04f0c8 */ +"unknownArtist" = "Unknown Artist"; + +/* loco:66fe3634a0cfdc15cf0c1a94 */ +"unknownTitle" = "Unknown Title"; + /* loco:6049df4d5c2c3a04bc397a7d */ "updateAvailableDescription" = "To get the best out of kDrive, we recommend you update your application."; diff --git a/kDrive/Resources/es.lproj/Localizable.strings b/kDrive/Resources/es.lproj/Localizable.strings index b6b919384f..5f47ad193d 100644 --- a/kDrive/Resources/es.lproj/Localizable.strings +++ b/kDrive/Resources/es.lproj/Localizable.strings @@ -1,10 +1,10 @@ /* - * Loco ios export: iOS Localizable.strings + * Loco ios export: Xcode Strings (legacy) * Project: kDrive * Locale: es, Spanish * Tagged: ios - * Exported by: Valentin Perignon - * Exported at: Fri, 26 Jul 2024 13:09:12 +0200 + * Exported by: Matthieu Déglon + * Exported at: Thu, 03 Oct 2024 08:22:20 +0200 */ /* loco:610a8791fa12ab20713c09e4 */ @@ -2053,6 +2053,12 @@ /* loco:62344c023cb45e6fcb219b43 */ "trashedFileRestoreFileToOriginalPlaceSuccess-plural" = "%d elementos restaurados en el emplazamiento original"; +/* loco:66fe3560501931dbfb04f0c8 */ +"unknownArtist" = "Artista desconocido"; + +/* loco:66fe3634a0cfdc15cf0c1a94 */ +"unknownTitle" = "Título desconocido"; + /* loco:6049df4d5c2c3a04bc397a7d */ "updateAvailableDescription" = "Para disfrutar de una experiencia óptima de kDrive, te aconsejamos que actualices tu aplicación."; diff --git a/kDrive/Resources/fr.lproj/Localizable.strings b/kDrive/Resources/fr.lproj/Localizable.strings index 44a7a6b9ac..a1bc7174d6 100644 --- a/kDrive/Resources/fr.lproj/Localizable.strings +++ b/kDrive/Resources/fr.lproj/Localizable.strings @@ -1,10 +1,10 @@ /* - * Loco ios export: iOS Localizable.strings + * Loco ios export: Xcode Strings (legacy) * Project: kDrive * Locale: fr, French * Tagged: ios - * Exported by: Valentin Perignon - * Exported at: Fri, 26 Jul 2024 13:09:12 +0200 + * Exported by: Matthieu Déglon + * Exported at: Thu, 03 Oct 2024 08:22:20 +0200 */ /* loco:610a8791fa12ab20713c09e4 */ @@ -2053,6 +2053,12 @@ /* loco:62344c023cb45e6fcb219b43 */ "trashedFileRestoreFileToOriginalPlaceSuccess-plural" = "%d éléments restaurés à leur emplacement d’origine"; +/* loco:66fe3560501931dbfb04f0c8 */ +"unknownArtist" = "Artiste inconnu"; + +/* loco:66fe3634a0cfdc15cf0c1a94 */ +"unknownTitle" = "Titre inconnu"; + /* loco:6049df4d5c2c3a04bc397a7d */ "updateAvailableDescription" = "Afin de profiter d’une expérience optimale de kDrive, nous vous conseillons de mettre à jour votre application."; diff --git a/kDrive/Resources/it.lproj/Localizable.strings b/kDrive/Resources/it.lproj/Localizable.strings index a74bf3ae51..d46fcfc9f6 100644 --- a/kDrive/Resources/it.lproj/Localizable.strings +++ b/kDrive/Resources/it.lproj/Localizable.strings @@ -1,10 +1,10 @@ /* - * Loco ios export: iOS Localizable.strings + * Loco ios export: Xcode Strings (legacy) * Project: kDrive * Locale: it, Italian * Tagged: ios - * Exported by: Valentin Perignon - * Exported at: Fri, 26 Jul 2024 13:09:12 +0200 + * Exported by: Matthieu Déglon + * Exported at: Thu, 03 Oct 2024 08:22:20 +0200 */ /* loco:610a8791fa12ab20713c09e4 */ @@ -2053,6 +2053,12 @@ /* loco:62344c023cb45e6fcb219b43 */ "trashedFileRestoreFileToOriginalPlaceSuccess-plural" = "%d elementi ipristinati nell’ubicazione di origine"; +/* loco:66fe3560501931dbfb04f0c8 */ +"unknownArtist" = "Artista sconosciuto"; + +/* loco:66fe3634a0cfdc15cf0c1a94 */ +"unknownTitle" = "Titolo sconosciuto"; + /* loco:6049df4d5c2c3a04bc397a7d */ "updateAvailableDescription" = "Per vivere la migliore esperienza con kDrive, ti consigliamo di aggiornare la tua applicazione."; diff --git a/kDriveCore/AudioPlayer/SingleTrackPlayer.swift b/kDriveCore/AudioPlayer/SingleTrackPlayer.swift index 122d7d2f37..2caaa3db9a 100644 --- a/kDriveCore/AudioPlayer/SingleTrackPlayer.swift +++ b/kDriveCore/AudioPlayer/SingleTrackPlayer.swift @@ -19,6 +19,7 @@ import Combine import InfomaniakCore import InfomaniakDI +import kDriveResources import MediaPlayer /// Track one file been played @@ -39,6 +40,8 @@ public final class SingleTrackPlayer { private var playableFileName: String? + private var trackMetadata: TrackMetadata? + // MARK: Player Observation private var interruptionObserver: NSObjectProtocol? @@ -87,6 +90,33 @@ public final class SingleTrackPlayer { reset() } + private func extractTrackMetadata(from asset: AVAsset) -> TrackMetadata { + var title: String = playableFileName ?? KDriveResourcesStrings.Localizable.unknownTitle + var artist = KDriveResourcesStrings.Localizable.unknownArtist + var artwork: UIImage? = nil + + let metadata = asset.commonMetadata + + for item in metadata { + if let commonKey = item.commonKey { + switch commonKey { + case .commonKeyTitle: + title = item.value as? String ?? title + case .commonKeyArtist: + artist = item.value as? String ?? artist + case .commonKeyArtwork: + if let data = item.value as? Data { + artwork = UIImage(data: data) + } + default: + break + } + } + } + + return TrackMetadata(title: title, artist: artist, artwork: artwork) + } + // MARK: - Load /// Load internal structures to play a single track @@ -96,6 +126,8 @@ public final class SingleTrackPlayer { playableFileName = playableFile.name if !playableFile.isLocalVersionOlderThanRemote { + let asset = AVAsset(url: playableFile.localUrl) + trackMetadata = extractTrackMetadata(from: asset) player = AVPlayer(url: playableFile.localUrl) setUpObservers() } else if let token = driveFileManager.apiFetcher.currentToken { @@ -105,6 +137,7 @@ public final class SingleTrackPlayer { let headers = ["Authorization": "Bearer \(token.accessToken)"] let asset = AVURLAsset(url: url, options: ["AVURLAssetHTTPHeaderFieldsKey": headers]) Task { + self.trackMetadata = self.extractTrackMetadata(from: asset) self.player = AVPlayer(playerItem: AVPlayerItem(asset: asset)) self.setUpObservers() } @@ -130,7 +163,17 @@ public final class SingleTrackPlayer { var nowPlayingInfo = [String: Any]() nowPlayingInfo[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaType.audio.rawValue nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = false - nowPlayingInfo[MPMediaItemPropertyTitle] = playableFileName ?? "" + + if let metadata = trackMetadata { + nowPlayingInfo[MPMediaItemPropertyTitle] = metadata.title + nowPlayingInfo[MPMediaItemPropertyArtist] = metadata.artist + if let artwork = metadata.artwork { + let artworkItem = MPMediaItemArtwork(boundsSize: artwork.size) { _ in artwork } + nowPlayingInfo[MPMediaItemPropertyArtwork] = artworkItem + } + } else { + nowPlayingInfo[MPMediaItemPropertyTitle] = playableFileName ?? "" + } MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } @@ -151,11 +194,6 @@ public final class SingleTrackPlayer { var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [String: Any]() if let position = player?.currentItem?.currentTime() { nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = Float(position.seconds) - - let remainingTime = position.formattedText - onRemainingTimeChange.send(remainingTime) - let positionSlider = Float(position.seconds) - onPositionChange.send(positionSlider) } if let rate = player?.rate { nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = rate @@ -164,12 +202,6 @@ public final class SingleTrackPlayer { if let player = player, let duration = player.currentItem?.duration { nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = Float(duration.seconds) - let elapsedTime = player.currentItem?.currentTime() ?? .zero - - let remainingTime = "−\((duration - elapsedTime).formattedText)" - onRemainingTimeChange.send(remainingTime) - let maximumPosition = duration.seconds.isFinite ? Float(duration.seconds) : 1 - onPositionMaximumChange.send(maximumPosition) } MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo diff --git a/kDriveCore/AudioPlayer/TrackMetadata.swift b/kDriveCore/AudioPlayer/TrackMetadata.swift new file mode 100644 index 0000000000..217c828d88 --- /dev/null +++ b/kDriveCore/AudioPlayer/TrackMetadata.swift @@ -0,0 +1,26 @@ +// +/* + Infomaniak kDrive - iOS App + Copyright (C) 2024 Infomaniak Network SA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +import UIKit + +struct TrackMetadata { + let title: String + let artist: String + let artwork: UIImage? +}