ページ

2008年8月12日火曜日

SimpleCap (39) Widgetのキャプチャ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

さていよいよ SimpleCap に処理を入れる。手こずると思いきやあっけなくできた。

メニューから "Widget"を選ぶと Dashboardが起動し、ウィンドウのキャプチャが始まる。


できました。


複数の Widgetも問題なし。



コードはほとんど書いていない。通常キャプチャ方式が増えると Handlerプロトコルに準拠したクラスを一つ作らなければならない。今回も WidgetHandler を用意した。ところで機能的にはウィンドウキャプチャと変わらないのでこれを再利用することができる。そこで WindowHandlerクラスを継承させる。

WidgetHandler.h

#import 
#import "WindowHandler.h"

@interface WidgetHandler : WindowHandler {

}
@end


これだけ。後はこのクラスを使う前に Dashboardを起動しておいてやるだけ。これだけで Widgetも今までのウィンドウキャプチャと同じ機能が実現できる。おお、オブジェクト指向やってて一番得した気分だ。
実際にはターゲットのウィンドウの種類が若干違うため、下記のコードだけ足してある。

WidgetHandler.m
@implementation WidgetHandler

- (BOOL)isWindow:(CFDictionaryRef)window normalWindow:(BOOL)normal
{
int layer;
CFNumberGetValue(CFDictionaryGetValue(window, kCGWindowLayer),
kCFNumberIntType, &layer);
CFStringRef owner_name;
owner_name = CFDictionaryGetValue(window, kCGWindowOwnerName);

if ([@"Dock" isEqualToString:(NSString*)owner_name] && (layer == 100)) {
return YES;
}
return NO;
}
@end


このメソッドはウィンドウが目的の種類かどうかをチェックするもの。元々はキャプチャ処理クラスのベースクラスである HandlerBaseに実装されていて、通常のウィンドウを対象にしたコードが書かれている。これを WidgetHandlerでオーバーライドして Widgetを対象にするようにした。これで WidgetHanlder の親クラス WindowHandler ををコード修正なしに振る舞いを変えられた。いいなオブジェクト指向は(くどい)。

- - - -
とまあいい事ばかり書いたが、困った点が一つある。Dashboardの起動が完了した状態でないとキャプチャがうまく働かない。当然でキャプチャ処理はその時点で表示されているウィンドウが対象であるため、確実にDashboard起動が完了した後(Widgetが表示された後)にキャプチャを開始させる必要がある。今はインチキして sleep(3)を入れてある。
[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Dashboard.app"];
[NSThread sleepForTimeInterval:3];
[_capture_controller startCaptureWithHandlerName:@"Widget" withObject:nil];


ちょっとしたプロセス監視が必要になるな。またプロセスが立ち上がったとしても Widgetの表示が完了しているとは限らない。さてどうしたものか。