記録

記録

ElectronでSubsonicクライアント作った話

f:id:hi_yamamoto:20160205132054p:plain

以前このブログでも書いたSubsonicという音楽ストリーミングサーバー用のクライアントソフト Sonictron を作った。 オリジナルのWeb版が音量調整とかいまいちやりづらくデスクトップアプリ欲しいとなったので、せっかくだからElectronで作ってみようと思い立った。

アプリの特徴

Web版とそれほど違いはないが、

  • グローバルショートカットで再生/停止、音量調整操作
  • web版では何故か無かった1曲リピート機能

Web版での最大の不満点だった音量調整部分が改善できたのでだいぶ満足してる。 SubsonicはかなりAPIが充実して色々出来そうなのでまだまだ機能の追加は出来そう。
今後はクロスフェード再生やNotificationなどを入れていく予定。

ソースコード&成果物

GitHub - hiyamamo/sonictron: subsonic client with electron
releaseページに各プラットフォーム毎のzipが置いてあるので、Subsonic自体使っている人があまりいなさそうだけど、もしよければ使ってみてください。
ちなみにSubsonicにはDemoサーバーが用意されており、サーバーを立ててない人でも使ってみることが出来る。SonictronではDemoサーバーに接続する設定も用意してあるので是非。

技術的選択

transpilerはbabelでタスクランナーはgulp。この辺りはかなり情報多くて助かった。 gulpfileはこちらの記事を参考にさせてもらいました。 基本はES2015の構文で書いてbabelでコンパイルした。

ViewはReact。
見た目的に3つのPane+Headerのプレイヤー部分とわけていたのでそれぞれRoot Componentでstate管理して、子Componentにprops流すという設計。stateはほぼStoreから受け取っているのでReact側でstateはほとんど変更しなかった。

Fluxフレームワークは最初はfacebook/flux使っていたが色々と複雑になるにつれてカオスになってきたので、azu/material-fluxを採用した。 正直どれが良いかよくわかんなかったので、参考にしたアプリで採用されていたものをそのまま採用した。
context, action, storeそれぞれでクラスを継承して使う形でシンプルでわかりやすかった。fluxのcontextをviewにpropsとして渡すのがめんどくさかったので<Provider>というComponentを作り、Reactのcontextからstoreやactionのインスタンスを取得出来るようにした。
最近のデファクトReduxになりつつあるようなので次はこっちも使ってみたい。

CSSフレームワークとしてphotonkitを採用した。photonkitはMacアプリ風の見た目に簡単に出来るもので、React用としてreact-photonkitといモジュールがあったのでそれを使った。
多少バグがあったのでreact-photonkitのほうにプルリク送ったが、開発止まってるみたいで未だマージされず。
フレームワークだけだと色々厳しいので自分でもかなりCSS書いたが案の定カオスになってしまったのでうまく設計出来るようになりたい。

大枠としては以上で、後は曲の再生にWeb Audio API使ってて、設定の保存とかはlocalStorageをつかってる。

Electronの話

ElectronはMain ProcessとRenderer Processで分かれており、プロセス間通信の手段としてIPCモジュールが用意されている。
今回音源の再生にWeb Audio APIを使っているので、再生状況等の状態は全部Rendererプロセス側で管理して、状態が変更される度にIPCでMainプロセスにメッセージを送って、Mainプロセス側で更に受け取った状態を管理するという形になっていて、結構厳しかった。
今回のアプリは大した規模ではなかったのでなんとかなったが規模が大きくなった場合すぐ破綻しそうなので、何かしら状態を共有出来るようないい感じの設計が必要だと感じた。
あとテストあんまり書いてないのでちゃんと書いていきたい。

さいごに

作ってるうちにElectronやReactについての知見が色々溜まった気がしたが、今となっては大部分を忘れたので思い出したらまた書く。(知見だと思ったらすぐ書くことが大事という学びがあった)

とりあえず最低限の機能が出来たので公開したが今後もどんどん機能追加等していきたい。
IssueやPull Requestお待ちしております。