2012-07-12 51 views
1

這是可能的AVPlayer從MPMusicPlayerController的ipodlibrary獲取音樂並播放,因爲avplayer無法從MPMusicPlayerController訪問iPodMusicPlayer,因爲AVPlayer支持後臺播放和訪問remoteEvents。 下面顯示的代碼來自addMusic項目。所以任何幫助,將不勝感激。謝謝avplayer可以播放來自mpmusicplayercontroller的音樂

void audioRouteChangeListenerCallback (
    void      *inUserData, 
    AudioSessionPropertyID inPropertyID, 
    UInt32     inPropertyValueSize, 
    const void    *inPropertyValue 
) { 

    // ensure that this callback was invoked for a route change 
    if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return; 

    // This callback, being outside the implementation block, needs a reference to the 
    //  MainViewController object, which it receives in the inUserData parameter. 
    //  You provide this reference when registering this callback (see the call to 
    //  AudioSessionAddPropertyListener). 
    MainViewController *controller = (MainViewController *) inUserData; 

    // if application sound is not playing, there's nothing to do, so return. 
    if (controller.appSoundPlayer.playing == 0) { 

     NSLog (@"Audio route change while application audio is stopped."); 
     return; 

    } else { 

     // Determines the reason for the route change, to ensure that it is not 
     //  because of a category change. 
     CFDictionaryRef routeChangeDictionary = inPropertyValue; 

     CFNumberRef routeChangeReasonRef = 
         CFDictionaryGetValue (
          routeChangeDictionary, 
          CFSTR (kAudioSession_AudioRouteChangeKey_Reason) 
         ); 

     SInt32 routeChangeReason; 

     CFNumberGetValue (
      routeChangeReasonRef, 
      kCFNumberSInt32Type, 
      &routeChangeReason 
     ); 

     // "Old device unavailable" indicates that a headset was unplugged, or that the 
     // device was removed from a dock connector that supports audio output. This is 
     // the recommended test for when to pause audio. 
     if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) { 

      [controller.appSoundPlayer pause]; 
      NSLog (@"Output device removed, so application audio was paused."); 

      UIAlertView *routeChangeAlertView = 
        [[UIAlertView alloc] initWithTitle: NSLocalizedString (@"Playback Paused", @"Title for audio hardware route-changed alert view") 
                message: NSLocalizedString (@"Audio output was changed", @"Explanation for route-changed alert view") 
               delegate: controller 
             cancelButtonTitle: NSLocalizedString (@"StopPlaybackAfterRouteChange", @"Stop button title") 
             otherButtonTitles: NSLocalizedString (@"ResumePlaybackAfterRouteChange", @"Play button title"), nil]; 
      [routeChangeAlertView show]; 
      // release takes place in alertView:clickedButtonAtIndex: method 

     } else { 

      NSLog (@"A route change occurred that does not require pausing of application audio."); 
     } 
    } 
} 



@implementation MainViewController 

@synthesize artworkItem;     
@synthesize userMediaItemCollection;  
@synthesize playBarButton;    
@synthesize pauseBarButton;    
@synthesize musicPlayer;     
@synthesize navigationBar;    
@synthesize noArtworkImage;    item has no associated artwork 
@synthesize backgroundColorTimer;  

@synthesize nowPlayingLabel;    
@synthesize appSoundButton;    
@synthesize addOrShowMusicButton;  
@synthesize appSoundPlayer;    
@synthesize soundFileURL;    
@synthesize interruptedOnPlayback;  
@synthesize playedMusicOnce;    
@synthesize playing;  

@implementation MainViewController 

@synthesize artworkItem;    // the now-playing media item's artwork image, displayed in the Navigation bar 
@synthesize userMediaItemCollection; // the media item collection created by the user, using the media item picker 
@synthesize playBarButton;    // the button for invoking Play on the music player 
@synthesize pauseBarButton;    // the button for invoking Pause on the music player 
@synthesize musicPlayer;    // the music player, which plays media items from the iPod library 
@synthesize navigationBar;    // the application's Navigation bar 
@synthesize noArtworkImage;    // an image to display when a media item has no associated artwork 
@synthesize backgroundColorTimer;  // a timer for changing the background color -- represents an application that is 
             //  doing something else while iPod music is playing 
@synthesize nowPlayingLabel;   // descriptive text shown on the main screen about the now-playing media item 
@synthesize appSoundButton;    // the button to invoke playback for the application sound 
@synthesize addOrShowMusicButton;  // the button for invoking the media item picker. if the user has already 
             //  specified a media item collection, the title changes to "Show Music" and 
             //  the button invokes a table view that shows the specified collection 
@synthesize appSoundPlayer;    // An AVAudioPlayer object for playing application sound 
@synthesize soundFileURL;    // The path to the application sound 
@synthesize interruptedOnPlayback;  // A flag indicating whether or not the application was interrupted during 
             //  application audio playback 
@synthesize playedMusicOnce;   // A flag indicating if the user has played iPod library music at least one time 
             //  since application launch. 
@synthesize playing;     // An application that responds to interruptions must keep track of its playing/ 
             //  not-playing state. 

#pragma mark Music control 
- (IBAction) AddMusicOrShowMusic: (id) sender {  

    // if the user has already chosen some music, display that list 
    if (userMediaItemCollection) { 

     MusicTableViewController *controller = [[MusicTableViewController alloc] initWithNibName: @"MusicTableView" bundle: nil]; 
     controller.delegate = self; 

     controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical; 

     [self presentModalViewController: controller animated: YES]; 
     [controller release]; 

    } else { 

     MPMediaPickerController *picker = 
      [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic]; 

     picker.delegate      = self; 
     picker.allowsPickingMultipleItems = YES; 
     picker.prompt      = NSLocalizedString (@"Add songs to play", "Prompt in media item picker"); 


     [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated: YES]; 

     [self presentModalViewController: picker animated: YES]; 
     [picker release]; 
    } 
} 


- (void) updatePlayerQueueWithMediaCollection: (MPMediaItemCollection *) mediaItemCollection { 

    // Configure the music player, but only if the user chose at least one song to play 
    if (mediaItemCollection) { 

     if (userMediaItemCollection == nil) { 

      [self setUserMediaItemCollection: mediaItemCollection]; 
      [musicPlayer setQueueWithItemCollection: userMediaItemCollection]; 
      [self setPlayedMusicOnce: YES]; 
      [musicPlayer play]; 


     } else { 


      BOOL wasPlaying = NO; 
      if (musicPlayer.playbackState == MPMusicPlaybackStatePlaying) { 
       wasPlaying = YES; 
      } 

      MPMediaItem *nowPlayingItem   = musicPlayer.nowPlayingItem; 
      NSTimeInterval currentPlaybackTime = musicPlayer.currentPlaybackTime; 

      NSMutableArray *combinedMediaItems = [[userMediaItemCollection items] mutableCopy]; 
      NSArray *newMediaItems    = [mediaItemCollection items]; 
      [combinedMediaItems addObjectsFromArray: newMediaItems]; 

      [self setUserMediaItemCollection: [MPMediaItemCollection collectionWithItems: (NSArray *) combinedMediaItems]]; 
      [combinedMediaItems release]; 

      [musicPlayer setQueueWithItemCollection: userMediaItemCollection]; 

      musicPlayer.nowPlayingItem   = nowPlayingItem; 
      musicPlayer.currentPlaybackTime  = currentPlaybackTime; 

      if (wasPlaying) { 
       [musicPlayer play]; 
      } 
     } 


     navigationBar.topItem.leftBarButtonItem.enabled = YES; 

     [addOrShowMusicButton setTitle: NSLocalizedString (@"Show Music", @"Alternate title for 'Add Music' button, after user has chosen some music") 
           forState: UIControlStateNormal]; 
    } 
} 


- (void) restorePlaybackState { 

    if (musicPlayer.playbackState == MPMusicPlaybackStateStopped && userMediaItemCollection) { 

     [addOrShowMusicButton setTitle: NSLocalizedString (@"Show Music", @"Alternate title for 'Add Music' button, after user has chosen some music") 
           forState: UIControlStateNormal]; 

     if (playedMusicOnce == NO) { 

      [self setPlayedMusicOnce: YES]; 
      [musicPlayer play]; 
     } 
    } 

} 


#pragma mark Media item picker delegate methods________ 


- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection { 

    [self dismissModalViewControllerAnimated: YES]; 

    [self updatePlayerQueueWithMediaCollection: mediaItemCollection]; 


    [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated: YES]; 
} 


- (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker { 

    [self dismissModalViewControllerAnimated: YES]; 

    [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated: YES]; 
} 



#pragma mark Music notification handlers__________________ 

- (void) handle_NowPlayingItemChanged: (id) notification { 

    MPMediaItem *currentItem = [musicPlayer nowPlayingItem]; 

    UIImage *artworkImage = noArtworkImage; 

    MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork]; 

    // Obtain a UIImage object from the MPMediaItemArtwork object 
    if (artwork) { 
     artworkImage = [artwork imageWithSize: CGSizeMake (30, 30)]; 
    } 

    // Obtain a UIButton object and set its background to the UIImage object 
    UIButton *artworkView = [[UIButton alloc] initWithFrame: CGRectMake (0, 0, 30, 30)]; 
    [artworkView setBackgroundImage: artworkImage forState: UIControlStateNormal]; 

    // Obtain a UIBarButtonItem object and initialize it with the UIButton object 
    UIBarButtonItem *newArtworkItem = [[UIBarButtonItem alloc] initWithCustomView: artworkView]; 
    [self setArtworkItem: newArtworkItem]; 
    [newArtworkItem release]; 

    [artworkItem setEnabled: NO]; 

    [navigationBar.topItem setRightBarButtonItem: artworkItem animated: YES]; 

    [nowPlayingLabel setText: [ 
      NSString stringWithFormat: @"%@ %@ %@ %@", 
      NSLocalizedString (@"Now Playing:", @"Label for introducing the now-playing song title and artist"), 
      [currentItem valueForProperty: MPMediaItemPropertyTitle], 
      NSLocalizedString (@"by", @"Article between song name and artist name"), 
      [currentItem valueForProperty: MPMediaItemPropertyArtist]]]; 

    if (musicPlayer.playbackState == MPMusicPlaybackStateStopped) { 

     [nowPlayingLabel setText: [ 
       NSString stringWithFormat: @"%@", 
       NSLocalizedString (@"Music-ended Instructions", @"Label for prompting user to play music again after it has stopped")]]; 

    } 
} 


- (void) handle_PlaybackStateChanged: (id) notification { 

    MPMusicPlaybackState playbackState = [musicPlayer playbackState]; 

    if (playbackState == MPMusicPlaybackStatePaused) { 

     navigationBar.topItem.leftBarButtonItem = playBarButton; 

    } else if (playbackState == MPMusicPlaybackStatePlaying) { 

     navigationBar.topItem.leftBarButtonItem = pauseBarButton; 

    } else if (playbackState == MPMusicPlaybackStateStopped) { 

     navigationBar.topItem.leftBarButtonItem = playBarButton; 

     // Even though stopped, invoking 'stop' ensures that the music player will play 
     //  its queue from the start. 
     [musicPlayer stop]; 

    } 
} 

- (void) handle_iPodLibraryChanged: (id) notification { 
] 
} 



#pragma mark Application playback control_________________ 

- (IBAction) playAppSound: (id) sender { 

    [appSoundPlayer play]; 
    playing = YES; 
    [appSoundButton setEnabled: NO]; 
} 

- (void) alertView: routeChangeAlertView clickedButtonAtIndex: buttonIndex { 

    if ((NSInteger) buttonIndex == 1) { 
     [appSoundPlayer play]; 
    } else { 
     [appSoundPlayer setCurrentTime: 0]; 
     [appSoundButton setEnabled: YES]; 
    } 

    [routeChangeAlertView release];   
} 



#pragma mark AV Foundation delegate methods____________ 

- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) appSoundPlayer successfully: (BOOL) flag { 

    playing = NO; 
    [appSoundButton setEnabled: YES]; 
} 

- (void) audioPlayerBeginInterruption: player { 

    NSLog (@"Interrupted. The system has paused audio playback."); 

    if (playing) { 

     playing = NO; 
     interruptedOnPlayback = YES; 
    } 
} 

- (void) audioPlayerEndInterruption: player { 

    NSLog (@"Interruption ended. Resuming audio playback."); 

     [[AVAudioSession sharedInstance] setActive: YES error: nil]; 

    if (interruptedOnPlayback) { 

     [appSoundPlayer prepareToPlay]; 
     [appSoundPlayer play]; 
     playing = YES; 
     interruptedOnPlayback = NO; 
    } 
} 



#pragma mark Table view delegate methods 

- (void) musicTableViewControllerDidFinish: (MusicTableViewController *) controller { 

    [self dismissModalViewControllerAnimated: YES]; 
    [self restorePlaybackState]; 
} 



#pragma mark Application setup 

- (void) setupApplicationAudio { 

    NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: @"sound" 
                 ofType:    @"caf"]; 

    NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath]; 
    self.soundFileURL = newURL; 
    [newURL release]; 

    [[AVAudioSession sharedInstance] setDelegate: self]; 

    // [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil]; 

    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil]; 

    UInt32 doSetProperty = 0; 
    AudioSessionSetProperty (
     kAudioSessionProperty_OverrideCategoryMixWithOthers, 
     sizeof (doSetProperty), 
     &doSetProperty 
          ); 


    // Registers the audio route change listener callback function 
    AudioSessionAddPropertyListener (
     kAudioSessionProperty_AudioRouteChange, 
     audioRouteChangeListenerCallback, 
     self 
    ); 

    // Activates the audio session. 

    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError]; 

    // Instantiates the AVAudioPlayer object, initializing it with the sound 
    AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil]; 
    self.appSoundPlayer = newPlayer; 
    [newPlayer release]; 

    [appSoundPlayer prepareToPlay]; 
    [appSoundPlayer setVolume: 1.0]; 
    [appSoundPlayer setDelegate: self]; 
} 


- (void) registerForMediaPlayerNotifications { 

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 

    [notificationCenter addObserver: self 
          selector: @selector (handle_NowPlayingItemChanged:) 
           name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification 
          object: musicPlayer]; 

    [notificationCenter addObserver: self 
          selector: @selector (handle_PlaybackStateChanged:) 
           name: MPMusicPlayerControllerPlaybackStateDidChangeNotification 
          object: musicPlayer]; 


    [musicPlayer beginGeneratingPlaybackNotifications]; 
} 



- (BOOL) useiPodPlayer { 

    if ([[NSUserDefaults standardUserDefaults] boolForKey: PLAYER_TYPE_PREF_KEY]) { 
     return YES;  
    } else { 
     return NO; 
    }  
} 

- (void) viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
    [self becomeFirstResponder]; 
} 

- (void) viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; 
    [self resignFirstResponder]; 
} 

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 


- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent { 
    if (receivedEvent.type == UIEventTypeRemoteControl) { 
     switch (receivedEvent.subtype) { 
      case UIEventSubtypeRemoteControlTogglePlayPause: 
       [self togglePlayPause]; 
       break; 
      case UIEventSubtypeRemoteControlPlay: 
       [self playAudio]; 
       break; 
      case UIEventSubtypeRemoteControlPause: 
       [self pauseAudio]; 
       break; 

      default: 
       break; 

     } 
    } 
} 

- (IBAction) playOrPauseMusic: (id)sender { 

    [self togglePlayPause]; 

} 


- (void)playAudio { 

    [musicPlayer play]; 
} 

- (void)pauseAudio { 
    [musicPlayer pause]; 
} 

- (void)togglePlayPause { 


    MPMusicPlaybackState playbackState = [musicPlayer playbackState]; 

    if (playbackState == MPMusicPlaybackStateStopped || playbackState == MPMusicPlaybackStatePaused) { 
     [musicPlayer play]; 
    } else if (playbackState == MPMusicPlaybackStatePlaying) { 
     [musicPlayer pause]; 
    } 
} 



// Configure the application. 
- (void) viewDidLoad { 

    [super viewDidLoad]; 

    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 



    [self setupApplicationAudio]; 

    [self setPlayedMusicOnce: NO]; 

    [self setNoArtworkImage: [UIImage imageNamed: @"no_artwork.png"]];  

    [self setPlayBarButton:  [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemPlay 
                       target: self 
                       action: @selector (playOrPauseMusic:)]]; 

    [self setPauseBarButton: [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemPause 
                       target: self 
                       action: @selector (playOrPauseMusic:)]]; 

    [addOrShowMusicButton setTitle: NSLocalizedString (@"Add Music", @"Title for 'Add Music' button, before user has chosen some music") 
          forState: UIControlStateNormal]; 

    [appSoundButton   setTitle: NSLocalizedString (@"Play App Sound", @"Title for 'Play App Sound' button") 
          forState: UIControlStateNormal]; 

    [nowPlayingLabel setText: NSLocalizedString (@"Instructions", @"Brief instructions to user, shown at launch")]; 


    if ([self useiPodPlayer]) { 

     [self setMusicPlayer: [MPMusicPlayerController iPodMusicPlayer]]; 

     if ([musicPlayer nowPlayingItem]) { 


      navigationBar.topItem.leftBarButtonItem.enabled = YES; 

      [self handle_NowPlayingItemChanged: nil]; 


      if ([musicPlayer playbackState] == MPMusicPlaybackStatePaused) { 
       navigationBar.topItem.leftBarButtonItem = playBarButton; 
      } 
     } 

    } else { 

     [self setMusicPlayer: [MPMusicPlayerController applicationMusicPlayer]]; 

     [musicPlayer setShuffleMode: MPMusicShuffleModeOff]; 
     [musicPlayer setRepeatMode: MPMusicRepeatModeNone]; 
    } 

    [self registerForMediaPlayerNotifications]; 


    [self setBackgroundColorTimer: [NSTimer scheduledTimerWithTimeInterval: 3.5 
                    target: self 
                    selector: @selector (updateBackgroundColor) 
                    userInfo: nil 
                    repeats: YES]]; 
} 

// Invoked by the backgroundColorTimer. 
- (void) updateBackgroundColor { 

    [UIView beginAnimations: nil context: nil]; 
    [UIView setAnimationDuration: 3.0]; 

    CGFloat redLevel = rand()/(float) RAND_MAX; 
    CGFloat greenLevel = rand()/(float) RAND_MAX; 
    CGFloat blueLevel = rand()/(float) RAND_MAX; 

    self.view.backgroundColor = [UIColor colorWithRed: redLevel 
               green: greenLevel 
               blue: blueLevel 
               alpha: 1.0]; 
    [UIView commitAnimations]; 
} 

#pragma mark Application state management_____________ 

- (void) didReceiveMemoryWarning { 
    // Releases the view if it doesn't have a superview. 
    [super didReceiveMemoryWarning]; 

    // Release any cached data, images, etc that aren't in use. 
} 


- (void) viewDidUnload { 


    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 


- (void)dealloc { 

    [[NSNotificationCenter defaultCenter] removeObserver: self 
                name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification 
                object: musicPlayer]; 

    [[NSNotificationCenter defaultCenter] removeObserver: self 
                name: MPMusicPlayerControllerPlaybackStateDidChangeNotification 
                object: musicPlayer]; 

    [musicPlayer endGeneratingPlaybackNotifications]; 
    [musicPlayer    release]; 

    [artworkItem    release]; 
    [backgroundColorTimer  invalidate]; 
    [backgroundColorTimer  release]; 
    [navigationBar    release]; 
    [noArtworkImage    release]; 
    [nowPlayingLabel   release]; 
    [pauseBarButton    release]; 
    [playBarButton    release]; 
    [soundFileURL    release]; 
    [userMediaItemCollection release]; 

    [super dealloc]; 
} 


@end 
+0

AVPlayer沒有問題訪問的iPod庫。 – sosborn 2012-07-12 06:06:20

+0

你能幫助我如何訪問它,..canü在我已經發布這將是一個很大的幫助程序編輯。 – orgami 2012-07-12 06:13:03

+0

我從MusicLibraryViewController獲取音樂它會顯示音樂的的tableView – orgami 2012-07-12 06:44:58

回答

3

這四行應該讓你開始:)

MPMediaItem *nowPlayingItem = musicPlayer.nowPlayingItem; 

NSURL * mediaURL = [nowPlayingItem valueForProperty:MPMediaItemPropertyAssetURL]; 

AVPlayerItem * myAVPlayerItem = [AVPlayerItem playerItemWithURL:mediaURL]; 

AVPlayer * myAvPlayer = [AVPlayer playerWithPlayerItem:myAVPlayerItem]; 
+0

這將在viewDidLoad中添加,如果我是正確的,我想知道如何,因爲我已經使用musicPlayer這是remoteEvents方法()MPMusicPlayerController對象訪問遠程活動 我應該將其更改爲avplayer或因爲現在musicPlayer正在播放的avPlayer或它不事關 我可以通過電子郵件 – orgami 2012-07-12 07:39:39

+2

聯繫ü對於其他人誰到這裏來學習的緣故,你應該保持在這裏,通過找到的任何解決方案電子郵件將無助於其他社區。因此,這裏是我通過e-mail給你寫了: 創建AVPlayer: AVPlayer * myAVPlayer = [[AVPlayer頁頭] INIT]; ,然後使用上面的代碼中插入一個mpmediaitem進去。 – 2012-07-12 08:58:36

+0

那麼首先,音頻隊列的東西是不是真的很重要,所有由avplayer自動處理。所以,你真的只需要五條線......然後它的工作原理...... – 2012-07-12 11:29:29