現状の進捗について
「ympdデーモンのmpd通信タイミング調整」を先週末にちょっと集中的に行っていました。
現状はデバッグメッセージてんこ盛りですがwebブラウザからの操作電文に基づいて応答を返すところまでは進みました。
解析の結果として、既存のympd内部では以下の処理が行われていることがわかりました。
-
メインループでmongoose(組込webサーバ)のポーリング制御(スリープ解除後にwebサーバで受信したhttpプロトコルのリクエスト処理を行い、またスリープに移行)を行っています。
ポーリング間隔は標準では200ミリ秒(これはympd.serviceのパラメータで指定された値)です。 -
webブラウザからwebsocketプロトコル経由で送信される電文はmongooseのコールバック関数より呼ばれ、
処理後にwebsocketプロトコルで返信します。 -
mpdとの通信状態はメインループで1秒以上の時間差があった場合のみ確認します。
このときに通信が切れていた場合は再接続、致命的なエラーが発生していた場合は接続しません。
また、確認の際にmpdに接続状態ならば、mpdの状態を接続中の全クライアント(webブラウザ)に通知します。
ympdサーバがmpdとの接続を維持するためには、以下のどちらかで運用する必要があります。
-
常にタイムアウト時間より短い間隔で通信を継続する
(現状のympdがこのやり方。約1秒単位でステータスを問い合わせする) -
mpdに対してidle命令を送って通信状態はサーバに維持させ、必要に応じてクライアントからidle解除の命令を送って電文処理を行い、処理終了後にまたidle命令でidle状態に戻す。
後者の場合、idle解除の命令のキックは以下の3つになります。
-
webブラウザからwebcoketでmpd関連の命令が届いた場合
実はidle状態の場合、mpdに対して「idle解除」以外の電文を送信しても処理はされません。
このため、webブラウザから受信したmpd関連の電文は一度FIFOバッファに保存し、バッファにデータがあることを検知した段階でidle解除を行って電文を処理させる必要がありました。 -
ympdサーバから各端末のwebブラウザにステータスを送る場合
webブラウザ側でステータスを受信しないと、再生ボタンなどは機能しません。
また、ステータスにはカウンターなどの情報があるため、再生中にプログレスバーが動作しません -
mpdから何らかのステータス変更を検知した場合
idle状態にした際にフラグを立てることにより、そのフラグ条件に一致した際には通知するようになっています。
現状のフラグ条件では「データベースの更新」・「キューの状態変更」・「再生状況の変更」・「リピート・コンシューム・ランダムなどのオプションの状態変更」などが受信できるようです。
このときの通知があるかどうかはpoll関数で受けるため、ポーリングをループ処理する必要があります。
ということはidleを使う場合はmpd処理部分を別スレッド化してループを回す必要があるということでした。
とりあえず手元のバージョンではmpd処理部分を50ミリ秒のpoll関数でループさせ、カウントが20回になった際はステータスをwebブラウザに送るように仕立てました。
ただし、カウンタについては前より値のバラツキ(2秒単位で更新する確立が高くなった)があること、
webブラウザからの電文を一旦FIFOバッファ格納するためにブラウザ操作→表示完了までのラグ(僅かな遅延)が見られるのが気になります。
カウンタのバラツキについては「ステータスを送るタイミングを従来の1秒間隔から0.5秒程度に増やす」か、「カウンタ値をミリ秒単位で取得して誤差を吸収させる」方法のどちらかで対応してみようと思います。
表示のラグについてはもう少し何とかしたいと思います。
最終的には今回開発したidle対応版で「ympd〜mpd間の通信の安定性」と「ympdの低負荷化により音質に優位性が確認出来た」かを皆さんにもお試しいただきたいと思いますので、もう少しお待ちくださいませ。