ios 显示播放器显示AVQueuePlayer类
// // AVQueuePlayerPrevious.m 的类封装的代码 // IntervalPlayer // // Created by Daniel Giovannelli on 2/18/13. // #import "AVQueuePlayerPrevious.h" @implementation AVQueuePlayerPrevious @synthesize itemsForPlayer = _itemsForPlayer; // CONSTRUCTORS -(id)initWithItems:(NSArray *)items { // This function calls the constructor for AVQueuePlayer, then sets up the nowPlayingIndex to 0 and // saves the array that the player was generated from as itemsForPlayer self = [super initWithItems:items]; if (self){ self.itemsForPlayer = [NSMutableArray arrayWithArray:items]; nowPlayingIndex = 0; isCalledFromPlayPreviousItem = NO; for (int songPointer = 0; songPointer < [items count]; songPointer++) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(songEnded:) name:AVPlayerItemDidPlayToEndTimeNotification object:[items objectAtIndex:songPointer]]; } } return self; } + (AVQueuePlayerPrevious *)queuePlayerWithItems:(NSArray *)items { // This function just allocates space for, creates, and returns an AVQueuePlayerPrevious from an array. // Honestly I think having it is a bit silly, but since its present in AVQueuePlayer it needs to be // overridden here to ensure compatability. If anyone has any insight on why this method exists at all, // let me know. AVQueuePlayerPrevious *playerToReturn = [[AVQueuePlayerPrevious alloc] initWithItems:items]; return playerToReturn; } // NEW METHODS -(void)songEnded:(NSNotification *)notification { // This method is called by NSNotificationCenter when a song finishes playing; all it does is increment // nowPlayingIndex if (nowPlayingIndex < [_itemsForPlayer count] - 1){ nowPlayingIndex++; } } -(void)playPreviousItem { // This function is the meat of this library: it allows for going backwards in an AVQueuePlayer, // basically by clearing the player and repopulating it from the index of the last song played. // It should be noted that if the player is on its first song, this function will do nothing. It will // not restart the song or anything like that; if you want that functionality you can implement it // yourself fairly easily using the isAtBeginning method to test if the player is at its start. if (nowPlayingIndex>0){ [self pause]; // Note: it is necessary to have seekToTime called twice in this method, once before and once after re-making the area. If it is not present before, the player will resume from the same spot in the next song when the previous song finishes playing; if it is not present after, the previous song will be played from the same spot that the current song was on. [self seekToTime:kCMTimeZero toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; // The next two lines are necessary since RemoveAllItems resets both the nowPlayingIndex and _itemsForPlayer int tempNowPlayingIndex = nowPlayingIndex; NSMutableArray *tempPlaylist = [[NSMutableArray alloc]initWithArray:_itemsForPlayer]; [self removeAllItems]; isCalledFromPlayPreviousItem = YES; for (int i = tempNowPlayingIndex - 1; i < [tempPlaylist count]; i++) { [self insertItem:[tempPlaylist objectAtIndex:i] afterItem:nil]; } isCalledFromPlayPreviousItem = NO; // The temp index is necessary since removeAllItems resets the nowPlayingIndex nowPlayingIndex = tempNowPlayingIndex - 1; // Not a typo; see above comment [self seekToTime:kCMTimeZero toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; [self play]; } } -(Boolean)isAtBeginning { // This function simply returns whether or not the AVQueuePlayerPrevious is at the first song. This is // useful for implementing custom behavior if the user tries to play a previous song at the start of // the queue (such as restarting the song). if (nowPlayingIndex == 0){ return YES; } else { return NO; } } // OVERRIDDEN AVQUEUEPLAYER METHODS -(void)removeAllItems { // This does the same thing as the normal AVQueuePlayer removeAllItems, but also sets the // nowPlayingIndex to 0. [super removeAllItems]; nowPlayingIndex = 0; [_itemsForPlayer removeAllObjects]; } -(void)removeItem:(AVPlayerItem *)item { // This method calls the superclass to remove the items from the AVQueuePlayer itself, then removes // any instance of the item from the itemsForPlayer array. This mimics the behavior of removeItem on // AVQueuePlayer, which removes all instances of the item in question from the queue. // It also subtracts 1 from the nowPlayingIndex for every time the item shows up in the itemsForPlayer // array before the current value. [super removeItem:item]; int appearancesBeforeCurrent = 0; for (int tracer = 0; tracer < nowPlayingIndex; tracer++){ if ([_itemsForPlayer objectAtIndex:tracer] == item) { appearancesBeforeCurrent++; } } nowPlayingIndex -= appearancesBeforeCurrent; [_itemsForPlayer removeObject:item]; } - (void)advanceToNextItem { // The only addition this method makes to AVQueuePlayer is advancing the nowPlayingIndex by 1. [super advanceToNextItem]; if (nowPlayingIndex < [_itemsForPlayer count] - 1){ nowPlayingIndex++; } } -(void)insertItem:(AVPlayerItem *)item afterItem:(AVPlayerItem *)afterItem { // This method calls the superclass to add the new item to the AVQueuePlayer, then adds that item to the // proper location in the itemsForPlayer array and increments the nowPlayingIndex if necessary. [super insertItem:item afterItem:afterItem]; if (!isCalledFromPlayPreviousItem){ if ([_itemsForPlayer indexOfObject:item] < nowPlayingIndex) { nowPlayingIndex++; } } if ([_itemsForPlayer containsObject:afterItem]){ // AfterItem is non-nil if ([_itemsForPlayer indexOfObject:afterItem] < [_itemsForPlayer count] - 1){ [_itemsForPlayer insertObject:item atIndex:[_itemsForPlayer indexOfObject:afterItem] + 1]; } else { [_itemsForPlayer addObject:item]; } } else { // afterItem is nil [_itemsForPlayer addObject:item]; } } -(int)getIndex { // This method simple returns the now playing index return nowPlayingIndex; } @end