     /**
        A `PlayerEvent` is an event an player generates over time.
 
-       - StartedBuffering: The player started buffering the audio file.
-       - ReadyToPlay:      The player is ready to play. It buffered enough data.
-       - LoadedMoreRange:  The player loaded more range of time.
-       - LoadedMetadata:   The player loaded metadata.
-       - LoadedDuration:   The player has found audio item duration.
-       - EndedPlaying:     The player ended playing the current item because it went through the
+       - StartedBuffering:  The player started buffering the audio file.
+       - ReadyToPlay:       The player is ready to play. It buffered enough data.
+       - LoadedMoreRange:   The player loaded more range of time.
+       - LoadedMetadata:    The player loaded metadata.
+       - LoadedDuration:    The player has found audio item duration.
+       - Progressed:        The player progressed in its playing.
+       - EndedPlaying:      The player ended playing the current item because it went through the
             file or because of an error.
-       - Interrupted:      The player got interrupted (phone call, Siri, ...).
+       - InterruptionBegan: The player got interrupted (phone call, Siri, ...).
+       - InterruptionEnded: The interruption ended.
+       - RouteChanged:      The player's route changed.
+       - SessionMessedUp:   The audio session is messed up.
      */
     enum PlayerEvent: Event {
         case StartedBuffering
         case ReadyToPlay
         case LoadedMoreRange(CMTime, CMTime)
         case LoadedMetadata([AVMetadataItem])
-        case LoadedDuration(NSTimeInterval)
+        case LoadedDuration(CMTime)
+        case Progressed(CMTime)
         case EndedPlaying(NSError?)
-        case Interrupted
+        case InterruptionBegan
+        case InterruptionEnded
+        case RouteChanged
+        case SessionMessedUp
     }
 
     /// The player to produce events with.

     Stops listening to the player events.
     */
    func stopProducingEvents() {
        guard listening else {
            return
        }

        listening = false
    }
}


import AVFoundation

// MARK: - AVPlayer+KVO
private extension AVPlayer {
    /// The list of properties that is observed through KVO.
    static var ap_KVOProperties: [String] {
        return [
            "currentItem.playbackBufferEmpty",
            "currentItem.playbackLikelyToKeepUp",
            "currentItem.duration",
            "currentItem.status",
            "currentItem.loadedTimeRanges"
        ]
    }
}

/**
 *  A `PlayerEventProducer` listens to notifications and observes events generated by an AVPlayer.
 */
