From 85d57a57f62445edee46c7f1749ebf79f0251cf8 Mon Sep 17 00:00:00 2001 From: Juliana Weinert Date: Wed, 20 Mar 2024 09:58:42 -0300 Subject: [PATCH 1/6] troca do AVPlayer para MP --- .DS_Store | Bin 0 -> 6148 bytes packages/.DS_Store | Bin 0 -> 8196 bytes .../ios/Flutter/AppFrameworkInfo.plist | 2 +- packages/audioplayers/example/ios/Podfile | 2 +- .../audioplayers/example/ios/Podfile.lock | 18 +- .../ios/Runner.xcodeproj/project.pbxproj | 8 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../project.pbxproj | 182 ++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 9491 bytes .../darwin/Classes/WrappedMediaPlayer.swift | 262 +++++++++--------- 12 files changed, 338 insertions(+), 153 deletions(-) create mode 100644 .DS_Store create mode 100644 packages/.DS_Store create mode 100644 packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.pbxproj create mode 100644 packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcuserdata/julianalima.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cffff878f410f5843a92fed024e395a5a9d02819 GIT binary patch literal 6148 zcmeHK&2AGh5FV$Y-L!>95ePUSt;DqoX_256mn3aeD)A#V2o8WkHoLT|Zr0KM5TUA4 z?(ht}0%u-?ci{xzcwMo{ZaE@^Jd*u+?3uCs*OXS77}B16F3r6~E(k8%2o-d`8IZ_<16Xb7Ja{vHiz0*xaj^buMD&7lA- zCDFv4g=h`*>cQt?1Otjygb2AuZfT593o(|__ZYo$qUvR3choP;H?MN`qZ1Z zt{g8|uOhC8xk!wviP;UI2lGCP-7h(I8?f;)mI&57D`t8CJw@3?v=UZ`InKwh6sIFP zy<}F*;vemuX*|(8;F~iE{5WZ~zKhCI^~&;!wPLMVZ~G^5+E0c_8h3}$Yt~*!88{c^ zq4U!Bri1$RJsBoLKlCEy;JY47-n{ZdS5CV!4c%Dz_Ok}7X4MAu+h=E6+xK@j?X3qp z=bQG~?sjX_ez?7JeqOU~+`aecXmA>gL&?hs5x9bsT-A61pHV0f@u44ufed+}*l!&~ zrPyvU(8IQFs>K3v#YGa=a*I^-D_vZ{W6Tp>qa$pc4(-!ZV98Rd4VU+5U=u{x1UyPU z6fvDZlWJ>Ra^%!D%*VhW@}dc|*7B96Y#1;M7zV%qe;;g(ZH==G)u#iQdIA8es8)h9 z|0=Mrt+B0fmLXaoB69_1u0lUCMCOiqTidlY&N9s0N$AIi&^-(NLJ_KW#J80>iFSr2 zHw+jC<{4PZ)H>h)z02SK^G-%H3>XIfD+WY$zrWwbl=R(Nm>l1=HqtvJ7PgyZs9ccg j>sS@|D!zrJ1Z_4KfNhPl3{e9yKLUydlNkp7Dg(a&&2tZP literal 0 HcmV?d00001 diff --git a/packages/.DS_Store b/packages/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bda52e9b9728e518c2994b869787bbcec35c8fe7 GIT binary patch literal 8196 zcmeHM%Z}496uq7)OsWB?fK922klbmbEwM#^zI}Te!bs}<*7;D?eRv5Q)TCxpO z!#n{#k)$ET6|f5Y3kqP(W^>l8`?}TURspNPf2ja}A6z6x z&tRcZeL9e-Eda2BYGo*6AD}p{LC;{JQBmPj?;eDq3bVx!nvQmty8}Igg+@&$q3I;d zorT$<2z7VxT-BX~r_ttC0jt2W0=)L0!;XDSAw_fh_moEWVtE+EGC&`mR=1I^e^-W5 z2`|V;L&N(L4C82&HJe|>#%ATr*)3;}xUdp_e`Pq2X_0z|E^+3uv_*wRYhtVMK z*LLp6B=e(WkSanH4$$SvqbLbw-j(Ad94T&3H#k+N+OJ)nOj_;Ee#33;?oAu+WWU{P zxHsE-(`nVYbnV8i`~6q(Q6k@~S0G`&Cv;w4ALk#+Uhs7Xh|S# z3TYz>7XsgH)ePc3W-4sM9Hl(L1~uY;BA< zhQF!VLc}hVC>^uLm=JFkbmqIwM(b*c4}A=l(R0K-r6Y_3_L<>WEJdA9hcsC5{%yf~ zt;Bl{KfyeIgU90R)0K@$HHt7QCC1aLN&fNIBzNJKhq!03(5Pk&GPMc=?fMU0tXTz4 zlLDLiVe9-G;O_eK|I_qJ_F1h0R)IfMKvWKT2VIcVs=k8EtGtW!42g~V6&e)<+1w8S eTp#~oh_Z{W%<&8s8c_qY2LVb3n^^@;RDmB#CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/packages/audioplayers/example/ios/Podfile b/packages/audioplayers/example/ios/Podfile index fdcc671eb..3e44f9c6f 100644 --- a/packages/audioplayers/example/ios/Podfile +++ b/packages/audioplayers/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/packages/audioplayers/example/ios/Podfile.lock b/packages/audioplayers/example/ios/Podfile.lock index d7286d1ba..a351b72a5 100644 --- a/packages/audioplayers/example/ios/Podfile.lock +++ b/packages/audioplayers/example/ios/Podfile.lock @@ -41,9 +41,9 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - SDWebImage (5.17.0): - - SDWebImage/Core (= 5.17.0) - - SDWebImage/Core (5.17.0) + - SDWebImage (5.19.0): + - SDWebImage/Core (= 5.19.0) + - SDWebImage/Core (5.19.0) - SwiftyGif (5.4.4) DEPENDENCIES: @@ -76,13 +76,13 @@ SPEC CHECKSUMS: audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 - file_picker: ce3938a0df3cc1ef404671531facef740d03f920 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 integration_test: 13825b8a9334a850581300559b8839134b124670 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + SDWebImage: 981fd7e860af070920f249fd092420006014c3eb SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f -PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189 +PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5 -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/packages/audioplayers/example/ios/Runner.xcodeproj/project.pbxproj b/packages/audioplayers/example/ios/Runner.xcodeproj/project.pbxproj index 6c7340e14..1ac392591 100644 --- a/packages/audioplayers/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/audioplayers/example/ios/Runner.xcodeproj/project.pbxproj @@ -216,7 +216,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { @@ -453,7 +453,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -581,7 +581,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -630,7 +630,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/packages/audioplayers/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/audioplayers/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 87131a09b..8e3ca5dfe 100644 --- a/packages/audioplayers/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/audioplayers/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcuserdata/julianalima.xcuserdatad/UserInterfaceState.xcuserstate b/packages/audioplayers_darwin/audioplayers_darwin.xcodeproj/project.xcworkspace/xcuserdata/julianalima.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..8eb96c2d1bc4765a554926b716cb6b32c99b6b85 GIT binary patch literal 9491 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 A5C8xG literal 0 HcmV?d00001 diff --git a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift index 08fc7f12c..f57518b87 100644 --- a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift +++ b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift @@ -1,14 +1,13 @@ -import AVKit +import Foundation +import MediaPlayer private let defaultPlaybackRate: Double = 1.0 - private let defaultVolume: Double = 1.0 - private let defaultLooping: Bool = false typealias Completer = () -> Void - -typealias CompleterError = (Error?) -> Void +typealias CompleterError = () -> Void +typealias StateUpdateDelegate = (MPMusicPlayerController) -> Void class WrappedMediaPlayer { private(set) var eventHandler: AudioPlayersStreamHandler @@ -16,80 +15,79 @@ class WrappedMediaPlayer { var looping: Bool private var reference: SwiftAudioplayersDarwinPlugin - private var player: AVPlayer + private var player: MPMusicPlayerController private var playbackRate: Double private var volume: Double - private var url: String? + private var id: UInt64? - private var completionObserver: TimeObserver? - private var playerItemStatusObservation: NSKeyValueObservation? + var stateUpdateDelegate: StateUpdateDelegate? init( reference: SwiftAudioplayersDarwinPlugin, eventHandler: AudioPlayersStreamHandler, - player: AVPlayer = AVPlayer.init(), + player: MPMusicPlayerController = MPMusicPlayerController.applicationMusicPlayer, playbackRate: Double = defaultPlaybackRate, volume: Double = defaultVolume, looping: Bool = defaultLooping, - url: String? = nil + url: UInt64? = nil ) { self.reference = reference self.eventHandler = eventHandler self.player = player - self.completionObserver = nil - self.playerItemStatusObservation = nil self.isPlaying = false self.playbackRate = playbackRate self.volume = volume self.looping = looping - self.url = url + self.id = url + + self.startNotifications() } func setSourceUrl( url: String, isLocal: Bool, - mimeType: String? = nil, completer: Completer? = nil, completerError: CompleterError? = nil ) { - let playbackStatus = player.currentItem?.status + let persistentId = UInt64(url) + let playbackStatus = player.playbackState - if self.url != url || playbackStatus == .failed || playbackStatus == nil { + if self.id != persistentId || playbackStatus == .interrupted || playbackStatus == .stopped { reset() - self.url = url + self.id = persistentId do { - let playerItem = try createPlayerItem(url: url, isLocal: isLocal, mimeType: mimeType) + let playerItem = try createPlayerItem(persistentId!, isLocal) // Need to observe item status immediately after creating: - setUpPlayerItemStatusObservation( - playerItem, - completer: completer, - completerError: completerError) +// setUpPlayerItemStatusObservation( +// player, +// completer: completer, +// completerError: completerError) // Replacing the player item triggers completion in setUpPlayerItemStatusObservation - self.player.replaceCurrentItem(with: playerItem) - self.setUpSoundCompletedObserver(self.player, playerItem) + replaceItem(with: playerItem) +// self.setUpSoundCompletedObserver(self.player, playerItem) } catch { - completerError?(error) + completerError?() } } else { - if playbackStatus == .readyToPlay { + if player.isPreparedToPlay { completer?() } } } func getDuration() -> Int? { - guard let duration = getDurationCMTime() else { + guard let duration = getDurationTimeInterval() else { return nil } - return fromCMTime(time: duration) + return Int(duration) } func getCurrentPosition() -> Int? { - guard let time = getCurrentCMTime() else { + guard let time = getCurrentTimeInterval() else { return nil } - return fromCMTime(time: time) + return Int(time) } func pause() { @@ -100,162 +98,130 @@ class WrappedMediaPlayer { func resume() { isPlaying = true configParameters(player: player) - if #available(iOS 10.0, macOS 10.12, *) { - player.playImmediately(atRate: Float(playbackRate)) - } else { player.play() - } updateDuration() } func setVolume(volume: Double) { self.volume = volume - player.volume = Float(volume) + let volumeView = MPVolumeView() + let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider; DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) { + slider?.value = Float(volume) + } } func setPlaybackRate(playbackRate: Double) { self.playbackRate = playbackRate if isPlaying { // Setting the rate causes the player to resume playing. So setting it only, when already playing. - player.rate = Float(playbackRate) + player.currentPlaybackRate = Float(playbackRate) } } - func seek(time: CMTime, completer: Completer? = nil) { - guard let currentItem = player.currentItem else { - completer?() - return - } - currentItem.seek(to: time) { - finished in - if !self.isPlaying { - self.player.pause() - } - self.eventHandler.onSeekComplete() - if finished { - completer?() + func seek(time: Float, completer: Completer? = nil) { + let currentTime = player.currentPlaybackTime + let seekTime = currentTime + TimeInterval(time) + + if currentTime > TimeInterval(time) { + while currentTime != seekTime { + player.beginSeekingForward() + } + player.endSeeking() + completer?() + self.eventHandler.onSeekComplete() + return + } else { + while currentTime != seekTime { + player.beginSeekingBackward() + } + player.endSeeking() + completer?() + self.eventHandler.onSeekComplete() + return } - } } func stop(completer: Completer? = nil) { pause() - seek(time: toCMTime(millis: 0), completer: completer) + seek(time: Float(0), completer: completer) } func release(completer: Completer? = nil) { stop { self.reset() - self.url = nil + self.id = nil completer?() } } func dispose(completer: Completer? = nil) { + player.endGeneratingPlaybackNotifications() release { + self.stopNotifications() completer?() } } - private func getDurationCMTime() -> CMTime? { - return player.currentItem?.asset.duration + private func getDurationTimeInterval() -> TimeInterval? { + return player.nowPlayingItem?.playbackDuration } - private func getCurrentCMTime() -> CMTime? { - return player.currentItem?.currentTime() + private func getCurrentTimeInterval() -> TimeInterval? { + return player.currentPlaybackTime } - private func createPlayerItem( - url: String, - isLocal: Bool, - mimeType: String? = nil - ) throws -> AVPlayerItem { - guard - let parsedUrl = isLocal - ? URL(fileURLWithPath: url.deletingPrefix("file://")) : URL(string: url) - else { - throw AudioPlayerError.error("Url not valid: \(url)") - } - - let playerItem: AVPlayerItem - - if let unwrappedMimeType = mimeType { - if #available(iOS 17, macOS 14.0, *) { - let asset = AVURLAsset( - url: parsedUrl, options: [AVURLAssetOverrideMIMETypeKey: unwrappedMimeType]) - playerItem = AVPlayerItem(asset: asset) + private func createPlayerItem(_ id: UInt64, _ isLocal: Bool) throws -> MPMediaItem { + let songFilter = MPMediaPropertyPredicate(value: id, forProperty: MPMediaItemPropertyPersistentID, comparisonType: .equalTo) + let query = MPMediaQuery(filterPredicates: Set([songFilter])) + if let items = query.items, let song = items.first { + return song } else { - let asset = AVURLAsset( - url: parsedUrl, options: ["AVURLAssetOutOfBandMIMETypeKey": unwrappedMimeType]) - playerItem = AVPlayerItem(asset: asset) + throw AudioPlayerError.error("ID not valid: \(id)") } - } else { - playerItem = AVPlayerItem(url: parsedUrl) - } - - playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithm.timeDomain - return playerItem } - private func setUpPlayerItemStatusObservation( - _ playerItem: AVPlayerItem, - completer: Completer? = nil, - completerError: CompleterError? = nil - ) { - playerItemStatusObservation = playerItem.observe(\AVPlayerItem.status) { (playerItem, change) in - let status = playerItem.status - self.eventHandler.onLog(message: "player status: \(status), change: \(change)") - - switch playerItem.status { - case .readyToPlay: - self.updateDuration() - completer?() - case .failed: - self.reset() - completerError?(nil) - default: - break - } - } - } - - private func setUpSoundCompletedObserver(_ player: AVPlayer, _ playerItem: AVPlayerItem) { - let observer = NotificationCenter.default.addObserver( - forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, - object: playerItem, - queue: nil - ) { - [weak self] (notification) in - self?.onSoundComplete() - } - self.completionObserver = TimeObserver(player: player, observer: observer) - } - - private func configParameters(player: AVPlayer) { + public func startNotifications() { + player.beginGeneratingPlaybackNotifications() + NotificationCenter.default.addObserver(self, + selector: #selector(stateChanged), + name: .MPMusicPlayerControllerPlaybackStateDidChange, + object: player) + NotificationCenter.default.addObserver(self, + selector: #selector(stateChanged), + name: .MPMusicPlayerControllerNowPlayingItemDidChange, + object: player) + } + + public func stopNotifications() { + player.endGeneratingPlaybackNotifications() + NotificationCenter.default.removeObserver(self, + name: .MPMusicPlayerControllerPlaybackStateDidChange, + object: player) + NotificationCenter.default.removeObserver(self, + name: .MPMusicPlayerControllerNowPlayingItemDidChange, + object: player) + } + + private func configParameters(player: MPMusicPlayerController) { if isPlaying { - player.volume = Float(volume) - player.rate = Float(playbackRate) + self.setVolume(volume: volume) + player.currentPlaybackRate = Float(playbackRate) } } private func reset() { - playerItemStatusObservation?.invalidate() - playerItemStatusObservation = nil - if let cObserver = completionObserver { - NotificationCenter.default.removeObserver(cObserver.observer) - completionObserver = nil - } - player.replaceCurrentItem(with: nil) + stopNotifications() + replaceItem(with: nil) } private func updateDuration() { - guard let duration = player.currentItem?.asset.duration else { - return - } - if CMTimeGetSeconds(duration) > 0 { - let millis = fromCMTime(time: duration) - eventHandler.onDuration(millis: millis) - } + let current: Double = player.currentPlaybackTime + let durationTotal: Double = player.nowPlayingItem!.playbackDuration + let duration = current / durationTotal + if duration > 0 { + let millis = Int(duration) * 1000 + eventHandler.onDuration(millis: millis) + } } private func onSoundComplete() { @@ -263,7 +229,7 @@ class WrappedMediaPlayer { return } - seek(time: toCMTime(millis: 0)) { + seek(time: 0) { if self.looping { self.resume() } else { @@ -274,4 +240,26 @@ class WrappedMediaPlayer { reference.controlAudioSession() eventHandler.onComplete() } + + private func onTimeInterval(time: CMTime) { + let millis = fromCMTime(time: time) + eventHandler.onCurrentPosition(millis: millis) + } + + private func replaceItem(with: MPMediaItem?) { + setQueue(song: with) + } + + private func setQueue(song: MPMediaItem?) { + if song == nil { + player.stop() + } else { + let descriptor = MPMusicPlayerMediaItemQueueDescriptor(itemCollection: MPMediaItemCollection(items: [song!])) + player.setQueue(with: descriptor) + } + } + + @objc private func stateChanged(notification: NSNotification) { + stateUpdateDelegate?(player) + } } From 5ff609b8b67a719950788ea7d9a1674432ad5dea Mon Sep 17 00:00:00 2001 From: Juliana Weinert Date: Wed, 20 Mar 2024 10:21:08 -0300 Subject: [PATCH 2/6] update pubspec --- packages/audioplayers/pubspec.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/audioplayers/pubspec.yaml b/packages/audioplayers/pubspec.yaml index d8d18d12d..15edc38c9 100644 --- a/packages/audioplayers/pubspec.yaml +++ b/packages/audioplayers/pubspec.yaml @@ -22,7 +22,8 @@ flutter: dependencies: audioplayers_android: ^5.0.0 - audioplayers_darwin: ^6.0.0 + audioplayers_darwin: + path: ../audioplayers_darwin audioplayers_linux: ^4.0.0 audioplayers_platform_interface: ^7.0.0 audioplayers_web: ^5.0.0 From deb61920e9991bd80ba13c6db90ba6688d41cdba Mon Sep 17 00:00:00 2001 From: Lucas Teixeira Date: Thu, 21 Mar 2024 07:51:31 -0300 Subject: [PATCH 3/6] Fix compile errors --- packages/audioplayers/pubspec.yaml | 3 +-- .../Classes/SwiftAudioplayersDarwinPlugin.swift | 13 ++++++------- .../darwin/Classes/WrappedMediaPlayer.swift | 9 ++------- packages/audioplayers_web/pubspec.yaml | 4 ++-- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/packages/audioplayers/pubspec.yaml b/packages/audioplayers/pubspec.yaml index 15edc38c9..d8d18d12d 100644 --- a/packages/audioplayers/pubspec.yaml +++ b/packages/audioplayers/pubspec.yaml @@ -22,8 +22,7 @@ flutter: dependencies: audioplayers_android: ^5.0.0 - audioplayers_darwin: - path: ../audioplayers_darwin + audioplayers_darwin: ^6.0.0 audioplayers_linux: ^4.0.0 audioplayers_platform_interface: ^7.0.0 audioplayers_web: ^5.0.0 diff --git a/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift b/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift index d545e4264..7af8a813c 100644 --- a/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift +++ b/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift @@ -205,8 +205,8 @@ public class SwiftAudioplayersDarwinPlugin: NSObject, FlutterPlugin { code: "DarwinAudioError", message: "Null position received on seek", details: nil)) return } - let time = toCMTime(millis: position) - player.seek(time: time) { + // let time = toCMTime(millis: position) + player.seek(time: Float(position)) { result(1) } return @@ -223,18 +223,17 @@ public class SwiftAudioplayersDarwinPlugin: NSObject, FlutterPlugin { } player.setSourceUrl( - url: url!, isLocal: isLocal, - mimeType: mimeType, + url: url!, + isLocal: isLocal, completer: { player.eventHandler.onPrepared(isPrepared: true) }, - completerError: { error in - let errorStr: String = error != nil ? "\(error!)" : "Unknown error" + completerError: { player.eventHandler.onError( code: "DarwinAudioError", message: "Failed to set source. For troubleshooting, see " + "https://github.com/bluefireteam/audioplayers/blob/main/troubleshooting.md", - details: "AVPlayerItem.Status.failed on setSourceUrl: \(errorStr)") + details: "AVPlayerItem.Status.failed on setSourceUrl") }) result(1) return diff --git a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift index f57518b87..62b81c355 100644 --- a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift +++ b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift @@ -241,11 +241,6 @@ class WrappedMediaPlayer { eventHandler.onComplete() } - private func onTimeInterval(time: CMTime) { - let millis = fromCMTime(time: time) - eventHandler.onCurrentPosition(millis: millis) - } - private func replaceItem(with: MPMediaItem?) { setQueue(song: with) } @@ -260,6 +255,6 @@ class WrappedMediaPlayer { } @objc private func stateChanged(notification: NSNotification) { - stateUpdateDelegate?(player) - } + stateUpdateDelegate?(player) + } } diff --git a/packages/audioplayers_web/pubspec.yaml b/packages/audioplayers_web/pubspec.yaml index 1a2aa517a..19ed30111 100644 --- a/packages/audioplayers_web/pubspec.yaml +++ b/packages/audioplayers_web/pubspec.yaml @@ -25,5 +25,5 @@ dev_dependencies: sdk: flutter environment: - sdk: '>=3.3.0 <4.0.0' - flutter: '>=3.19.0' + sdk: '>=3.0.0 <4.0.0' + flutter: '>=3.13.0' From f8b88b58fed606bdf6bb642d4f52e43089a3c10c Mon Sep 17 00:00:00 2001 From: Lucas Teixeira Date: Thu, 21 Mar 2024 10:18:07 -0300 Subject: [PATCH 4/6] Fix duration --- .../darwin/Classes/WrappedMediaPlayer.swift | 98 ++++++++++--------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift index 62b81c355..deb678ad7 100644 --- a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift +++ b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift @@ -54,21 +54,28 @@ class WrappedMediaPlayer { let playbackStatus = player.playbackState if self.id != persistentId || playbackStatus == .interrupted || playbackStatus == .stopped { - reset() - self.id = persistentId - do { - let playerItem = try createPlayerItem(persistentId!, isLocal) - // Need to observe item status immediately after creating: -// setUpPlayerItemStatusObservation( -// player, -// completer: completer, -// completerError: completerError) - // Replacing the player item triggers completion in setUpPlayerItemStatusObservation - replaceItem(with: playerItem) -// self.setUpSoundCompletedObserver(self.player, playerItem) - } catch { - completerError?() - } + reset() + self.id = persistentId + do { + let playerItem = try createPlayerItem(persistentId!, isLocal) + + // Replacing the player item triggers completion in setUpPlayerItemStatusObservation + replaceItem(with: playerItem) + +// self.setUpSoundCompletedObserver(self.player, playerItem) + + player.prepareToPlay(completionHandler: { error in + if error == nil { + self.updateDuration() + completer?() + } else { + self.reset() + completerError?() + } + }) + } catch { + completerError?() + } } else { if player.isPreparedToPlay { completer?() @@ -80,14 +87,14 @@ class WrappedMediaPlayer { guard let duration = getDurationTimeInterval() else { return nil } - return Int(duration) + return Int(duration) * 1000 } func getCurrentPosition() -> Int? { guard let time = getCurrentTimeInterval() else { return nil } - return Int(time) + return Int(time) * 1000 } func pause() { @@ -119,26 +126,30 @@ class WrappedMediaPlayer { } func seek(time: Float, completer: Completer? = nil) { - let currentTime = player.currentPlaybackTime - let seekTime = currentTime + TimeInterval(time) - - if currentTime > TimeInterval(time) { - while currentTime != seekTime { - player.beginSeekingForward() - } - player.endSeeking() - completer?() - self.eventHandler.onSeekComplete() - return - } else { - while currentTime != seekTime { - player.beginSeekingBackward() - } - player.endSeeking() - completer?() - self.eventHandler.onSeekComplete() - return - } + player.currentPlaybackTime = TimeInterval(time) + self.eventHandler.onSeekComplete() + completer?() + +// let currentTime = player.currentPlaybackTime +// let seekTime = currentTime + TimeInterval(time) +// +// if currentTime > TimeInterval(time) { +// while currentTime != seekTime { +// player.beginSeekingForward() +// } +// player.endSeeking() +// completer?() +// self.eventHandler.onSeekComplete() +// return +// } else { +// while currentTime != seekTime { +// player.beginSeekingBackward() +// } +// player.endSeeking() +// completer?() +// self.eventHandler.onSeekComplete() +// return +// } } func stop(completer: Completer? = nil) { @@ -214,15 +225,12 @@ class WrappedMediaPlayer { replaceItem(with: nil) } - private func updateDuration() { - let current: Double = player.currentPlaybackTime - let durationTotal: Double = player.nowPlayingItem!.playbackDuration - let duration = current / durationTotal + private func updateDuration() { + let duration = getDuration() ?? 0 if duration > 0 { - let millis = Int(duration) * 1000 - eventHandler.onDuration(millis: millis) - } - } + eventHandler.onDuration(millis: duration) + } + } private func onSoundComplete() { if !isPlaying { From 1a7cab0775ef0426e2a3de1d29a4b74be6634736 Mon Sep 17 00:00:00 2001 From: Juliana Weinert Date: Fri, 22 Mar 2024 11:12:54 -0300 Subject: [PATCH 5/6] fix volume --- .../darwin/Classes/WrappedMediaPlayer.swift | 38 +++---------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift index deb678ad7..7120cbdc4 100644 --- a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift +++ b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift @@ -53,7 +53,7 @@ class WrappedMediaPlayer { let persistentId = UInt64(url) let playbackStatus = player.playbackState - if self.id != persistentId || playbackStatus == .interrupted || playbackStatus == .stopped { + if self.id != persistentId || persistentId != nil || playbackStatus == .interrupted || playbackStatus == .stopped { reset() self.id = persistentId do { @@ -61,9 +61,7 @@ class WrappedMediaPlayer { // Replacing the player item triggers completion in setUpPlayerItemStatusObservation replaceItem(with: playerItem) - -// self.setUpSoundCompletedObserver(self.player, playerItem) - + player.prepareToPlay(completionHandler: { error in if error == nil { self.updateDuration() @@ -104,18 +102,13 @@ class WrappedMediaPlayer { func resume() { isPlaying = true - configParameters(player: player) player.play() updateDuration() } - func setVolume(volume: Double) { - self.volume = volume - let volumeView = MPVolumeView() - let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider; DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) { - slider?.value = Float(volume) + func setVolume(volume: Double) { + self.volume = volume } - } func setPlaybackRate(playbackRate: Double) { self.playbackRate = playbackRate @@ -129,27 +122,6 @@ class WrappedMediaPlayer { player.currentPlaybackTime = TimeInterval(time) self.eventHandler.onSeekComplete() completer?() - -// let currentTime = player.currentPlaybackTime -// let seekTime = currentTime + TimeInterval(time) -// -// if currentTime > TimeInterval(time) { -// while currentTime != seekTime { -// player.beginSeekingForward() -// } -// player.endSeeking() -// completer?() -// self.eventHandler.onSeekComplete() -// return -// } else { -// while currentTime != seekTime { -// player.beginSeekingBackward() -// } -// player.endSeeking() -// completer?() -// self.eventHandler.onSeekComplete() -// return -// } } func stop(completer: Completer? = nil) { @@ -215,7 +187,7 @@ class WrappedMediaPlayer { private func configParameters(player: MPMusicPlayerController) { if isPlaying { - self.setVolume(volume: volume) +// self.setVolume(volume: volume) player.currentPlaybackRate = Float(playbackRate) } } From fb8ec081577ba9da3d36165c1731bc558201e3dc Mon Sep 17 00:00:00 2001 From: Juliana Weinert Date: Mon, 25 Mar 2024 16:04:09 -0300 Subject: [PATCH 6/6] fix seek --- .../Classes/SwiftAudioplayersDarwinPlugin.swift | 1 - .../darwin/Classes/WrappedMediaPlayer.swift | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift b/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift index 7af8a813c..e10e775ad 100644 --- a/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift +++ b/packages/audioplayers_darwin/darwin/Classes/SwiftAudioplayersDarwinPlugin.swift @@ -205,7 +205,6 @@ public class SwiftAudioplayersDarwinPlugin: NSObject, FlutterPlugin { code: "DarwinAudioError", message: "Null position received on seek", details: nil)) return } - // let time = toCMTime(millis: position) player.seek(time: Float(position)) { result(1) } diff --git a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift index 7120cbdc4..689c492fd 100644 --- a/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift +++ b/packages/audioplayers_darwin/darwin/Classes/WrappedMediaPlayer.swift @@ -112,14 +112,10 @@ class WrappedMediaPlayer { func setPlaybackRate(playbackRate: Double) { self.playbackRate = playbackRate - if isPlaying { - // Setting the rate causes the player to resume playing. So setting it only, when already playing. - player.currentPlaybackRate = Float(playbackRate) - } } func seek(time: Float, completer: Completer? = nil) { - player.currentPlaybackTime = TimeInterval(time) + player.currentPlaybackTime = TimeInterval(time/1000) self.eventHandler.onSeekComplete() completer?() } @@ -185,13 +181,6 @@ class WrappedMediaPlayer { object: player) } - private func configParameters(player: MPMusicPlayerController) { - if isPlaying { -// self.setVolume(volume: volume) - player.currentPlaybackRate = Float(playbackRate) - } - } - private func reset() { stopNotifications() replaceItem(with: nil)