[iOS][Swift]ミュージックライブラリの音楽の再生、情報の表示(MPMusicPlayerController使用)

MPMusicPlayerControllerを使ったミュージックライブラリアイテムの再生に関してこちらに記事を書きました。
[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(MPMusicPlayerController使用) | nackpan Blog
この記事では、ミュージックライブラリから一つの曲を選んで再生・一時停止・停止を行いました。

今回のサンプルでは、MPMusicPlayerControllerを使用して複数のアイテムを順に再生します。
また、再生中の音楽アイテムの情報(アートワーク、アルバム名等)を表示します。
前回のサンプルでは、選曲するとすぐに再生を開始していましたが、今回は選曲するとアイテム情報を表示しますが再生は開始しないこととしました。PLAYボタンを押すと再生開始です。
再生されているアイテムが変更されると、それを検知して変更後のアイテム情報を表示します。
ファイル 2016-04-13 7 24 35
(今回のサンプルのスクリーンショット)

MusicPlayerControllerを使って、ミュージックライブラリのアイテムを再生し、情報を表示する

iPodライブラリアクセス プログラミングガイド(PDF)
iPod Library Access Programming Guide(英語版)
このappleのドキュメントにライブラリにアクセスして再生する方法、必要な曲を選択する方法、現在再生中の音楽の情報を知る方法等、まとめてあります。
(ちなみに、日本語ドキュメント – Apple DeveloperのページにappleのiOS用日本語ドキュメントがまとめてあります。英語版へのリンクもあります)

iOSシミュレータでは動作しないので、実機を用いてください。

Single View Applicationでプロジェクトを作成。
ss 2015-09-16 6.46.53

ViewController.SwiftにMediaPlayerフレームワークをimportします。

import UIKit
import MediaPlayer

class ViewController: UIViewController {

UI配置

ボタンとラベルとイメージビュー(Image View)を配置。
ss 2016-04-13 2.02.06

UIとViewControllerとの接続

ラベルおよびイメージビューとViewController.swiftをOutletを作成して接続。
ss 2016-04-12 21.53.43outletLabels
ss 2016-04-12 21.52.55

ボタンとViewController.swiftをactionを作成して接続。
ss 2016-04-13 2.35.53Action
ss 2015-09-13 9.09.50

プレイヤー準備

プレイヤーを表すpropertyをViewController.swiftに加えます。

class ViewController: UIViewController, MPMediaPickerControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var artistLabel: UILabel!
    @IBOutlet weak var albumLabel: UILabel!
    @IBOutlet weak var songLabel: UILabel!

    var player = MPMusicPlayerController()
    
    override func viewDidLoad() {

プレイヤーのインスタンスを作成。

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        player = MPMusicPlayerController.applicationMusicPlayer()
        //player = MPMusicPlayerController.systemMusicPlayer()
        
    }

(ここで、applicationMusicPlayerではなく、systemMusicPlayerを用いると、「ミュージック」アプリでの再生状況(再生アイテムや、シャッフル、リピートなどのモード)を反映したものになる)

再生中アイテムの変更通知

今回は、複数の曲を選択して順に再生していきます。
アイテム情報を表示するには、現在再生中のアイテムがなにか分かっていなければなりません。
ミュージックプレーヤー通知という仕組みで、再生中アイテムに変更があった場合には通知を受け取ることができます。
この通知を受けて、プレイヤーが現在再生中のアイテムを取得し情報表示を更新します。

まず、再生中アイテム変更イベントを監視します。

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        player = MPMusicPlayerController.applicationMusicPlayer()
        //player = MPMusicPlayerController.systemMusicPlayer()
        
        // 再生中のItemが変わった時に通知を受け取る
        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.addObserver(self, selector: #selector(ViewController.nowPlayingItemChanged(_:)), name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification, object: player)
        // 通知の有効化
        player.beginGeneratingPlaybackNotifications()
        
    }

再生中のアイテムが変更になったときに、ViewController.nowPlayingItemChanged(_:)を呼び出すように指定しています。

また、ViewControllerのdeinit内に、通知を受け取る必要がなくなった場合の後処理を書いておきます。

    deinit {
        // 再生中アイテム変更に対する監視をはずす
        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.removeObserver(self, name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification, object: player)
        // ミュージックプレーヤー通知の無効化  
        player.endGeneratingPlaybackNotifications()
    }

再生中のアイテムが変更になった際に呼び出されるViewController.nowPlayingItemChanged(_:)の内容を書きます。

    /// 再生中の曲が変更になったときに呼ばれる  
    func nowPlayingItemChanged(notification: NSNotification) {
        
        if let mediaItem = player.nowPlayingItem {
            updateSongInformationUI(mediaItem)
        }
        
    }

MPMusicPlayerControllerのプロパティnowPlayingItemで再生中のアイテムを取得できます。
(今回は使いませんが、アイテムをsetすることもできます)
nowPlayingItemはMPMediaItem型のプロパティです。

MPMediaItem

ミュージックライブラリに対するアクセスでは、MPMediaItemというクラスでアイテム情報を扱います。
MPMediaItem Class Reference
MPMediaItemは、title, artist, artworkなどなど、さまざまな情報をもっています。
アイテム情報を表示する際には、現在再生中のアイテムから情報を取得してラベルやイメージビューに表示します。

    /// 曲情報を表示する
    func updateSongInformationUI(mediaItem: MPMediaItem) {
    
        // 曲情報表示
        // (a ?? b は、a != nil ? a! : b を示す演算子です)  
        // (aがnilの場合にはbとなります)
        artistLabel.text = mediaItem.artist ?? "不明なアーティスト"
        albumLabel.text = mediaItem.albumTitle ?? "不明なアルバム"
        songLabel.text = mediaItem.title ?? "不明な曲"
        
        // アートワーク表示
        if let artwork = mediaItem.artwork {
            let image = artwork.imageWithSize(imageView.bounds.size)
            imageView.image = image
        } else {
            // アートワークがないとき
            // (今回は灰色表示としました)
            imageView.image = nil
            imageView.backgroundColor = UIColor.grayColor()
        }
        
    }

メディアアイテムピッカー

曲を選択するために、メディアアイテムピッカーを用います。
(メディアアイテムピッカーというのは、iOSで用意されているあらかじめ設定済みのViewController。ミュージックライブラリの選択画面と同じようなことが出来る)
ss 2015-09-13 11 41 39

メディアアイテムピッカーでの「選択完了したとき」や「キャンセルされたとき」のイベントを、ViewControllerで受け取れるようにします。
そのために、ViewControllerをメディアアイテムピッカーのデリゲートとして設定します。
「選曲」ボタンを押すと、メディアアイテムピッカーを作成して、デリゲートの設定を行い、ライブラリの曲を選択できるようにします。
「選択完了したとき」「キャンセルされたとき」のメソッドを記述します。

import UIKit
import MediaPlayer

class ViewController: UIViewController, MPMediaPickerControllerDelegate {
    @IBAction func pick(sender: AnyObject) {
        // MPMediaPickerControllerのインスタンスを作成
        let picker = MPMediaPickerController()
        // ピッカーのデリゲートを設定
        picker.delegate = self
        // 複数選択にする。(falseにすると、単数選択になる)
        picker.allowsPickingMultipleItems = true
        // ピッカーを表示する
        presentViewController(picker, animated: true, completion: nil)
        
    }
    
    /// メディアアイテムピッカーでアイテムを選択完了したときに呼び出される
    func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        
        // プレイヤーを止める
        player.stop()
        
        // 選択した曲情報がmediaItemCollectionに入っているので、これをplayerにセット。
        player.setQueueWithItemCollection(mediaItemCollection)
        
        // 選択した曲から最初の曲の情報を表示
        if let mediaItem = mediaItemCollection.items.first {
            updateSongInformationUI(mediaItem)
        }
        
        // ピッカーを閉じ、破棄する
        dismissViewControllerAnimated(true, completion: nil)
        
    }
    
    //選択がキャンセルされた場合に呼ばれる
    func mediaPickerDidCancel(mediaPicker: MPMediaPickerController) {
        // ピッカーを閉じ、破棄する
        dismissViewControllerAnimated(true, completion: nil)
    }

選択完了した時に呼び出されるmediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection)で、MPMediaItemCollection型の引数mediaItemCollectionがありますが、これにアイテム情報が入っています。
MPMediaItemCollection Class Reference
MPMediaItemCollectionクラスは、MPMediaItemを集めて管理しているクラスです。
そのプロパティitemsがMPMediaItemの配列になっていますので、今回はそこから先頭のMPMediaItemを取得してそれを元に情報を表示しています。

再生・一時停止・停止

各ボタンのアクションに、「再生」「一時停止」「停止」機能を加えます。

    @IBAction func pushPlay(sender: AnyObject) {
        player.play()
    }

    @IBAction func pushPause(sender: AnyObject) {
        player.pause()
    }

    @IBAction func pushStop(sender: AnyObject) {
        player.stop()
    }

iOSシミュレータでは動作しません。実機を用いてください。 「選曲」ボタンを押すと、メディアアイテムピッカーが表示されるので、曲を選択してください。複数の曲を選択できます。「PLAY」ボタンで音楽の再生。「PAUSE」ボタンで一時停止。「STOP」ボタンで音楽を止めて、再生位置を一番始めに戻します。


ViewController.swift全文

//
//  ViewController.swift
//  MPMusicPlayerControllerDemo2
//
//  Created by KUWAJIMA MITSURU on 2016/04/12.
//  Copyright © 2016年 nackpan. All rights reserved.
//

import UIKit
import MediaPlayer

class ViewController: UIViewController, MPMediaPickerControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var artistLabel: UILabel!
    @IBOutlet weak var albumLabel: UILabel!
    @IBOutlet weak var songLabel: UILabel!

    var player = MPMusicPlayerController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        player = MPMusicPlayerController.applicationMusicPlayer()
        //player = MPMusicPlayerController.systemMusicPlayer()
        
        // 再生中のItemが変わった時に通知を受け取る
        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.addObserver(self, selector: #selector(ViewController.nowPlayingItemChanged(_:)), name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification, object: player)
        // 通知の有効化
        player.beginGeneratingPlaybackNotifications()
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func pick(sender: AnyObject) {
        // MPMediaPickerControllerのインスタンスを作成
        let picker = MPMediaPickerController()
        // ピッカーのデリゲートを設定
        picker.delegate = self
        // 複数選択にする。(falseにすると、単数選択になる)
        picker.allowsPickingMultipleItems = true
        // ピッカーを表示する
        presentViewController(picker, animated: true, completion: nil)
        
    }
    
    /// メディアアイテムピッカーでアイテムを選択完了したときに呼び出される
    func mediaPicker(mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {
        
        // プレイヤーを止める
        player.stop()
        
        // 選択した曲情報がmediaItemCollectionに入っているので、これをplayerにセット。
        player.setQueueWithItemCollection(mediaItemCollection)
        
        // 選択した曲から最初の曲の情報を表示
        if let mediaItem = mediaItemCollection.items.first {
            updateSongInformationUI(mediaItem)
        }
        
        // ピッカーを閉じ、破棄する
        dismissViewControllerAnimated(true, completion: nil)
        
    }

    
    /// 選択がキャンセルされた場合に呼ばれる
    func mediaPickerDidCancel(mediaPicker: MPMediaPickerController) {
        // ピッカーを閉じ、破棄する
        dismissViewControllerAnimated(true, completion: nil)
    }
    
    /// 曲情報を表示する
    func updateSongInformationUI(mediaItem: MPMediaItem) {
    
        // 曲情報表示
        // (a ?? b は、a != nil ? a! : b を示す演算子です)  
        // (aがnilの場合にはbとなります)
        artistLabel.text = mediaItem.artist ?? "不明なアーティスト"
        albumLabel.text = mediaItem.albumTitle ?? "不明なアルバム"
        songLabel.text = mediaItem.title ?? "不明な曲"
        
        // アートワーク表示
        if let artwork = mediaItem.artwork {
            let image = artwork.imageWithSize(imageView.bounds.size)
            imageView.image = image
        } else {
            // アートワークがないとき
            // (今回は灰色表示としました)
            imageView.image = nil
            imageView.backgroundColor = UIColor.grayColor()
        }
        
    }
    

    
    
    @IBAction func pushPlay(sender: AnyObject) {
        player.play()
    }
    
    @IBAction func pushPause(sender: AnyObject) {
        player.pause()
    }
    
    @IBAction func pushStop(sender: AnyObject) {
        player.stop()
    }
    
    
    /// 再生中の曲が変更になったときに呼ばれる  
    func nowPlayingItemChanged(notification: NSNotification) {
        
        if let mediaItem = player.nowPlayingItem {
            updateSongInformationUI(mediaItem)
        }
        
    }
    
    deinit {
        // 再生中アイテム変更に対する監視をはずす
        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.removeObserver(self, name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification, object: player)
        // ミュージックプレーヤー通知の無効化  
        player.endGeneratingPlaybackNotifications()
    }
    

}

関連

[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(MPMusicPlayerController使用) | nackpan Blog
[iOS][Swift]MPMediaQueryを使って曲を絞り込む | nackpan Blog
[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(AVAudioPlayer使用) | nackpan Blog

投稿者:

nackpan

nackpan

iOSアプリを作っています。 リピーティングに便利な「語学学習支援プレイヤー」つくりました。

「[iOS][Swift]ミュージックライブラリの音楽の再生、情報の表示(MPMusicPlayerController使用)」への1件のフィードバック

  1. 非常に参考になりました!
    他の記事も含めて最高に分かりやすいです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください