The jonki

呼ばれて飛び出てじょじょじょじょーんき

【iOS】iPod Library Accessの使い方(2)簡易音楽プレイヤーを作る

【iOS】iPod Library Accessの使い方(1)曲情報を取得するの続き

再生・停止・曲送り、曲戻し、アーティスト/タイトル/ジャケット写真の表示、ができる簡易な音楽プレイヤーを作りました。
NSNotificationCenterって便利ね。



コード

JPlayerViewController.h
//
//  JPlayerViewController.h
//  JPlayer
//
//  Created by jonki on 12/12/26.
//  Copyright (c) 2012年 jonki. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>

@interface JPlayerViewController : UIViewController

@property BOOL isPlaying;
@property MPMusicPlayerController *player;
@property NSNotificationCenter *ncenter;


// 各ウィジェットとそれに紐付くIBAction
@property (strong, nonatomic) IBOutlet UIButton *nextButton;
- (IBAction)pushedNextButton:(id)sender;
@property (strong, nonatomic) IBOutlet UIButton *playOrStopButton;
- (IBAction)pushedPlayOrStopBUtton:(id)sender;
@property (strong, nonatomic) IBOutlet UIButton *prevButton;
- (IBAction)pushedPrevButton:(id)sender;
@property (strong, nonatomic) IBOutlet UILabel *songInfoLabel;
@property (strong, nonatomic) IBOutlet UILabel *artistInfoLabel;
@property (strong, nonatomic) IBOutlet UIImageView *artworkImage;


@end
JPlayerViewController.m
//
//  JPlayerViewController.m
//  JPlayer
//
//  Created by jonki on 12/12/26.
//  Copyright (c) 2012年 jonki. All rights reserved.
//

#import "JPlayerViewController.h"

@interface JPlayerViewController ()

@end

@implementation JPlayerViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    // とりあえず起動時に全曲シャッフルして再生キューにぶっこむ
    _player = [MPMusicPlayerController applicationMusicPlayer];
    [_player setQueueWithQuery:[MPMediaQuery songsQuery]];
    [_player setShuffleMode:MPMusicShuffleModeSongs];
    [_player play];
    _isPlaying = YES;
    [_playOrStopButton setTitle:@"Ⅱ" forState:UIControlStateNormal];
    
    // Notificationの設定
    _ncenter = [NSNotificationCenter defaultCenter];
    [_ncenter addObserver:self
              selector: @selector(handle_PlaybackStateChanged)
              name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
              object:_player];
    [_ncenter addObserver:self
              selector:@selector(handle_NowPlayingItemChanged)
              name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
              object:_player];
    [_ncenter addObserver:self
                 selector:@selector(handle_VolumeChanged)
                     name:MPMusicPlayerControllerVolumeDidChangeNotification
                   object:_player];
    [_player beginGeneratingPlaybackNotifications];
    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewDidUnload {
    // Notificationの解除
    [_ncenter removeObserver:self];
    [_player endGeneratingPlaybackNotifications];
    
    [self setNextButton:nil];
    [self setPrevButton:nil];
    [self setPlayOrStopButton:nil];
    [self setSongInfoLabel:nil];
    [self setArtistInfoLabel:nil];
    [self setArtworkImage:nil];
    [super viewDidUnload];
}


#pragma mark 音楽ののNotificationハンドラ
- (void)handle_PlaybackStateChanged {
    NSLog(@"PlaybackSattechanged");
}

- (void)handle_NowPlayingItemChanged {
    NSLog(@"NowPlayingItemChanged");
    
    MPMediaItem *nowPlayingItem = [_player nowPlayingItem];
    NSString *artist = [nowPlayingItem valueForProperty:MPMediaItemPropertyArtist];
    NSString *title  = [nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];

    _songInfoLabel.text = title;
    _artistInfoLabel.text = artist;

    MPMediaItemArtwork *artwork = [nowPlayingItem valueForProperty:MPMediaItemPropertyArtwork];
    UIImage *image = [artwork imageWithSize:CGSizeMake(140.0f, 140.0f)];
    [_artworkImage setImage:image];
}

- (void)handle_VolumeChanged {
    NSLog(@"VolumeChanged");
}

#pragma mark 音楽の操作

- (IBAction)pushedNextButton:(id)sender {
    [_player skipToNextItem];
}

- (IBAction)pushedPlayOrStopBUtton:(id)sender {
    if( _isPlaying )
    {
        [_player pause];
        [_playOrStopButton setTitle:@"再生" forState:UIControlStateNormal]; //再生マークは機種依存でhatenaに投稿できないので漢字で
        _isPlaying = NO;
    }
    else
    {
        [_player play];
        [_playOrStopButton setTitle:@"Ⅱ" forState:UIControlStateNormal];
        _isPlaying = YES;
    }
}

- (IBAction)pushedPrevButton:(id)sender {
    [_player skipToPreviousItem];
}

#pragma mark デバッグプリント用に残してある
- (void)showNowPlayingSongInfo {
    NSLog(@"現在再生中の曲情報を表示する");
    MPMediaItem *nowPlayingItem = [_player nowPlayingItem];
    NSLog(@"Genre       = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyGenre]);
    NSLog(@"Album Title = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyAlbumTitle]);
    NSLog(@"Artist      = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyArtist]);
    NSLog(@"Title       = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyTitle]);
}

- (void)showSongInfoWithSongQuery {
    NSLog(@"曲名でソートして、全曲リストを表示する");
    MPMediaQuery *query = [MPMediaQuery songsQuery];
    int counter = 0;
    for( MPMediaItem *item in [query items])
    {
        NSLog(@"%@", [item valueForProperty:MPMediaItemPropertyTitle]);
        ++counter;
        if(counter > 4) break; // 全部出すと多いのでこの辺でbreak
    }
}

- (void)showSongInfoWithArtistQuery {
    NSLog(@"アーティスト名でソートして、全曲リストを表示する");
    MPMediaQuery *query = [MPMediaQuery artistsQuery];
    int counter = 0;
    for( MPMediaItem *item in [query items])
    {
        NSLog(@"%@", [item valueForProperty:MPMediaItemPropertyArtist]);
        ++counter;
        if(counter > 4) break; // 全部出すと多いのでこの辺でbreak
    }
}

- (void)showPlaylistInfo {
    NSLog(@"プレイリストを表示する");
    MPMediaQuery *query = [MPMediaQuery playlistsQuery];
    for( MPMediaPlaylist *plist in [query collections] )
    {
        NSLog(@"%@", [plist valueForProperty:MPMediaPlaylistPropertyName]);
    }
}

@end

【iOS】Modern Objective-Cの用法をまとめる

もうこの時代Modern Objective Cを使わないと化石扱いされるので便利なところだけをスクレイピング。どんどん追記する予定。
ちなみにHatena diaryでのObjective Cの記法は"objc"で挟めば良い。

synthesizeはオワコン

変数を定義したときに、@propertyと@synthesizeでシンクロしなくてよくなった。getter/setterが簡単になる。

TestViewController.h
@property (strong, nonatomic) IBOutlet UILabel *testLabel;
TestViewController.m

selfかアンダースコアつければアクセスできる

- (IBAction)debugButtonPush:(id)sender {
    self.testLabel.text = @"hoge"; //明記する
    _testLabel.text = @"unko"; //暗黙的アクセス
}

【iOS】iPod Library Accessの使い方(1)曲情報を取得する

iPod Library Accessなるものを使えば実機のiPodの曲にアクセスできます。MediaPlayer.frameworksをインポートしておきましょう。

コード

TestViewController.h
#import <MediaPlayer/MediaPlayer.h>

// 略

// どっかにこれを宣言しておく
@property MPMusicPlayerController *player;
TestViewController.m
- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    // Viewのロード時に全曲読み込んでシャッフル再生をはじめる
    _player = [MPMusicPlayerController applicationMusicPlayer];
    [_player setQueueWithQuery:[MPMediaQuery songsQuery]];
    [_player setShuffleMode:MPMusicShuffleModeSongs];
    [_player play];
}

// 略

- (void)showNowPlayingSongInfo {
    NSLog(@"現在再生中の曲情報を表示する");
    MPMediaItem *nowPlayingItem = [_player nowPlayingItem];
    NSLog(@"Genre       = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyGenre]);
    NSLog(@"Album Title = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyAlbumTitle]);
    NSLog(@"Artist      = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyArtist]);
    NSLog(@"Title       = %@", [nowPlayingItem valueForProperty:MPMediaItemPropertyTitle]);
}

- (void)showSongInfoWithSongQuery {
    NSLog(@"曲名でソートして、全曲リストを表示する");
    MPMediaQuery *query = [MPMediaQuery songsQuery];
    int counter = 0;
    for( MPMediaItem *item in [query items])
    {
        NSLog(@"%@", [item valueForProperty:MPMediaItemPropertyTitle]);
        ++counter;
        if(counter > 4) break; // 全部出すと多いのでこの辺でbreak
    }
}

- (void)showSongInfoWithArtistQuery {
    NSLog(@"アーティスト名でソートして、全曲リストを表示する");
    MPMediaQuery *query = [MPMediaQuery artistsQuery];
    int counter = 0;
    for( MPMediaItem *item in [query items])
    {
        NSLog(@"%@", [item valueForProperty:MPMediaItemPropertyArtist]);
        ++counter;
        if(counter > 4) break; // 全部出すと多いのでこの辺でbreak
    }
}

- (void)showPlaylistInfo {
    NSLog(@"プレイリストを表示する");
    MPMediaQuery *query = [MPMediaQuery playlistsQuery];
    for( MPMediaPlaylist *plist in [query collections] )
    {
        NSLog(@"%@", [plist valueForProperty:MPMediaPlaylistPropertyName]);
    }
}

- (IBAction)debugButtonPush:(id)sender {
    [self showNowPlayingSongInfo];
    [self showSongInfoWithSongQuery];
    [self showSongInfoWithArtistQuery];
    [self showPlaylistInfo];
}
出力結果例
現在再生中の曲情報を表示する
2012-12-26 18:18:26.150 JPlayer[1907:707] 
Genre       = ロック
2012-12-26 18:18:26.152 JPlayer[1907:707] Album Title = 500 Greatest Rock Classics
2012-12-26 18:18:26.154 JPlayer[1907:707] Artist      = 500 Greatest Rock Classics
2012-12-26 18:18:26.155 JPlayer[1907:707] Title       = Good Times Bad Times
2012-12-26 18:18:26.156 JPlayer[1907:707] 曲名でソートして、全曲リストを表示する
2012-12-26 18:18:26.363 JPlayer[1907:707] あぁ青春
2012-12-26 18:18:26.364 JPlayer[1907:707] あいあい
2012-12-26 18:18:26.366 JPlayer[1907:707] アイシテル
2012-12-26 18:18:26.367 JPlayer[1907:707] アイソトープ
2012-12-26 18:18:26.369 JPlayer[1907:707] アイデンティティー (Live ver)
2012-12-26 18:18:26.370 JPlayer[1907:707] アーティスト名でソートして、全曲リストを表示する
2012-12-26 18:18:26.716 JPlayer[1907:707] 絢香 × コブクロ
2012-12-26 18:18:26.718 JPlayer[1907:707] 絢香
2012-12-26 18:18:26.719 JPlayer[1907:707] 絢香
2012-12-26 18:18:26.720 JPlayer[1907:707] 絢香
2012-12-26 18:18:26.722 JPlayer[1907:707] 絢香
2012-12-26 18:18:26.724 JPlayer[1907:707] プレイリストを表示する
2012-12-26 18:18:26.994 JPlayer[1907:707] 林檎

続編

次回は音楽プレイヤーを作ってアプリっぽくします。
【iOS】iPod Library Accessの使い方(2)簡易音楽プレイヤーを作る