                 debug("Received a message for player: \(player)")
             }
             
-            if keyPath == kStatusKey && self.currentPlayerItem != nil && object is AVPlayerItem {
-                if self.currentPlayerItem!.status == .ReadyToPlay {
-                    self.player!.play()
-                    self.currentState = .Playing
-                    self.delegate?.twistStatusChanged()
-                } else {
-                    debug("Status updated but not ready to play")
+            if self.currentPlayerItem != nil && object is AVPlayerItem {
+                guard let keyPath = keyPath else { return }
+                switch keyPath {
+                case kStatusKey:
+                    if self.currentPlayerItem!.status == .ReadyToPlay {
+                        self.player!.play()
+                        self.currentState = .Playing
+                        self.triggerPlaybackStateChanged()
+                    } else {
+                        debug("Status updated but not ready to play")
+                    }
+                case kLoadedTimeRangesKey:
+                    if let availableDuration = self.availableDurationForCurrentItem() {
+                        let duration = self.currentPlayerItem!.duration
+                        let totalDuration = CMTimeGetSeconds(duration)
+                        self.delegate?.twist(self, loaded: availableDuration, outOf: totalDuration)
+                    }
+                default:
+                    print("Unhandled key :\(keyPath)")
                 }
             }
         } else {
             super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
         }
     }
+    
+    func availableDurationForCurrentItem() -> NSTimeInterval? {
+        guard let currentItem = self.currentPlayerItem else { return nil }
+        let loadedTimeRanges = currentItem.loadedTimeRanges
+        if let timeRange = loadedTimeRanges.first?.CMTimeRangeValue {
+            let startSeconds = CMTimeGetSeconds(timeRange.start)
+            let durationSeconds = CMTimeGetSeconds(timeRange.duration)
+            return startSeconds + durationSeconds
+        }
+        return nil
+    }
+    
+    func triggerPlaybackStateChanged() {
+        self.delegate?.twistStatusChanged()
+        self.updateMPRemoteCommandButtons()
+    }
+    
+    func updateMPRemoteCommandButtons() {
+        let commandCenter = MPRemoteCommandCenter.sharedCommandCenter()
+        commandCenter.nextTrackCommand.enabled = self.hasNextItem
+        commandCenter.previousTrackCommand.enabled = self.hasPreviousItem
+        commandCenter.playCommand.enabled = self.currentState == .Paused
+        commandCenter.pauseCommand.enabled = self.currentState == .Playing
+        commandCenter.togglePlayPauseCommand.enabled = self.isPlayable()
+    }
 }
            debug("Playing current Item")
            self.player!.play()
            self.currentState = .Playing
            self.delegate?.twistStatusChanged()
        }
    }


            debug("Pausing current item")
            self.player?.pause()
            self.currentState = .Paused
            self.triggerPlaybackStateChanged()
        }
    }

    public func stop() {
        if (self.player != nil) {
            self.cleanupCurrentItem()
            debug("Stopping current item")
            self.triggerPlaybackStateChanged()
        }
    }
    
    func cleanupCurrentItem() {
        self.currentState = .Waiting
        self.currentPlayerItem?.removeObserver(self, forKeyPath: kStatusKey)
        self.currentPlayerItem?.removeObserver(self, forKeyPath: kLoadedTimeRangesKey)
        self.currentPlayerItem = nil
        self.player = nil
    }

    public func next() {
        if !isPlayable() {
            return
        }
    
        if hasNextItem {
            self.cleanupCurrentItem()
            self.play(self.currentIndex + 1)
        }
    }
    
    // TODO:
    // Check the repeat
    // Check the shuffle settings
    var hasNextItem: Bool {
        return self.currentIndex < self.dataSource!.twistNumberOfItems() - 1
    }
    
    // Check the repeat
    // Check the shuffle settings
    var hasPreviousItem: Bool {
        return self.currentIndex != 0
    }

    public func previous() {
