diff --git a/Example/.DS_Store b/Example/.DS_Store
new file mode 100644
index 0000000..591f077
Binary files /dev/null and b/Example/.DS_Store differ
diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj
index 387e0d0..88e8acc 100644
--- a/Example/Example.xcodeproj/project.pbxproj
+++ b/Example/Example.xcodeproj/project.pbxproj
@@ -145,7 +145,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
- LastUpgradeCheck = 0800;
+ LastUpgradeCheck = 1020;
ORGANIZATIONNAME = teodorpatras;
TargetAttributes = {
137DF0851D2043F400C15E86 = {
@@ -157,7 +157,7 @@
};
buildConfigurationList = 137DF0811D2043F400C15E86 /* Build configuration list for PBXProject "Example" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -253,19 +253,28 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -301,19 +310,28 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -348,7 +366,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.jukebox.example;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -361,7 +379,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.jukebox.example;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
diff --git a/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme
index dd14de0..5cb3266 100644
--- a/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme
+++ b/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme
@@ -1,6 +1,6 @@
Bool {
+ internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
application.isStatusBarHidden = true
return true
diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift
index b485355..fc4d758 100644
--- a/Example/Example/ViewController.swift
+++ b/Example/Example/ViewController.swift
@@ -58,7 +58,7 @@ class ViewController: UIViewController, JukeboxDelegate {
let color = UIColor(red:0.84, green:0.09, blue:0.1, alpha:1)
indicator.color = color
- slider.setThumbImage(UIImage(named: "sliderThumb"), for: UIControlState())
+ slider.setThumbImage(UIImage(named: "sliderThumb"), for: UIControl.State())
slider.minimumTrackTintColor = color
slider.maximumTrackTintColor = UIColor.black
@@ -99,9 +99,9 @@ class ViewController: UIViewController, JukeboxDelegate {
})
if jukebox.state == .ready {
- playPauseButton.setImage(UIImage(named: "playBtn"), for: UIControlState())
+ playPauseButton.setImage(UIImage(named: "playBtn"), for: UIControl.State())
} else if jukebox.state == .loading {
- playPauseButton.setImage(UIImage(named: "pauseBtn"), for: UIControlState())
+ playPauseButton.setImage(UIImage(named: "pauseBtn"), for: UIControl.State())
} else {
volumeSlider.value = jukebox.volume
let imageName: String
@@ -111,7 +111,7 @@ class ViewController: UIViewController, JukeboxDelegate {
case .paused, .failed, .ready:
imageName = "playBtn"
}
- playPauseButton.setImage(UIImage(named: imageName), for: UIControlState())
+ playPauseButton.setImage(UIImage(named: imageName), for: UIControl.State())
}
print("Jukebox state changed to \(jukebox.state)")
diff --git a/Jukebox.xcodeproj/project.pbxproj b/Jukebox.xcodeproj/project.pbxproj
index aa0ec86..532125d 100644
--- a/Jukebox.xcodeproj/project.pbxproj
+++ b/Jukebox.xcodeproj/project.pbxproj
@@ -171,7 +171,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
- LastUpgradeCheck = 0800;
+ LastUpgradeCheck = 1020;
ORGANIZATIONNAME = teodorpatras;
TargetAttributes = {
137DF0621D2041F500C15E86 = {
@@ -186,10 +186,11 @@
};
buildConfigurationList = 137DF05D1D2041F500C15E86 /* Build configuration list for PBXProject "Jukebox" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
+ Base,
);
mainGroup = 137DF0591D2041F500C15E86;
productRefGroup = 137DF0641D2041F500C15E86 /* Products */;
@@ -259,14 +260,22 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -310,14 +319,22 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -357,12 +374,13 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.Jukebox;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -377,11 +395,12 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.Jukebox;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -392,7 +411,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.JukeboxTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -403,7 +422,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.JukeboxTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 5.0;
};
name = Release;
};
diff --git a/Jukebox.xcodeproj/xcshareddata/xcschemes/Jukebox.xcscheme b/Jukebox.xcodeproj/xcshareddata/xcschemes/Jukebox.xcscheme
index 78aaa1f..17bb157 100644
--- a/Jukebox.xcodeproj/xcshareddata/xcschemes/Jukebox.xcscheme
+++ b/Jukebox.xcodeproj/xcshareddata/xcschemes/Jukebox.xcscheme
@@ -1,6 +1,6 @@
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/README.md b/README.md
index c723c52..67914c0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@

-
+
[](http://cocoapods.org/pods/Jukebox)
[](https://travis-ci.org/teodorpatras/Jukebox)
[](http://cocoapods.org/pods/Jukebox)
diff --git a/Source/Jukebox.swift b/Source/Jukebox.swift
index b7d0200..6c1766d 100644
--- a/Source/Jukebox.swift
+++ b/Source/Jukebox.swift
@@ -90,7 +90,7 @@ extension Jukebox {
invalidatePlayback()
state = .ready
UIApplication.shared.endBackgroundTask(backgroundIdentifier)
- backgroundIdentifier = UIBackgroundTaskInvalid
+ backgroundIdentifier = UIBackgroundTaskIdentifier.invalid
}
/**
@@ -135,11 +135,15 @@ extension Jukebox {
*/
public func seek(toSecond second: Int, shouldPlay: Bool = false) {
guard let player = player, let item = currentItem else {return}
-
- player.seek(to: CMTimeMake(Int64(second), 1))
+ player.seek(to: CMTimeMake(value: Int64(second), timescale: 1))
+ player.play()
item.update()
if shouldPlay {
- player.play()
+ if #available(iOS 10.0, *) {
+ player.playImmediately(atRate: 1.0)
+ } else {
+ player.play()
+ }
if state != .playing {
state = .playing
}
@@ -167,7 +171,7 @@ extension Jukebox {
- parameter item: item to be removed
*/
public func remove(item: JukeboxItem) {
- if let index = queuedItems.index(where: {$0.identifier == item.identifier}) {
+ if let index = queuedItems.firstIndex(where: {$0.identifier == item.identifier}) {
queuedItems.remove(at: index)
}
}
@@ -221,7 +225,7 @@ open class Jukebox: NSObject, JukeboxItemDelegate {
fileprivate var player : AVPlayer?
fileprivate var progressObserver : AnyObject!
- fileprivate var backgroundIdentifier = UIBackgroundTaskInvalid
+ fileprivate var backgroundIdentifier = UIBackgroundTaskIdentifier.invalid
fileprivate(set) open weak var delegate : JukeboxDelegate?
fileprivate (set) open var playIndex = 0
@@ -297,7 +301,7 @@ open class Jukebox: NSObject, JukeboxItemDelegate {
func jukeboxItemDidLoadPlayerItem(_ item: JukeboxItem) {
delegate?.jukeboxDidLoadItem(self, item: item)
- let index = queuedItems.index{$0 === item}
+ let index = queuedItems.firstIndex{$0 === item}
guard let playItem = item.playerItem
, state == .loading && playIndex == index else {return}
@@ -418,9 +422,9 @@ open class Jukebox: NSObject, JukeboxItemDelegate {
fileprivate func startProgressTimer(){
guard let player = player , player.currentItem?.duration.isValid == true else {return}
- progressObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(0.05, Int32(NSEC_PER_SEC)), queue: nil, using: { [unowned self] (time : CMTime) -> Void in
+ progressObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(0.05, preferredTimescale: Int32(NSEC_PER_SEC)), queue: nil, using: { [unowned self] (time : CMTime) -> Void in
self.timerAction()
- }) as AnyObject!
+ }) as AnyObject?
}
fileprivate func stopProgressTimer() {
@@ -436,47 +440,48 @@ open class Jukebox: NSObject, JukeboxItemDelegate {
fileprivate func configureBackgroundAudioTask() {
backgroundIdentifier = UIApplication.shared.beginBackgroundTask (expirationHandler: { () -> Void in
UIApplication.shared.endBackgroundTask(self.backgroundIdentifier)
- self.backgroundIdentifier = UIBackgroundTaskInvalid
+ self.backgroundIdentifier = UIBackgroundTaskIdentifier.invalid
})
}
fileprivate func configureAudioSession() throws {
- try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
- try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeDefault)
+ try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
+ try AVAudioSession.sharedInstance().setMode(AVAudioSession.Mode.default)
try AVAudioSession.sharedInstance().setActive(true)
}
fileprivate func configureObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(Jukebox.handleStall), name: NSNotification.Name.AVPlayerItemPlaybackStalled, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionInterruption), name: NSNotification.Name.AVAudioSessionInterruption, object: AVAudioSession.sharedInstance())
+ NotificationCenter.default.addObserver(self, selector: #selector(handleAudioSessionInterruption), name: AVAudioSession.interruptionNotification, object: AVAudioSession.sharedInstance())
}
+
// MARK:- Notifications -
- func handleAudioSessionInterruption(_ notification : Notification) {
+ @objc func handleAudioSessionInterruption(_ notification : Notification) {
guard let userInfo = notification.userInfo as? [String: AnyObject] else { return }
guard let rawInterruptionType = userInfo[AVAudioSessionInterruptionTypeKey] as? NSNumber else { return }
- guard let interruptionType = AVAudioSessionInterruptionType(rawValue: rawInterruptionType.uintValue) else { return }
+ guard let interruptionType = AVAudioSession.InterruptionType(rawValue: rawInterruptionType.uintValue) else { return }
switch interruptionType {
case .began: //interruption started
self.pause()
case .ended: //interruption ended
if let rawInterruptionOption = userInfo[AVAudioSessionInterruptionOptionKey] as? NSNumber {
- let interruptionOption = AVAudioSessionInterruptionOptions(rawValue: rawInterruptionOption.uintValue)
- if interruptionOption == AVAudioSessionInterruptionOptions.shouldResume {
+ let interruptionOption = AVAudioSession.InterruptionOptions(rawValue: rawInterruptionOption.uintValue)
+ if interruptionOption == AVAudioSession.InterruptionOptions.shouldResume {
self.resumePlayback()
}
}
}
}
- func handleStall() {
+ @objc func handleStall() {
player?.pause()
player?.play()
}
- func playerItemDidPlayToEnd(_ notification : Notification){
+ @objc func playerItemDidPlayToEnd(_ notification : Notification){
if playIndex >= queuedItems.count - 1 {
stop()
} else {
diff --git a/Source/JukeboxItem.swift b/Source/JukeboxItem.swift
index 0157bfa..5b0ad9c 100644
--- a/Source/JukeboxItem.swift
+++ b/Source/JukeboxItem.swift
@@ -47,7 +47,7 @@ open class JukeboxItem: NSObject {
var delegate: JukeboxItemDelegate?
fileprivate var didLoad = false
open var localTitle: String?
- open let URL: Foundation.URL
+ public let URL: Foundation.URL
fileprivate(set) open var playerItem: AVPlayerItem?
fileprivate (set) open var currentTime: Double?
@@ -136,7 +136,7 @@ open class JukeboxItem: NSObject {
}
open override var description: String {
- return ""
+ return ""
}
// MARK:- Private methods -
@@ -161,7 +161,7 @@ open class JukeboxItem: NSObject {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(JukeboxItem.notifyDelegate), userInfo: nil, repeats: false)
}
- func notifyDelegate() {
+ @objc func notifyDelegate() {
timer?.invalidate()
timer = nil
self.delegate?.jukeboxItemDidUpdate(self)
@@ -185,7 +185,7 @@ open class JukeboxItem: NSObject {
for item in metadataArray
{
- item.loadValuesAsynchronously(forKeys: [AVMetadataKeySpaceCommon], completionHandler: { () -> Void in
+ item.loadValuesAsynchronously(forKeys: [AVMetadataKeySpace.common.rawValue], completionHandler: { () -> Void in
self.meta.process(metaItem: item)
DispatchQueue.main.async {
self.scheduleNotification()
@@ -197,17 +197,19 @@ open class JukeboxItem: NSObject {
}
private extension JukeboxItem.Meta {
+
mutating func process(metaItem item: AVMetadataItem) {
- switch item.commonKey
+ guard let commonKey = item.commonKey else { return }
+ switch commonKey
{
- case "title"? :
+ case .commonKeyTitle :
title = item.value as? String
- case "albumName"? :
+ case .commonKeyAlbumName :
album = item.value as? String
- case "artist"? :
+ case .commonKeyArtist :
artist = item.value as? String
- case "artwork"? :
+ case .commonKeyArtwork :
processArtwork(fromMetadataItem : item)
default :
break