Rubyでスクリーンショットサーバ(2)
Mozshotさんがベースにしたという、このソースを読んでみることにします。
*1
まずは動かしてみます。ソースをダウンロード後、以下のスクリプトを用意します。
snap.rb
#!/usr/bin/rubyENV['DISPLAY'] = ':1.0'
require 'gtkmozembed'
require 'moz-snapshooter'
以下のように実行してみます。
[root@devel ~]# Xvfb :1 -screen 0 1024x768x24 &
[1] 19816_XSERVTransSocketOpenCOTSServer: Unable to open socket for inet6
_XSERVTransOpen: transport open failed for inet6/xxxxxxxxxx:1
_XSERVTransMakeAllCOTSServerListeners: failed to open listener for inet6
Could not init font path element /usr/X11R6/lib/X11/fonts/CID/, removing from list![root@devel ~]# ruby snap.rb
1
Wrote screenshot-thumb.pngCould not init font path element /usr/X11R6/lib/X11/fonts/CID/, removing from list!
なにやらエラーが出ていますが、とりあえあずは無視します。
カレントディレクトリにscreenshot-thumb.pngというファイルが作成されていれば成功です。
勉強の意味で、勝手にソースにコメントをつけてみました(snapshotメソッドのところはまだ理解してませんが。)。
moz-snapshooter.rb コメント付き
#
# MozSnapshooter
# Web site thumbnailer
#
# Copyright (C) 2005 Mirko Maischberger
# Released in the Public Domain
#
# From an idea by Andrew McCall -
# http://www.hackdiary.com/archives/000055.htmlrequire 'gtkmozembed'
#########################################################
#
# MozSnapshooterクラス
# Gtk::Windowのサブクラス
#
#########################################################class MozSnapshooter < Gtk::Window
#########################################
#
# initializeメソッド
#
#########################################
def initialize# Gtk::Window.initialize(=Gtk::Window.new)を呼び出す
# 他のウィジェットを含むことのできる新しいコンテナ(トップレベルウィンドウ)を作成
super# selfはGtk::Window.newでできたオブジェクト
# コンテナのタイトルとボーダーを設定
# Gtk::Window#title=
# Gtk::Container#border_width=self.title="MozSnapshooter"
self.border_width = 1# width,highを設定
self.resize(780, 570)# プロファイルのパスを設定
# ENV['HOME'].mozillaディレクトリにRubyGeckoプロファイルを作成
# ENV['HOME']の最後にスラッシュがないので、~/配下ではなく
# username.mozillaというディレクトリがつくられてしまった…Gtk::MozEmbed.set_profile_path(ENV['HOME'] + '.mozilla', 'RubyGecko')
# Gtk::Container#<<
# Gtk::Container#addと同じ。
# コンテナ(トップレベルウィンドウ)にMozEmbedウィジェットを追加 しているself << Gtk::MozEmbed.new
# childって何?おそらくコンテナに追加されたMozEmbedウィジェットのオブジェクトだろう
# chrome(クロム)のフラグをセットしている
# chromeはmozillaの外観などに対する設定ファイルがあるディレクトリ。
# ALLCHROMEなので、すべてのchromeをセットしている。
# http://cow.neondragon.net/index.php/415-Fun-With-Firefox-Chrome-Urlsself.child.chrome_mask = Gtk::MozEmbed::ALLCHROME
# Gtk::Widget#set_size_request
# MozEmbedウィジェットのサイズを指定
# なぜかコンテナより大きいself.child.set_size_request(816,600)
# GLib::Instantiatable#signal_connect
# net_stopシグナルを受信したら、on_net_stopハンドラを呼び出す。
# net_stopシグナルはページをロードし終わったら、発生する。
# asincronouslyって何?self.child.signal_connect("net_stop") { on_net_stop }
# http://www.ruby-lang.orgをロード
self.child.location = "http://www.ruby-lang.org"
# インスタンス変数
# net_stopシグナルを受信してスクリーンショットを取るまでの
# 時間を定義している(1/1000秒単位)@countdown = 2
# destroyシグナルを受信したら、終了。
# The user is bored, let's quit.self.signal_connect("destroy") do
$stderr.print "closing...\n"
Gtk.main_quit
endself.show_all
end
#########################################
#
# on_net_stopメソッド
#
# 先にあったnet_stopシグナルのハンドラを定義
# 1/1000秒後、falseがリターンするまでブロックを実行。
# @countdownで定めた時間が経過したら、
# screenshotメソッドを実行。
#
#########################################def on_net_stop
Gtk::timeout_add(1000) do
@countdown -= 1
if(@countdown > 0)
puts @countdown
true
else
screenshot
false
end
end
end#########################################
#
# screenshotメソッド
#
# スクリーンショットを作成
#
#########################################def screenshot
# Gtk::MozEmbed#parent_window
# 親のウィンドウ(コンテナ)を取得
gdkw = self.child.parent_window# geometryを取得
x, y, width, height, depth = gdkw.geometry
width -= 16
pixbuf = Gdk::Pixbuf.from_drawable(nil, gdkw, 0, 0, width, height)
pixbuf = pixbuf.scale(320, 200, Gdk::Pixbuf::INTERP_HYPER)
pixbuf.save("screenshot-thumb.png","png")
puts "Wrote screenshot-thumb.png"
Gtk.main_quit
end
end
ブラウジング・スナップショットとも外部コマンドに頼ってませんし、ブラウジング終了のシグナルを受信してからスナップショットをとっているところがいいです。なんかPythonのソースと似てますね。Rubyの勉強が終わったらPythonにも手をつけてみようと思います。
次はいよいよMozshotさんのソースに挑戦してみようと思います。
*1:ちなみに私のプログラミングスキルは、
Perl->ハッシュのリファレンスがわかるくらい
C->しばらく使ってないとポインタを忘れる
Ruby->いきなりrailsに手を出して四苦八苦
という感じです。オブジェクト指向もよくわかっていません。
ですので、その程度のレベルということでお願いします。