xtne6f / EDCB

BonDriver based multifunctional EPG software
Other
162 stars 37 forks source link

EpgTimer(NW)の長期番組表対応など #32

Closed xtne6f closed 5 years ago

xtne6f commented 5 years ago

bcb753b2a7d72b265b7db4ff5f261e12edb59b2a でWebUI側対応は完了しているが、EpgTimer側はCtrlCmdインタフェース( 3805668/EpgTimerSrvMain.cpp#L1597 )の拡張が必要。 インタフェースの拡張は難しくないが、現状EpgTimerの番組表は「全番組情報をSrvからDLしてキャッシュ」→「一枚ないし複数枚の画面上にすべて描画」のように行われるため、長期の番組情報には対応できない。恐らく作業量多めなのでとりあえず先送りしてIssueを立てた。 EpgTimerで使いやすいインタフェースならよいのでEpgTimerの改変と並行して適当に仕様を考えるが、例えばLuaインタフェースの GetEventMinMaxTimeArchiveEnumEventInfoArchive のように時間範囲を扱えるものがたぶん妥当。ほかCtrlCmdインタフェース全般含めてなにかあれば気軽に提案してください。

tkntrec commented 5 years ago

更新お疲れ様です。 インタフェースはSendEnumPg系に時間範囲を追加するだけで良さそうですね。 表示は、任意期間表示+1週間(or期間)ジャンプボタン等を追加すればいいんでしょうか。 ただ「番組表へジャンプ」との整合など問題はありそうです。 (実は既存のカスタムボタンにWebUI設定しておくだけで結構事足りてしまったり‥なんて)

xtne6f commented 5 years ago

改変コストが低そうなのは、デフォルト表示を前週まで(今日だと2/3(日)~)にして今までどおり描画、さらに番組表上部のタイムラインに前後週移動するジャンプボタンつけて一週間単位で描画、でしょうか。過去番組の保存が一週間単位なので効率も良です。 あと過去番組全部覚えているわけで、録画済み一覧も要工夫かも。 インタフェースはSendEnumPg系になりますね。現SendEnumPgArcInfo、SendEnumPgArcAllを撤去して(過去表示は改変版だけなので互換をとる意味がない)サービス範囲と時間範囲の引数を追加しようと思います。 なんにしろあと二週間ほど番組情報貯めないと雰囲気つかめない気がするので、そちらでも貯めておいてもらえると幸いです。

tkntrec commented 5 years ago

インタフェースを統一するなら、SearchPgあたりも同様にした方がいいかもしれませんね。検索による番組表もありますし。(番組表からの視点で言えば、SendPg系がフィルタとしてEpgSearchKeyInfoをパラメータに取る方が分かりやすい気もしますが)

xtne6f commented 5 years ago

暫定でSearchPgの拡張も含めて更新いれてみました(misc,misc-uiブランチ)。ここからEpgTimerの改変を加えてみて不足がないか確かめる感じになります。

tkntrec commented 5 years ago

動作確認出来ました。

サービス指定はEpgTimer的には64bitキーの方が扱い易いですが、これは他のクライアントもあるのでしょうがないでしょうか。

あと、番組表の視点からすると、時間範囲に放映されている番組を返す(スタート側は番組の終了で判定する)モードとか欲しいところですが、番組データの処理メソッドとしての性格を考えると、やはり表示側で対処(余分に取得して細工)するべきですかね。

xtne6f commented 5 years ago

16bit×3のキーにするとワイルドカード(今は-1)をどう表現しよう?という問題があって、空いている上位16bitをフラグに使う手もありますが幾分まどろっこしい感があります。戻り値の番組情報のスケールを考えるとがんばって詰めこむ場面でもないので、各値にInt64使うことにしました。

時間範囲が開始時間基準なのはほとんど実装の都合です。番組長さも見ると条件判定が複雑になったり二分探索の最適化が素直に書けなくなったりしてきます。検索画面の時間絞り込みなどが開始時間基準なのと合わせたってのも(ちょっとだけ)あります。

tkntrec commented 5 years ago

ちょっと思ったのですが、キーリストは可変長ですし、未指定→全サービス扱いとするのはマズイのでしょうか? 番組表のサービスリスト(CustomEpgTabInfo.ViewServiceList)に時間範囲を追加するだけでkeyAndRangeが完成するので楽ちんな気がします。(Srv側も直接比較するだけでOK)

xtne6f commented 5 years ago

割り切ればそれも悪くないのですが、そうするとONID,TSIDを固定してServiceIDを任意にする、あるいはONIDを固定して他を任意にする、が表現できないです。 特に過去情報では呼び出し側が事前に把握できないサービス(消滅した等)も存在する場合があって、特定ネットワークを全部列挙するなどがやりづらい気がします。

xtne6f commented 5 years ago

と書いていて「じゃあ地上波列挙するときどうすんの」ってのがよぎったので、むしろワイルドカードよりもう少しリッチな仕様にしなきゃいけないかも…

xtne6f commented 5 years ago

EnumPg系のパラメータ(paramとします)の解釈を以下のように変更します。 param[0] = 1番目のサービス指定のORマスク
param[1] = 1番目のサービス指定の64bitキー param[2] = 2番目のサービス指定のORマスク ...

マッチは以下のように判定します。 if ({検索対象の64bitキー} BitwiseOr param[0] == param[1]) {...

例えば通常のサービス指定はORマスクを0にします。 ワイルドカードはORマスクとキー両方のビットを立てて(0xFFFF)表現します。

tkntrec commented 5 years ago

何だか結構大がかりな変更になってしまったようですみません。 結局リッチな仕様にしたのですね。 自分で使う機会があるか分かりませんが、地上波は~0x‥7800‥でいいのかな?

xtne6f commented 5 years ago

内部的にはむしろシンプルになりました。 地上は0x7880~0x7FE8が定説(省令かなんかだったような)ですね。バイナリで 01111000 10000000 ~ 01111111 11101000 なので、xをマスクとして

01111000 1xxxxxxx
01111001 xxxxxxxx
0111101x xxxxxxxx
0111110x xxxxxxxx
01111110 xxxxxxxx
01111111 0xxxxxxx
01111111 10xxxxxx
01111111 110xxxxx
01111111 11100xxx
01111111 11101000

あたりのパターンでいけると思います(なんかわかりづらくてすいません…)。 任意の比較判定はだいたいこのくらい+αの数のサービス指定で表現できるはず。

xtne6f commented 5 years ago

こちらでは必要なものはひととおり実装できた感じです。安定をみて数日内にwork-plus-sに移します。

tkntrec commented 5 years ago

お疲れです。 仕方のないことですが、最初の番組表の読み込みは結構時間かかりますね。 ちょっと確認なのですが、 ・SendSearchPgMinimum()は、現状EpgTimerNW的には効果無いですが、将来はSrv側で対応予定なのでしょうか。(あとstart_timeくらいは欲しいかも) ・SpecialViewServicesの導入は、予想とちょっと違っていましたが、確かにこれで用は足りていますね。(せっかくのワイルドカード仕様が‥というか結局TSIDは識別に使えるのか問題?)  あとCreate64Keyとかに放り込むとゴミが出るので上位4bitでの表現の方が扱いやすいのですが、どうでしょうか?

xtne6f commented 5 years ago

SendSearchPgMinimum()は今回の件とは独立で、目的はメモリ削減です。検索番組表ごとに番組情報オブジェクトを構築するのは無駄に感じたためです※。通信面でボトルネックかどうかは確信もてないので今のところコマンド追加の予定なしです(プルリク歓迎)。

CtrlCmdは先んじてある程度汎用にしたいので、実際にいま利用するかどうかはまた別件です。 ViewServiceListは内部の設定値なので、どう解釈するかはEpgTimerに閉じた話になります。そのうえで、下位48bitを0固定もアリかと思うんですが(例えばViewServiceBS=0x2000000000000に)、 0x1000000000000以上はもともと利用されていないので互換に支障はなく、0固定に利点を感じませんでした。

※.NETはイミュータブル文字列なので、同値はもっと積極的にインターンされると思っていましたが、違いました。例えば以下のコードはフルに400MB消費します(かなり意外だった)。

const int N = 200;
var list = new List<string>(N);
var foo1mb = string.Concat(Enumerable.Repeat("foo", 1024 * 1024 / 2 / 3));
for (int i = 0; i < N; i++) list.Add(foo1mb + foo1mb);
Console.ReadKey();
tkntrec commented 5 years ago

了解です。 自分はEpgTimerNWメインで使うので、通信(回数)を減らしたい意識が強いです。 特にオリジナルの頃は所要時間が長くて不便な思いをしたから、というのが大きいようです。 (今はかなりおかげさまで改善されていて、コマンドあたり0.2秒くらいです)

メモリの件は、そのコード確かに、回収待ちとかではなく実際に400MB消費してますね。 ただ、EpgTimerでは番組データそのものより、描画データが非常に大きいですよね。 自分は描画後textDrawLists捨てちゃってますが、これだけでも1枚あたり10~数十MB、 あとは、Windows側で保持している描画データがその2倍くらいでしょうか。

textDrawLists再利用すれば減る‥かどうか私には分かりませんが、難易度は高そうですね。 同一イベントで、幅と高さが同じなら複数番組表で使い回せる?

tkntrec commented 5 years ago

ひとつご報告ですが、番組表編集画面(EpgDataViewSetting)で 未選択でサービス削除ボタン使うとエラーになります。 他は大丈夫ですが、そこだけ未選択チェックが抜けているようです。

xtne6f commented 5 years ago

ありがとう、修正しました。 こちらはGlyphRunが結局DrawGlyphRun()の先で生き続ける気がしてtextDrawListは残してます(でも実際どうなのかは不明)。タブごとに描画タイミングが違うので使いまわしはしんどいかも。

xtne6f commented 5 years ago

ひと通り対応できたので区切ります(検索まわりのUIがまだ弱いですが…)。

// @tkntrec 氏いつもありがとうございます。