1

这是可能的 AVPlayer 从 MPMusicPlayerController 的 ipodlibrary 获取音乐并播放吗,因为 avplayer 无法从 MPMusicPlayerController 访问 iPodMusicPlayer,因为 AVPlayer 支持后台播放和访问 remoteEvents。下面显示的代码来自 addMusic 项目。所以任何帮助将不胜感激。谢谢

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
4

1 回答 1

3

这四行应该让你开始:)

MPMediaItem *nowPlayingItem = musicPlayer.nowPlayingItem;

NSURL * mediaURL = [nowPlayingItem valueForProperty:MPMediaItemPropertyAssetURL];

AVPlayerItem * myAVPlayerItem = [AVPlayerItem playerItemWithURL:mediaURL];

AVPlayer * myAvPlayer = [AVPlayer playerWithPlayerItem:myAVPlayerItem];
于 2012-07-12T07:02:56.610 回答