2024年5月24日金曜日

TvRockの予約録画時のスリープからの復帰方法について

 いまさらTvRockかとお呆れのかたもございましょうが、お許しください。

(成果物だけほしい方向け: `tvrock.schから補正'版はこちら、`TvRock単体で動作`版はこちらです)

表題の件ですが、タスクスケジューラとそれ以外があります。そして、今回はそれ以外のほうのお話をさせていただきます。

その前に、まず小ネタから。

0.9t8ではTvRockDTV.x64.dllがないためにTvTestとかTSTaskの64bit版が動かないとお嘆きの方に。実は0.9u2で生成させたTvRockDTV.x64.dllをそのまま保持しておいて0.9t8に戻せばTvTestやTSTaskの64bit版が使えます。

他は64bit化したものの、TvRockだけはどうにも余人を以て代え難く、しかし0.9u2はTvRockがOSのスリープを(powercfg /requestsoverrideしてしまわない限り)阻止し続けるので使いたくないという方向けのニッチすぎる情報でした。

さて、TvRockで録画を予約するときに「復帰処理をタスクスケジューラで行う」にチェックボックスを入れていなくてもきちんとスリープから復帰して録画が開始されますが、powercfg /waketimersを行ってもスリープ状態の解除タイマーはありません。

以前から気になっていたのですが、今回こんなネタを知ったのでスリープからの復帰時間の補正をするツールを書くついでにだいたい見当はつくけど確かめてみようということでghidraを用いてバイナリを紐解いてみました。

思った通りWM_POWERBROADCASTを受けたときにwParamがPBT_APMSUSPENDのとき、つまりスリープに入る直前にSetWaitableTimerして、レジュームした直後(PBT_APMRESUMEAUTOMATIC)にCancelしてました。

そのため、普段はpowercfg /waketimersを行っても見えません。普段は登録されていないのですから当たり前です。

ここで、先のACPI Wake Alarmによる遅延のために何とかしたいとする場合は、予約前の準備時間以上スリープしないようにシステムを設定しておくのが無難でしょう。

あえてプログラムを書こうという場合、いくつかアプローチがありますが、私はtvrockと同様にWM_POWERBROADCASTでPBT_APMSUSPENDを受けたときにtvrock.schから現在時刻からの直近で4時間以上未来の録画予約があれば予想遅延時間を引いた時刻でwaitable timerを設定しています。この方法だとPBT_APMSUSPENDをもらってから2秒以内にすべてを終わらせる必要があるのでCで書きました

でもこれは物好きだからやっているだけで、普段からtvrock.schを監視しておいて、変更されたらschtasksコマンドやpowershellを使ってタスクスケジューラ経由でスリープを解除させる方法が簡単だと思います。TvRock.exeではTvRock.schを開く際はCreateFile()で排他しているので書き込み中にリードしたりといった事故は起きないと思います。

ちなみにtvrock.schのSTARTはunix epochなJSTです。

tvrockを卒業することになるかと思いきや、解決策が見つかってしまったのでまだまだ使い続けることになりそうです。やっといてなんですが、もう録画してまで見るものがないのでした。

最後で恐縮ですが、TvRock, TvTest, RecTest, TSTask, Spinel, BonDriverProxyEx, BonDriver_PT3-ST, pt2wdm の作者様方のみならず、多くの関係者の方に心から感謝しています。

以上、このような駄文を読ませてしまい、誠に申し訳ございませんでした。

ACPI Wake Alarmによるスリープからの復帰における遅延時間のデータ (ASUS PRIME B760M-AJ D4)

 表題の件ですが、Windows10や11で使用したときにn時間以上スリープさせた場合、ACPI Wake Alarmによってレジュームすると予定時刻より遅れて復帰するということを知りました。

いやあ、全然知りませんでした。11年ぶりにPCを新調したらこんな落とし穴があったなんて。

先達はあらまほしき事なり、というわけで「アルチーナの魔法の島」さんの「Intel 300シリーズチップセット以降のスリープ解除遅延問題」を読ませていただきました。大変有用な情報をありがとうございます。

UFEIでレガシーなRTCを選べれば回避できるとのことですが、当方がWindows11で運用しているASUS PRIME B760M-AJ D4には項目がありませんでした。

そこで、まずはスリープからACPI Wake Alarmによって復帰というかレジュームというか起床したケースをPower-Troubleshooterが記録したイベントログから拾って表にしてみました。当方の環境では最低でも一日に一回必ず走るジョブがあるので、スリープ時間が一日以上のデータはないのが残念です。

実スリープ
時間
期待スリープ時間遅延秒数遅延秒/時
10:44:1210:39:3028226.45817045
12:23:3812:18:0733126.90631562
6:53:4106:50:4917225.12069455
9:57:0109:52:4126026.3209696
5:38:4205:36:2613624.25443377
14:25:1814:18:4938927.1769295
8:56:1908:52:2823126.02979842
4:33:1104:31:2810322.76522593
9:10:3209:06:3423826.1267305
18:33:0918:24:4150827.59161751
6:46:1106:43:2316824.98863777
7:51:0707:47:4720025.65290198
9:03:2108:59:2723426.02650848
10:44:2010:39:3728326.54715064
5:56:1005:53:4514524.59363958
7:07:2807:04:3017825.1590106
4:32:4204:30:5810423.02866281
4:33:4504:32:0110422.93977085
4:30:2504:28:4310222.77491782
4:57:3604:55:4011623.54002255

遅延秒数とあるのは期待スリープ時間と実スリープ時間との差分で、「本来復帰すべきだった時刻よりもどの程度遅れたか」を計算した秒数です。確かに遅れまくってます。

9時間スリープさせると3.85分の遅刻で、18時間33分では8.46分遅刻する、と。

表だけだとよくわからんので、googleさんにグラフ化してもらいました。

ACPI Wake Alarmによる復帰遅延秒数グラフ

グラフの右側の目盛りは左側の目盛りが合計の遅延秒数で、右側は1時間当たりの遅延秒数です。

先の先達のブログ様では3.5時間以上の場合にACPI Wake Alarmで起床するようになるという情報でしたが、当方でも4時間未満の起床は起床させたプロセスが正しく記録されていました。

一方、一時間おきに25秒程度づつ遅延するということでしたが、こうしてみると、私のケースでは一時間当たりの遅延秒数は、スリープ時間の合計時間によって放物線を描いていて少々異なるようです。

遅延秒数のほうはきれいに値が出ているので、xをスリープから復帰する時刻までの秒数、yを遅延秒数とすると、遅延時間を計算する式はだいたいy=0.008x-27.5くらいでよさそうです。

y切片がマイナスなのですか。長時間のスリープ時はホニャララするとかしないとかの省電力がらみなんでしょうか。でも遅刻はまずいんじゃないかなあ、と思うのは日本人だからでしょうか。

誰にも役に立たない情報ですが、まずは以上です。

ここまでお読みいただいてありがとうございました。