From 59c2000675ca18bd520b656f42ef94fddf30071e Mon Sep 17 00:00:00 2001 From: Hans Seiffert Date: Fri, 30 Sep 2016 21:51:49 +0200 Subject: [PATCH 1/5] Refactor project name from `AudioPlayer ` to `AudioPlayerManager` and improve class names --- AudioPlayer/Core/Private/AudioPlayerLog.swift | 25 --- .../Core/Private/AudioPlayerQueue.swift | 133 ------------- .../Player/AudioPlayer+MPMediaItem.swift | 70 ------- .../Core/Public/Player/AudioPlayer+URL.swift | 67 ------- AudioPlayer/Headers/AudioPlayer.h | 18 -- ...ayer.podspec => AudioPlayerManager.podspec | 0 .../contents.xcworkspacedata | 2 +- .../.swiftlint.yml | 0 .../project.pbxproj | 124 ++++++------ .../contents.xcworkspacedata | 0 .../xcschemes/AudioPlayerManager.xcscheme | 18 +- .../Core/Private/AudioTracksQueue.swift | 125 ++++++++++++ AudioPlayerManager/Core/Private/Log.swift | 23 +++ .../Core/Private/MediaLibraryHelper.swift | 2 +- .../MPMediaItem+AudioPlayerManager.swift | 4 +- .../AudioPlayerManager+MPMediaItem.swift | 69 +++++++ .../AudioPlayerManager+RemoteControl.swift | 6 +- .../Player/AudioPlayerManager+URL.swift | 67 +++++++ .../Public/Player/AudioPlayerManager.swift | 180 +++++++++--------- .../Core/Public/Track/AudioTrack.swift | 34 ++-- .../Core/Public/Track/AudioURLTrack.swift | 54 +++--- .../Core/Public/Track/MediaPlayerTrack.swift | 34 ++-- .../Headers/AudioPlayerManager.h | 18 ++ .../PLists/AudioPlayerManager-Info.plist | 0 Example/Core/AppDelegate.swift | 4 +- ...ultiplePlayerInstancesViewController.swift | 29 +-- .../MusicLibraryViewController.swift | 6 +- .../PlayerViewController.swift | 46 ++--- .../URLViewController.swift | 4 +- ...MultiplePlayerInstancesTableViewCell.swift | 2 +- Example/Example.xcodeproj/project.pbxproj | 40 ++-- Example/PLists/Example-Info.plist | 2 +- 32 files changed, 596 insertions(+), 610 deletions(-) delete mode 100644 AudioPlayer/Core/Private/AudioPlayerLog.swift delete mode 100644 AudioPlayer/Core/Private/AudioPlayerQueue.swift delete mode 100644 AudioPlayer/Core/Public/Player/AudioPlayer+MPMediaItem.swift delete mode 100644 AudioPlayer/Core/Public/Player/AudioPlayer+URL.swift delete mode 100644 AudioPlayer/Headers/AudioPlayer.h rename AudioPlayer.podspec => AudioPlayerManager.podspec (100%) rename {AudioPlayer.xcworkspace => AudioPlayerManager.xcworkspace}/contents.xcworkspacedata (73%) rename {AudioPlayer => AudioPlayerManager}/.swiftlint.yml (100%) rename {AudioPlayer/AudioPlayer.xcodeproj => AudioPlayerManager/AudioPlayerManager.xcodeproj}/project.pbxproj (65%) rename {AudioPlayer/AudioPlayer.xcodeproj => AudioPlayerManager/AudioPlayerManager.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) rename AudioPlayer/AudioPlayer.xcodeproj/xcshareddata/xcschemes/AudioPlayer.xcscheme => AudioPlayerManager/AudioPlayerManager.xcodeproj/xcshareddata/xcschemes/AudioPlayerManager.xcscheme (80%) create mode 100644 AudioPlayerManager/Core/Private/AudioTracksQueue.swift create mode 100644 AudioPlayerManager/Core/Private/Log.swift rename {AudioPlayer => AudioPlayerManager}/Core/Private/MediaLibraryHelper.swift (96%) rename AudioPlayer/Core/Public/MPMediaItem+AudioPlayer.swift => AudioPlayerManager/Core/Public/MPMediaItem+AudioPlayerManager.swift (87%) create mode 100644 AudioPlayerManager/Core/Public/Player/AudioPlayerManager+MPMediaItem.swift rename AudioPlayer/Core/Public/Player/AudioPlayer+RemoteControl.swift => AudioPlayerManager/Core/Public/Player/AudioPlayerManager+RemoteControl.swift (86%) create mode 100644 AudioPlayerManager/Core/Public/Player/AudioPlayerManager+URL.swift rename AudioPlayer/Core/Public/Player/AudioPlayer.swift => AudioPlayerManager/Core/Public/Player/AudioPlayerManager.swift (59%) rename AudioPlayer/Core/Public/Track/AudioPlayerItem.swift => AudioPlayerManager/Core/Public/Track/AudioTrack.swift (70%) rename AudioPlayer/Core/Public/Track/URLAudioPlayerItem.swift => AudioPlayerManager/Core/Public/Track/AudioURLTrack.swift (61%) rename AudioPlayer/Core/Public/Track/MediaItemAudioPlayerItem.swift => AudioPlayerManager/Core/Public/Track/MediaPlayerTrack.swift (66%) create mode 100644 AudioPlayerManager/Headers/AudioPlayerManager.h rename AudioPlayer/PLists/AudioPlayer-Info.plist => AudioPlayerManager/PLists/AudioPlayerManager-Info.plist (100%) diff --git a/AudioPlayer/Core/Private/AudioPlayerLog.swift b/AudioPlayer/Core/Private/AudioPlayerLog.swift deleted file mode 100644 index e473a10..0000000 --- a/AudioPlayer/Core/Private/AudioPlayerLog.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// AudioPlayerLog.swift -// AudioPlayer -// -// Created by Hans Seiffert on 02.08.16. -// Copyright © 2016 Hans Seiffert. All rights reserved. -// - -import UIKit - -// MARK: - AudioPlayerLog - -func AudioPlayerLog(message: AnyObject = "", file: String = #file, function: String = #function, line: Int = #line) { - #if DEBUG - if (AudioPlayerLogSettings.Verbose == true) { - if (AudioPlayerLogSettings.DetailedLog == true), - let className = NSURL(string: file)?.lastPathComponent?.componentsSeparatedByString(".").first { - let log = "\(NSDate()) - [\(className)].\(function)[\(line)]: \(message)" - print(log) - } else { - print(message) - } - } - #endif -} diff --git a/AudioPlayer/Core/Private/AudioPlayerQueue.swift b/AudioPlayer/Core/Private/AudioPlayerQueue.swift deleted file mode 100644 index 1ff39ef..0000000 --- a/AudioPlayer/Core/Private/AudioPlayerQueue.swift +++ /dev/null @@ -1,133 +0,0 @@ -// -// AudioPlayerQueue.swift -// AudioPlayer -// -// Created by Hans Seiffert on 02.08.16. -// Copyright © 2016 Hans Seiffert. All rights reserved. -// - -import UIKit - -class AudioPlayerQueue: NSObject { - - // MARK: - Private variables - - private var currentItem : AudioPlayerItem? - - private var queue = [AudioPlayerItem]() - private var currentItemQueueIndex = 0 - - private var history = [AudioPlayerItem]() - - // MARK: Set - - func replace(playerItems: [AudioPlayerItem]?, startPosition: Int) { - if let _playerItems = playerItems { - // Add the current playing item to the history - if let _currentItem = self.currentItem { - self.history.append(_currentItem) - } - // Replace the items in the queue with the new ones - self.queue = _playerItems - self.currentItemQueueIndex = startPosition - self.currentItem?.cleanupAfterPlaying() - self.currentItem = _playerItems[startPosition] - } else { - self.queue.removeAll() - self.currentItem?.cleanupAfterPlaying() - self.currentItem = nil - self.currentItemQueueIndex = 0 - } - } - - func prepend(playerItems: [AudioPlayerItem]) { - // Insert the player items at the beginning of the queue - self.queue.insertContentsOf(playerItems, at: 0) - // Adjust the current player item index to the new size - self.currentItemQueueIndex += playerItems.count - } - - func append(playerItems: [AudioPlayerItem]) { - self.queue.appendContentsOf(playerItems) - } - - // MARK: Forward - - func canForward() -> Bool { - return (self.queue.count > 0 && self.followingPlayerItem() != nil) - } - - func forward() -> Bool { - if (self.canForward() == true), - let _currentItem = self.currentItem, - _followingPlayerItem = self.followingPlayerItem() { - // Add current player item to the history - _currentItem.cleanupAfterPlaying() - // Replace current player item with the new one - self.currentItem = _followingPlayerItem - // Adjust the current item index - self.currentItemQueueIndex += 1 - // Add the former item to the history - self.history.append(_currentItem) - return true - } - return false - } - - private func followingPlayerItem() -> AudioPlayerItem? { - let followingIndex = self.currentItemQueueIndex + 1 - if (followingIndex < self.queue.count) { - return self.queue[followingIndex] - } - return nil - } - - // MARK: Rewind - - func canRewind() -> Bool { - return (self.previousItem() != nil) - } - - func rewind() -> Bool { - if (self.canRewind() == true), - let _currentItem = self.currentItem { - _currentItem.cleanupAfterPlaying() - // Replace the current player item with the former one - self.currentItem = self.previousItem() - // Adjust the current item index - self.currentItemQueueIndex -= 1 - return true - } - return false - } - - private func previousItem() -> AudioPlayerItem? { - let previousIndex = self.currentItemQueueIndex - 1 - if (previousIndex >= 0) { - return self.queue[previousIndex] - } - return nil - } - - // MARK: Get - - func currentPlayingItem() -> AudioPlayerItem? { - return self.currentItem - } - - func previousPlayingItem() -> AudioPlayerItem? { - return self.previousItem() - } - - func count() -> Int { - return self.queue.count - } - - // History - - private func appendCurrentPlayingItemToQueue() { - if let _currentItem = self.currentItem { - self.history.append(_currentItem) - } - } -} diff --git a/AudioPlayer/Core/Public/Player/AudioPlayer+MPMediaItem.swift b/AudioPlayer/Core/Public/Player/AudioPlayer+MPMediaItem.swift deleted file mode 100644 index 76009f3..0000000 --- a/AudioPlayer/Core/Public/Player/AudioPlayer+MPMediaItem.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// AudioPlayer+MPMediaItem.swift -// AudioPlayer -// -// Created by Hans Seiffert on 02.08.16. -// Copyright © 2016 Hans Seiffert. All rights reserved. -// -import MediaPlayer - -extension AudioPlayer { - - // MARK: - Play - - public func play(mediaItem mediaItem: MPMediaItem) { - if let _playerItem = HSMediaItemAudioPlayerItem(mediaItem: mediaItem) { - self.play(_playerItem) - } - } - - public func play(mediaItems mediaItems: [MPMediaItem], startPosition: Int) { - // Play first item directly and add the other items to the queue in the background - if let firstPlayableItem = HSMediaItemAudioPlayerItem.firstPlayableItem(mediaItems, startPosition: startPosition) { - // Play the first player item directly - self.play(firstPlayableItem.playerItem) - // Split the items into array which contain the ones which have to be prepended and appended them to the queue - var mediaItemsToPrepend = Array(mediaItems) - mediaItemsToPrepend.removeRange(firstPlayableItem.index.. Bool { - return self.isPlaying(persistentID: mediaItem.persistentID) - } - - public func isPlaying(mediaItemCollection: MPMediaItemCollection) -> Bool { - for mediaItem in mediaItemCollection.items { - if (self.isPlaying(mediaItem: mediaItem) == true) { - return true - } - } - return false - } - - public func isPlaying(persistentID persistentID: MPMediaEntityPersistentID) -> Bool { - if (self.isPlaying() == true), - let _currentMediaItem = self.currentPlayerItem() as? HSMediaItemAudioPlayerItem { - return ("\(persistentID)" == _currentMediaItem.identifier()) - } - return false - } -} diff --git a/AudioPlayer/Core/Public/Player/AudioPlayer+URL.swift b/AudioPlayer/Core/Public/Player/AudioPlayer+URL.swift deleted file mode 100644 index de0e563..0000000 --- a/AudioPlayer/Core/Public/Player/AudioPlayer+URL.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// AudioPlayer+URL.swift -// AudioPlayer -// -// Created by Hans Seiffert on 02.08.16. -// Copyright © 2016 Hans Seiffert. All rights reserved. -// -import MediaPlayer - -extension AudioPlayer { - - // MARK: - Play - - public func play(urlString urlString: String) { - self.play(url: NSURL(string: urlString)) - } - - public func play(urlStrings urlStrings: [String], startPosition: Int) { - self.play(urls: HSURLAudioPlayerItem.convertToURLs(urlStrings), startPosition: startPosition) - } - - public func play(url url: NSURL?) { - if let _playerItem = HSURLAudioPlayerItem(url: url) { - self.play(_playerItem) - } - } - - public func play(urls urls: [NSURL?], startPosition: Int) { - // Play the first item directly and add the other items to the queue in the background - if let firstPlayableItem = HSURLAudioPlayerItem.firstPlayableItem(urls, startPosition: startPosition) { - // Play the first item directly - self.play(firstPlayableItem.playerItem) - // Split the items into array which contain the ones which have to be prepended and appended to queue - var urlsToPrepend = Array(urls) - if (firstPlayableItem.index > 0) { - // If the index of the first playable item is greater than 0 there are items to prepend - urlsToPrepend.removeRange(firstPlayableItem.index.. Bool { - return self.isPlaying(url: NSURL(string: urlString)) - } - - public func isPlaying(url url: NSURL?) -> Bool { - return (self.isPlaying() == true && self.currentPlayerItem()?.identifier() == url?.absoluteString) - } -} diff --git a/AudioPlayer/Headers/AudioPlayer.h b/AudioPlayer/Headers/AudioPlayer.h deleted file mode 100644 index 7f6b3a9..0000000 --- a/AudioPlayer/Headers/AudioPlayer.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// AudioPlayer.h -// AudioPlayer -// -// Created by Hans Seiffert on 02.08.16. -// Copyright © 2016 Hans Seiffert. All rights reserved. -// - -#import - -//! Project version number for AudioPlayer. -FOUNDATION_EXPORT double AudioPlayerVersionNumber; - -//! Project version string for AudioPlayer. -FOUNDATION_EXPORT const unsigned char AudioPlayerVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - diff --git a/AudioPlayer.podspec b/AudioPlayerManager.podspec similarity index 100% rename from AudioPlayer.podspec rename to AudioPlayerManager.podspec diff --git a/AudioPlayer.xcworkspace/contents.xcworkspacedata b/AudioPlayerManager.xcworkspace/contents.xcworkspacedata similarity index 73% rename from AudioPlayer.xcworkspace/contents.xcworkspacedata rename to AudioPlayerManager.xcworkspace/contents.xcworkspacedata index 77cdc44..5f423ab 100644 --- a/AudioPlayer.xcworkspace/contents.xcworkspacedata +++ b/AudioPlayerManager.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ + location = "group:AudioPlayerManager/AudioPlayerManager.xcodeproj"> diff --git a/AudioPlayer/.swiftlint.yml b/AudioPlayerManager/.swiftlint.yml similarity index 100% rename from AudioPlayer/.swiftlint.yml rename to AudioPlayerManager/.swiftlint.yml diff --git a/AudioPlayer/AudioPlayer.xcodeproj/project.pbxproj b/AudioPlayerManager/AudioPlayerManager.xcodeproj/project.pbxproj similarity index 65% rename from AudioPlayer/AudioPlayer.xcodeproj/project.pbxproj rename to AudioPlayerManager/AudioPlayerManager.xcodeproj/project.pbxproj index b1c7175..fd61cf5 100644 --- a/AudioPlayer/AudioPlayer.xcodeproj/project.pbxproj +++ b/AudioPlayerManager/AudioPlayerManager.xcodeproj/project.pbxproj @@ -7,37 +7,37 @@ objects = { /* Begin PBXBuildFile section */ - 3A48663D1D50B5BA00CC4A04 /* AudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A48663C1D50B5BA00CC4A04 /* AudioPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3A48663D1D50B5BA00CC4A04 /* AudioPlayerManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A48663C1D50B5BA00CC4A04 /* AudioPlayerManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A4866431D50B80400CC4A04 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4866421D50B80400CC4A04 /* MediaPlayer.framework */; }; - 3A7BFA411D9EC5DA007E521D /* AudioPlayerLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7BFA3E1D9EC5DA007E521D /* AudioPlayerLog.swift */; }; - 3A7BFA421D9EC5DA007E521D /* AudioPlayerQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7BFA3F1D9EC5DA007E521D /* AudioPlayerQueue.swift */; }; + 3A7BFA411D9EC5DA007E521D /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7BFA3E1D9EC5DA007E521D /* Log.swift */; }; + 3A7BFA421D9EC5DA007E521D /* AudioTracksQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7BFA3F1D9EC5DA007E521D /* AudioTracksQueue.swift */; }; 3A7BFA431D9EC5DA007E521D /* MediaLibraryHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7BFA401D9EC5DA007E521D /* MediaLibraryHelper.swift */; }; - 3ACAE0F21D52403F009B20AD /* MPMediaItem+AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayer.swift */; }; - 3ACAE0F31D52403F009B20AD /* AudioPlayer+MPMediaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0E91D52403F009B20AD /* AudioPlayer+MPMediaItem.swift */; }; - 3ACAE0F41D52403F009B20AD /* AudioPlayer+RemoteControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EA1D52403F009B20AD /* AudioPlayer+RemoteControl.swift */; }; - 3ACAE0F51D52403F009B20AD /* AudioPlayer+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EB1D52403F009B20AD /* AudioPlayer+URL.swift */; }; - 3ACAE0F61D52403F009B20AD /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EC1D52403F009B20AD /* AudioPlayer.swift */; }; - 3ACAE0F71D52403F009B20AD /* AudioPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EE1D52403F009B20AD /* AudioPlayerItem.swift */; }; - 3ACAE0F81D52403F009B20AD /* MediaItemAudioPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EF1D52403F009B20AD /* MediaItemAudioPlayerItem.swift */; }; - 3ACAE0F91D52403F009B20AD /* URLAudioPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0F01D52403F009B20AD /* URLAudioPlayerItem.swift */; }; + 3ACAE0F21D52403F009B20AD /* MPMediaItem+AudioPlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayerManager.swift */; }; + 3ACAE0F31D52403F009B20AD /* AudioPlayerManager+MPMediaItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0E91D52403F009B20AD /* AudioPlayerManager+MPMediaItem.swift */; }; + 3ACAE0F41D52403F009B20AD /* AudioPlayerManager+RemoteControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EA1D52403F009B20AD /* AudioPlayerManager+RemoteControl.swift */; }; + 3ACAE0F51D52403F009B20AD /* AudioPlayerManager+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EB1D52403F009B20AD /* AudioPlayerManager+URL.swift */; }; + 3ACAE0F61D52403F009B20AD /* AudioPlayerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EC1D52403F009B20AD /* AudioPlayerManager.swift */; }; + 3ACAE0F71D52403F009B20AD /* AudioTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EE1D52403F009B20AD /* AudioTrack.swift */; }; + 3ACAE0F81D52403F009B20AD /* MediaPlayerTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0EF1D52403F009B20AD /* MediaPlayerTrack.swift */; }; + 3ACAE0F91D52403F009B20AD /* AudioURLTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACAE0F01D52403F009B20AD /* AudioURLTrack.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 3A48660C1D50A7D700CC4A04 /* AudioPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AudioPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3A48663C1D50B5BA00CC4A04 /* AudioPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayer.h; sourceTree = ""; }; - 3A48663E1D50B6A000CC4A04 /* AudioPlayer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AudioPlayer-Info.plist"; sourceTree = ""; }; + 3A48660C1D50A7D700CC4A04 /* AudioPlayerManager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AudioPlayerManager.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A48663C1D50B5BA00CC4A04 /* AudioPlayerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioPlayerManager.h; sourceTree = ""; }; + 3A48663E1D50B6A000CC4A04 /* AudioPlayerManager-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AudioPlayerManager-Info.plist"; sourceTree = ""; }; 3A4866421D50B80400CC4A04 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; - 3A7BFA3E1D9EC5DA007E521D /* AudioPlayerLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioPlayerLog.swift; sourceTree = ""; }; - 3A7BFA3F1D9EC5DA007E521D /* AudioPlayerQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioPlayerQueue.swift; sourceTree = ""; }; + 3A7BFA3E1D9EC5DA007E521D /* Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = ""; }; + 3A7BFA3F1D9EC5DA007E521D /* AudioTracksQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioTracksQueue.swift; sourceTree = ""; }; 3A7BFA401D9EC5DA007E521D /* MediaLibraryHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaLibraryHelper.swift; sourceTree = ""; }; - 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MPMediaItem+AudioPlayer.swift"; sourceTree = ""; }; - 3ACAE0E91D52403F009B20AD /* AudioPlayer+MPMediaItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayer+MPMediaItem.swift"; sourceTree = ""; }; - 3ACAE0EA1D52403F009B20AD /* AudioPlayer+RemoteControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayer+RemoteControl.swift"; sourceTree = ""; }; - 3ACAE0EB1D52403F009B20AD /* AudioPlayer+URL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayer+URL.swift"; sourceTree = ""; }; - 3ACAE0EC1D52403F009B20AD /* AudioPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = ""; }; - 3ACAE0EE1D52403F009B20AD /* AudioPlayerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioPlayerItem.swift; sourceTree = ""; }; - 3ACAE0EF1D52403F009B20AD /* MediaItemAudioPlayerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaItemAudioPlayerItem.swift; sourceTree = ""; }; - 3ACAE0F01D52403F009B20AD /* URLAudioPlayerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLAudioPlayerItem.swift; sourceTree = ""; }; + 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MPMediaItem+AudioPlayerManager.swift"; sourceTree = ""; }; + 3ACAE0E91D52403F009B20AD /* AudioPlayerManager+MPMediaItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayerManager+MPMediaItem.swift"; sourceTree = ""; }; + 3ACAE0EA1D52403F009B20AD /* AudioPlayerManager+RemoteControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayerManager+RemoteControl.swift"; sourceTree = ""; }; + 3ACAE0EB1D52403F009B20AD /* AudioPlayerManager+URL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AudioPlayerManager+URL.swift"; sourceTree = ""; }; + 3ACAE0EC1D52403F009B20AD /* AudioPlayerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioPlayerManager.swift; sourceTree = ""; }; + 3ACAE0EE1D52403F009B20AD /* AudioTrack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioTrack.swift; sourceTree = ""; }; + 3ACAE0EF1D52403F009B20AD /* MediaPlayerTrack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPlayerTrack.swift; sourceTree = ""; }; + 3ACAE0F01D52403F009B20AD /* AudioURLTrack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioURLTrack.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,7 +66,7 @@ 3A48660D1D50A7D700CC4A04 /* Products */ = { isa = PBXGroup; children = ( - 3A48660C1D50A7D700CC4A04 /* AudioPlayer.framework */, + 3A48660C1D50A7D700CC4A04 /* AudioPlayerManager.framework */, ); name = Products; sourceTree = ""; @@ -83,7 +83,7 @@ 3A48662E1D50A9B300CC4A04 /* PLists */ = { isa = PBXGroup; children = ( - 3A48663E1D50B6A000CC4A04 /* AudioPlayer-Info.plist */, + 3A48663E1D50B6A000CC4A04 /* AudioPlayerManager-Info.plist */, ); path = PLists; sourceTree = ""; @@ -91,7 +91,7 @@ 3A48663B1D50B5BA00CC4A04 /* Headers */ = { isa = PBXGroup; children = ( - 3A48663C1D50B5BA00CC4A04 /* AudioPlayer.h */, + 3A48663C1D50B5BA00CC4A04 /* AudioPlayerManager.h */, ); path = Headers; sourceTree = ""; @@ -107,8 +107,8 @@ 3ACAE0C11D51F804009B20AD /* Private */ = { isa = PBXGroup; children = ( - 3A7BFA3E1D9EC5DA007E521D /* AudioPlayerLog.swift */, - 3A7BFA3F1D9EC5DA007E521D /* AudioPlayerQueue.swift */, + 3A7BFA3E1D9EC5DA007E521D /* Log.swift */, + 3A7BFA3F1D9EC5DA007E521D /* AudioTracksQueue.swift */, 3A7BFA401D9EC5DA007E521D /* MediaLibraryHelper.swift */, ); path = Private; @@ -117,7 +117,7 @@ 3ACAE0E51D52403F009B20AD /* Public */ = { isa = PBXGroup; children = ( - 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayer.swift */, + 3ACAE0E71D52403F009B20AD /* MPMediaItem+AudioPlayerManager.swift */, 3ACAE0E81D52403F009B20AD /* Player */, 3ACAE0ED1D52403F009B20AD /* Track */, ); @@ -127,10 +127,10 @@ 3ACAE0E81D52403F009B20AD /* Player */ = { isa = PBXGroup; children = ( - 3ACAE0E91D52403F009B20AD /* AudioPlayer+MPMediaItem.swift */, - 3ACAE0EA1D52403F009B20AD /* AudioPlayer+RemoteControl.swift */, - 3ACAE0EB1D52403F009B20AD /* AudioPlayer+URL.swift */, - 3ACAE0EC1D52403F009B20AD /* AudioPlayer.swift */, + 3ACAE0E91D52403F009B20AD /* AudioPlayerManager+MPMediaItem.swift */, + 3ACAE0EA1D52403F009B20AD /* AudioPlayerManager+RemoteControl.swift */, + 3ACAE0EB1D52403F009B20AD /* AudioPlayerManager+URL.swift */, + 3ACAE0EC1D52403F009B20AD /* AudioPlayerManager.swift */, ); path = Player; sourceTree = ""; @@ -138,9 +138,9 @@ 3ACAE0ED1D52403F009B20AD /* Track */ = { isa = PBXGroup; children = ( - 3ACAE0EE1D52403F009B20AD /* AudioPlayerItem.swift */, - 3ACAE0EF1D52403F009B20AD /* MediaItemAudioPlayerItem.swift */, - 3ACAE0F01D52403F009B20AD /* URLAudioPlayerItem.swift */, + 3ACAE0EE1D52403F009B20AD /* AudioTrack.swift */, + 3ACAE0EF1D52403F009B20AD /* MediaPlayerTrack.swift */, + 3ACAE0F01D52403F009B20AD /* AudioURLTrack.swift */, ); path = Track; sourceTree = ""; @@ -152,16 +152,16 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 3A48663D1D50B5BA00CC4A04 /* AudioPlayer.h in Headers */, + 3A48663D1D50B5BA00CC4A04 /* AudioPlayerManager.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 3A48660B1D50A7D700CC4A04 /* AudioPlayer */ = { + 3A48660B1D50A7D700CC4A04 /* AudioPlayerManager */ = { isa = PBXNativeTarget; - buildConfigurationList = 3A4866201D50A7D700CC4A04 /* Build configuration list for PBXNativeTarget "AudioPlayer" */; + buildConfigurationList = 3A4866201D50A7D700CC4A04 /* Build configuration list for PBXNativeTarget "AudioPlayerManager" */; buildPhases = ( 3A4866071D50A7D700CC4A04 /* Sources */, 3A4866081D50A7D700CC4A04 /* Frameworks */, @@ -173,9 +173,9 @@ ); dependencies = ( ); - name = AudioPlayer; + name = AudioPlayerManager; productName = HSAudioPlayer; - productReference = 3A48660C1D50A7D700CC4A04 /* AudioPlayer.framework */; + productReference = 3A48660C1D50A7D700CC4A04 /* AudioPlayerManager.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -193,7 +193,7 @@ }; }; }; - buildConfigurationList = 3A4866061D50A7D700CC4A04 /* Build configuration list for PBXProject "AudioPlayer" */; + buildConfigurationList = 3A4866061D50A7D700CC4A04 /* Build configuration list for PBXProject "AudioPlayerManager" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -205,7 +205,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 3A48660B1D50A7D700CC4A04 /* AudioPlayer */, + 3A48660B1D50A7D700CC4A04 /* AudioPlayerManager */, ); }; /* End PBXProject section */ @@ -242,17 +242,17 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3A7BFA411D9EC5DA007E521D /* AudioPlayerLog.swift in Sources */, - 3A7BFA421D9EC5DA007E521D /* AudioPlayerQueue.swift in Sources */, - 3ACAE0F61D52403F009B20AD /* AudioPlayer.swift in Sources */, - 3ACAE0F71D52403F009B20AD /* AudioPlayerItem.swift in Sources */, - 3ACAE0F91D52403F009B20AD /* URLAudioPlayerItem.swift in Sources */, - 3ACAE0F81D52403F009B20AD /* MediaItemAudioPlayerItem.swift in Sources */, - 3ACAE0F51D52403F009B20AD /* AudioPlayer+URL.swift in Sources */, + 3A7BFA411D9EC5DA007E521D /* Log.swift in Sources */, + 3A7BFA421D9EC5DA007E521D /* AudioTracksQueue.swift in Sources */, + 3ACAE0F61D52403F009B20AD /* AudioPlayerManager.swift in Sources */, + 3ACAE0F71D52403F009B20AD /* AudioTrack.swift in Sources */, + 3ACAE0F91D52403F009B20AD /* AudioURLTrack.swift in Sources */, + 3ACAE0F81D52403F009B20AD /* MediaPlayerTrack.swift in Sources */, + 3ACAE0F51D52403F009B20AD /* AudioPlayerManager+URL.swift in Sources */, 3A7BFA431D9EC5DA007E521D /* MediaLibraryHelper.swift in Sources */, - 3ACAE0F21D52403F009B20AD /* MPMediaItem+AudioPlayer.swift in Sources */, - 3ACAE0F41D52403F009B20AD /* AudioPlayer+RemoteControl.swift in Sources */, - 3ACAE0F31D52403F009B20AD /* AudioPlayer+MPMediaItem.swift in Sources */, + 3ACAE0F21D52403F009B20AD /* MPMediaItem+AudioPlayerManager.swift in Sources */, + 3ACAE0F41D52403F009B20AD /* AudioPlayerManager+RemoteControl.swift in Sources */, + 3ACAE0F31D52403F009B20AD /* AudioPlayerManager+MPMediaItem.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -364,12 +364,12 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "PLists/AudioPlayer-Info.plist"; + INFOPLIST_FILE = "PLists/AudioPlayerManager-Info.plist"; INSTALL_PATH = "@executable_path/../Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = de.seiffert.hans.swift.audioplayer; - PRODUCT_NAME = AudioPlayer; + PRODUCT_BUNDLE_IDENTIFIER = de.seiffert.hans.swift.audioplayermanager; + PRODUCT_NAME = AudioPlayerManager; PROVISIONING_PROFILE = ""; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -391,12 +391,12 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "PLists/AudioPlayer-Info.plist"; + INFOPLIST_FILE = "PLists/AudioPlayerManager-Info.plist"; INSTALL_PATH = "@executable_path/../Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = de.seiffert.hans.swift.audioplayer; - PRODUCT_NAME = AudioPlayer; + PRODUCT_BUNDLE_IDENTIFIER = de.seiffert.hans.swift.audioplayermanager; + PRODUCT_NAME = AudioPlayerManager; SKIP_INSTALL = YES; }; name = Release; @@ -404,7 +404,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 3A4866061D50A7D700CC4A04 /* Build configuration list for PBXProject "AudioPlayer" */ = { + 3A4866061D50A7D700CC4A04 /* Build configuration list for PBXProject "AudioPlayerManager" */ = { isa = XCConfigurationList; buildConfigurations = ( 3A48661E1D50A7D700CC4A04 /* Debug */, @@ -413,7 +413,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 3A4866201D50A7D700CC4A04 /* Build configuration list for PBXNativeTarget "AudioPlayer" */ = { + 3A4866201D50A7D700CC4A04 /* Build configuration list for PBXNativeTarget "AudioPlayerManager" */ = { isa = XCConfigurationList; buildConfigurations = ( 3A4866211D50A7D700CC4A04 /* Debug */, diff --git a/AudioPlayer/AudioPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/AudioPlayerManager/AudioPlayerManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from AudioPlayer/AudioPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to AudioPlayerManager/AudioPlayerManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/AudioPlayer/AudioPlayer.xcodeproj/xcshareddata/xcschemes/AudioPlayer.xcscheme b/AudioPlayerManager/AudioPlayerManager.xcodeproj/xcshareddata/xcschemes/AudioPlayerManager.xcscheme similarity index 80% rename from AudioPlayer/AudioPlayer.xcodeproj/xcshareddata/xcschemes/AudioPlayer.xcscheme rename to AudioPlayerManager/AudioPlayerManager.xcodeproj/xcshareddata/xcschemes/AudioPlayerManager.xcscheme index 418d186..87ec207 100644 --- a/AudioPlayer/AudioPlayer.xcodeproj/xcshareddata/xcschemes/AudioPlayer.xcscheme +++ b/AudioPlayerManager/AudioPlayerManager.xcodeproj/xcshareddata/xcschemes/AudioPlayerManager.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "AudioPlayerManager.framework" + BlueprintName = "AudioPlayerManager" + ReferencedContainer = "container:AudioPlayerManager.xcodeproj"> @@ -46,9 +46,9 @@ + BuildableName = "AudioPlayerManager.framework" + BlueprintName = "AudioPlayerManager" + ReferencedContainer = "container:AudioPlayerManager.xcodeproj"> @@ -64,9 +64,9 @@ + BuildableName = "AudioPlayerManager.framework" + BlueprintName = "AudioPlayerManager" + ReferencedContainer = "container:AudioPlayerManager.xcodeproj"> diff --git a/AudioPlayerManager/Core/Private/AudioTracksQueue.swift b/AudioPlayerManager/Core/Private/AudioTracksQueue.swift new file mode 100644 index 0000000..8c2faa7 --- /dev/null +++ b/AudioPlayerManager/Core/Private/AudioTracksQueue.swift @@ -0,0 +1,125 @@ +// +// AudioTracksQueue.swift +// AudioPlayerManager +// +// Created by Hans Seiffert on 02.08.16. +// Copyright © 2016 Hans Seiffert. All rights reserved. +// + +import UIKit + +class AudioTracksQueue: NSObject { + + // MARK: - Private variables + + private(set) var currentTrack : AudioTrack? + + private var previousTrack : AudioTrack? { + let previousIndex = self.currentItemQueueIndex - 1 + if (previousIndex >= 0) { + return self.queue[previousIndex] + } + return nil + } + + private var queue = [AudioTrack]() + private var currentItemQueueIndex = 0 + + private var history = [AudioTrack]() + + // MARK: Set + + func replace(tracks: [AudioTrack]?, startIndex: Int) { + if let _tracks = tracks { + // Add the current track to the history + if let _currentTrack = self.currentTrack { + self.history.append(_currentTrack) + } + // Replace the tracks in the queue with the new ones + self.queue = _tracks + self.currentItemQueueIndex = startIndex + self.currentTrack?.cleanupAfterPlaying() + self.currentTrack = _tracks[startIndex] + } else { + self.queue.removeAll() + self.currentTrack?.cleanupAfterPlaying() + self.currentTrack = nil + self.currentItemQueueIndex = 0 + } + } + + func prepend(tracks: [AudioTrack]) { + // Insert the tracks at the beginning of the queue + self.queue.insertContentsOf(tracks, at: 0) + // Adjust the current index to the new size + self.currentItemQueueIndex += tracks.count + } + + func append(tracks: [AudioTrack]) { + self.queue.appendContentsOf(tracks) + } + + // MARK: Forward + + func canForward() -> Bool { + return (self.queue.count > 0 && self.followingTrack() != nil) + } + + func forward() -> Bool { + if (self.canForward() == true), + let _currentTrack = self.currentTrack, + _followingTrack = self.followingTrack() { + // Add current track to the history + _currentTrack.cleanupAfterPlaying() + // Replace the current track with the new one + self.currentTrack = _followingTrack + // Adjust the current track index + self.currentItemQueueIndex += 1 + // Add the former track to the history + self.history.append(_currentTrack) + return true + } + return false + } + + private func followingTrack() -> AudioTrack? { + let followingIndex = self.currentItemQueueIndex + 1 + if (followingIndex < self.queue.count) { + return self.queue[followingIndex] + } + return nil + } + + // MARK: Rewind + + func canRewind() -> Bool { + return (self.previousTrack != nil) + } + + func rewind() -> Bool { + if (self.canRewind() == true), + let _currentTrack = self.currentTrack { + _currentTrack.cleanupAfterPlaying() + // Replace the current track with the former one + self.currentTrack = self.previousTrack + // Adjust the current index + self.currentItemQueueIndex -= 1 + return true + } + return false + } + + // MARK: Get + + func count() -> Int { + return self.queue.count + } + + // History + + private func appendCurrentPlayingItemToQueue() { + if let _currentTrack = self.currentTrack { + self.history.append(_currentTrack) + } + } +} diff --git a/AudioPlayerManager/Core/Private/Log.swift b/AudioPlayerManager/Core/Private/Log.swift new file mode 100644 index 0000000..86ad7ae --- /dev/null +++ b/AudioPlayerManager/Core/Private/Log.swift @@ -0,0 +1,23 @@ +// +// Log.swift +// AudioPlayerManager +// +// Created by Hans Seiffert on 02.08.16. +// Copyright © 2016 Hans Seiffert. All rights reserved. +// + +import UIKit + +// MARK: - Log + +func Log(message: AnyObject = "", file: String = #file, function: String = #function, line: Int = #line) { + if (AudioPlayerManager.Verbose == true) { + if (AudioPlayerManager.DetailedLog == true), + let className = NSURL(string: file)?.lastPathComponent?.componentsSeparatedByString(".").first { + let log = "\(NSDate()) - [\(className)].\(function)[\(line)]: \(message)" + print(log) + } else { + print(message) + } + } +} diff --git a/AudioPlayer/Core/Private/MediaLibraryHelper.swift b/AudioPlayerManager/Core/Private/MediaLibraryHelper.swift similarity index 96% rename from AudioPlayer/Core/Private/MediaLibraryHelper.swift rename to AudioPlayerManager/Core/Private/MediaLibraryHelper.swift index 03b1514..8d47fd1 100644 --- a/AudioPlayer/Core/Private/MediaLibraryHelper.swift +++ b/AudioPlayerManager/Core/Private/MediaLibraryHelper.swift @@ -1,6 +1,6 @@ // // HSMediaLibraryHelper.swift -// AudioPlayer +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. diff --git a/AudioPlayer/Core/Public/MPMediaItem+AudioPlayer.swift b/AudioPlayerManager/Core/Public/MPMediaItem+AudioPlayerManager.swift similarity index 87% rename from AudioPlayer/Core/Public/MPMediaItem+AudioPlayer.swift rename to AudioPlayerManager/Core/Public/MPMediaItem+AudioPlayerManager.swift index 9b3837c..fe1a538 100644 --- a/AudioPlayer/Core/Public/MPMediaItem+AudioPlayer.swift +++ b/AudioPlayerManager/Core/Public/MPMediaItem+AudioPlayerManager.swift @@ -1,6 +1,6 @@ // -// MPMediaItem+AudioPlayer.swift -// AudioPlayer +// MPMediaItem+AudioPlayerManager.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. diff --git a/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+MPMediaItem.swift b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+MPMediaItem.swift new file mode 100644 index 0000000..0775d7e --- /dev/null +++ b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+MPMediaItem.swift @@ -0,0 +1,69 @@ +// +// AudioPlayerManager+MPMediaItem.swift +// AudioPlayerManager +// +// Created by Hans Seiffert on 02.08.16. +// Copyright © 2016 Hans Seiffert. All rights reserved. +// +import MediaPlayer + +extension AudioPlayerManager { + + // MARK: - Play + + public func play(mediaItem mediaItem: MPMediaItem) { + if let _track = MediaPlayerTrack(mediaItem: mediaItem) { + self.play(_track) + } + } + + public func play(mediaItems mediaItems: [MPMediaItem], startIndex: Int) { + // Play first track directly and add the other tracks to the queue in the background + if let firstPlayableItem = MediaPlayerTrack.firstPlayable(mediaItems, startIndex: startIndex) { + // Play the first track directly + self.play(firstPlayableItem.track) + // Split the tracks into array which contain the ones which have to be prepended and appended them to the queue + var tracksToPrepend = Array(mediaItems) + tracksToPrepend.removeRange(firstPlayableItem.index.. Bool { + return self.isPlaying(persistentID: mediaItem.persistentID) + } + + public func isPlaying(mediaItemCollection: MPMediaItemCollection) -> Bool { + for mediaItem in mediaItemCollection.items { + if (self.isPlaying(mediaItem: mediaItem) == true) { + return true + } + } + return false + } + + public func isPlaying(persistentID persistentID: MPMediaEntityPersistentID) -> Bool { + if (self.isPlaying() == true), + let _currentTrack = self.currentTrack as? MediaPlayerTrack { + return ("\(persistentID)" == _currentTrack.identifier()) + } + return false + } +} diff --git a/AudioPlayer/Core/Public/Player/AudioPlayer+RemoteControl.swift b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+RemoteControl.swift similarity index 86% rename from AudioPlayer/Core/Public/Player/AudioPlayer+RemoteControl.swift rename to AudioPlayerManager/Core/Public/Player/AudioPlayerManager+RemoteControl.swift index e8cfc47..1dec27d 100644 --- a/AudioPlayer/Core/Public/Player/AudioPlayer+RemoteControl.swift +++ b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+RemoteControl.swift @@ -1,6 +1,6 @@ // -// AudioPlayer+RemoteControl.swift -// AudioPlayer +// AudioPlayerManager+RemoteControl.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. @@ -8,7 +8,7 @@ import UIKit -extension AudioPlayer { +extension AudioPlayerManager { public func remoteControlReceivedWithEvent(event: UIEvent?) { if let _event = event { diff --git a/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+URL.swift b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+URL.swift new file mode 100644 index 0000000..0677faa --- /dev/null +++ b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager+URL.swift @@ -0,0 +1,67 @@ +// +// AudioPlayerManager+URL.swift +// AudioPlayerManager +// +// Created by Hans Seiffert on 02.08.16. +// Copyright © 2016 Hans Seiffert. All rights reserved. +// +import MediaPlayer + +extension AudioPlayerManager { + + // MARK: - Play + + public func play(urlString urlString: String) { + self.play(url: NSURL(string: urlString)) + } + + public func play(urlStrings urlStrings: [String], startIndex: Int) { + self.play(urls: AudioURLTrack.convertToURLs(urlStrings), startIndex: startIndex) + } + + public func play(url url: NSURL?) { + if let _track = AudioURLTrack(url: url) { + self.play(_track) + } + } + + public func play(urls urls: [NSURL?], startIndex: Int) { + // Play the first track directly and add the other tracks to the queue in the background + if let firstPlayableItem = AudioURLTrack.firstPlayableItem(urls, startIndex: startIndex) { + // Play the first track directly + self.play(firstPlayableItem.track) + // Split the tracks into an array which contain the ones which have to be prepended and appended to queue + var urlsToPrepend = Array(urls) + if (firstPlayableItem.index > 0) { + // If the index of the first playable URL is greater than 0 there are URL to prepend + urlsToPrepend.removeRange(firstPlayableItem.index.. Bool { + return self.isPlaying(url: NSURL(string: urlString)) + } + + public func isPlaying(url url: NSURL?) -> Bool { + return (self.isPlaying() == true && self.currentTrack?.identifier() == url?.absoluteString) + } +} diff --git a/AudioPlayer/Core/Public/Player/AudioPlayer.swift b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager.swift similarity index 59% rename from AudioPlayer/Core/Public/Player/AudioPlayer.swift rename to AudioPlayerManager/Core/Public/Player/AudioPlayerManager.swift index 3cfce32..85fbb96 100644 --- a/AudioPlayer/Core/Public/Player/AudioPlayer.swift +++ b/AudioPlayerManager/Core/Public/Player/AudioPlayerManager.swift @@ -1,6 +1,6 @@ // -// AudioPlayer.swift -// AudioPlayer +// AudioPlayerManager.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. @@ -10,20 +10,20 @@ import Foundation import AVFoundation import MediaPlayer -public class AudioPlayer: NSObject { +public class AudioPlayerManager: NSObject { // MARK: - PUBLIC - // MARK: - Properties - public static let sharedInstance = AudioPlayer() + public static let sharedInstance = AudioPlayerManager() // MARK: - Configuration - /// Set this to true if the `AudioPlayer` log should be enabled. The default is `false`. - public static var Verbose = false + /// Set this to true if the `AudioPlayerManager` log should be enabled. The default is `false`. + public static var Verbose = true - /// Set this to true if the `AudioPlayer` log should containt detailed information about the calling class, function and line. The default is `true`. + /// Set this to true if the `AudioPlayerManager` log should containt detailed information about the calling class, function and line. The default is `true`. public static var DetailedLog = true /// Set this to true to use the systems `MPNowPlayingInfoCenter` (control center and lock screen). The default value is `true`. @@ -39,33 +39,34 @@ public class AudioPlayer: NSObject { // The `NSTimeInterval` of the players update interval. Eg. the PlaybackTimeChangeCallbacks will be called then. public var playingTimeRefreshRate : NSTimeInterval = 0.1 + public var currentTrack : AudioTrack? { + return self.queue.currentTrack + } + // MARK: - Initializaiton - public class func audioPlayer() -> AudioPlayer { - let audioPlayer = AudioPlayer() - audioPlayer.setup() - return audioPlayer + public class func standaloneInstance() -> AudioPlayerManager { + return self.standaloneInstance(useNowPlayingInfoCenter: nil, useRemoteControlEvents: nil) } - public class func audioPlayer(useNowPlayingInfoCenter useNowPlayingInfoCenter: Bool, useRemoteControlEvents: Bool) -> AudioPlayer { - let audioPlayer = AudioPlayer() - audioPlayer.useRemoteControlEvents = useRemoteControlEvents - audioPlayer.useNowPlayingInfoCenter = useNowPlayingInfoCenter - audioPlayer.setup() - return audioPlayer + public class func standaloneInstance(useNowPlayingInfoCenter useNowPlayingInfoCenter: Bool?, useRemoteControlEvents: Bool?) -> AudioPlayerManager { + let manager = AudioPlayerManager() + if let _useRemoteControlEvents = useRemoteControlEvents { + manager.useRemoteControlEvents = _useRemoteControlEvents + } + if let _useNowPlayingInfoCenter = useNowPlayingInfoCenter { + manager.useNowPlayingInfoCenter = _useNowPlayingInfoCenter + } + return manager } public override init() { super.init() - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AudioPlayer.playerItemDidFinishPlaying), name: AVPlayerItemDidPlayToEndTimeNotification, object: nil) + NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AudioPlayerManager.trackDidFinishPlaying), name: AVPlayerItemDidPlayToEndTimeNotification, object: nil) } public func setup() { - self.setup(useNowPlayingInfoCenter: self.useNowPlayingInfoCenter, useRemoteControlEvents: self.useRemoteControlEvents) - } - - public func setup(useNowPlayingInfoCenter useNowPlayingInfoCenter: Bool, useRemoteControlEvents: Bool) { self.setupRemoteControlEvents() self.setupAudioSession() } @@ -95,60 +96,60 @@ public class AudioPlayer: NSObject { self.didStopPlayback = false self.startPlaybackTimeChangeTimer() self.callPlayStateChangeCallbacks() - if let _currentPlayerItem = self.currentPlayerItem() { - NSNotificationCenter.defaultCenter().postNotificationName(self.playerStateChangedNotificationKey(playerItem: _currentPlayerItem), object: nil) + if let _currentTrack = self.currentTrack { + NSNotificationCenter.defaultCenter().postNotificationName(self.playerStateChangedNotificationKey(track: _currentTrack), object: nil) } } } - public func play(playerItem: AudioPlayerItem) { - AudioPlayerLog("play(playerItem: \(playerItem))") + public func play(audioTrack: AudioTrack) { + Log("play(audioTrack: \(audioTrack))") self.stop() - self.play([playerItem], startPosition: 0) + self.play([audioTrack], startIndex: 0) } - public func play(playerItems: [AudioPlayerItem], startPosition: Int) { - AudioPlayerLog("play(playerItems: \(playerItems.count) items, startPosition: \(startPosition))") - self.replace(playerItems, startPosition: startPosition) - // Start playing the new item - self.restartCurrentPlayerItem() + public func play(audioTracks: [AudioTrack], startIndex: Int) { + Log("play(audioTracks: \(audioTracks.count) tracks, startIndex: \(startIndex))") + self.replace(audioTracks, startIndex: startIndex) + // Start playing the new track + self.restartCurrentTrack() } - public func replace(playerItem: AudioPlayerItem) { - AudioPlayerLog("replace(playerItem: \(playerItem))") - self.replace([playerItem], startPosition: 0) + public func replace(audioTrack: AudioTrack) { + Log("replace(audioTrack: \(audioTrack))") + self.replace([audioTrack], startIndex: 0) } - public func replace(playerItems: [AudioPlayerItem], startPosition: Int) { - AudioPlayerLog("replace(playerItems: \(playerItems.count) items, startPosition: \(startPosition))") + public func replace(audioTracks: [AudioTrack], startIndex: Int) { + Log("replace(audioTracks: \(audioTracks.count) tracks, startIndex: \(startIndex))") self.stop() - var reducedPlayerItems = [] as [AudioPlayerItem] - for index in 0.. Bool { - if ((self.currentPlayerItem()?.currentTimeInSeconds() > Float(1) && self.currentPlayerItem() != nil) || self.canRewindInQueue()) { + if ((self.currentTrack?.currentTimeInSeconds() > Float(1) && self.currentTrack != nil) || self.canRewindInQueue()) { return true } return false } public func rewind() { - if (self.currentPlayerItem()?.currentTimeInSeconds() <= Float(1) && self.canRewindInQueue() == true) { + if (self.currentTrack?.currentTimeInSeconds() <= Float(1) && self.canRewindInQueue() == true) { self.stop() if (self.queue.rewind() == true) { - self.restartCurrentPlayerItem() + self.restartCurrentTrack() } } else { - // Move to the beginning of the player item if we aren't in the beginning. + // Move to the beginning of the track if we aren't in the beginning. self.player?.seekToTime(CMTimeMake(0, 1)) // Update the now playing info to show the new playback time self.updateNowPlayingInfo() @@ -225,14 +226,14 @@ public class AudioPlayer: NSObject { } public func seek(toProgress progress: Float) { - let progressInSeconds = Int64(progress * (self.currentPlayerItem()?.durationInSeconds() ?? 0)) + let progressInSeconds = Int64(progress * (self.currentTrack?.durationInSeconds() ?? 0)) let time = CMTimeMake(progressInSeconds, 1) self.seek(toTime: time) } // MARK: - Internal helper - public func playerItemDidFinishPlaying() { + public func trackDidFinishPlaying() { self.forward() } @@ -248,7 +249,7 @@ public class AudioPlayer: NSObject { // MARK: - Playback time change callback - public func addPlaybackTimeChangeCallback(sender: AnyObject, callback: (playerItem: AudioPlayerItem) -> Void) { + public func addPlaybackTimeChangeCallback(sender: AnyObject, callback: (track: AudioTrack) -> Void) { let uid = "\(unsafeAddressOf(sender))" if var _callbacks = self.playbackPositionChangeCallbacks[uid] { _callbacks.append(callback) @@ -264,7 +265,7 @@ public class AudioPlayer: NSObject { // MARK: - Play state change callback - public func addPlayStateChangeCallback(sender: AnyObject, callback: (playerItem: AudioPlayerItem?) -> Void) { + public func addPlayStateChangeCallback(sender: AnyObject, callback: (track: AudioTrack?) -> Void) { let uid = "\(unsafeAddressOf(sender))" if var _callbacks = self.playStateChangeCallbacks[uid] { _callbacks.append(callback) @@ -284,10 +285,6 @@ public class AudioPlayer: NSObject { return self.player?.rate > 0 } - public func currentPlayerItem() -> AudioPlayerItem? { - return self.queue.currentPlayingItem() - } - // MARK: - INTERNAL - // MARK: - Properties @@ -320,22 +317,22 @@ public class AudioPlayer: NSObject { static let Status = "status" } - private let audioPlayerStateChangedPrefix = "AudioPlayer.\(NSUUID().UUIDString).playerStateChanged" + private let audioPlayerManagerStateChangedPrefix = "AudioPlayerManager.\(NSUUID().UUIDString).playerStateChanged" - private var player : AVPlayer? + private var player : AVPlayer? - private var queue = AudioPlayerQueue() + private var queue = AudioTracksQueue() - private var didStopPlayback = false + private var didStopPlayback = false // MARK: Callbacks - private var playStateChangeCallbacks = Dictionary (Void))]>() - private var playbackPositionChangeCallbacks = Dictionary (Void))]>() + private var playStateChangeCallbacks = Dictionary (Void))]>() + private var playbackPositionChangeCallbacks = Dictionary (Void))]>() - private var playbackPositionChangeTimer : NSTimer? - private var stopPlaybackTimeChangeTimer = false + private var playbackPositionChangeTimer : NSTimer? + private var stopPlaybackTimeChangeTimer = false - private var addedPlayerStateObserver = false + private var addedPlayerStateObserver = false // MARK: - Initializaiton @@ -367,8 +364,8 @@ public class AudioPlayer: NSObject { // MARK: - Play - private func restartCurrentPlayerItem() { - AudioPlayerLog("restartCurrentPlayerItem") + private func restartCurrentTrack() { + Log("restartCurrentTrack") if (self.player != nil) { if (self.addedPlayerStateObserver == true) { self.addedPlayerStateObserver = false @@ -377,14 +374,13 @@ public class AudioPlayer: NSObject { self.stop() } - if - let _currentPlayerItem = self.queue.currentPlayingItem() { + if let _currentTrack = self.queue.currentTrack { self.player = AVPlayer() self.initPlayer() - _currentPlayerItem.loadResource() - if let _avPlayerItem = _currentPlayerItem.getAVPlayerItem() { - _currentPlayerItem.prepareForPlaying(_avPlayerItem) - self.player?.replaceCurrentItemWithPlayerItem(_avPlayerItem) + _currentTrack.loadResource() + if let _playerItem = _currentTrack.getPlayerItem() { + _currentTrack.prepareForPlaying(_playerItem) + self.player?.replaceCurrentItemWithPlayerItem(_playerItem) } } } @@ -399,19 +395,19 @@ public class AudioPlayer: NSObject { private func updateNowPlayingInfo() { if (self.useNowPlayingInfoCenter == true) { - MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = self.currentPlayerItem()?.nowPlayingInfo + MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = self.currentTrack?.nowPlayingInfo } } // MARK: - Plaback time change callback func callPlaybackTimeChangeCallbacks() { - // Increase the current items playing time if the player is playing - if let _currentPlayerItem = self.currentPlayerItem() { + // Increase the current tracks playing time if the player is playing + if let _currentTrack = self.currentTrack { for sender in self.playbackPositionChangeCallbacks.keys { if let _callbacks = self.playbackPositionChangeCallbacks[sender] { for playbackPositionChangeClosure in _callbacks { - playbackPositionChangeClosure(playerItem: _currentPlayerItem) + playbackPositionChangeClosure(track: _currentTrack) } } } @@ -423,7 +419,7 @@ public class AudioPlayer: NSObject { private func startPlaybackTimeChangeTimer() { self.stopPlaybackTimeChangeTimer = false - self.playbackPositionChangeTimer = NSTimer.scheduledTimerWithTimeInterval(self.playingTimeRefreshRate, target: self, selector: #selector(AudioPlayer.callPlaybackTimeChangeCallbacks), userInfo: nil, repeats: true) + self.playbackPositionChangeTimer = NSTimer.scheduledTimerWithTimeInterval(self.playingTimeRefreshRate, target: self, selector: #selector(AudioPlayerManager.callPlaybackTimeChangeCallbacks), userInfo: nil, repeats: true) self.playbackPositionChangeTimer?.fire() } @@ -433,16 +429,16 @@ public class AudioPlayer: NSObject { for sender in self.playStateChangeCallbacks.keys { if let _callbacks = self.playStateChangeCallbacks[sender] { for playStateChangeClosure in _callbacks { - playStateChangeClosure(playerItem: self.currentPlayerItem()) + playStateChangeClosure(track: self.currentTrack) } } } } } -extension AudioPlayer { +extension AudioPlayerManager { - public func playerStateChangedNotificationKey(playerItem playerItem: AudioPlayerItem) -> String { - return "\(self.audioPlayerStateChangedPrefix)_\(playerItem.identifier() ?? "")" + public func playerStateChangedNotificationKey(track track: AudioTrack) -> String { + return "\(self.audioPlayerManagerStateChangedPrefix)_\(track.identifier() ?? "")" } } diff --git a/AudioPlayer/Core/Public/Track/AudioPlayerItem.swift b/AudioPlayerManager/Core/Public/Track/AudioTrack.swift similarity index 70% rename from AudioPlayer/Core/Public/Track/AudioPlayerItem.swift rename to AudioPlayerManager/Core/Public/Track/AudioTrack.swift index 4cd464a..962a878 100644 --- a/AudioPlayer/Core/Public/Track/AudioPlayerItem.swift +++ b/AudioPlayerManager/Core/Public/Track/AudioTrack.swift @@ -1,6 +1,6 @@ // -// AudioPlayerItem.swift -// AudioPlayer +// AudioTrack.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. @@ -10,13 +10,13 @@ import Foundation import AVFoundation import MediaPlayer -public class AudioPlayerItem : NSObject { +public class AudioTrack : NSObject { // MARK: - PUBLIC - // MARK: - Properties - public var avPlayerItem : AVPlayerItem? + public var playerItem : AVPlayerItem? public var nowPlayingInfo : [String : NSObject]? @@ -26,7 +26,7 @@ public class AudioPlayerItem : NSObject { // Reloads the resource in the child class if necessary. } - public func getAVPlayerItem() -> AVPlayerItem? { + public func getPlayerItem() -> AVPlayerItem? { // Return the AVPlayerItem in the subclasses return nil } @@ -42,8 +42,8 @@ public class AudioPlayerItem : NSObject { // MARK: - Helper public func durationInSeconds() -> Float { - if let _avPlayerItem = self.avPlayerItem where _avPlayerItem.duration != kCMTimeIndefinite { - return Float(CMTimeGetSeconds(_avPlayerItem.duration)) + if let _playerItem = self.playerItem where _playerItem.duration != kCMTimeIndefinite { + return Float(CMTimeGetSeconds(_playerItem.duration)) } return Float(0) } @@ -56,8 +56,8 @@ public class AudioPlayerItem : NSObject { } public func currentTimeInSeconds() -> Float { - if let _avPlayerItem = self.avPlayerItem { - return Float(CMTimeGetSeconds(_avPlayerItem.currentTime())) + if let _playerItem = self.playerItem { + return Float(CMTimeGetSeconds(_playerItem.currentTime())) } return Float(0) } @@ -65,16 +65,16 @@ public class AudioPlayerItem : NSObject { // MARK: - Displayable Time strings public func displayablePlaybackTimeString() -> String { - return AudioPlayerItem.displayableStringFromTimeInterval(NSTimeInterval(self.currentTimeInSeconds())) + return AudioTrack.displayableStringFromTimeInterval(NSTimeInterval(self.currentTimeInSeconds())) } public func displayableDurationString() -> String { - return AudioPlayerItem.displayableStringFromTimeInterval(NSTimeInterval(self.durationInSeconds())) + return AudioTrack.displayableStringFromTimeInterval(NSTimeInterval(self.durationInSeconds())) } public func displayableTimeLeftString() -> String { let timeLeft = self.durationInSeconds() - self.currentTimeInSeconds() - return "-\(AudioPlayerItem.displayableStringFromTimeInterval(NSTimeInterval(timeLeft)))" + return "-\(AudioTrack.displayableStringFromTimeInterval(NSTimeInterval(timeLeft)))" } public func isPlayable() -> Bool { @@ -85,21 +85,21 @@ public class AudioPlayerItem : NSObject { // MARK: - Lifecycle - func prepareForPlaying(avPlayerItem: AVPlayerItem) { - self.avPlayerItem = avPlayerItem + func prepareForPlaying(playerItem: AVPlayerItem) { + self.playerItem = playerItem self.initNowPlayingInfo() } func cleanupAfterPlaying() { - self.avPlayerItem = nil + self.playerItem = nil self.nowPlayingInfo?.removeAll() } // MARK: - Now playing info public func updateNowPlayingInfoPlaybackDuration() { - if let _avPlayerItem = self.avPlayerItem { - let duration = NSNumber(integer: Int(CMTimeGetSeconds(_avPlayerItem.asset.duration))) + if let _playerItem = self.playerItem { + let duration = NSNumber(integer: Int(CMTimeGetSeconds(_playerItem.asset.duration))) self.nowPlayingInfo?[MPMediaItemPropertyPlaybackDuration] = duration } } diff --git a/AudioPlayer/Core/Public/Track/URLAudioPlayerItem.swift b/AudioPlayerManager/Core/Public/Track/AudioURLTrack.swift similarity index 61% rename from AudioPlayer/Core/Public/Track/URLAudioPlayerItem.swift rename to AudioPlayerManager/Core/Public/Track/AudioURLTrack.swift index fc65542..ad8c31a 100644 --- a/AudioPlayer/Core/Public/Track/URLAudioPlayerItem.swift +++ b/AudioPlayerManager/Core/Public/Track/AudioURLTrack.swift @@ -1,6 +1,6 @@ // -// HSURLAudioPlayerItem.swift -// AudioPlayer +// AudioURLTrack.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. @@ -10,7 +10,7 @@ import Foundation import AVFoundation import MediaPlayer -public class HSURLAudioPlayerItem: AudioPlayerItem { +public class AudioURLTrack: AudioTrack { // MARK: - Properties @@ -30,24 +30,24 @@ public class HSURLAudioPlayerItem: AudioPlayerItem { self.url = url } - public class func playerItems(urlStrings: [String], startPosition: Int) -> (playerItems: [HSURLAudioPlayerItem], startPosition: Int) { - return self.playerItems(HSURLAudioPlayerItem.convertToURLs(urlStrings), startPosition: startPosition) + public class func items(urlStrings: [String], startIndex: Int) -> (tracks: [AudioURLTrack], startIndex: Int) { + return self.items(AudioURLTrack.convertToURLs(urlStrings), startIndex: startIndex) } - public class func playerItems(urls: [NSURL?], startPosition: Int) -> (playerItems: [HSURLAudioPlayerItem], startPosition: Int) { - var reducedPlayerItems = [HSURLAudioPlayerItem]() - var reducedStartPosition = startPosition - // Iterate through all given URLs and create the player items + public class func items(urls: [NSURL?], startIndex: Int) -> (tracks: [AudioURLTrack], startIndex: Int) { + var reducedTracks = [AudioURLTrack]() + var reducedStartIndex = startIndex + // Iterate through all given URLs and create the tracks for index in 0.. 0) { - // There is a problem with the URL. Ignore the URL and shift the start position if it is higher than the current index - reducedStartPosition -= 1 + if let _playerItem = AudioURLTrack(url: _url) { + reducedTracks.append(_playerItem) + } else if (index <= startIndex && reducedStartIndex > 0) { + // There is a problem with the URL. Ignore the URL and shift the start index if it is higher than the current index + reducedStartIndex -= 1 } } - return (playerItems: reducedPlayerItems, startPosition: reducedStartPosition) + return (tracks: reducedTracks, startIndex: reducedStartIndex) } // MARK: - Lifecycle @@ -55,16 +55,16 @@ public class HSURLAudioPlayerItem: AudioPlayerItem { override func prepareForPlaying(avPlayerItem: AVPlayerItem) { super.prepareForPlaying(avPlayerItem) // Listen to the timedMetadata initialization. We can extract the meta data then - self.avPlayerItem?.addObserver(self, forKeyPath: Keys.TimedMetadata, options: NSKeyValueObservingOptions.Initial, context: nil) + self.playerItem?.addObserver(self, forKeyPath: Keys.TimedMetadata, options: NSKeyValueObservingOptions.Initial, context: nil) } override func cleanupAfterPlaying() { // Remove the timedMetadata observer as the AVPlayerItem will be released now - self.avPlayerItem?.removeObserver(self, forKeyPath: Keys.TimedMetadata, context: nil) + self.playerItem?.removeObserver(self, forKeyPath: Keys.TimedMetadata, context: nil) super.cleanupAfterPlaying() } - public override func getAVPlayerItem() -> AVPlayerItem? { + public override func getPlayerItem() -> AVPlayerItem? { if let _url = self.url { return AVPlayerItem(URL: _url) } @@ -96,12 +96,12 @@ public class HSURLAudioPlayerItem: AudioPlayerItem { return urls } - public class func firstPlayableItem(urls: [NSURL?], startPosition: Int) -> (playerItem: HSURLAudioPlayerItem, index: Int)? { + public class func firstPlayableItem(urls: [NSURL?], startIndex: Int) -> (track: AudioURLTrack, index: Int)? { // Iterate through all URLs and check whether it's not nil - for index in startPosition.. reuturn nil then @@ -115,8 +115,8 @@ public class HSURLAudioPlayerItem: AudioPlayerItem { } private func extractMetadata() { - AudioPlayerLog("Extracting meta data of player item with url: \(url)") - for metadataItem in (self.avPlayerItem?.asset.commonMetadata ?? []) { + Log("Extracting meta data of player item with url: \(url)") + for metadataItem in (self.playerItem?.asset.commonMetadata ?? []) { if let _key = metadataItem.commonKey { switch _key { case AVMetadataCommonKeyTitle : self.nowPlayingInfo?[MPMediaItemPropertyTitle] = metadataItem.stringValue @@ -133,13 +133,13 @@ public class HSURLAudioPlayerItem: AudioPlayerItem { } } // Inform the player about the updated meta data - AudioPlayer.sharedInstance.didUpdateMetadata() + AudioPlayerManager.sharedInstance.didUpdateMetadata() } } // MARK: - KVO -extension HSURLAudioPlayerItem { +extension AudioURLTrack { override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) { if (keyPath == Keys.TimedMetadata) { diff --git a/AudioPlayer/Core/Public/Track/MediaItemAudioPlayerItem.swift b/AudioPlayerManager/Core/Public/Track/MediaPlayerTrack.swift similarity index 66% rename from AudioPlayer/Core/Public/Track/MediaItemAudioPlayerItem.swift rename to AudioPlayerManager/Core/Public/Track/MediaPlayerTrack.swift index 5924fec..dc53438 100644 --- a/AudioPlayer/Core/Public/Track/MediaItemAudioPlayerItem.swift +++ b/AudioPlayerManager/Core/Public/Track/MediaPlayerTrack.swift @@ -1,6 +1,6 @@ // -// HSMediaItemAudioPlayerItem.swift -// AudioPlayer +// MediaPlayerTrack.swift +// AudioPlayerManager // // Created by Hans Seiffert on 02.08.16. // Copyright © 2016 Hans Seiffert. All rights reserved. @@ -10,7 +10,7 @@ import Foundation import AVFoundation import MediaPlayer -public class HSMediaItemAudioPlayerItem: AudioPlayerItem { +public class MediaPlayerTrack: AudioTrack { // MARK: - Properties @@ -33,18 +33,18 @@ public class HSMediaItemAudioPlayerItem: AudioPlayerItem { self.mediaItem = mediaItem } - public class func playerItems(mediaItems: [MPMediaItem], startPosition: Int) -> (items: [HSMediaItemAudioPlayerItem], startPosition: Int) { - var reducedPlayerItems = [HSMediaItemAudioPlayerItem]() - var updatedPosition = startPosition + public class func items(mediaItems: [MPMediaItem], startIndex: Int) -> (tracks: [MediaPlayerTrack], startIndex: Int) { + var reducedTracks = [MediaPlayerTrack]() + var updatedIndex = startIndex for index in 0.. 0) { - updatedPosition -= 1 + if let _playerItem = MediaPlayerTrack(mediaItem: mediaItem) { + reducedTracks.append(_playerItem) + } else if (index <= startIndex && updatedIndex > 0) { + updatedIndex -= 1 } } - return (items: reducedPlayerItems, startPosition: updatedPosition) + return (tracks: reducedTracks, startIndex: updatedIndex) } // MARK: - Lifecycle @@ -55,7 +55,7 @@ public class HSMediaItemAudioPlayerItem: AudioPlayerItem { } } - public override func getAVPlayerItem() -> AVPlayerItem? { + public override func getPlayerItem() -> AVPlayerItem? { if let _url = self.mediaItem?.assetURL { return AVPlayerItem(URL: _url) } @@ -87,15 +87,15 @@ public class HSMediaItemAudioPlayerItem: AudioPlayerItem { return self.mediaItem?.isPlayable() ?? true } - public class func firstPlayableItem(mediaItems: [MPMediaItem], startPosition: Int) -> (playerItem: HSMediaItemAudioPlayerItem, index: Int)? { + public class func firstPlayable(mediaItems: [MPMediaItem], startIndex: Int) -> (track: MediaPlayerTrack, index: Int)? { // Iterate through all media items - for index in startPosition.. + +//! Project version number for AudioPlayerManager. +FOUNDATION_EXPORT double AudioPlayerManagerVersionNumber; + +//! Project version string for AudioPlayerManager. +FOUNDATION_EXPORT const unsigned char AudioPlayerManagerVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + diff --git a/AudioPlayer/PLists/AudioPlayer-Info.plist b/AudioPlayerManager/PLists/AudioPlayerManager-Info.plist similarity index 100% rename from AudioPlayer/PLists/AudioPlayer-Info.plist rename to AudioPlayerManager/PLists/AudioPlayerManager-Info.plist diff --git a/Example/Core/AppDelegate.swift b/Example/Core/AppDelegate.swift index cd05426..80f7b85 100644 --- a/Example/Core/AppDelegate.swift +++ b/Example/Core/AppDelegate.swift @@ -7,7 +7,7 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -43,6 +43,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // MARK: Remote control override func remoteControlReceivedWithEvent(event: UIEvent?) { - AudioPlayer.sharedInstance.remoteControlReceivedWithEvent(event) + AudioPlayerManager.sharedInstance.remoteControlReceivedWithEvent(event) } } diff --git a/Example/Core/ViewController/MultiplePlayerInstances/MultiplePlayerInstancesViewController.swift b/Example/Core/ViewController/MultiplePlayerInstances/MultiplePlayerInstancesViewController.swift index 6cf92f1..14a99e1 100644 --- a/Example/Core/ViewController/MultiplePlayerInstances/MultiplePlayerInstancesViewController.swift +++ b/Example/Core/ViewController/MultiplePlayerInstances/MultiplePlayerInstancesViewController.swift @@ -7,12 +7,12 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager import MediaPlayer class MultiplePlayerInstancesViewController: UIViewController { - private var data : [(mediaItem: MPMediaItem, audioPlayer: AudioPlayer?)] = [] + private var data : [(mediaItem: MPMediaItem, audioPlayerManager: AudioPlayerManager?)] = [] @IBOutlet private weak var tableView: UITableView? @@ -23,7 +23,7 @@ class MultiplePlayerInstancesViewController: UIViewController { self.data = [] for mediaItem in tempData { if (mediaItem.cloudItem == false && mediaItem.assetURL != nil) { - self.data.append((mediaItem: mediaItem, audioPlayer: nil)) + self.data.append((mediaItem: mediaItem, audioPlayerManager: nil)) if (self.data.count >= 20) { break } @@ -50,8 +50,8 @@ extension MultiplePlayerInstancesViewController: UITableViewDelegate, UITableVie if let _cell = tableView.dequeueReusableCellWithIdentifier("multiplePlayerInstancesCell", forIndexPath: indexPath) as? MultiplePlayerInstancesTableViewCell { let _mediItem = self.data[indexPath.row].mediaItem - let audioPlayer = self.data[indexPath.row].audioPlayer - _cell.setup(_mediItem, isPlaying: (audioPlayer?.isPlaying() ?? false)) + let audioPlayerManager = self.data[indexPath.row].audioPlayerManager + _cell.setup(_mediItem, isPlaying: (audioPlayerManager?.isPlaying() ?? false)) return _cell } return UITableViewCell() @@ -60,17 +60,18 @@ extension MultiplePlayerInstancesViewController: UITableViewDelegate, UITableVie func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) - var audioPlayer = self.data[indexPath.row].audioPlayer - if (audioPlayer == nil) { - audioPlayer = AudioPlayer.audioPlayer() - audioPlayer?.useRemoteControlEvents = false - audioPlayer?.useNowPlayingInfoCenter = false - self.data[indexPath.row].audioPlayer = audioPlayer + var audioPlayerManager = self.data[indexPath.row].audioPlayerManager + if (audioPlayerManager == nil) { + audioPlayerManager = AudioPlayerManager.standaloneInstance() + audioPlayerManager?.setup() + audioPlayerManager?.useRemoteControlEvents = false + audioPlayerManager?.useNowPlayingInfoCenter = false + self.data[indexPath.row].audioPlayerManager = audioPlayerManager } - if (audioPlayer?.isPlaying() == true) { - audioPlayer?.stop() + if (audioPlayerManager?.isPlaying() == true) { + audioPlayerManager?.stop() } else { - audioPlayer?.play(mediaItem: self.data[indexPath.row].mediaItem) + audioPlayerManager?.play(mediaItem: self.data[indexPath.row].mediaItem) } } } diff --git a/Example/Core/ViewController/SharedInstancePlayer/MusicLibraryViewController.swift b/Example/Core/ViewController/SharedInstancePlayer/MusicLibraryViewController.swift index 6907d2c..d3a71f5 100644 --- a/Example/Core/ViewController/SharedInstancePlayer/MusicLibraryViewController.swift +++ b/Example/Core/ViewController/SharedInstancePlayer/MusicLibraryViewController.swift @@ -7,7 +7,7 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager import MediaPlayer class MusicLibraryViewController: UIViewController { @@ -17,7 +17,7 @@ class MusicLibraryViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - AudioPlayer.sharedInstance.setup() + AudioPlayerManager.sharedInstance.setup() let tempData = MPMediaQuery.songsQuery().items ?? [] self.data = [] @@ -49,6 +49,6 @@ extension MusicLibraryViewController: UITableViewDelegate, UITableViewDataSource func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) - AudioPlayer.sharedInstance.play(mediaItems: self.data, startPosition: indexPath.row) + AudioPlayerManager.sharedInstance.play(mediaItems: self.data, startIndex: indexPath.row) } } diff --git a/Example/Core/ViewController/SharedInstancePlayer/PlayerViewController.swift b/Example/Core/ViewController/SharedInstancePlayer/PlayerViewController.swift index 155a735..0ba533b 100644 --- a/Example/Core/ViewController/SharedInstancePlayer/PlayerViewController.swift +++ b/Example/Core/ViewController/SharedInstancePlayer/PlayerViewController.swift @@ -7,7 +7,7 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager import MediaPlayer class PlayerViewController: UIViewController { @@ -28,39 +28,39 @@ class PlayerViewController: UIViewController { self.updateButtonStates() // Listen to the player state updates. This state is updated if the play, pause or queue state changed. - AudioPlayer.sharedInstance.addPlayStateChangeCallback(self, callback: { [weak self] (playerItem: AudioPlayerItem?) in + AudioPlayerManager.sharedInstance.addPlayStateChangeCallback(self, callback: { [weak self] (track: AudioTrack?) in self?.updateButtonStates() - self?.updateSongInformation(playerItem) + self?.updateSongInformation(track) }) - // Listen to the playback time changed. This event occurs every `AudioPlayer.PlayingTimeRefreshRate` seconds. - AudioPlayer.sharedInstance.addPlaybackTimeChangeCallback(self, callback: { [weak self] (playerItem: AudioPlayerItem?) in - self?.updatePlaybackTime(playerItem) + // Listen to the playback time changed. This event occurs every `AudioPlayerManager.PlayingTimeRefreshRate` seconds. + AudioPlayerManager.sharedInstance.addPlaybackTimeChangeCallback(self, callback: { [weak self] (track: AudioTrack?) in + self?.updatePlaybackTime(track) }) } deinit { // Stop listening to the callbacks - AudioPlayer.sharedInstance.removePlayStateChangeCallback(self) - AudioPlayer.sharedInstance.removePlaybackTimeChangeCallback(self) + AudioPlayerManager.sharedInstance.removePlayStateChangeCallback(self) + AudioPlayerManager.sharedInstance.removePlaybackTimeChangeCallback(self) } func updateButtonStates() { - self.rewindButton?.enabled = AudioPlayer.sharedInstance.canRewind() - let imageName = (AudioPlayer.sharedInstance.isPlaying() == true ? "ic_pause" : "ic_play") + self.rewindButton?.enabled = AudioPlayerManager.sharedInstance.canRewind() + let imageName = (AudioPlayerManager.sharedInstance.isPlaying() == true ? "ic_pause" : "ic_play") self.playPauseButton?.setImage(UIImage(named: imageName), forState: .Normal) - self.playPauseButton?.enabled = AudioPlayer.sharedInstance.canPlay() - self.forwardButton?.enabled = AudioPlayer.sharedInstance.canForward() + self.playPauseButton?.enabled = AudioPlayerManager.sharedInstance.canPlay() + self.forwardButton?.enabled = AudioPlayerManager.sharedInstance.canForward() } - func updateSongInformation(playerItem: AudioPlayerItem?) { - self.songLabel?.text = "\((playerItem?.nowPlayingInfo?[MPMediaItemPropertyTitle] as? String) ?? "-")" - self.albumLabel?.text = "\((playerItem?.nowPlayingInfo?[MPMediaItemPropertyAlbumTitle] as? String) ?? "-")" - self.artistLabel?.text = "\((playerItem?.nowPlayingInfo?[MPMediaItemPropertyArtist] as? String) ?? "-")" - self.updatePlaybackTime(playerItem) + func updateSongInformation(track: AudioTrack?) { + self.songLabel?.text = "\((track?.nowPlayingInfo?[MPMediaItemPropertyTitle] as? String) ?? "-")" + self.albumLabel?.text = "\((track?.nowPlayingInfo?[MPMediaItemPropertyAlbumTitle] as? String) ?? "-")" + self.artistLabel?.text = "\((track?.nowPlayingInfo?[MPMediaItemPropertyArtist] as? String) ?? "-")" + self.updatePlaybackTime(track) } - func updatePlaybackTime(playerItem: AudioPlayerItem?) { - self.positionLabel?.text = "\(playerItem?.displayablePlaybackTimeString() ?? "-")/\(playerItem?.displayableDurationString() ?? "-")" + func updatePlaybackTime(track: AudioTrack?) { + self.positionLabel?.text = "\(track?.displayablePlaybackTimeString() ?? "-")/\(track?.displayableDurationString() ?? "-")" } } @@ -69,18 +69,18 @@ class PlayerViewController: UIViewController { extension PlayerViewController { @IBAction func didPressRewindButton(sender: AnyObject) { - AudioPlayer.sharedInstance.rewind() + AudioPlayerManager.sharedInstance.rewind() } @IBAction func didPressStopButton(sender: AnyObject) { - AudioPlayer.sharedInstance.stop() + AudioPlayerManager.sharedInstance.stop() } @IBAction func didPressPlayPauseButton(sender: AnyObject) { - AudioPlayer.sharedInstance.togglePlayPause() + AudioPlayerManager.sharedInstance.togglePlayPause() } @IBAction func didPressForwardButton(sender: AnyObject) { - AudioPlayer.sharedInstance.forward() + AudioPlayerManager.sharedInstance.forward() } } diff --git a/Example/Core/ViewController/SharedInstancePlayer/URLViewController.swift b/Example/Core/ViewController/SharedInstancePlayer/URLViewController.swift index 70a8b43..9b515d1 100644 --- a/Example/Core/ViewController/SharedInstancePlayer/URLViewController.swift +++ b/Example/Core/ViewController/SharedInstancePlayer/URLViewController.swift @@ -7,7 +7,7 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager class URLViewController: UIViewController { @@ -34,6 +34,6 @@ extension URLViewController: UITableViewDelegate, UITableViewDataSource { func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) - AudioPlayer.sharedInstance.play(urlStrings: self.data, startPosition: indexPath.row) + AudioPlayerManager.sharedInstance.play(urlStrings: self.data, startIndex: indexPath.row) } } diff --git a/Example/Core/Views/MultiplePlayerInstancesTableViewCell.swift b/Example/Core/Views/MultiplePlayerInstancesTableViewCell.swift index c94f134..06c4069 100644 --- a/Example/Core/Views/MultiplePlayerInstancesTableViewCell.swift +++ b/Example/Core/Views/MultiplePlayerInstancesTableViewCell.swift @@ -7,7 +7,7 @@ // import UIKit -import AudioPlayer +import AudioPlayerManager import MediaPlayer class MultiplePlayerInstancesTableViewCell: UITableViewCell { diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 2abd726..26c9699 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -11,21 +11,21 @@ 3A48667E1D50C72100CC4A04 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3A4866771D50C72100CC4A04 /* Assets.xcassets */; }; 3A48667F1D50C72100CC4A04 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A4866781D50C72100CC4A04 /* LaunchScreen.storyboard */; }; 3A4866801D50C72100CC4A04 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A4866791D50C72100CC4A04 /* Main.storyboard */; }; - 3A7BFA441D9EC6B5007E521D /* AudioPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A7BFA3D1D9EC5CA007E521D /* AudioPlayer.framework */; }; 8701E7D81D69066D00F21C2D /* MultiplePlayerInstancesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8701E7D71D69066D00F21C2D /* MultiplePlayerInstancesViewController.swift */; }; 8701E7E41D6907DD00F21C2D /* MultiplePlayerInstancesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8701E7E31D6907DD00F21C2D /* MultiplePlayerInstancesTableViewCell.swift */; }; 8701E7EA1D6907F300F21C2D /* MusicLibraryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8701E7E71D6907F300F21C2D /* MusicLibraryViewController.swift */; }; 8701E7EB1D6907F300F21C2D /* URLViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8701E7E81D6907F300F21C2D /* URLViewController.swift */; }; 8701E7EC1D6907F300F21C2D /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8701E7E91D6907F300F21C2D /* PlayerViewController.swift */; }; + 8795E3381D9EE5E2009ECAB0 /* AudioPlayerManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8795E3371D9EE28A009ECAB0 /* AudioPlayerManager.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 3A7BFA3C1D9EC5CA007E521D /* PBXContainerItemProxy */ = { + 8795E3361D9EE28A009ECAB0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3A7BFA381D9EC5CA007E521D /* AudioPlayer.xcodeproj */; + containerPortal = 8795E3321D9EE28A009ECAB0 /* AudioPlayerManager.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3A48660C1D50A7D700CC4A04; - remoteInfo = AudioPlayer; + remoteInfo = AudioPlayerManager; }; /* End PBXContainerItemProxy section */ @@ -50,12 +50,12 @@ 3A4866781D50C72100CC4A04 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 3A4866791D50C72100CC4A04 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 3A4866901D50CA2A00CC4A04 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; - 3A7BFA381D9EC5CA007E521D /* AudioPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AudioPlayer.xcodeproj; path = ../AudioPlayer/AudioPlayer.xcodeproj; sourceTree = ""; }; 8701E7D71D69066D00F21C2D /* MultiplePlayerInstancesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MultiplePlayerInstancesViewController.swift; path = MultiplePlayerInstances/MultiplePlayerInstancesViewController.swift; sourceTree = ""; }; 8701E7E31D6907DD00F21C2D /* MultiplePlayerInstancesTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MultiplePlayerInstancesTableViewCell.swift; path = Views/MultiplePlayerInstancesTableViewCell.swift; sourceTree = ""; }; 8701E7E71D6907F300F21C2D /* MusicLibraryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MusicLibraryViewController.swift; sourceTree = ""; }; 8701E7E81D6907F300F21C2D /* URLViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLViewController.swift; sourceTree = ""; }; 8701E7E91D6907F300F21C2D /* PlayerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; }; + 8795E3321D9EE28A009ECAB0 /* AudioPlayerManager.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AudioPlayerManager.xcodeproj; path = ../AudioPlayerManager/AudioPlayerManager.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -63,7 +63,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3A7BFA441D9EC6B5007E521D /* AudioPlayer.framework in Frameworks */, + 8795E3381D9EE5E2009ECAB0 /* AudioPlayerManager.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -73,7 +73,7 @@ 3A48664F1D50C69100CC4A04 = { isa = PBXGroup; children = ( - 3A7BFA381D9EC5CA007E521D /* AudioPlayer.xcodeproj */, + 8795E3321D9EE28A009ECAB0 /* AudioPlayerManager.xcodeproj */, 3A48666F1D50C72100CC4A04 /* Core */, 3A4866761D50C72100CC4A04 /* Resources */, 3A4866741D50C72100CC4A04 /* PLists */, @@ -135,14 +135,6 @@ name = Frameworks; sourceTree = ""; }; - 3A7BFA391D9EC5CA007E521D /* Products */ = { - isa = PBXGroup; - children = ( - 3A7BFA3D1D9EC5CA007E521D /* AudioPlayer.framework */, - ); - name = Products; - sourceTree = ""; - }; 8701E7DB1D69067200F21C2D /* MultiplePlayerInstances */ = { isa = PBXGroup; children = ( @@ -169,6 +161,14 @@ path = SharedInstancePlayer; sourceTree = ""; }; + 8795E3331D9EE28A009ECAB0 /* Products */ = { + isa = PBXGroup; + children = ( + 8795E3371D9EE28A009ECAB0 /* AudioPlayerManager.framework */, + ); + name = Products; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -225,8 +225,8 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = 3A7BFA391D9EC5CA007E521D /* Products */; - ProjectRef = 3A7BFA381D9EC5CA007E521D /* AudioPlayer.xcodeproj */; + ProductGroup = 8795E3331D9EE28A009ECAB0 /* Products */; + ProjectRef = 8795E3321D9EE28A009ECAB0 /* AudioPlayerManager.xcodeproj */; }, ); projectRoot = ""; @@ -237,11 +237,11 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 3A7BFA3D1D9EC5CA007E521D /* AudioPlayer.framework */ = { + 8795E3371D9EE28A009ECAB0 /* AudioPlayerManager.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; - path = AudioPlayer.framework; - remoteRef = 3A7BFA3C1D9EC5CA007E521D /* PBXContainerItemProxy */; + path = AudioPlayerManager.framework; + remoteRef = 8795E3361D9EE28A009ECAB0 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ diff --git a/Example/PLists/Example-Info.plist b/Example/PLists/Example-Info.plist index 68a8d95..7b9649e 100644 --- a/Example/PLists/Example-Info.plist +++ b/Example/PLists/Example-Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - AudioPlayer-Example + AudioPlayerManager-Example CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier From a16d79beda4b99cae2e882a66e96e11a418c936c Mon Sep 17 00:00:00 2001 From: Hans Seiffert Date: Fri, 30 Sep 2016 21:54:15 +0200 Subject: [PATCH 2/5] Update README.md with new project name --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f21d4c2..df7fca7 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# AudioPlayer +# AudioPlayerManager -[![Build Status](https://travis-ci.org/tschob/AudioPlayer.svg?branch=master)](https://travis-ci.org/tschob/AudioPlayer) -[![CocoaPods compatible](https://img.shields.io/cocoapods/v/AudioPlayer.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayer) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/tschob/AudioPlayer) -[![License](https://img.shields.io/cocoapods/l/AudioPlayer.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayer) -[![Platform](https://img.shields.io/cocoapods/p/AudioPlayer.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayer) +[![Build Status](https://travis-ci.org/tschob/AudioPlayerManager.svg?branch=master)](https://travis-ci.org/tschob/AudioPlayerManager) +[![CocoaPods compatible](https://img.shields.io/cocoapods/v/AudioPlayerManager.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayerManager) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/tschob/AudioPlayerManager) +[![License](https://img.shields.io/cocoapods/l/AudioPlayerManager.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayerManager) +[![Platform](https://img.shields.io/cocoapods/p/AudioPlayerManager.svg?style=flat)](http://cocoadocs.org/docsets/AudioPlayerManager) ## Feature -AudioPlayer is a small audio player which takes care of the AVPlayer setup and usage. It uses an internal queue to play multiple items automatically in a row. All path based items which are supported from AVPlayer can be used (MPMediaItems and remote URLs). +AudioPlayerManager is a small audio player which takes care of the AVPlayer setup and usage. It uses an internal queue to play multiple items automatically in a row. All path based items which are supported from AVPlayer can be used (MPMediaItems and remote URLs). ## Requirements - iOS 8+ @@ -25,7 +25,7 @@ AudioPlayer is a small audio player which takes care of the AVPlayer setup and u $ gem install cocoapods ``` -To integrate AudioPlayer into your Xcode project using CocoaPods, specify it in your `Podfile`: +To integrate AudioPlayerManager into your Xcode project using CocoaPods, specify it in your `Podfile`: ```ruby source 'https://github.com/CocoaPods/Specs.git' @@ -33,7 +33,7 @@ platform :ios, '8.0' use_frameworks! target '' do - pod 'AudioPlayer' + pod 'AudioPlayerManager' end ``` @@ -48,12 +48,12 @@ $ pod install There two basic usages: - A singleton player which play one item at a time ``` -AudioPlayer.sharedInstance.setup() +AudioPlayerManager.sharedInstance.setup() ``` - Multiple player instances which can be used at the same time ``` -let audioPlayer = AudioPlayer.audioPlayer() +let audioPlayer = AudioPlayerManager.audioPlayer() ``` ### Setup @@ -61,41 +61,41 @@ let audioPlayer = AudioPlayer.audioPlayer() In both usage cases you need to `setup()` the player instance before using it. ``` -AudioPlayer.sharedInstance.setup() +AudioPlayerManager.sharedInstance.setup() ``` This will setup the `AVAudioSession` playback plus activation state and initialize the remote control events plus now playing info center configuration. If you want to modify the basic settings you can this during or after calling `setup`. ``` -AudioPlayer.sharedInstance.setup(useNowPlayingInfoCenter: false, useRemoteControlEvents: false) +AudioPlayerManager.sharedInstance.setup(useNowPlayingInfoCenter: false, useRemoteControlEvents: false) ``` ``` -AudioPlayer.sharedInstance.setup() -AudioPlayer.sharedInstance.playingTimeRefreshRate = 1.0 +AudioPlayerManager.sharedInstance.setup() +AudioPlayerManager.sharedInstance.playingTimeRefreshRate = 1.0 ``` If you want to reveive remote control events you simply have to pass the events from the app delegate to the audio player instace ``` override func remoteControlReceivedWithEvent(event: UIEvent?) { - AudioPlayer.sharedInstance.remoteControlReceivedWithEvent(event) + AudioPlayerManager.sharedInstance.remoteControlReceivedWithEvent(event) } ``` ### Playback -AudioPlayer can play local `MPMediaItem`s and stream items from a remote URL. You can pass either one or multiple items to the player. +AudioPlayerManager can play local `MPMediaItem`s and stream items from a remote URL. You can pass either one or multiple items to the player. The following line will replace the current queue of the audio player with the chosen item. The playback will stop automatically if the item was played. ``` -AudioPlayer.sharedInstance.play(url: self.trackUrl) +AudioPlayerManager.sharedInstance.play(url: self.trackUrl) ``` If you want to play multiple items you can pass an array and start position. The audio player will replace the current queue with the given array and jump right to the item at the given position. The queue allows the user to rewind also to items with a lower index than the start position. ``` let songs = (MPMediaQuery.songsQuery().items ?? []) -AudioPlayer.sharedInstance.play(mediaItems: songs, startPosition: 5) +AudioPlayerManager.sharedInstance.play(mediaItems: songs, startPosition: 5) ``` @@ -105,4 +105,4 @@ tschob, Hans Seiffert ## License -AudioPlayer is available under the [MIT license](https://github.com/tschob/AudioPlayer/blob/master/LICENSE). \ No newline at end of file +AudioPlayerManager is available under the [MIT license](https://github.com/tschob/AudioPlayerManager/blob/master/LICENSE). \ No newline at end of file From ba2ff484532cf7c13e7517570baafe45df937531 Mon Sep 17 00:00:00 2001 From: Hans Seiffert Date: Fri, 30 Sep 2016 21:58:11 +0200 Subject: [PATCH 3/5] Fix old method name in the README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index df7fca7..7c7bdb1 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,11 @@ The following line will replace the current queue of the audio player with the c AudioPlayerManager.sharedInstance.play(url: self.trackUrl) ``` -If you want to play multiple items you can pass an array and start position. The audio player will replace the current queue with the given array and jump right to the item at the given position. The queue allows the user to rewind also to items with a lower index than the start position. +If you want to play multiple items you can pass an array and start index. The audio player will replace the current queue with the given array and jump right to the item at the given index. The queue allows the user to rewind also to items with a lower index than the start index. ``` let songs = (MPMediaQuery.songsQuery().items ?? []) -AudioPlayerManager.sharedInstance.play(mediaItems: songs, startPosition: 5) +AudioPlayerManager.sharedInstance.play(mediaItems: songs, startIndex: 5) ``` From eb3f08792e2989630110ba43f307d6a148f49e1e Mon Sep 17 00:00:00 2001 From: Hans Seiffert Date: Fri, 30 Sep 2016 21:59:03 +0200 Subject: [PATCH 4/5] Update travis.yml with the new project name --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f60491e..934f6fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,11 @@ osx_image: xcode7.3 sudo: false env: global: - - FRAMEWORK_NAME=AudioPlayer + - FRAMEWORK_NAME=AudioPlayerManager - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 - - WORKSPACE=AudioPlayer.xcworkspace - - IOS_FRAMEWORK_SCHEME="AudioPlayer" + - WORKSPACE=AudioPlayerManager.xcworkspace + - IOS_FRAMEWORK_SCHEME="AudioPlayerManager" - IOS_SDK=iphonesimulator - IOS_EXAMPLE_SCHEME="Example" matrix: From cf125647f1b422057c4c761a93354175a4626754 Mon Sep 17 00:00:00 2001 From: Hans Seiffert Date: Fri, 30 Sep 2016 22:06:48 +0200 Subject: [PATCH 5/5] Update podspec --- AudioPlayerManager.podspec | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/AudioPlayerManager.podspec b/AudioPlayerManager.podspec index d173703..347cf5d 100644 --- a/AudioPlayerManager.podspec +++ b/AudioPlayerManager.podspec @@ -7,22 +7,22 @@ # Pod::Spec.new do |s| - s.name = 'AudioPlayer' + s.name = 'AudioPlayerManager' s.version = File.read('VERSION') s.summary = 'Small Wrapper around AVPlayer which let you play local and remote songs using a build in queue.' - s.description = 'AudioPlayer is a small audio player which takes care of the AVPlayer setup and usage. It uses an internal queue to play multiple items automatically in a row. All path based items which are supported from AVPlayer can be used (MPMediaItems and remote URLs).' - s.homepage = 'https://github.com/tschob/AudioPlayer' + s.description = 'AudioPlayerManager is a small audio player which takes care of the AVPlayer setup and usage. It uses an internal queue to play multiple items automatically in a row. All path based items which are supported from AVPlayer can be used (MPMediaItems and remote URLs).' + s.homepage = 'https://github.com/tschob/AudioPlayerManager' # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Hans Seiffert' => 'hans.seiffert@gmail.com' } - s.source = { :git => 'https://github.com/tschob/AudioPlayer.git', :tag => s.version.to_s } + s.source = { :git => 'https://github.com/tschob/AudioPlayerManager.git', :tag => s.version.to_s } s.platform = :ios s.ios.deployment_target = '8.0' - s.source_files = 'AudioPlayer/**/*.{swift,h}' - s.public_header_files = 'AudioPlayer/**/*.h' + s.source_files = 'AudioPlayerManager/**/*.{swift,h}' + s.public_header_files = 'AudioPlayerManager/**/*.h' s.frameworks = 'UIKit' s.frameworks = 'MediaPlayer'