グリッドアプリケーションのアイテムとして音楽を使ってみる

現在、https://msdn.microsoft.com/ja-jp/jj556277.aspx から公開しているBasic Photo、Entertainment Photoのテンプレートは、Visual Studio 2012のグリッドアプリテンプレート(XAML/C#)をベースに作られています。
このポストではBasic Photoアプリテンプレートをベースに説明を進めます。

Basic Photoテンプレートは名前からすると写真を扱うアプリ用に見えますが、アイテムは音楽の曲でも構いません。Windows PhoneのPCクライアントアプリであるZuneでMusic CDをキャプチャすると、ライブラリのミュージックフォルダーにアルバム情報と曲のファイルが構造化されて格納されます。論理構造的にはアルバムがあってそのアルバムに属する曲が入っているわけです。

アルバム => SampleDataGroup
曲      => SampleDataItem

とすれば、Basic Photo(グリッドアプリ)が想定している、グループ、アイテム構造をそのまま利用できます。ピクチャフォルダーを覗いてみると、アルバムと曲のグループ関係以外の要素が組み込まれています。これを愚直にWindows.Storage名前空間のクラス群を使って辿って、データ構造を作るのもいいのですが、もっと便利にアルバム、曲構造を扱う方法があるので、紹介します。

先ず、Basic Photoテンプレートでアプリケーションプロジェクトを一つ作ってください。

Package.appxmanifestを開き、機能タブで、音楽ライブラリにチェックを入れます。これでミュージックフォルダーにアプリがアクセスできるようになります。

テンプレートで作ったプロジェクトのグループ、アイテムは、DataModel/SampleDataSource.csファイルのSampleDataSourceクラスのコンストラクター内で定義されています。

                var group1 = new SampleDataGroup("Group-1",
                        "Group Title: 1",

から

                        group6));
                this.AllGroups.Add(group6);

までを、

            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            {
                …
            }

で囲んでしまいます。これで囲まれたコードは、Visual StudioやBlendでXAMLを見ているときだけ有効で、アプリの実行時は有効でなくなります。

ミュージックフォルダーに格納されているアルバム、楽曲情報からSampleDataGroup、SampleDataItemを構築するメソッドをSampleDataSourceクラスに追加します。ファイルアクセス系のAPIで非同期メソッドを使うので、非同期メソッドとして定義します。

        public async void BuildMusicItemsAsync()
        {
            …
        }

このメソッドを、アプリで最初に表示されるページのGroupedItemsPageのLoadStateでコールするため、SampleDataSourceクラスに、

        public static SampleDataSource Current
        {
            get
            {
                if (_sampleDataSource == null)
                {
                    _sampleDataSource = new SampleDataSource();
                }
                return _sampleDataSource;
            }
        }

と、スタティックプロパティを追加します。GroupedItemsPage.xaml.csのLoadStateメソッド内で、

            SampleDataSource.Current.BuildMusicItemsAsync();

を// TODO: の下に書いておきます。これで準備は完了です。

ミュージックフォルダーからアルバム、曲を取り出すには、以下の様にします。

                // ミュージックフォルダーへの参照取得
                var musicFolders = Windows.Storage.KnownFolders.MusicLibrary;

                // ミュージックフォルダーからアルバムフォルダーの取り出し
                var qalbums = musicFolders.CreateFolderQuery(Windows.Storage.Search.CommonFolderQuery.GroupByAlbum);
                var albums = await qalbums.GetFoldersAsync();
                foreach (var album in albums)
                {
                    // アルバム属性の取り出し。albumPropsから、アーティストやアルバム名を取り出せる
                    var albumProps = await album.Properties.GetMusicPropertiesAsync();
                    // アルバムに対応するSampleDataGroupインスタンスを作成
                    var albumGroup = new SampleDataGroup(album.FolderRelativeId, albumProps.Album, albumProps.Artist, ””, "");

                    // 曲ファイルの取り出し
                    var qmusic = album.CreateFileQuery(Windows.Storage.Search.CommonFileQuery.OrderByMusicProperties);
                    var musics = await qmusic.GetFilesAsync();
                    foreach (var music in musics)
                    {
                        // 曲属性の取り出し。musicPropertiesから、曲名、アーティスト、ジャンル、アルバムなどが取り出せる
                        var musicProperties = await music.Properties.GetMusicPropertiesAsync();

                        // 曲に対応するSampleDataItemインスタンスを作成
                        var musicItem = new SampleDataItem(music.Path, musicProperties.Title, musicProperties.Album, musicProperties.AlbumArtist, "", albumGroup);
                        musicItem.MusicFile = music;
                        albumGroup.Items.Add(musicItem);
                    }

                    this.AllGroups.Add(albumGroup);
                }

 説明し忘れていましたが、後々のためSampleDataItemクラスに曲ファイルへの参照を保持するStorageFile型のプロパティ(名前はMusicFile)を追加しておきます。

これで基本的な骨格は出来上がりです。アルバムや曲に関する画像は何もやっていないのでちょっと寂しい出来上がりなので、それは皆さん工夫してください。それから、GroupedItemsPageのLoadStateメソッドは適宜何回もコールされます。このままの実装では何回も何回もこのコードが実行されてしまうので、構築完了を示すフラグを用意して、

        if (!musicPrepared)
        {
            ...
            musicPrepared = true;
        }

とガードを入れてください。あとは例えば、ItemDetaiPageにアプリバーなどでPlayボタンを定義してそのクリックハンドラで

            var selectedItem = (SampleDataItem)this.flipView.SelectedItem;
            await Windows.System.Launcher.LaunchFileAsync(selectedItem.MusicFile);

などと書いてやれば、曲の演奏も可能です。

以上、アルバム、曲をアプリで扱う方法を説明してきました。SampleDataGroup、SampleDataItemは何をグループ、アイテムとして使ってよいので、色々とアイデアを練ってみてください。ページの表示でテキストだけで何となく見栄えを保つ方法は、NewsReaderテンプレートを、アプリ実行時にグループ、アイテムを追加削除したい場合は、Entertainment Photoを参考にしてみてくださいね。

では、また。