Skip to content
This repository was archived by the owner on Jul 20, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions Jukebox.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@
TargetAttributes = {
137DF0621D2041F500C15E86 = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 0800;
LastSwiftMigration = 1010;
};
137DF06C1D2041F500C15E86 = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 0800;
LastSwiftMigration = 1010;
};
};
};
Expand Down Expand Up @@ -362,7 +362,8 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
Expand All @@ -381,7 +382,8 @@
PRODUCT_BUNDLE_IDENTIFIER = com.teodorpatras.Jukebox;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.2;
};
name = Release;
};
Expand All @@ -392,7 +394,8 @@
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_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
Expand All @@ -403,7 +406,8 @@
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_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.2;
};
name = Release;
};
Expand Down
49 changes: 33 additions & 16 deletions Source/Jukebox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ extension Jukebox {
public func stop() {
invalidatePlayback()
state = .ready
UIApplication.shared.endBackgroundTask(backgroundIdentifier)
backgroundIdentifier = UIBackgroundTaskInvalid
UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(backgroundIdentifier.rawValue))
backgroundIdentifier = UIBackgroundTaskIdentifier.invalid
}

/**
Expand Down Expand Up @@ -136,7 +136,7 @@ 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))
item.update()
if shouldPlay {
player.play()
Expand Down Expand Up @@ -221,7 +221,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
Expand Down Expand Up @@ -418,7 +418,7 @@ 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!
}
Expand All @@ -435,48 +435,55 @@ open class Jukebox: NSObject, JukeboxItemDelegate {

fileprivate func configureBackgroundAudioTask() {
backgroundIdentifier = UIApplication.shared.beginBackgroundTask (expirationHandler: { () -> Void in
UIApplication.shared.endBackgroundTask(self.backgroundIdentifier)
self.backgroundIdentifier = UIBackgroundTaskInvalid
UIApplication.shared.endBackgroundTask(convertToUIBackgroundTaskIdentifier(self.backgroundIdentifier.rawValue))
self.backgroundIdentifier = UIBackgroundTaskIdentifier.invalid
})
}

fileprivate func configureAudioSession() throws {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setMode(AVAudioSessionModeDefault)
if #available(iOS 10.0, *) {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
} else {
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:withOptions:error:"), with: AVAudioSession.Category.playback, with: [])
// Set category without options (<= iOS 9) setCategory(_:)
AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback) }
try AVAudioSession.sharedInstance().setActive(true)

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 {
Expand Down Expand Up @@ -515,3 +522,13 @@ private extension Collection {
private extension CMTime {
var isValid : Bool { return (flags.intersection(.valid)) != [] }
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToUIBackgroundTaskIdentifier(_ input: Int) -> UIBackgroundTaskIdentifier {
return UIBackgroundTaskIdentifier(rawValue: input)
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromAVAudioSessionCategory(_ input: AVAudioSession.Category) -> String {
return input.rawValue
}
17 changes: 14 additions & 3 deletions Source/JukeboxItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -185,7 +185,7 @@ open class JukeboxItem: NSObject {

for item in metadataArray
{
item.loadValuesAsynchronously(forKeys: [AVMetadataKeySpaceCommon], completionHandler: { () -> Void in
item.loadValuesAsynchronously(forKeys: [convertFromAVMetadataKeySpace(AVMetadataKeySpace.common)], completionHandler: { () -> Void in
self.meta.process(metaItem: item)
DispatchQueue.main.async {
self.scheduleNotification()
Expand All @@ -199,7 +199,7 @@ open class JukeboxItem: NSObject {
private extension JukeboxItem.Meta {
mutating func process(metaItem item: AVMetadataItem) {

switch item.commonKey
switch convertFromOptionalAVMetadataKey(item.commonKey)
{
case "title"? :
title = item.value as? String
Expand Down Expand Up @@ -237,3 +237,14 @@ private extension CMTime {
return time
}
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromAVMetadataKeySpace(_ input: AVMetadataKeySpace) -> String {
return input.rawValue
}

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromOptionalAVMetadataKey(_ input: AVMetadataKey?) -> String? {
guard let input = input else { return nil }
return input.rawValue
}