Search
Categories
Articles
Rainmeter関連
ファイル置き場
お知り合いなど

スポンサーサイト

--.--.-- | スポンサー広告

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Rainmeter-dev] DynamicVariables

2009.10.08 | Rainmeter-dev // Issue/DynamicVariables

0 Comments

Rainmeter1.1の新機能として追加予定の"DynamicVariables"についての、私的なまとめです。
本家でのコード変更についてのコメントや、私自身の変更案、コミット予定/済みなものなどが入り混じっていますので、決して公開されているビルドに反映されているものばかりではありません。ご注意ください。

■更新履歴 (※更新のたびに、たぶん一番上にあがってきます)
- 2009.10.08 : MeterButtonの"ButtonCommand"が対象から抜けていたので追加

以下、続きに格納。

スキンでの値指定にMeasureの値をそのまま突っ込める更新が入ったみたいで、どんな風に変わったのかなーとソースコードとずっとにらめっこしてたけど、難しい!><
特に、今までの[Variables]なものの反映や、Substituteの実行順とか。処理が今までのものとは置き換わってるから、まずそこを把握することから始めないといけない……。

Forumにはcase sensitive(と言うのね……)な件だけ書きこんでみた。
DynamicVariables対応のために、スキンから設定値を読みだす部分が大きく変更されていて、今までは各MeasureやMeterが設定値をファイルから読み出していたのが、変更後は、スキンのファイルの内容を一度すべてCConfigParserの持つハッシュマップに登録し、そこから各MeasureやMeterがキーを使って設定値を取り出す仕組みになっています。そのハッシュマップへの登録には、"Section名::Key名"という文字列をキーとして、設定値を突っ込んであるんですが(例えばColor=000000なら、"MeterCPU::Color"というキーを使って000000という値を登録/読み出す)、スキンによっては小文字でcolorと書いてあるものもあって、"MeterCPU::color"(Skinから登録されたキー)≠"MeterCPU::Color"(読み出そうとするMeter側が使うキー)となり、読み出しに失敗します。Meterの種類を指定するキーを、Meter=ではなくMETER=とかmeter=とか書いて起動してみるとよくわかります(MeasureかMeterの指定がないよと怒られる)。

修正するとすれば、登録時にキーを全部大文字にするか、逆に小文字にしてしまうかして、読み出し時も合わせておけばよさそう……と思っていたら、r193で全部小文字にして使うように修正されました。

でも、挙動が変なのはこれのせいだけではないみたい。いろいろ大変そう……。
特にプラグイン内部の処理を変えないといけないのが面倒くさそうです。今はプラグインはDynamicVariablesから除外されてるみたいですが。でも、便利そうだから早くバグとりが終わるといいなぁ。

***

issue 101は、単純にIfMouseDownActionなどのAction系の設定読み込み時に[Measure]の置き換えをしないようにするだけでよさそうです。どうせ実行時に[Measure]の置き換えやるんだし。

    m_LeftMouseDownAction = parser.ReadString(section, L"LeftMouseDownAction", L"", false);

4番目の引数がtrueだと、ReadString()内で[Measure]の置き換えをします(r192でのデフォルト動作)。falseにすると置き換えません。

ちなみに、issue 101の例だと、デフォルト動作(置き換え)でのIfMouseDownActionの中身は、

!Execute ["http://www.google.com/search?&q=[Hours]:00:00"]

という具合になってます。[Hours]については後述。
DynamicVariables=0でも、初期化時には置き換えがあるので、[Minutes]と[Seconds]が置き換わってます。00なのは、Measureの値が初期化段階でまだ更新されてないからです。クリックされると、実行時に[Hours]の部分だけ今の時間に置き換えられて実行されます。
DynamicVariables=1になっているときは、毎Update時にIfMouseDownActionが読み直されて、[Minutes]と[Seconds]の部分にはUpdate時の分秒が入り、[Hours]は同じようにクリック実行時の時間が入って、一見うまく動いてるように見えるけれど、状態としてはいびつです。

なぜに[Hours]だけそのまんまで、[Minutes]と[Seconds]だけMeasureの値に置き換わった状態で保持しちゃうのかというと、単純にReadString()内でのMeasureの"[]"探索が、Multiple-BANGを区切るための"[]"を考慮してないためです。"["を見つけたら次は"]"を見つけるという処理しかしてないので、例だと

["http://www.google.com/search?&q=[Hours]

までがMeasure名の区切りと判定されて、それを置き換えようとするもんだから「そんなMeasure名は登録されてないから置き換えられないよ」と言われ、[Hours]だけが置き換えを逃れるという……。

***

r217で、上記のいびつな状態を修正しました(Multiple-BANGの[]を考慮して置き換えるように修正)。
反面、issue 110のようなものも出てきました。issue 101にあったように、現時点でのDynamicVariablesの仕様を考慮すれば、当然動かなくなります。

以前のような振る舞いとの互換性を保つためには、Action系の設定だけは、DynamicVariables=0なら置き換えなし、DynamicVariables=1なら置き換えありが妥当かなと思います。
例えばMeterなら、何よりもまずDynamicVariablesを使うかどうかの設定を取得し、その値に応じて、他の設定を取得するように変更します。今回はAction系だけ、DynamicVariablesの設定に依存して取得するように変更します。

/*
** ReadConfig
**
** Reads the meter-specific configs from the ini-file. The base implementation
** reads the common settings for all meters. The inherited classes must call 
** the base implementation if they overwrite this method.
**
*/
void CMeter::ReadConfig(const WCHAR* section)
{
    CConfigParser& parser = m_MeterWindow->GetParser();
 
    // The MeterStyle defines a template where the values are read if the meter doesn't have it itself
    const std::wstring& style = parser.ReadString(section, L"MeterStyle", L"");
    parser.SetStyleTemplate(style);
 
    m_DynamicVariables = 0!=parser.ReadInt(section, L"DynamicVariables", 0);
 
    /* snip */
 
    m_RightMouseDownAction = parser.ReadString(section, L"RightMouseDownAction", L"", m_DynamicVariables);
    m_LeftMouseDownAction = parser.ReadString(section, L"LeftMouseDownAction", L"", m_DynamicVariables);
    m_MiddleMouseDownAction = parser.ReadString(section, L"MiddleMouseDownAction", L"", m_DynamicVariables);
    m_RightMouseUpAction = parser.ReadString(section, L"RightMouseUpAction", L"", m_DynamicVariables);
    m_LeftMouseUpAction = parser.ReadString(section, L"LeftMouseUpAction", L"", m_DynamicVariables);
    m_MiddleMouseUpAction = parser.ReadString(section, L"MiddleMouseUpAction", L"", m_DynamicVariables);
    m_MouseOverAction = parser.ReadString(section, L"MouseOverAction", L"", m_DynamicVariables);
    m_MouseLeaveAction = parser.ReadString(section, L"MouseLeaveAction", L"", m_DynamicVariables);
 
    /* snip */
}

置き換えを行うかどうかを指定する4番目の引数に、m_DynamicVariablesをそのまま渡します。
DynamicVariables=0のときには、m_DynamicVariablesはfalseとなり、設定読み込み時の[Measure]置き換えは行われません。代わりに、Action実行時に[Measure]の置き換えが行われます(以前のような振る舞い)。
DynamicVariables=1のときには、m_DynamicVariablesはtrueとなり、設定読み込み時に[Measure]の置き換えが行われます。Action実行時には、[Measure]が[OtherMeasure]のような文字列に置き換えられたような場合だけ、置き換えが行われます。

このような変更を、他に同様なActionの読み込みを行っているMeasure/Meterで行えばよいかなと。
現時点では、スキン内の[Rainmeter]セクションに定義するActionは変更対象外です。DynamicVariablesとは関係がないし、そもそも置き換え用の[Measure]が登録されていない段階なので、置き換え自体ができません。同様の理由で、"TrayExecuteL"などのActionも変更対象外です。

(※今のところは、これでできるんじゃないかっていう想像上の対策で、まだコード化してテストとかはしていません(別の部分をずっと触っていたので)。とりあえずここ数日で試してみる予定……)

(※m_DynamicVariablesを使っちゃいけないような気がするので保留)

***

"DynamicVariables"を根本的な部分から考えると、現状の仕様では、後々混乱を起こすんじゃなかろうかというのが率直な感想です。
そもそも仕様があるんだろうかという。フォーラムなどでそのへんの(想像→具体化→実装の)話し合いが行われていたんだろうと思うので、どういった感じで実装まで進んでいったのか、もう一度見直さないといけないかなと思っています(読んだような気はするけど、だいぶ頭から抜けちゃった感が)。

experimentalな機能がtrunkに追加されるのは、オーナーであるRainy氏の手によるものだから仕方ないとして、それが次期リリースの目玉として取り上げられていて、もう取り下げられなくなっているというのは、いろいろと拙速だった面もあるのかなぁと……。
そもそもバグフィックスや新機能が混在しちゃってる状況が異様なのかなぁとも。なんで1.1のままリリースを急ぐ必要があるのかなぁと……。外部にも迷惑がかかるからリリースは遅らせられないという状況が目前にあるのであれば、それは別に1.0リリース時のコードを使って、影響のあるWebParserだけ(?)を修正した1.0.1を急きょリリースするという手を使ってもいいと思うんですよね。
(そういうのはtag打ちではソースを変更できそうにないから、必要なところ取りをしたbranchを作らないといけないんだろうか。仕組みがあまり分かってない)
スキン側にも問題があって、その修正はしたけれどいろんな新機能に依存しちゃってるから……って理由もあるんですかね。

話を戻すと、"DynamicVariables=1"によって、Measure/Meter内のすべての設定が影響を受けるというのが、あまり好きな振る舞いではありません。実現可能性などは全くわかりませんが、例えば、"DynamicVariables=FontColor,FontSize"のように、動的に変更したいものだけを記載できるようにするとか、そういったアプローチのほうが好きです。当然、Hiddenを指定したときの!RainmeterShowMeter/HideMeterの振る舞いの定義や、同様にX/Yを設定したときの!RainmeterMoveMeterの振る舞いの定義など、問題としては同じものが残ってきますが、関係のないものを巻き込むことは少なくできると思います。

"DynamicVariables"の仕組み自体は、使えると便利になると思っているので、なんとか不具合を減らして実用的に(少しでも今後のスキンの互換性が保てるように)していきたいところです。
(ちなみに、DynamicVariablesの搭載に伴って、最初はいろいろとおかしなところもあった設定読み込み部の大規模更新は、(MeterStyleや@Includeの導入も含め)以前の水準以上になってきてるんじゃないかなーと思っています)

***

なんだかいろいろと勘違いをしてる気がしてきた!

"DynamicVariables"っていうのはその名の通り、#VARIABLE#なもの(以下、変数)を動的に変更するためだけの機能なんだろうか……。[Measure]が使える(=動的な[Measure]値を設定値として使える)ということに捉われすぎてた気がする。
DynamicVariables=1とすることで、!RainmeterSetVariableを使って動的に変数の値を変更できるようになるけれど、実際にその変数を動作に反映させるには、Measure/Meterの各設定を再計算してやらないといけない(Measure/Meterが動作に使っている値は、変数を置き換えて計算を済ませた値なので)。

……その流れのなかで、「再計算の仕組みを作るなら、今まで要望の多かった[Measure]の値も一緒に使える!」ということで、ねじ込まれた感が。初期コードからして、m_DynamicVariablesの値に関係なく[Measure]置き換えが有効になってるのも、"DynamicVariables"の機能の一部ではなく、独立した機能っていうことなのかもしれない。
だとしたら、上に書いたような「m_DynamicVariablesの値によって、Actionでの[Measure]置き換えを切り替える」なんてことはしちゃマズイ!

結局のところ、(現状とりあえずできる)最善策は、最初の考えに立ち返り、「Actionはすべて[Measure]の置き換えなしで読み込む(第4引数をfalseで読み込む)」ことかもしれない。
もちろん、Action内に書かれた[Measure]が実行時以外にも置き換え済みであることを想定して作ったスキンは、その意図通りには動かなくなってしまいますが……。

現時点(r233)でMeasure/Meterに存在するAction :

Measure.cpp
IfAboveAction
IfBelowAction
IfEqualAction

MeasureNet.cpp
TrafficAction

Meter.cpp
RightMouseDownAction
LeftMouseDownAction
MiddleMouseDownAction
RightMouseUpAction
LeftMouseUpAction
MiddleMouseUpAction
MouseOverAction
MouseLeaveAction

MeterButton.cpp
ButtonCommand      //2009.10.08 抜けていたので追加

現時点(r233)でそれ以外の場所に存在するAction :
(※これらは仕組み上置き換えが起きないので、対象外)

MeterWindow.cpp - スキンファイル毎の[Rainmeter]セクション
RightMouseDownAction
LeftMouseDownAction
MiddleMouseDownAction
RightMouseUpAction
LeftMouseUpAction
MiddleMouseUpAction
MouseOverAction
MouseLeaveAction
OnRefreshAction

Rainmeter.cpp - Rainmeter.iniの[Rainmeter]セクション
TrayExecuteL
TrayExecuteR
TrayExecuteM
TrayExecuteDL
TrayExecuteDR
TrayExecuteDM

(※プラグインでは、現時点では第4引数をfalseとしてReadString()を呼び出しているので、対象外。もしfalseでなくなれば根本的に対処が必要)

Webparser.cpp
FinishAction

***

MeterButtonのButtonCommandがうっかり抜けていたので、上記に追加しました。
これだけCommandになってて抽出漏れだった(自分用Rainmeterでは修正してたのに!)

また、この変更はtrunkへ追加済みです。次回のベータ版またはRC版で反映される予定です。

« Perfume Second Tour 2009 「直角二等辺三角形TOUR」 [Rainmeter] MeasureNetはbits/s? それともBytes/s? »

- Comments
0 Comments

管理者にだけ表示を許可する
- Trackbacks
0 Trackbacks


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。