Archive for the ‘gmusicbrowser’ Category

[10/1 8:18 この問題は解決した。原因と対処を最後に示す。]

面倒なことは、いつも突然やって来る。昨日、ふと、SpotifyとGMB(gmusicbrowser)を切り替えると音量が違うのが気になっていたので、それを可能な限り合わせたくなって、テスト信号を作って再生したら、思わぬことに気付いてしまった。

MP3のスイープ信号を再生したら、GMBからの音がおかしかったのだ。特定の周波数(例: 5.5kHz)が小さくなった。以下に問題の波形(問題の起こった5.5kHzの正弦波の再生波形の比較)を示す。上は問題がある場合、下は問題のない場合である(左チャネルだけを抜粋した)。なぜか変調が掛かっている感じで、音量が小刻みに振動している。そのために音が濁って聞こえる。

興味から、この変調波の周波数を調べたいのだが、普通にスペクトルを出しても出ず、なぜかLPFでも抽出できない(LFP後のスペクトルが出ない)。目視では24Hz程度と分かるが、なぜLPFで取れないのだろうか。振幅がとても小さいのか(そうなら、こんなに振れない気がする)。まだまだ知識が足らないようだ。。。

↑ 分かった! スペクトルを拡大したら、5.5kHz付近に2つの山があった。それらが干渉していたのだ。2つの差は約25Hzで、上記の目視と一致した。でも、なぜこういうことが起こるのだろうか? 新たな謎だ。

参考のため、実際の音(再生音を収録したもの)をこちらに置く。最初が問題のある場合、次が問題のない場合である。音量が大きいが、小さくしても現象は変わらなかった。多くの環境で再生できるようにMP3にしたので、環境によってはどちらも同じように(問題があるように聞こえる)可能性がある。

同じ音でもFLACのファイルを再生する場合は問題が起こらず、出力系をJACKからPulseAudioに換えても問題は起こった。それから、同じMP3のファイルを他のプレーヤー(例: XPlayer)やGstreamer(以下、GST)の再生プログラム(gst-play-1.0)で再生しても同じ現象が起こるが、問題の起こらないプレーヤー(例: Spotify, AlsaPlayer)もあるので、GMBが再生に使っているGSTのMP3デコーダ(デフォルトのもの)に問題がある可能性が高いことが分かった。

更に試したら、madというデコーダを使うと問題が起こらなくなることが分かった。以下に、gst-launch-1.0での例を示す。下記太字の"mad"を"decodebin"に変えると、問題が起こる。

gst-launch-1.0 filesrc location=test.mp3 ! mad ! audioconvert ! autoaudiosink

結局、GSTのデフォルトのデコーダ(decodebin?)に問題があるようなのだが、仮にGSTのバージョンが古いせいだとしても、OSのパッケージのものを使っているため、それより新しいものにバージョンを上げるのはかなりの手間(自分でコンパイルする)なので、上の例のようにGMBで使うMP3デコーダを変更するようにした。

MP3デコーダはmad以外にmpg123audiodecやavdec_mp3でも問題が起こらなかった。ただ、gst-launch-1.0で使う場合にはmadしか音が出なかった(他はprerollのエラーが起こった)。これは、僕がGSTの使い方を良く理解していないせいだ思う。

それで、3つの中では(名前から)一番品質が良さそうな(イメージの)avdec_mp3を使うことにした。ただ、何か問題があった時やデフォルトのデコーダで試したい時に手軽にデコーダを変更できるように、GMBの拡張設定で変えられるようにした。

他に分からなかったのは、GSTのパイプライン(上記のコマンド例のようなもの)でMP3デコーダを指定する順番が最初でないと うまく動かなかった(再生開始しない)ことだが、これも僕がGSTを良く理解していないせいだと思う。

 

昨夜から延々と試行錯誤と対処をして、ようやく本題の音量を合わせる話に進むことができた。テスト信号とメーターで音量を比較してみたら、結局、音量正規化を行わない場合には、どちらも同じ音量で再生されることが分かった(まあ、デジタルなのだから、大きく違ったらおかしいが・・・)。僕のシステムではDACの前に部屋の特性補正用のイコライザを入れているが、両方とも音量を100%にしてもオーバーフローは起こらないようだった。ただ、念のため(論理的でない「気休め」)、イコライザの前で1dB下げるようにした。

音量正規化を行う場合には、SpotifyとGMBの音量は異なっていた(これが、気になっていた音量差である)。それぞれの仕組みや目標音量が異なるためだろう。手持ちとSpotify両方にある数曲で調べたら、曲にもよるが、1〜3dB程度Spotifyが大きかった。それでミキサー(jack_mixer)を使って2dB程度下げたら、差が1dB以下となった。これで聴感的にも合えばいいが・・・ → 残念ながら、曲によってSpotifyの正規化後の音量が違うようで、あまり合わない感じだ。

まったく、手製のシステムは不意に問題が起こって気が抜けないものだ。まあ、オーディオ道 趣味なんてそんなものだろうw ただ、JACKだといろいろな部品をマウスで配線して手軽に試行錯誤や確認ができるのは便利だし、いろいろな知らなかったことが分かるのはおもしろい。

それから、MP3デコーダの問題はダウンロード購入したMP3音源の音質劣化を起こすことに気付いて確認したら、確かに若干音がおかしくなっていた。具体的には、ルプーのモーツァルト ピアノ協奏曲 第21番(1975)で弦(バイオリン)の音量が大きい箇所で違和感がある。実際、今年の頭に音が悪いことに気付いて書いている(これはこっちの問題だし、苦情を言ったら確実に泥沼化して疲弊しただろうから、黙ってて良かったw)。今聴くと、MP3デコーダを変更すると、違和感がほとんどなくなって、すっきりした気分のいい音(曇り空がちょっとした青空になった感じ)になる。確かに、録音が古いことによる音の悪さもあるのだが、MP3デコーダの問題が大きかったようだ。

もちろん、他のMP3音源でも同じ問題があるはずだが、特定の音(例: 5.5kHz)が続く場合にしか顕著にならないようで、たまたま僕の手持ちの曲ではそのパターンが少なかったらしく、気付かなかったようだ。実際、ルガンスキーのラフマニノフ ピアノ協奏曲 第2,3番(2005, 2003)ではまったく差が分からず、以前どおりのいい音にしか聞こえない。

それにしても、ルプーについては本当に音が悪いことが分かっていたなんて、僕の耳と環境は随分良くなったものだ。つい最近まで何がいい音か分からなかったことを思うと、全く感慨深い・・・

 

(10/1 8:18追記) MP3の音がおかしい問題の原因が分かり、対処できた。

しつこく試したり調べていたら、ヒントになる投稿が見つかった。どうも、GSTにインストールしていたFluendo MP3 Decoder(flump3dec、パッケージ: gstreamer1.0-fluendo-mp3)が古い(その投稿が2007年なので、それより前!)うえにバグがあったようだ。そして、今(実際には2007年以前から)はそれがなくてもMP3を再生できるとのこと。僕が自分でgstreamer1.0-fluendo-mp3をインストールしたのかは今となっては分からないが、余計だったようだ(← 別のPCには入っていないので、自分で入れたようだ)。

それで、gstreamer1.0-fluendo-mp3をアンインストールして問題のファイル(5.5kHzおよびスイープ)を再生してみたら、正しい音が出た(再度インストールしたら、やっぱり駄目になった)。ルプーのモーツァルト ピアノ協奏曲 第21番も大丈夫そうだ。それで、GMBのMP3デコーダの指定も止めて、デフォルトに戻した。

いつものように最後はあっけなかったが、原因が分かって良かった。それにしても、余計なパッケージは削除して欲しいものだ(→ Ubuntuの人)・・・

  •   0
  •   0

5/22(US時刻)に、USなどでGoogle Play Music (GPM)がYouTube Musicに統合された。日本もそのうちそうなるらしい。4月下旬のニュースでは「Google Play Musicが年内に終了」などどいうセンセーショナルな見出しでびっくりしたのだが、中身を読むと、実際には上記のようなことで、全然「終了」ではない(それどころか、実質的には名前が変わった程度)のだが、記者が無知なのかアクセス数を稼ぎたいのか知らないが、大げさな見出しになっていた。(→ 先週、より正確なニュースがあった)

僕は、GPMが終了することはまずないと信じていたので(というのは、これくらいのサービスは、Googleのパワーやリソースをもってすれば、全然問題ない(Spotifyは結構辛そうな気がする)。逆に、投資に比べて利益(お金以外も)が多そうだ。)、それについては全然心配しなかったのだが(仮に終わりになっても、Spotifyなどの代わりがあるから、お気に入りの曲・アルバム一覧などを保存して、移るだけだ)、ちょっと気にあることがあった。それは、GPMをYouTubeに統合するために、システムの内部構造が多少変わる可能性があり、その変化の影響で、今僕がgmusicbrowser (GMB)でGPMを聴ために使っている、gmusicapiなどのプログラムがうまく動かなくなったら、GMBでGPMが聴けなくなって不便を強いられるのではないかという心配だった。その後、疲れのせいかちょっと調子が悪くて余裕がなくて、たまたま、移行した頃から家ではGPMを聴いておらず、移行の件もすっかり忘れていた。

そして今朝。たまたまGPMを掛けたら、なぜか再生できなかった。アプリを再起動したり何度試しても駄目で、無事死亡した。ログを見たら、HTTPエラー403(Forbidden)で曲取得用URLの取得に失敗していた。最初は、自分のPCのLinuxの更新でPython(gmusicapiを動かすプログラム)やgmusicapiを駄目にしたかとか、GPMの認証がおかしくなったのかと思ってその辺りを調整してみたが、駄目だった。それからGPMが移行したことを思い出して、それに関係しているのかも知れないと思った。そして、苦労して作ったシステムが、気付いたら音もなくバベルの塔のように瓦解してしまっていて、また一から作り直しになるのかと、結構重苦しい気分になった。

HTTPエラーが出ていることから、GPMの通信手順がちょっと変わったのかとか、曲のURLを取得するためのURLが変更になったのかと思った。それで、gmusicapiを最新版にしたり、AndroidのGPMアプリの中に新しいURLが書かれていないか調べたが、前者は効果がなく、後者は見当たらなかった(アプリでは使っていないのか、別のページからリダイレクトしているのか)。あとは、参照するDNSサーバを変えてみたり、locale(言語)を変えてみたりしたが、効果はなかった(思い付いて試してみたのだが、まあ、効果がなくて当たり前だ)。

そこで、試しにパスワードを異常なものにしてみたら、別のエラー(HTTP 401だったと思う)が出たので、認証自体は問題なく通っていることが分かった。また、gmusicapiを使ってGPMの曲の検索をしてみたら、正常にできた。要は、本当に、曲のURLを取得する要求(だけ)がハネられている(Forbidden)なのだ。

それで、いつから駄目になったのか(いつまでちゃんと使えていたのか)を調べたら、5/23の6時頃までは正常に再生できていた(それが最後だった)ことが分かった。切り替えがUS時刻の5/22 0時だったとしたら、それは日本時間の5/22 13時前後だから、切り替え後しばらくは使えていたようだ(ここは不思議だ。切り替えはUSの午後から夜だったのかも知れない)。

八方塞がりになったので、検索してみた(Googleだと「自サービスに関する望ましくない情報」としてブロックされている可能性があったので、Bingも使った)のだが、ほとんど出て来ないので、まだ誰も困っていないようだ。それから、gmusicapiが公開されているサーバ、Githubの問題掲示板(Issues)を見てみたら、何となく、それらしいのがあった。スレッド名は以下である:

get_stream_url gives 403 with 'DEVICE_NOT_AUTHORIZED' for Mobileclient.FROM_MAC_ADDRESS #590

去年からの問題ではあるのだが、近頃になって3人が投稿している。そして、(現時点で最後の)fizzybunkという人の投稿を読んで確信した。近頃(移行に関連して?)、曲のURL取得要求を出す時に指定するデバイスIDには(正しい)AndroidデバイスのIDを指定する必要があり、それ以外はエラー403になるようになったようだ。以下に主要な部分を載せる:

I even have tried using a valid android device_id that is registered with the account, seems the only way I am able to get Mobileclient.get_stream_url() to work is being logged into the account on the mobile app with the device of the device_id at the same time. Otherwise it is throwing a 403 error.

今までは、(デフォルトの、)PCのMACアドレスから生成した仮のデバイスIDが使われていたのだが、それでは駄目になったのだ。それで、今使っているスマフォ(AQUOS)のデバイスIDを指定すれば動きそうだとは思ったのだが、とんでもないヘマをしたらAQUOSでも聴けなくなってしまう可能性もあったので、まずは、iPhoneのIDで試したが、駄目だった。

それどころか、iPhoneのGPMのアプリを動かしたあとでGPMのデバイス一覧を調べたら、今日からiPhoneは「PC」扱いになっていた。以前はスマフォ("iOS")だったのに、それとは別に、(ちゃんとしたGPMのアプリを動かしたというのに)PC扱いのデバイスが増えてしまった。GPMに登録できるデバイス数は10個までで年間に4個しか解除できないので、これは結構ひどい。iPhoneの人から文句が出そうだが、まだ誰も騒いでいないようだ。

他に試したことも全然駄目だったので、意を決してAQUOSのデバイスIDで試したら、嘘のようにちゃんと動いた。fizzybunkさんの書き込みは正しかったのだ。

(ほぼ一日を潰して、)とりあえずは復旧した。が、AQUOSのデバイスIDを使うことで、AQUOS側に影響が出ないとも限らないし(ただし、分身の術を使わない限りw、PCのGMBとスマフォで同時に聴くことはないので、競合の問題はない)、今後、更に別の変更がなされて問題が起こりそうで心配だ。前者については、もし問題が起こるようなら、昔使っていたNexus 4にGPMのアプリを入れて、そのIDを使おうと思う。※ 後者はGoogleの腹一つなので、全くどうしようもない。ただ、世の中には多くのGPMアプリが出回っているから大きな変更はできないはずで、今回のようなちょっとしたことであることに期待する。

※AQUOSのデバイスIDを使って曲のURLを取得していると、AQUOSがすぐに(数時間以内)Googleからログアウトしてしまって不便なので、Nexus 4のIDを使うことにした。この問題はGithubの別のスレッドにもあったので予期してはいたが、いろいろな落とし穴が多そうだ・・・ (5/28 6:15)

ただ、本当に駄目になってしまったら、新しい曲の取り方を探すか、別のサービス(例: Spotify)に移ることを考えることにする。だが、仮にSpotifyに移ったって、通信手順などは非公開なので、曲にアクセスするためのプログラムはやっぱり第三者がリバースエンジニアリングで作ったものだから、いつ動かなくなっても不思議はない。だから、サービスを移るのはそれほど本質的でなさそうだ(ただ、SpotifyにはLinuxのアプリがあり、GPMのブラウザよりは使いやすそうなので、GMBで全然聴けなくなってしまった時に移る先としては、意味がある)。

まあ、結局のところ、Google様が心変わりしないように祈りながら音楽を聴く程度しか、できることはなさそうだw

 

PS. それにしても、今回の変更で、日本、いや、世界中で、ものすごい数の人が「あれー!? 再生できない?」って言いそうなものなのに全然そうでないってことは、LinuxでGPMを苦労工夫して聴いている人は、本当に少ないってことのようだ・・・

  •   0
  •   0

面倒なのでずっと放置していたのだが、以前から気になっていたgmusicbrowserの(GMB)問題を一個修正した。きっかけは、今朝か昨夜だったか、シャフル再生中に、ある曲を聴きたくなったのだが、その問題のために躊躇したことだ。

その問題というのは、アルバムなり全曲のシャフルなりのプレイリストを再生中に一時的に別の曲を再生する(「キュー」機能)と、それが終わった後に本来の次の曲に戻らず、一時的に再生した曲がプレイリスト中にあればその次に飛び、なければプレイリストの先頭に戻ってしまうというものだ。

調べたら、元々そういう機能が作りこまれていないようなので(作者の精魂が尽きた?)、機能を追加した。相変わらずPerl言語はチンプンカンプンだし(Perlを作った人は、頭が腐っているか狂っている。どっちにしても、かなりおかしい。どうしてあそこまで分かりにくくしたのか、是非聞いてみたい)、GMBの造りも完全には理解できていないので苦労したが、何とかできた。なかなか疲れたし、昼食もとれなかった。「どうなってんだろう」と、軽い気持ちでエディタを開いたのが運の尽きだったw

それはともかく、終わってから、こういうのはデロリアン(タイムマシン)を改良しながら飛び続けたり、アイスティーに入れる氷を作るために巨大な装置を作ったドクに似ているかもなあと、ちょっと思った。

ちなみに、早速、聴きたかった「俺ら東京さ行ぐだ」を聴いて満足した。一体、どうしてそこまで好きなのか?w

 

PS. 今、「ついでにあの問題も・・・」と思い付いてしまった。午後も駄目っぽいなw

結局手を付けてしまって、案の定、手こずったが、ようやく何とかなった。またGMBの迷路のような造りが少し分かった。が、すぐに忘れそうだw (23:43)

ちなみに、その問題は、アルバムアーティストが設定されていないアルバムのジャケット画像がおかしくなる(別の同名のアルバムのものが表示される)というものだった。なぜか、GPMの曲を再生する時だけ起こるのだが、例えば、"Live in Japan"や"Greatest hits"という名前のアルバムで驚かされた。GMBのバグ以外に、ジャケット画像情報の格納の仕方が結構残念なことに気付いたのだが、さすがに抜本的な改良は難しい。 (5/6 0:12)

PS2. プログラミング言語の選択には、その人の個性とか趣味が現れるようで、職場の僕の居るチームでは、見事に各自が別々の言語を使っている。僕はPHP(awkやsedも)、隣の人はPerlといった具合だ(Cは、全員、必要な時に使う)。それで特に問題が起こらず、うまく行っているのも、おもしろいw おそらく、偉い人が、無理に「統一して効率を上げよう」と思うほど馬鹿でないのが効いているのだろうw (5/6 0:35)

  •   0
  •   0

この連休にはオーディオ(スピーカー・部屋)の音響特性の測定と調整をしようと思っていた。が、今日は下の家族が居るようで、子どもが走り回ったりして雑音が出るので延期した。それで、ちょっと前に思い付いた機能を作ってみた。

僕は、gmusicbrowser(GMB)の出力は標準のPulseAudioでなくJACKに出すようにしている。それに深い意味や大きなメリットがある訳ではないのだが、イコライザや出力はJACKなので、PulseAudioを介さずに直接JACKに入れることで、わずかに音の劣化が減ることを期待しているのだ。

が、それにはちょっとした問題がある。GMBのJACK出力は、曲を再生中以外ではなくなってしまうので、そのままでは再生するたびに接続しなければならず、全く実用的でない。それで、jack-plumbingという自動接続プログラムで接続するようにした。

それで問題なく使えていたのだが、先日、一つだけ問題が見つかった。音源がモノラル(正確にはチャネル数が1)の場合、左のスピーカーからしか音が出ないのだ(JACKでなく、PulseAudioの時は出ていた)。

どういうことかというと、GMBやJACKにはモノラルをステレオに変換(正確には、単一チャネルの音を両チャネルに出す)する機能がないため、モノラルの場合にはGMBからは最初の出力ポート(左チャネル)しか生成されず、jack-plumbingにもチャネル数が1の時は重複接続するような機能はないため、結局、左チャネルの入力ポートにしか接続されないので、左からしか音が出ないのだ。

モノラル(1チャネル)の音源なんてほとんどないから、我慢・無視すればいいだけなのだが、好奇心とか興味でなんとかしたくなった。それで、それにはGMBの改造が要るので、どうせやるなら、ついでにJACKへの自動接続機能も付けて、jack-plumbingを廃止したくなった。やり方は大体分かっていたので、今日は実装と修正をした。

それから、別件だが、少し前に、特定のアプリの音を特定の出力(例: ヘッドフォン)だけに出したくなって、それも実現していた。

以下に、それぞれの実現方法や実装の概要やちょっと苦労した点を書く。

(4/29 13:25追記) さっき、昨日思い付いたこと(下記の「Gstreamerの機能でも接続できるのかも知れない。」)を試したら、意外に苦労はしたものの、概ねうまく行った。おかげで、処理を大幅に簡素化できた。Gstreamerには分からないことが多過ぎて、まだ気に入らないこと(モノラルの処理)があるのだが、とりあえずは良しとする。以下に、その内容を"[4/29]"として追記する。

(4/30 9:42追記) 昨夜(4/29)、上に書いた「気に入らないこと(モノラルの処理)」もできた。Gstreamerの動作が調べたことと違うので、やっぱり苦労した。他に、特定アプリの音に関する接続漏れが見つかったので、修正した。以下に、それらの内容を"[4/30]"として追記する。

GMBからJACKへの自動接続機能

  • GMBで再生時、Gstreamer(再生用ライブラリ)の再生準備をした後(playbinというものの初期化後)、指定したJACKの接続先(入力ポート)に接続する。
    • JACKへの接続にはjack_connectコマンドを使った。もしかしたら、Gstreamerの機能でも接続できるのかも知れない。
    • [4/29] GstreamerのJACKモジュール、jackaudiosinkの自動接続機能でJACKに接続できるようになった。今までできなかったのは、仕様(使い方)を理解していなかったのと、JACKサーバに知らない機能があったためだった。
      • jackaudiosinkのプロパティconnectを"auto"にし、port-patternに接続先を設定(正規表現。例: "jack_mixer:In .+")すれば自動的に接続される。
      • JACKサーバのバージョンによっては、self connect(アプリが自分で接続する機能)が無効化されているために接続できない場合がある。その場合は、jack_controlコマンドでself connectモードを" "(self connect有効)に設定し、サーバを再起動する。
        • 例:  jack_control eps self-connect-mode " "
      • self connectを有効にした時、PulseAudioサーバのバージョンによっては、pacmdでmodule-jack-sinkをロードした時に、自動的にデフォルト出力に接続される場合がある。その場合は、ロード時に自動接続を無効化すればいい。
        • 例: pacmd load-module module-jack-sink connect=false
      • ただし、私はJACKサーバをjackdbusで起動しており、その場合にはmodule-jack-sinkが自動でロードされるようで、上記の指定は無効なので、JACKサーバの起動後に自分で切断している。設定ファイルに書けばいいのだろうが、JACKの開始スクリプトに書いた方が確実と考えた。
  • 曲をスキップさせたり再生ゲインのモードを変更した時などにはplaybinが初期化されるので、再度接続する。
    • [4/29] jackaudiosinkの機能で接続する場合には不要になった。
  • 理由は分からないのだが、playbinの初期化直後は接続に失敗するので、その場合は一定時間後にリトライするようにした。
    • たまたま、GMBには500msの周期処理(UpdateTime)があることに気付いたので、その中にリトライを追加した。
    • [4/29] jackaudiosinkの機能で接続する場合には、自分で接続しないので失敗することもなく、リトライは不要になった。
  • 接続済みの場合に再度接続しようとすると、無駄な処理の繰り返しになって負荷が増えるので、接続しようとする前に接続済みかどうかを調べるようにした。
    • JACKの接続確認にはjack_lspコマンドを使う自作のコマンドを使った。
    • [4/29] jackaudiosinkの機能で接続する場合には、自分で接続しないので不要になった。
  • 接続先ポートはGUIで設定できるようにすべきだが、頻繁に変える訳ではないので、今はプログラムの中に記述している。

GMBでのモノ→ステレオ変換

  • 上記のJACKへの自動接続時に、再生しようとしている曲がモノラル(チャネル数=1)だった場合、最初のチャネル(左)をJACKの右チャネル入力にも重複接続する。
  • [4/29] Gstreamerの信号処理機能を使えば、1チャネルを2チャネルにすることも可能そうだが、方法が分からなかったので、ミキサーにモノラル入力を追加し、モノラルの場合には、出力先をそこにすることにした。
    • 試しにモノラル入力に音を入れてみたら左右両方に出力されることが分かったので、こうした。
  • [4/30] Gstreamerの信号処理機能を使い、1チャネルを2チャネルにするようにした。
    • GMBのイコライザの処理を参考にして、Gstreamerの「パイプライン」というものを追加した。
    • 調べたところでは、"audioconvert ! audio/x-raw,channels=2"(チャネルを2つに増やす)というパイプラインでできるはずなのだが、どうしてもエラーになってしまう。また、"audioconvert mix-matrix='<<(float)1.0, (float)0.0>, <(float)1.0, (float)0.0>>'"(左チャネルの音を右チャネルにも出す)も駄目だった。試行錯誤の結果、"audiochannelmix left-to-right=1 right-to-right=0  ! audioconvert"(左チャネルの音を右チャネルにも出す)は成功したので、これを使うことにした。
  • 曲がステレオ(チャネル数>1)に戻った場合は、右チャネルへの重複接続※を切断し、通常の接続を行う。
    • JACK接続の切断にはjack_disconnectコマンドを使った。
    • [4/29] ※「右チャネルへの重複接続」は「モノラル入力への接続」と読み替える。
    • [4/29] jackaudiosinkの機能で接続する場合には明示的な切断手順がないため、一旦、playbinの状態を初期化してから設定すことにし直した。以下に手順を示す。
      1. playbinをset_state("null")で初期状態にする。
      2. 同様に、Ready状態にする。
      3. 出力先を変更する(port-patternを設定)。
      4. 1と同様に、Paused状態、Playing状態にする。→ 再生が再開する。
    • [4/30] GMBからは常に2チャネルが出力されるようになったので、重複接続やモノラル入力への接続切り替えは不要になった。
  • この時、通常の接続を接続する前に重複接続を切断すると、一瞬音が切れるように聞こえるので、通常の、右から右への接続を行ってから、重複接続(左から右)を切断するようにした。
    • こうすると、一瞬音が混じるはずだが、音が切れるよりはマシなので、こうした。実際には混じって聞こえる感じはしないので、一種の錯覚なのだろう。
    • [4/29] jackaudiosinkの機能で接続する場合には音が途切れないので、不要になった。

特定のアプリの音を特定の出力だけに出す。

  • PulseAudioに、新しい出力先を作る。
    • 新しい出力先を作るには、pacmdコマンドでmodule-jack-sinkをロードした(pactlでもできるはず)。
    • 例: pacmd load-module module-jack-sink channels=2 client_name=PA_alt_jack_sink  sink_name=PA_alt_jack_sink
  • 対象のアプリの音をその新しい出力に出すようにする。
    • アプリの音の出力先は、音量調節アプリ(pavucontrol)で設定すれば、それが記憶されて、以降は自動で出力されるようになるが、プログラムで明示的に接続した方が、後日、設定したことを忘れて困ることがないと思うので、次のようにした。
      • pactl subscribeコマンドでPulseAudioのイベントを監視し、対象のクライアントが接続されたら、pactl move-sink-inputコマンドで、対象のクライアントの出力を新しい出力に接続する。
      • subscribeではクライアントIDしか出力されないので、pactl list sink-inputsコマンドでクライアント名を取得して対象のクライアントかどうかを判定し、同時に得られるクライアントの出力(sink-input)IDをmove-sink-inputに指定する。
    • なお、pactlコマンドもクライアントとして認識されるので、上記処理でpactlを実行するたびに新規クライアントのイベントが生成されて無限ループになってしまうので、pactlコマンドの実行後は新規クライアントのイベントを1個読み捨てるようにした。そのため、タイミングによっては本当の新規クライアントイベントが破棄される可能性があるが、起こる確率が低いので、対処はしていない。

以下にJACKの接続例とミキサーの図を示す。

左図で、左中央の"gmusicbrowser"がGMBの出力で、上記の自動接続機能によって中央のミキサーの入力(jack_mixerのIN L,R)に自動接続される。モノラル時には、上記の変換機能によって、中央図のように、GMBの1つの出力が重複してL,Rチャネルに自動接続されて、両方のスピーカーから音が出るようになる。

[4/29] 改良後のJACKの接続例とミキサーの図を示す。

[4/29] モノラル時には、上段右図のように、GMBの出力がミキサーのモノラル入力(jack_mixerのMono_In)に入り、ミキサーによってL,Rチャネルに出力されるので、両方のスピーカーから音が出るようになる。

[4/30] モノラル時も左右チャネルから音が出るようになったので、ミキサーのモノラル入力への接続は行わなくなった。そのため、モノラル時の接続状態は上の「通常(ステレオ)再生時」と同じである。

特定アプリの音は、PulseAudioから左下のPA_alt_jack_sinkに出力され、ミキサーの入力(jack_mixerのAlt_In L,R)に接続されている(この接続は勝手に切れないので、静的な設定にしている)。ミキサーでは、この音(の中央列: Alt_In)をミュートしている(図のMボタンがミュート)ので、通常の出力(MAIN L,R)からは出ないのでスピーカーからは出ず、特定の出力(Realtek_aout)だけに出力される。ミュートを解除すれば、通常の出力にも流れて、イコライザ(jack_rack)を経由してJACKの標準の出力(system)に出て、スピーカーからも出すこともできる。

[4/30] 特定アプリ以外の音(通常の音)をヘッドフォンに出すことを忘れていたので、接続を追加した(jack_mixer: In Out L/R → Realtek_aout: playback_1/2)。

まあ、オーディオシステムは、あくまでも音楽を聴くのが目的であって、こういう作業はまったく本質ではない、自己満足とか慰みの領域ではあるのだが、自分で構築したシステム(暇さえあれば、自分のアイデアで改良できる)で音楽を聴けるのは、なかなか楽しい。そして、こんなことはWindowsやMacではまず無理(可能ではあるだろうが、手軽にはできない)だろうから、Linux+JACKにして良かったと思う。とはいえ、実は、こここに書いたことだけなら、WindowsやMacではやる必要のない作業なのかも知れないw

が、それにしても、こういう作業をすると、今まで知らなかった・やったことのないことを見つけたり気付いたりすることがあって、技術者としてはおもしろいし、いつか仕事でも使えるかも知れないから、一石三鳥だw まじめな話、Windowsだと、基本機能になければ(その基本機能もコロコロ変わる)、他人が作ったアプリを探して使うしかない(ものすごく時間を掛けて、自分で作れば別)から、おもしろくないしつぶしが効かない。あ、Mac?、あんなものは林檎社がUNIXを腐らせしまっているので、全く論外ですw

 

PS. 今の録音エンジニアなどの方には当たり前なのだろうが、今回のように、「接続を忘れてたから追加する」とかいうのがマウス1個wでできるのは、JACKの大きなメリットのように思う。昔(僕が中高大の頃)は、本物のケーブルで接続しなければならなかったから、端子やケーブルや機器が足りなければ接続できなかったし、端子の形状が違っても駄目だったし、信号レベルやインピーダンスも考慮すべきだったし、並列・直列接続し過ぎると音質が劣化するし、ミキサーを介さずに複数の出力を同じ入力に繋げるのは電気・音質的に良くないことだった。

今はそんなことを全く意識する必要がなく、自由に接続できるので、すごく便利だ。機器にしたって、「ミキサー(あるいはミキサーのチャネル)がない・足りないからから増やそう」と思っても、お金を工面して買いに行くw必要などなく、即座に無料で増やせる。もちろん、PulseAudioやALSAでもそういう変更は可能だが、GUIではできず、設定ファイルを書き換える必要があるから、「ちょっとやってみよう」という気にはならない。

そういうことがあるから、いろいろな手間や欠点があったにも関わらず、JACKに乗り換えようと思ったのかも知れない。 (4/29 10:34)

 

(4/29 5:02 加筆・修正; 13:58 改良した内容を追記; 4/30 10:16 4/29夜の改良・修正点を追記、その他、若干修正; 4/30 10:37 題を変更; 4/30 17:59 若干修正)

  •   0
  •   0

プログラムの「詰め」というのは、とにかく手間と時間が掛かる。大体、中心となる部分を作るのの10倍以上の時間が掛かるのではないだろうか。プログラムを使い物にするにはどうしても必要な作業のだが、退屈だし疲れるので、余り好きではない。それでも、なかなかうまく行かなかったことを打開するような、ちょっとしたアイデアがひらめくことがあって、それが本当にうまく行った時は楽しい。だから、いじりだすとなかなか止められない。仕事と違って、納期も予算もないのが困るw

一方、世の中には、すごいアイデアを思い付いたら、素早く目を引くデモ的な物(ポップ音楽だったら、サビとかデモ版)を作って、有名になったりお金をせしめたりしたら手放して(どこかに売って)、トンズラする(あるいは、別の物を作り出す)、スマートな人が結構居るようだが、無責任で嫌いだ。確かに、いいアイデアを出せるのはすごいと思うが、「最初にちょろっと書くのは誰だって楽しいんだよ!」とか「もう少し面倒見ろよ」と言いたくなる。

という訳で、日々続けているGPMDP (Google Play Music Desktop Player)の改良(もはや改造と言った方がいいだろう)は大分いい感じになってきた。まだ詰め切れていない点や不具合や抜本的な改良案もあるのだが、おおよそ7.5割くらいの出来になって、普通に(これには「変わったことはしてはいけない」という意味もあるw)音楽を聴けるレベルになった。具体的には、GMBだけで聴いている時と使い勝手での違和感がほとんどなくなった。例えば、GMBのリモコンで操作できるので本当に便利だ。実際に、昨夜からは、(実装・修正するだけじゃなくて)GPMの曲を聴くのに使っている。

問題だったユースケース(GPMDPをどういうふうにGMBと統合・機能分担して使うか)も、作業しているうちに大分詰められた。基本的には、GPMDPは曲の検索に使い、GPMDPの再生ボタンを押したら、実際の再生や再生の操作はGMBで行おうと思っている。まだ完全にシームレスになったとは言えないが、なかなかうまく統合できたと思う。

今週はさまざまな改良や修正をしたのだが、主にGPMDPとGMB (gmusicbrowser)との連携動作(例: 曲の追加や変更の同期)に関するものなので、見た目では、先週と比べて目立った違いは余りない。大きな違いは、(実際に曲を再生している)GMBで次の曲に移ったことがGPMDPにも伝わって、曲情報やジャケット画像が更新されることだ。以下にデモ動画を置くので、興味のある方はご覧頂きたい。

画面左半分はGMBの、右半分はGPMDPのウインドウである。GMBで再生中の曲が次に変わると、少ししてから(その次の曲の取得と処理の時間: これは如何ともし難い)GMBにその次の曲が追加され(画面左下、5曲目)、GPMDPの曲情報やジャケット画像(画面右中央)が更新される。

下の動画は、力技でやっているうえに、まだバグがあって、(いつ何が起こるか分からず、)ドキドキする機能なのだが、GMB(画面左下)でリスト中の前の曲をダブルクリックして移動した場合でも、GPMDP(画面右中央)も戻るようになっている(戻るのが遅いのは愛嬌w)。もちろん、取得されている範囲で、先の曲に進むこともできる。

リストの最後(7曲目)に2曲目の曲が追加されるのはバグである。難しい。。。

冷静に考えれば、再生中の曲のGPMDPへの同期なんて、音楽を聴くには不要な機能で、本当に飾りなのだが、「おもしろそうで、不可能でないならやってみたい」という、技術者の無駄なこだわりがあって実装したw

(10/1 6:38 わずかに修正)

 

PS. プレーヤーにGMBを使ったのは正解だった。最初は単純な再生だけを考えていたので、alsaplayerなどの軽いものにしようかと思っていたのだが、機能的に不十分な点があったので、最初からGMBで試した。また、GMBはコマンドラインにPerlのプログラムを指定して実行できるという、夢(麻薬)のような機能があり、それでGMBの内部データにアクセスできるので、かなり役に立っている。もう開発は停まっているようだが、セキュリティホールになるので、公開版に入れ続けるのは難しいかも知れない。

PS2. かなりハードルが高いのだが、将来的には、GPMDPじゃなくて、ブラウザのGPMのページから直接GMBと連携できないかと思っている。GPMDPが必要なのではなく、GPMのページ内の要素にアクセスするために使っているだけなので、ブラウザのアドオンか何かでできるのではないだろうか。

同時に、可能な限り機能を外部に出して、JavaScriptの部分を減らして開発効率を向上させ、GPMのページ構成になるべく依存しないようにもしたい。

とは言え、本当にやりたいのは音楽を聴くことなので、苦労してそこまでやることもないかとも思っている。

(10/1 17:44追記) と書きつつも、(だるくてドライブを止めたため、)暇だったので、ちょっとだけ試してみた。一番最初に気になった、GPMのページ中の再生ボタンを押したらGMBに曲を送れるようにする時に必要な、ボタンのイベントハンドラを変更できるかを試した。

最初は、安直に、ローカルのHTMLでiframeでGPMのトップページを読み込んで、JavaScriptで書き換えればできるだろうと思ったのだが、駄目だった。それから、いくつかのライブラリやAJAXやjQueryまで試したが、駄目だった。

どうも、セキュリティ上の制限のようで、ローカルのファイルからGPMのサイトを呼び出すのが駄目なようだ(おそらく、元がローカルファイルじゃなくても、サイトをまたがるようなことが駄目なのだろう)。それを回避したかったのだが、できなかった。この制限は「同一生成元ポリシー」というものらしく、かなり昔からあるようだ。

それで、一旦、ローカルのHTMLを使うのは諦めて、(GPMDPを改造して使う前提で、)GPMのページ中の再生ボタンのイベントハンドラを変更できるかを試した。JavaScriptには疎いので、それすらも苦労したが、できた。getElementById()で再生ボタンの要素を探して、onclickメンバにハンドラを設定すれば良い。以下のようにすると、GPMの再生ボタンを押すと関数click_func()が呼ばれる。

var elem= document.getElementById("buttonContent");
elem.onclick= click_func;

function click_func() {...}

onclick(onClick)は属性ではないとのことで、setAttribute()で設定しても呼ばれないことに気付かず、苦労した。あと、ボタンの本来のハンドラが依然として有効(どうやっているのか不明)なのがちょっと気に入らないが、まあ、細かいことだ。

(10/2 7:08追記) その後、GPMの再生につながるボタンは山ほどあるので、それらを全部書き換えるのは現実的でないことに気付いた。それらの呼び先を修正するのも困難なので、やっぱり、低レベルなところはGPMDP(実際には、その下位のライブラリ)に依存するのがよさそうだ・・・

  •   0
  •   1

GPMDPの改良。音量の正規化の改良について考えていたら、確か、以下のようなことだったと思うが、GPMDPでなく、外部プレーヤーで再生した方がいいのではないかということになった。

  • GPMDPの構造上避けられない、曲の開始と同時に一時停止しても先頭が一瞬再生されることがある問題は、外部プレーヤーを使わないと解決できない。
  • 再生ゲインの計算のために曲のファイルをキャッシュしているのだから、そのファイルをVLCやgmusicbrowser (GMB)などの外部のプレーヤーで再生することができる。
  • 再生ゲイン対応のプレーヤーなら、音量(ボリューム)の設定やファイルにを再生ゲインを乗算しなくても、再生ゲインタグに設定するだけで、プレーヤーによって反映されるのも良さそう。
  • GPMDPは使い勝手がいいとは言えないし、リモコンを2個にしたり、2つのプレーヤー間の切り替えもしたくないので、操作性を改善する点でもGMBで再生したい。

いずれにしても、昨夜までに構想が練り上がった気がしたし、基本的なところは容易にできそうだったので、今朝、GPMの曲をGPMDPでなく外部プレーヤーで再生できるようにしようとする作業を初めてしまった。そして、確かに、再生できるようにすること自体は簡単だった。14時前には、GMBで再生できるようになった。

GPMの曲をGMBで再生

図の左上はGMBのミニプレーヤーで、右はGPMDPのウインドウである。GPMDPが再生しているように見えるGPMの曲は、実際にはGMBで再生されている。その証拠に、双方で同じ曲・アルバムになっているし、僕はこのアルバムは持っていないし、GPMDPの再生時間は0だが、GPMは0ではない。

が、やっぱり難航し、この時間になっても終わっていない。残っている難しいことは、以下である。

  • 次に再生する曲を途切れないようにGMBに送り続ける(今は、最初の1曲の再生が終わったら停まってしまう)。また、ギャップレス再生のためには、再生中の曲が終わる前に送る必要がある。
  • GMBとGPMDPの連携 (例: GMBの再生が終わったことを検出して、次の曲を再生開始する)
  • GMBとGPMDPの操作の統合 (例:GPMDPで一時停止したら、GMBを一時停止させる)。GMBに統一すればいいのだが、曲の検索など、どうしてもGPMDPでしかできないことがある。まだ、ユースケースの検討が充分でないので、方針が固まっていないせいもある。

でも、今日のところは、目論見どおりGMBで再生できたので、良しとする。

(気が向いたら、詳細を追記します。)

(9/24 21:35追記) どうにかこうにか、次に再生する曲をGMBに送り続けられるようになった。GMBも自分で作ったGPMDPの追加プログラムも、想定外の動きをしたりして、なかなか大変だった(おもしろかったけどw)。

GPMの次の曲を自動でGMBに追加

図の左はGMBのウインドウで、右はGPMDPのウインドウである。GPMDPのプレイリストの、現在再生中の次の曲がGMBに自動的に追加され、連続再生できるようになった。

余談: 上のジャケットの工藤静香、なんかお化けみたいだ。。。

動き出したばかりで、まだまだ荒削りで、さまざまな不具合はあるが、とりあえずは音楽が聴ける状態になったので、一段落だ。それに、(GMBの)リモコンで一時停止などの操作ができるのは、すごく便利だ。

不具合の例:

再生していると、再生中の次の曲以降も勝手にGMBに追加される。まあ、悪いことではないが、想定外の動作なので複雑な心境だ。そして、それに伴ってGPMDPの下部のプレーヤー部分は、まだ再生していない曲になってしまう。しかも、それは上側のキューの再生中(と思っている)曲とも違うのが解せない。

  • 再生中の曲: "Here comes the Sun"
  • GPMDPが再生中(と思っている)曲: "Let it be"(上部)、「二人静」(下部)

細かいことが多いので、先は長そうだw

PS. 今日からか、URLに"?hl=en"を付けても無視するようになったようで、日本語で表示されるようになってしまった。やっぱり、ネットサービスはvolatileだなあ。 ← URLの書き方を間違えていたようだったので、撤回する。 (9/25 20:26)

(9/25 22:56 わずかに修正、余談を追加)

  •   0
  •   1

先週末に、gmusicbrowser (GMB)に、デスクトップウィジェットのアルバムアートを押すと、メインウインドウをアイコンにしたり戻したりする機能を付けた。GMBは、メインウインドウを閉じた時に、タスクトレイに最小化(アイコンにする)できるのだが、タスクトレイアイコンが小さくて押しにくいので、もっと楽に操作したかったのだ。

実装は意外に難航した。普通に最小化したのでなく、タスクトレイに最小化したのを復帰させると、その前より幅が広くなるという問題が解決できなかった。それで、普通に最小化した時にしか復帰できないようにした。

そして、今朝気付いた。実際には、GMBをタスクトレイに最小化しない設定にして(その時は間違って閉じないように注意する必要がある)、普通のアイコン(小さくない)で操作すれば充分だし、その方が操作が一貫している。あるいは、メインウインドウを閉じた時に、タスクトレイでなく普通に最小化するように変更するほうが、ずっと簡単だったような気がする。それに、今気付いたが、この機能では、アルバムアートがない場合は操作できないという欠点がある。

本当の問題は、「タスクトレイアイコンが小さくて押しにくい」というだけのことだったのだから、何か押しやすいものがあれば良かった訳で、それは(既にある)普通のアイコンそのものなので、苦労して新しい機能を作らなくても良かったのだ。

まあ、折角作ったのだから戻さないでおこう。そして、後で、幅が広くなる問題を解決したい。これは、GMBの起動時にも起こることがあるので、何かがおかしいようだ。

そして、物でもソフトでもシステムでも世の中の仕組みでも、安易にいろいろな機能や施策を追加しがちだが、その前に、本当の問題をもっと良く考えた方が、複雑にならず、コストも掛からず、新たな問題も生まれないのだろうと思う。とは言え、安易に見えるけど、実際には、多くの「頭のいい」人たちがいろいろ考えた末におかしくなってしまうことも多々あるので、なかなか難しい。

PS. 世の中の仕組みなどは、実際には、「いろいろ考える」方向が意図的に異なっていて、本当の問題は分かっているけど、根本から解決する気は毛頭なく、「頭のいい」人たちの都合のいいように「解決しようとしている振り」をするように見せて、みんなを欺いていることが多い気がする。

PS2. 本題のGMBだが、昨夜、メインウインドウの閉じるボタンを押した時に、タスクトレイでなくアイコンに最小化することができるように変更した。また、閉じた時の動作設定に、従来の動作(閉じた時にタスクトレイに最小化または終了)に加えて、アイコンに最小化する動作も追加して選択できるようにした。これで、間違って閉じるを押して終了することもないし、ウィジェットでもアイコンでも押せば復帰できるから、操作も統一できた。(1/25 4:47)

設定ウインドウの追加した部分

  •   0
  •   1

GMBでアルバムアートの検索をするプラグインPicture finderは、USのYahoo!でしか動かない。Googleなどを選択しても、結果が何も出ない。

APIが変わったのだろうと思ったが、実際に調べたら、確かにGoogleの検索結果のフォーマットは変わっていた。それで、とりあえず、Googleで検索できるようにした。

新しいフォーマット(構造化されたデータのようだ)に合わせて、fetch_cover.pmを修正した。まだまだPerlは良く分からない(し、分かりたくもない)が、既存のソースから類推してやってみたら、出来た。参考までに、主要な変更点を載せようと思ったのだが、良く考えると、日本のユーザーはとても少ないだろうし、分かる方は既にやっているだろうから、止める(もし欲しい方がいらっしゃいましたら、お知らせ下さい。無保証にて差し上げます)。

日本のYahoo!にも対応したかったが、面倒だし、中で使っているのはGoogleなので、止めた。他のサイト(例: last.fmやAmazon)にも対応したかったが、やっぱり面倒なので、とりあえず、Googleだけで満足することにする。

ただ、そのGoogleにしたって、彼らの心変わりによって、いつか変更が要るようになるのだろうな。でも、出力がHTMLである限りは大丈夫だ。でも、それもそのうち変わる気がする。。。

  •   0
  •   1

 

この週末は、デジカメからの画像取り込みプログラムの改良(同一カメラで1万枚以上への対応)や掃除や散歩やドライブなど、有意義なことをしようと思っていた。

のであるが、実際には、したかったことは何もできなった。

昨日は、疲れのせいかだるかったので、家にこもってEvernoteからDropbox Paperへの移行をした程度だ。移行は、本文はコピー・ペーストでできるのだが、埋め込んだ画像はできないので、それを手作業で復元する(元のファイルがPCに残っているのはそのまま、オリジナルがあるものはリサイズして、Paperに埋め込む。ないものは、EvernoteからダウンロードしてリサイズしてPaperに埋め込む)必要があって、結構時間が掛かった。日記1個に30分くらい掛かった。全部で7本を移行して、日記の残っていた分は終わった。が、あとドライブ関係が44本もあるので、移行プログラムを作りたくなって来た。

今朝は、「今日こそは」と思っていたのだが、思わぬ落とし穴にはまった。発端はgmusicbrowser(GMB)の、次のリストだ。

Something wrong!

何の変哲もない、普通の(と言うには重複が多いがw)ビートルズのアルバムの一覧の一部に見えるが、常々感じていた不満(何が悪いかすぐに気付いた方は、ちょっとした愛好家ですね)を思い出して、余計なことを考え付いてしまった。

同じ年に出たアルバムをちゃんと発売順にできないものだろうか?

説明すると、上の図の上半分の黄色いのは"Magical mystery tour" (1967年11月発売)、下半分のごちゃごちゃしたのは"Sgt. Pepper's lonely hearts club band" (1967年6月発売)である。それぞれ同じ年に出たのではあるが、気に入らないことに、リストには発売の逆順に出ているのだ。タイトルがアルファベットの順だとM→Sなので、上のように並んでしまっているのだ。

まあ、「そんな細かいこと、自分で分かってればいいじゃん」とは思うし、今まで我慢して来たのだが、他の例では、デビューアルバムの前にセカンドアルバムが出ることもあった覚えがある。さすがにそれはどうかと思う。要は、元になったMP3の仕様(ID3)が安直で、現実に対応できていないのだ。それを見なかったことにして使い続けるのは、技術者としてはやっぱり嫌なのだ。

技術的な問題以外にも、仮に上のリストの順で「全曲再生」したら、曲順がおかしくて、それこそ話にならない。

ソートに使われる発売日の情報は音楽ファイルに格納されているのだが、基本的には年だけしか格納できない。せめて月まで入れられればいいのだが、仕様上は無理だ。

それで、いくつかの案を考えた(それだけで数時間掛かった気がする)。

  1. 余り使っていないフィールド(例: Mood(TMOO), Grouping(TIT1), Rating, Discname(TSST)など)を流用する。
  2. GMBにカスタムフィールド(例:リリース日(例: "19670601"), 同じ年の時の順番(例: 1, 2))を追加する。
  3. GMBにAlbum sort order(TSOA)フィールドを実装する。
  4. GMBに他のフィールド(例: Original release time(TDOR))を実装する。
  5. 新しい独自フィールドを実装する(TXXXを使う)。
  6. GMBに2個の追加フィールド(1: リリース日、2: リリース日があればリリース日、なければ年)と、後者のフィールド(2番)を使うソート条件を追加する。

検討したところ、最後の6が残り(正確には、1-5の検討の結果、6のように2段階にしないとうまく行かないことが分かった)、「ちょっと試しに」実装に着手してしまったのが運の尽きである。半分は意外にすんなりできて、下のように、「リリース日または年」のフィールドが表示できたのだが、例のリストのソート順に反映することができなくて、(昼寝もしたけど)気付いたら外は暗くなっていて、とてもがっかりした。

「リリース日または年」が出るようになった (年はアルバム名の右の<<の右にも表示されている。上のエントリのアルバム名とリリース日は、テスト用の架空のもの)

随分時間を掛けてうまく行かない理由を調べたのだが、どこを直せばいいのか、まだ分からない。ソート時に、追加したフィールドをどうしても参照できない。この辺りのプログラムは、他と比べて今ひとつ直感的でなくて分かりにくく、GMBの暗部を見た気がした。まあ、何にでも触れて欲しくないことはあるだろうから、仕方ないね(僕のプログラムにだって、結構ある)。

試行錯誤の結果、何がどうなっているのは分からないが、どうにか、リリース日(なければ年)でアルバムをソートできるようになり、問題の"Magical-"が"Sgt. Pepper's-"の下に出るようになった。

リリース日でアルバムをソートできるようになった。

ところが、一難去ってまた一難。今度は、次のような、ちょっと困った状況に陥ってしまった。

"Baby it's you"はどこに置けば?

一番上の"Baby it's you"は、近年発売されたシングルなのだが、録音は1963年なので、入手した時に年に録音の年を入れた。これをどこに配置すべきなのか、結論が出ない。正しいリリース日にすると、初期の曲なのに最後の方に出るし、録音日にすればそれらしい場所に出るが、リリース日を入れるべき箇所に録音日を入れるのは掟破りな気がする。

規則に従ってリリース日を入れて、最後の方に出すのがまっとうなのだろうが、もっといい規則を決めたいところだ。「録音年」のフィールドを作ると、何かいいことがあるだろうか? (12/13 23:00)

"Baby it's you"の「リリース日」の解決策が見つかった。放送日をリリース日に入れることにした。ただ、シングルとして発売されたこの曲は、アルバム"Live at the BBC"に入っているのとはバージョンが違うので、調べても放送日が良く分からない。ただ、録音日は3日しかなく、そのうちアルバム版と同じ日に収録されたと推測できる。そして、もしかしたら放送されなかったのかも知れない。が、いくら考えても埒が明かないので、アルバム版の放送日とした。(12/15 5:09)

  •   0
  •   1

以前からやりたかったのだが、gmusicbrowser(GMB)のレイアウトと使い勝手を改良した。Perlで書かれたGMBのプログラムや、レイアウト設定ファイルを、見様見真似で試行錯誤して、なんとかした。主な変更点は以下のとおりである。

  • メインウインドウ (ベース= "Lists, Library & Context")
    • 現在の再生ゲインのモードを、"--"(off), "T"(トラック), "A"(アルバム)のように表示できるようにした。アイコンでも表示可能なのだが、適当な画像ファイルがなかったので、とりあえず文字にした。この部品は新たに作った。
    • 上記再生ゲインの表示を押すと、off → トラック→ アルバム → offのように順にモードが切り替わるようにした。
    • タイトルなどの文字やアルバムアートを大きくし、パーツの配置を改良した。
    • ボリュームを水平のスライダーにし、音量の値も表示するようにした。ボリュームは実際にはほとんど操作しないのだが、現在の音量が一目で分かるのはいい。
  • デスクトップウィジェット (ベース= "screenlet")
    • 再生位置のバーの右に、再生順序(シャフルなど)、フィルタ(自動プレイリスト)、キューの状態(次の曲の指定の有無、再生中の曲が終わったら停まるなど)、再生ゲインのモードを追加した。これは、メインウインドウに表示されているものと同じである。
    • 再生位置のバーの中に再生位置(時間)を表示するようにした。
    • タイトルなどの文字を大きくし、発表年も表示するようにした。
    • 文字領域の背景を不透明にした。

まだ収まりが悪いところや色がイマイチなところがあって、いろいろ直したいのだが、かなり僕の理想に近くなった。特に、デスクトップウィジェット(MusicBeeのコンパクト/ミニプレーヤーに相当)で再生ゲインのモードが表示・切り替えできるのは、MusicBeeではできなかった(要望しても対応してもらえなかった)ことで、長年の悲願だったから、結構嬉しい。

残念なのは、以下のことはすぐにはできないことだ。どれも、GMBの構造上、設定や小さい変更での対応は困難なようだ。

  • メインウインドウの曲一覧などのフォントが(設定では)変えられない。見難くはないから、とりあえずは問題ないのだが、中国(台湾?)系のフォントのようで、例えば、「福」の偏が「示」になったりしているのがちょっと気になる。
  • (特にデスクトップウィジェットで、)タイトルなどが長い場合に、複数行での表示ができない。

それでも、こうやってプログラムや設定を変えることでかなりのカスタマイズができるところは、完全にMusicBeeを超えている。特に、レイアウトの設定ファイルは独自の言語のようになっているのだが、もしそうでなかったら、こんなに自由なカスタマイズはできなかっただろう。その点は(最初は訳が分からなくて戸惑ったものの)感心している。それで、偶然にせよ、なかなかすごい「原石」を見つけたものだと自画自賛している。

あと、PerlでGUI(GTK)のプログラムが作れるのは、PHPにはできないことなので、すごく羨ましい。それにしても、どうしてPHPではできないのだろうか?

試行錯誤して、なんとか、デスクトップウィジェットでタイトルなどが長い場合に改行できるようにした。GMBがテキスト表示に使っている、GTKのLabelウィジェットのワードラップの機能を使うようにした。これには、設定だけでなくGMB本体の改造が必要だった。

アルバム画像下の曲情報は、以下のようにデスクトップウィジェットのレイアウトファイル(desktop.layout)に記述して表示している。

HBtrk_info= 8Text(font= 'Noto Sans CJK JP Regular 10',
color=black, opacity=1,

width-chars=32, wrap=1, wrap-mode=word,
markup="$title
<span size='xx-small'>\n\n</span>
$artist<span size='xx-small'>\n\n</span>
$album ($year)")

下線部で最大幅とワードラップを指定しているが、これをサポートする機能をGMBに追加した。GTKを良く理解せずに作っているので、最大幅はピクセル数で指定したいができておらず(そのため、文字数によって、右側に微妙に空白ができたり、ウインドウの幅が広がったりする)、文字の大きさや空行(無理に作っている)の高さなど、いろいろ改良・調整したい点はあるが、とりあえず、やりたいことができたので、うれしい。(11/9 23:53)

空行の高さは、タイトルなどの各項目を別のLabelにして、パディングを指定して縦に並べることで解決した。ただ、最後の要素(アルバム)にはパディングを指定しなくても隙間が空くのが謎だ。

また、右側の微妙な空白は、width-charsを指定しなければできないことが分かった。ただ、その場合、max-widthやmaxwidthを指定してもウインドウの幅が広がることがあるのが謎だ。(11/10 6:22)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-10_06-03-57

行間を改良

HBtitle= 8Text0(font= 'Noto Sans CJK JP Regular 12', color=black, opacity=1, \
width-chars=32, wrap=1, wrap-mode=word, \
markup="$title")
:
VBmain = Cover(yalign=0, forceratio=1,hover_delay=1, \
hover_layout_pos=.5w x w,hover_layout=play_controls) \
8HBtb_ind HBtitle 4HBartist HBalbum

思わぬ欠点が見つかった。ウインドウのサイズが広がった後に、行数が少なくなると、下の方が空いて間抜けになってしまう。ちょっと調べたところでは、gtk_widget_set_redraw_on_allocate()で直りそうな感じだが、さてどうだろう? (11/10 19:46)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-10_19-43-56

間抜けな状態

更に試行錯誤したのだが、なかなか広がったウインドウは小さくならない。そこで、次善の策として、アルバムアートと曲情報の部分で余白を吸収するようにしてみたら、今までよりはマシになった。また、どういう訳か、アルバムアートが段々大きくなることがあったので、サイズを厳密に指定した。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-10_22-02-22

余白が目立たないようにした。

HBcover= Cover(minsize=250, maxsize=250, forceratio=1, \
hover_delay=1,hover_layout_pos=.5w x w,\
hover_layout=play_controls)
:
VBmain = _HBcover 8HBtb_ind _VBtrk_info

こういう試行錯誤って、GMBやGTKやPerlをもっとちゃんと勉強すれば効率良くできるのだろうが、趣味なのでそこまでの気力は出ない(もし、PHPでGTKが使えるのなら、俄然やる気が出るのだがw)。逆に、いろいろつまずいたり、回り道・寄り道しながら自分の希望を叶えていくのがおもしろいと思う。そして、仕事じゃないから最短経路をとる必要はなく、こういう遊びがかえって仕事のヒントになることもあると思う。(11/10 22:17)

(Labelウィジェットのワードラップ機能が今ひとつのせいなのか、)改行時に文字列右側にできる無駄な空白が嫌なので、ちょっと頑張ってTextViewウィジェットを使えるようにして、解決した。

ただし、どういう訳かTextViewの背景色を設定することが難しいようなので、とりあえず全体を白にした。それでも、どういう訳か微妙に色が違っていた(TextViewがわずかに黒くなっていた)ので、それに全体を合わせた。が、それでもまだ合わないようだ。あと、上下に広がったウインドウが狭まらないのは相変わらずである。そこら辺は今後の課題としても、かなり良くなったのは確かだ。

あと、TextViewにしたことで、曲名などをマウスで選択してコピーすることができるようになった。これもMusicBeeで叶えてもらえなかった(「ホットキーでできるからいいでしょ」と言われた)ことなので、感慨深いものがある。

ただし、曲名とアーティストとアルバム名をそれぞれ別の要素にしているので、コピーも別々にしかできない。とある理由(TextViewの中では、フォントサイズを容易に変更できない)で別々にしたのだが、できれば何とかしたい。でもまあ、選択・コピーできないよりはずっといいだろう。

ちなみに、デスクトップウィジェットのレイアウトファイル(desktop.layout)でのTextViewの指定は、以下のようになる(タイトル表示の部分)。

HBtitle= 5TextView0(font= 'Noto Sans CJK JP Regular 12', \
color=black, bgcolor=lightgray, minwidth=200, maxwidth=250, \
wrap-mode=word, markup='%t')

(11/11 21:18)

ちょっと苦労したが、曲名とアーティストとアルバム名を同じTextViewに入れられた。insert_with_tags()を使い、TextViewの中でフォントサイズを指定するようにした。これをTextViewのサブクラス"SongInfoView"と名付け、以下のような指定で曲情報が出るようにした(フォント指定は未実装)。

HBsong_info2= 5SongInfoView(font= 'Noto Sans CJK JP Regular', \
color=black, bgcolor=lightgray, minwidth=200, maxwidth=250, \
wrap-mode=word)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-11_23-15-12

全部の曲情報を一度で選択できるようにした。

まったく"The long and winding road"だが、いろいろアイデアが出て楽しい。(11/11 23:22)

選択はできるが、Ctrl-Cではコピーできないというオチがあった。右クリックでメニューを出して"Copy"を選択すれば可能なので、キーを登録すればいいのだろう。やっぱり長い道のりだw (11/11 23:51)

ショートカット(あるはアクセラレーション)は有効にならず、広がったウインドウは、どうしても縮まない。前者は、どうもOSレベルの設定が関係しているようだ。もちろん個人の設定ファイルもあるようだし、「デスクトップ環境」なのだから、その方が筋がとおっているのだが、アプリだけで手軽に対処するのが難しいし、ログインし直さないと試せないので面倒だ。そして、後者は深い謎だ。八方手を尽くしたが、どうにもならなかった。GTKをちゃんと勉強しないと駄目かも知れない。

そして、昨夜からの収穫は、(外見上は)本当に微妙な修正だ。タイトルなどを一度にコピーできるようにした時に、行間が数ピクセル広がってしまったのを直した。なんか、大昔、LaTeX(って知ってる方はいますか?)で資料を書いて、微妙なところを何度も直して(印刷して紙を無駄にして)、最後にできた紙(の内容でなく外見)を見て悦に入っていた頃の雰囲気を感じているのだが、なんとも複雑な気分だ。まあ、僕は賛同していないが、神は細部に宿るのかも知れないし、趣味だからいいよねw

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-12_17-39-53

行間を調整

そして、何度もくどいのだが、(謎はあるものの)こうやって自分でちょっとプログラムを書いて自分好みに自由に改造できるのは、ありがたいし楽しい。ただ音楽を聴けるだけじゃなくて、その道具に手が入れられるようになったのは、常に歯痒かったMusicBee/Windows時代に比べるとすごい進歩だし、結構感激している(酔ってるせいもあるが)。これは、GMBの基本思想が良く、オープンソースにしてくれて、今の実装が悪くない(Perl自体が読みにくく、コメントは少ないけど、まあ酷くはない)ことに加えて、スクリプト言語(Perl)/Linuxベースであることもある(やっぱり、腐り切った窓でC#なんて使ってられない)。そして、こういう機会を与えてくれた、gmusicbrowserの作者のQuentin Sculoには本当に感謝している。いつか、改良・変更部分を整理して提出したいと思っている。(11/12 18:28)

ここからはいつものディスになるのだが、僕がMusicBeeを止め(られ)た原因は、作者の(勝手な)方針について行けなかったということだ。作者本人が個人で作っているのだから、何をしたって自由なんだろうけど、ただ、他人の意見を余り聞かず、ソース公開せずに他人の力をほとんど借りようとせず、Windowsにべったり固執し、全く必要がなくメリットが感じられないことを「改良」して、バージョンアップしたと言って悦に入っているのは、MicrosoftやAppleのように筋が悪いし、もし彼がソフト技術者だったら、「終わっている」と思う(一言で言えば、ガキだ)。途中まではいい方向に進んでいたし、機能的には他を寄せ付けないのに、とても残念である。(11/12 18:42)

試行錯誤の結果、デスクトップウィジェットのサイズ(特に高さ)が行数に応じて縮まるようになった。ごく当たり前に、ウィジェットのresize()メソッドに小さ目のサイズを指定すれば縮んだ。以前にも試したのだが、ウィジェットのnewの中から呼んだのが失敗して、それでresizeは使えないと思い込んでいたのだ。どうも、newが終わらないとうまく動かないメソッドがあるようだ。もちろん、newの中でresizeなんてするのは良くないのだが、GTKやGMBでウィジェットのメソッドの呼び出し順序が良く分かっていないので、newの時に描画する文字列を設定することになって、結果的にresizeもしている。(11/14 22:31)

その後、ワードラップでの改行の高さが若干高く(広く)て下の要素との区切りと見分けが付きにくい場合があったので、微妙に改良した。更に、プレイリストやアルバム中の何曲目を再生しているかを、"3/10"のように表示できるようにした。(11/18 21:52)

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88_2016-11-18_21-48-21

微妙な改良

 

※まずいないとは思いますが、もし、日本語が読めてGMBを使っていて、「ここの投稿を参考に改造したいけど、詳細が書いてなくて今ひとつ分からない」という方がいらっしゃっいましたら、可能な範囲でお教えしますので、お知らせ下さい。でも、プログラミングのスキルがあることが前提です(申し訳ないですが、「コピペでなんとかしたい」という方は駄目です)。そして、そういう方は、自分でできてしまうような気がします。(11/10 19:31)

(11/11 10:14 わずかに修正, 11/12 追記)

  •   0
  •   2