RubyCocoaでスクリーンセーバを作る

RubyCocoaでスクリーンセーバを作る手順を解説する。

MacOSのスクリーンセーバ

MacOSでは以下の手順でスクリーンセーバを作ることができる。 XCodeにスクリーンセーバのテンプレートは用意されていないが、 「Cocoa Bundle」のプロジェクトを作成し/ ScreenSaverViewのサブクラスのObjective-Cプログラムを追加し/ 拡張子をsaverに変更すれば スクリーンセーバ用のbundleをビルドすることができる。

RubyCocoaでの実装

ScreenSaverViewのサブクラスを直接Rubyで書くことは(多分)できないので、 Objective-Cで作ったクラスからRubyプログラムを呼べばよい。

まず以下のようなWikipediaSaverLoader.mを作る。 RBBundleInitが RubyCocoaを初期化しRubyプログラムをロードする関数で、 Leopardの/Developer/Examples/RubyCocoa/RubyAnywhere/などに使用例がある。

#import <Cocoa/Cocoa.h>
#import <RubyCocoa/RBRuntime.h>
#import <ScreenSaver/ScreenSaver.h>
#import <WebKit/WebKit.h>

@interface WikipediaSaverLoader : ScreenSaverView
{
  id wikipediaSaver;
}
@end

@implementation WikipediaSaverLoader
- (id)initWithFrame:(NSRect)frameRect isPreview:(BOOL)preview
{
  [super initWithFrame:frameRect isPreview:preview];
  
  static int installed = 0;
  if (! installed) {
    if (RBBundleInit("WikipediaSaver.rb", [self class], nil))
      NSLog(@"WikipediaSaverLoader.install: failed");
    else {
      NSLog(@"WikipediaSaverLoader.install: success");
      installed = 1;
    }

    Class rubyClass = NSClassFromString(@"WikipediaSaver");
    NSAssert(nil != rubyClass, @"could not find Ruby class");

    wikipediaSaver = [[rubyClass alloc] initWithFrame:frameRect isPreview:preview];
    NSAssert(nil != wikipediaSaver, @"Ruby instance should not be nil");

    [wikipediaSaver setSaver:self];
  }

  return self;
}

- (NSTimeInterval) animationTimeInterval {
  return [wikipediaSaver animationTimeInterval];
}

- (void)animateOneFrame
{
  [wikipediaSaver animateOneFrame];
}

@end
これをスクリーンセーバとして登録すると animateOneFrameが定期的にシステムから呼ばれるので、 そこからRubyCocoaプログラムを呼ぶようにすればよい。

スクリーンセーバ本体のWikipediaSaver.rbは以下のようにRubyで記述することができる。 ここでは15秒おきにWikipediaのランダムページを表示するようにしている。

require 'osx/cocoa'
include OSX

require_framework 'ScreenSaver'
require_framework 'Webkit'

class WikipediaSaver < ScreenSaverView
  def initWithFrame_isPreview(frameRect,p)
    super_initWithFrame_isPreview(frameRect,p)
  end

  def animateOneFrame
    @webView.mainFrame.loadRequest(@request)
  end

  def animationTimeInterval
    15
  end

  def setSaver(saver)
    @saver = saver
    setup
  end

  def setup
    url = "http://ja.wikipedia.org/wiki/%E7%89%B9%E5%88%A5:Random"
    @nsurl = NSURL.URLWithString(url)

    screenRect = NSScreen.mainScreen.frame
    @webView = WebView.alloc.initWithFrame(screenRect)
    @saver.addSubview(@webView)

    @request = NSURLRequest.requestWithURL(@nsurl)
    @webView.mainFrame.loadRequest(@request)
  end
end

ダウンロード

このドキュメントとソース、スクリーンセーバ本体を WikipediaSaver.dmgにまとめてある。 ソースはPastieにも貼っておいた。 ( ObjC, Ruby ) Enjoy!


2008/1/18 Toshiyuki Masui @ Pitecan.com