Medoly Ver. 1.9.5

Ver. 2 直前で、気になってた部分の修正が多いです。落ち穂拾いみたいな感じです。

2015-03-27 Ver. 1.9.5
– 区間ループ追加 (Android 4.1以降)
– 区間ループの開始・終了初期値にLOOPSTART / LOOPLENGTH の値を設定
– ループカウンタ及びループカウンタによる終了タイマー追加
– ギャップレスループ化 (Android 4.1以降)
– ランダム再生追加
– 再生シーケンスポップアップ内容の見直し
– アプリ個別ボリューム設定追加
– メディアストレージ情報のリンク追加 (メディアスキャン廃止)
– 設定のインポート・エクスポート追加
– 他アプリからのM3Uファイル共有受付サポート
– キーボード操作一部サポート
– タブメニューの表示位置調整
– 共有メディアが再生キューに登録されない場合がある問題修正
– 一部ダイアログ見直し
– 巻き戻し・早送りのボタン非表示でレイアウトが崩れる問題修正

再生シーケンスポップアップ内容の見直し

今回の機能変更に伴い、メイン画面左下にあるボタンのポップアップメニュー(再生シーケンスメニュー)の内容を大きく見直しました。

まず、再生中の曲に対する再生挙動を独立させ、「再生完了時に次の曲を再生」「再生完了時に停止」「ループ」「区間ループ」の4種類から選択できるようにしました。また、再生順の項目にランダム再生項目を追加しました。あと、一部ラベルの内容を見直してます。
 

区間ループ追加 (Android 4.1以降)

今回、ユーザ様からの要望があったため、区間ループ機能を追加しました。
区間ループ(ABループ)とは、局の特定の2地点をループさせる機能です。リスニング学習や耳コピ作業等、リピートさせて同じ所を何度も聞くような用途に用いられたりします。
先述したように、区間ループの追加に伴い、シーケンスメニューの内容を大幅に見直しています。メニューの「区間ループ」を選択すると、ループ位置の設定が表示されます。
「A」がループ開始位置(ミリ秒)、「B」がループ終了位置(ミリ秒)となります。 この時間の間で再生中の曲をループさせます。

「現在」ボタンを押すと、現在の再生時間を設定します。「<」「>」ボタンで、時間を微調整します。「初期値」ボタンを押すと、メディアの初期値の値が入力されます。通常は「A」が0、「B」が曲の再生時間が入りますが、一部特殊なメディアについては初期値が異なります(後述)。
変更された値は「設定」ボタンを押すまで反映されません。未反映の値は数値が黄色く表示されます。
また、シークバー上にループ位置を示す記号が表示されます。

他の区間ループ機能を持つプレイヤーに比べて使いにくいかもしれませんが、まぁオマケ程度の機能なので…。

区間ループの開始・終了初期値にLOOPSTART / LOOPLENGTH の値を設定

先ほど挙げた区間ループ機能ですが、実は同等の機能が1年以上前に既に実装されていました。LOOPSTART / LOOPLENGTH というタグによる2点間のループ機能です。これは、音楽ファイルにあるタグを読みとって、タグに指定された2点間をループさせるもので、これは元々ゲームBGM等で用いられているものです。
今回、この機能を区間ループと統合しており、区間ループ再生を行うとこの機能が使用できるようにしています。具体的には、区間ループの初期値として、LOOPSTART / LOOPLENGTH タグから求められる時間が設定されるようになり、従来と同様にループが行われるようになります。

 

 

ループカウンタ及びループカウンタによる終了タイマー追加

メイン画面の下部に表示されている再生キュー状態の中に、ループ時にカウントアップされるループカウンタを追加しています。これをトリガーとして、ループ回数で再生を終了させることができます。
まぁ、何となくループカウント数を追加してみたので、ついでに付けてみた機能です。大して使い出があるとは私もあまり思っていません(笑)。


ギャップレスループ化 (Android 4.1以降)

ユーザ様の要望により、ループ処理を見直してギャップレス化しています。従来は単純に先頭にシークさせていただけですが、これだと再生終了→再生開始の間に僅かな無再生時間が発生し、音が途切れてしまいます。今回、これをギャップレス化して、再生終了→再生開始の間が途切れないようにしました。
これを作る際、単純にAndroidの再生ループ機能を使えば良いのかとも思ったのですが、それでも途切れる機種があったり、そもそも「再生完了」を検出するイベントが発生しないので色々不都合があったり(実は発生する機種もあるようで、どちらかに決め打ちできない)で、割と難航しました。そんなわけで、ループを真面目に作るならMediaPlayerのsetLoopメソッドは使うべきではないと思います。

今回は、従来のギャップレス再生と同様の方法でギャップレスループを実現させています。そんなわけで、ループさせる毎に再生するメディアプレイヤーのオブジェクトが入れ替わってたりします。従来と全く異なる方法でループさせているので、何か問題があったら報告いただけると助かります。
 

ランダム再生追加

ランダム再生機能は以前から気になっていたので、今回実装してみました。これは再生キュー上にある曲から、ランダムに選曲していく機能です。「シャッフル再生」というよく似た機能がありますが、それとは若干異なります。
「シャッフル再生」は、再生キューの順番を入れ替えて再生する機能です。そのため、再生済みの曲は再生されませんし、再生キューの全ての曲の再生が終わると再生キューの完了と判定されます。一方今回の「ランダム再生」は、全ての再生キューの中からランダムに選曲していきます。現在再生されている曲が次にまた流れる可能性もありますし、逆に全く流れない曲も出てくる可能性があります。とにかく、順序や再生済等の情報は一切無視します。再生キューが完了するという概念もありません。
実装はしてみたものの、使い所は難しいかもしれません。私としても、今回の変更でポップアップメニューに余白が出来ていたし、以前から気になってたので追加してみるかぁ、ぐらいの感覚です。
なお、使ってて気になるのは、ランダムに再生しているつもりでも、再生曲が妙に偏るような感じがします。アプリのバグかもしれませんが…。余談ですが、一部のサービスでは、シャッフル再生させる場合、アーティスト等の情報をなるべくばらけさせるようにして、「人間がよりランダムらしく感じられる」ように意図を持って並べ替えることもあるようです。

アプリ個別ボリューム設定追加

今まで、ボリューム調整はAndroid標準の音量設定に任せきりだったのですが、本バージョンよりアプリ固有の音量設定を持たせるようにしました。

画面右上のメニューより、音量スライダーのポップアップを表示させることができます。スライダーの移動でボリュームの変更を行うことができます。左側のボタンはトグルスイッチとなっていて、音量ボタンを押した際にAndroid標準の音量調整ではなく、アプリ固有の音量調整を行うことができます(現状ではアプリを表示させた状態でのみ機能します)。右側のボタンは、Android標準の音量設定を呼び出すためのボタンです。
余談ですが、今回アプリ固有のボリュームを追加したのは、他のアプリとの音量バランスの調整を行うためです。以前、音楽を聞きながらカーナビアプリを起動していたのですが、音楽とカーナビ音声の音量バランス調整がどうしても上手くいかず、カーナビの音量が音楽の音量に対して小さくて聞き取りにくいという問題がありました。そんなわけで、アプリ固有ボリュームの必要性を認識した次第です。

メディアストレージ情報のリンク追加 (メディアスキャン廃止)

以前から気になっていたのですが、今回で設定にあった「メディアスキャン」という項目は廃止しました。というのも、これは全く機能していなかったためです。

そもそも、Androidがどのように端末に保存されたメディアファイルをスキャンしているかというと、バックグラウンドでメディアファイルの変更を監視し、端末のメディアデータベースを更新するアプリが動作しています。このアプリがどのようなタイミングでスキャンを行っているかがよく分からないのですが、確実なのは「ストレージがマウントされたタイミング」で行われるということです。つまり、SDカードを抜き差ししたり、Androidの設定からSDカードのマウント解除→再マウントといった作業を行うとスキャンが開始されます。あるいは、端末の再起動を行うことでも実行されます。
以前はこのストレージをマウントさせるイベントを手動で実行する方法があったのですが(実際、初期の頃はこれで実装してました)、最近のAndroidではこれを行うとエラーとなります。理由としては恐らく、ユーザがSDカードのマウントイベントを自由に実行できるのはおかしいから、という事だと思います。その代替手段としてあちこちのサイトで紹介されている手法があり、とりあえずそれを実行するようにしていたのですが、正直な話、自分でもこれでまともにスキャンできた試しがありません。
たまにスキャンについての問い合わせを頂くのですが、自分でもどうしたら良いか分からず困っていたところだったので、とりあえずバッサリ切り捨てることにしました。
その代わりとして、メディアストレージ情報へのリンクを置いておくことにしました。これが端末に保存されているメディア情報を保持している共通データベースになり、Android端末であれば確実に持っているはずです。メディアの数に応じてサイズが増減し、9500曲ほど入っている自分の端末では124MB程度のサイズになっています。これに対して「データを削除」を行うと、全ての保存されたメディア情報が全て消去されます。ただ、次にストレージが再マウント(再起動)されるともう一度スキャンが開始され、データベースが再構築されます。データベースの情報がおかしい場合は、これで一端データベースを再構築すると調子が良くなる可能性があります。なお、Android共通のプレイリストを利用している場合、メディアストレージ情報を削除すると一緒に消去されますのでご注意ください。プレイリストをM3Uファイルで保存されていた場合、再スキャン時に自動的にプレイリストに登録されます。
余談ですが、Google Play上には再スキャンを行うことができるアプリがいくつか登録されていますが、それらのアプリは自分でメディアをスキャンして、自分でメディアストレージのデータベースに登録する処理を行っているようです。(それ以外に、メディアファイルを移動させるとデータベース上の登録情報を更新してくれるファイラ等もあるようです。)一部使用してみましたが、データベースの整合性がうまくとれなくなるアプリを見かけたりしました。どなたか、上手く動作するスキャンアプリ(もしくは、その実装方法)がありましたら教えてください…。
そもそも、Androidがメディアスキャン機能をもっとしっかり作れという話ではあるのですが。

設定のインポート・エクスポート追加

設定をインポート・エクスポートする機能を追加しました。設定の「その他」より使用できます。エクスポートは保存先のファイルパスを指定することで、現状の設定情報をファイルに書き出します。インポートは読み込み元の設定ファイルパスを指定し、設定内容を現在のアプリに反映させます。あんまりきちんとテストしてないので、何か問題が起きるかもしれませんが、何か問題がありましたら情報ください。

この機能は以前、ユーザ様から要望があったと思うのですが、どこから要望を受けたか覚えていないという酷い有様だったりします。
設定ファイルの中身はJSON形式で出力されているため、テキストファイルで開くと中身が見えます。設定のキーの名前についてはあまり突っ込まないであげてください…。大文字と小文字が入り乱れているのは作ってる課程で色々あった末に統一されなかった経緯がありますので、何となくお察しください。
なお、設定を適当に弄って読み込ませてエラーとなっても、当方は関知しません。弄る方が悪い。
余談ですが、Googleにはこうした設定情報をGoogle Drive等に保存して、各端末で設定を共有できるような簡単なAPIを作ってほしいなぁ、と常々思ってます。もっと設定情報を簡単にバックアップしたり、共有できるようにしてほしい。
今回も本当は、出来ることならユーザーに端末のディレクトリ構造を意識させるような作りにはしたくなかったのですが、設定がどこに保存されるのか(どうやって復帰させるか)を、ユーザがきちんと認識できるように作らないと意味が無いと思ったので、「よく分からない場所に勝手に保存するよりは、ユーザ自身に決めさせた方がまだマシ」という判断でこういう作りになりました。
この辺について何か良い案があれば、どなたか教えて下さい…。


他アプリからのM3Uファイル共有受付サポート

他のアプリからM3Uファイルを本アプリに「共有」させると、再生キューにM3Uファイルの内容が展開されるようにしました。(事前にメディアストレージにプレイリストとして登録されている必要があります。)

ファイル書き出しはできるのに、読み込みができないのは何だかなぁ、と思っていたので処理を追加しました。
とりあえず今回は再生キューの更新ではなく追加のみとします。


キーボード操作一部サポート

キーボード操作に対応しました。「一部」というのは、まだ途中だからです。全部作ると大変なので…。他のプレイヤーとできるだけ似通ったキー操作にしたいのですが、イマイチ共通性が見出せないので、とりあえず「VLC」と「Kodi (旧XBMC)」辺りのキーアサインを参考にしてます。

現状ではまだ中途半端な状態(というか、色々大変)なので、とりあえず保留とさせてください。そのうち、きちんと整えてキーアサイン一覧も表示させるようにします。

タブメニューの表示位置調整

タブを押した際に表示されるメニューがタブ幅より小さい場合、タブの中央にメニューが表示されるように座標修正しました。

修正前は、メニューが端に寄っていたので、ちょっと使いにくかったためです。



共有メディアが再生キューに登録されない場合がある問題修正

メディアファイルをMedolyに「共有」とした場合、再生キューに登録される機能がありますが、場合によっては上手く登録されない問題がありました。これは、単純に自分の知識不足の問題です。
これは、以前は「onStart」イベントのみで送られたファイルを受け取っていたのですが、その場合はアプリのスリープ状態から受け取ることができませんでした。この場合、「onNewIntent」というイベントを使用するのが正解でした。


一部ダイアログ見直し

ダイアログの表示内容を一部見直しています。動作的な変更はありません。

巻き戻し・早送りのボタン非表示でレイアウトが崩れる問題修正

設定で巻き戻し・早送りボタンを非表示かすると、レイアウトが潰れてしまう問題があったため、修正しました。