ClutterActor on GtkContainer

Clutter は魅力的ではあるが描写の全部を自前で用意する必要がある。
つまり GtkButton, GtkListView のような Widget は無い。

それなら ClutterActor を GtkContainer 上に pack できればよくね?
やってみると普通に拒否、全くの別物だからそりゃ当然の話だ。

しかし GNOME3 自体はしっかり連携している。
知らないだけで何か方法があるはずだ。

/usr/lib64/girepository-1.0
をよく見ると GtkClutter というものがある。

Clutter Gtk integration on Vimeo

WPF のような新規ウイジェットではなく GTK+ をエフェクトするみたい。
そりゃ GTK+3 自体が新規だし元から連携していてもおかしくない。

Clutter-Gtk 1.0.2 Reference Manual

どうやら GtkClutterWindow は GtkWindow のサブクラス。
ClutterActor が表面に張り付いている状態って認識でいいのかな?
Python からは get_stage() で ClutterStage が取得できそうである。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import Gtk, Clutter, GtkClutter, ClutterX11

def quit(widget, data=None):
    Gtk.main_quit()

#ClutterX11.set_use_argb_visual(True)
#ClutterX11.set_display(ClutterX11.get_default_display())
#ClutterX11.disable_event_retrieval()
Clutter.init(sys.argv)

w = GtkClutter.Window()
w.connect("destroy", quit)
w.set_title("GtkClutter.Window")
w.resize(300, 200)

stage = w.get_stage()
stage.set_size(300.0, 200.0)
w.show_all()
Gtk.main()

WARNING 出まくり、初期化とか色々やってみたけど駄目だった。
とりあえず get_stage() だけはできている、使い方が悪いのだろう。
ついでにこの場合 delete-event ではなく destroy 指定でないと終了しない。

直感でやっても上手くいかない、もっと良い方法は無いだろうかと検索。

Stage Widget

gtk_clutter_embed_new ()
で作成した Object なら Gtk+ コンテナに入れられるようだ。
試すと上手くいったので ClutterGst でやってみる。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import Gtk, Clutter, GtkClutter, ClutterGst

class ClutterEmbedTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        # Video Texture
        tx = ClutterGst.VideoTexture()
        tx.set_uri("file:///home/sasakima-nao/movie/bike/ninjya1000_1.mp4")
        # Create the Clutter Widget
        embed = GtkClutter.Embed.new()
        embed.connect("size-allocate", self.on_size_allocate, tx)
        # ClutterStage
        stage = embed.get_stage()
        stage.add_actor(tx)
        # Buttons
        play = Gtk.Button(stock=Gtk.STOCK_MEDIA_PLAY)
        play.connect("clicked", self.on_play, tx)
        # packing
        vbox = Gtk.VBox()
        vbox.pack_start(embed, True, True, 0)
        vbox.pack_start(play, False, False, 0)
        self.add(vbox)
        self.set_title("ClutterEmbedTest")
        self.connect("delete-event", self.on_quit)
        self.show_all()

    def on_size_allocate(self, widget, allocation, tx):
        w = widget.get_allocation().width
        h = widget.get_allocation().height
        tx.set_size(w, h)

    def on_play(self, widget, tx):
        tx.set_playing(True)

    def on_quit(self, widget, data=None):
        Gtk.main_quit()

if __name__ == '__main__':
    # initialized
    Clutter.init(sys.argv)
    ClutterGst.init(0, "")
    ClutterEmbedTest()
    Gtk.main()

よしコレなら何も警告は出ない。
警告が出ないようガンバった WPF 3.0 アプリが 3.5 で無意味にされた過去が…
初心者はワケワカだろうけど、こんな苦労も数年後には無意味になるのでしょう。

やはり親ウインドウサイズに連動しないので size-allocate シグナルを利用。
ClutterActor のサイズは float だけど int のままサイズ変更できた。
コレで GTK+ Widget と ClutterActor の共存アプリケーションができる。

アスペクト比保持とかはどうやるんだろう?
というか最初のビデオでは GTK+ widget にエフェクトが掛かっていたような…
まだ先は長い、リファレンスマニュアル無しで作るのは狂気だがコレが楽しい。

Fedora 15 Google Chrome

前々回書いたとおりの状況なので現在 Opera が使えない。
メーラーやダウンローダーも Opera なのにまいったな…

とはいえ、メーラーは実は BlackBerry からしか利用していなかったりする。
全アドレス IMAP だし、BlackBerry の IMAP プッシュ配信便利すぎ。
ダウンローダーも wget でいいとして、とにかく WWW ブラウザだ。
自作している奴はまあテスト専用なので。

チョロミウムにしようと思ったけどリポジトリに無かった。
面倒なので chrome にする、Google のトップページから辿って探す。
あら Fedora 64bit 用 RPM があるのね、コレでいいや。

起動時になんか SELinux にブロックされる。

SELinux blocks Chrome with latest Chrome/Fedora 15 updates – Google Chrome Help

$ su
# grep chrome /var/log/audit/audit.log | audit2allow -M mypol
# semodule -i mypol.pp

でブロックは回避できるようになったみたい。
この時期でコレなので Fedora 16 でも同じだろう、SELinux は難しい…

[セキュアOS SELinux入門]第6回 最も簡単な設定方法 – オープンソース:ITpro

とにかく Google USA 検索は Python や GTK+ コード検索で必須だ。
他ブックマークレット等のカスタマイズは以前書いた以下と同じ。
Opera to Chrome p1 | PaePoi

Google の仕様が変わったので USA はこうしています。
http://www.google.com/search?&hl=en&lr=lang_us&q=%s

ブックマークはどうせ使わないしアンカー作成ブックマークレット専用だな。
Shift+Ctrl+B で出したり引っ込めたりなのか、ふむふむ。
検索するとき Ctrl+E, Ctrl+T なのについ癖で F2 を押してしまう。

拡張は Smooth Gestures と tab to-the Front のみ。
Opera ならこの2つは標準機能なので何もいらないのにな。
後は Youtube FLV をキャッシュからコピーする Nautilus スクリプトがいるな。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    youtube_chrome.py (~/.gnome2/nautilus-script)
    Chrome Cache File to Nautilus Current Directry
    Support Google Chrome x86, x86_64
    Support Japanese language Directory
    
    Version 1.0
"""

import os
from urllib import unquote

mp4 = ["ftypmmp4", "ftypmp42", "ftypisom"]

# src directory is Google Chrome Cache Path
src_path = os.path.expanduser("~/.cache/google-chrome/Default/Cache")
# copy directory is Nautilus current directory
dst_path = unquote(os.environ["NAUTILUS_SCRIPT_CURRENT_URI"][7:])

ls = os.listdir(src_path)
for f in ls:
    src = os.path.join(src_path, f)
    # size < 1MB is continue:
    if os.path.getsize(src) < 1048576:
        continue
    o = open(src)
    # FLV
    flvarray = o.read(3)
    # mp4
    o.seek(4)
    mp4array = o.read(8)
    o.close()
    # Copy and Set Extension
    if flvarray == "FLV":
        os.system('cp {0} "{1}/{2}.flv"'.format(src, dst_path, f))
    elif mp4array in mp4:
        os.system('cp {0} "{1}/{2}.mp4"'.format(src, dst_path, f))

Opera より簡単だった、てかループを一階層減らしただけ。
ダウンロードに拡張を使うほうが Chrome らしいんだろうけどね。
見た後で取り出したい時ってもうキャッシュにあるのにもったいないじゃないか。

スピードダイアルとかは使っていないしコレで充分かな。
検索か動画かでしか使っていないような。

しかし起動が早すぎて笑った!
画像だらけのエロサイトでも問題無くなったんだね。
Font は何もしなくても綺麗に表示されるのが一番嬉しかったり、あぁ Opera 屋。
ヤバイ凄く気に入りそうだ、Opera が対策してくれるまでのつなぎなのに。

ClutterGst PyGI

どうも GTK3 は xid を得る方法も全然違うようで。
python – DrawingArea Cannot Get XID – Stack Overflow

expose-event が draw に変わっていたりでもうよく解らない。
PyGI で Gst を扱う情報が見つからず全然アプリ開発が進まない。

ClutterGst というのがあるけどよく解らないので検索。

PyClutter video tutorial ? Hindsight Labs

こんなのを見つけたけど古いバインディングだ。
PyGI で書き直して実験してみることにした。

いくら探しても ClutterGst の Reference Manual が見つからない。
しかたがないので dir() で漁って例外で確認しているけどよくワカラン。
例外で playbin2 がどうとか出た、描写エンジンは playbin2 なんだね。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import sys
from gi.repository import Clutter, ClutterGst

class TestStage(Clutter.Stage):
    def __init__(self):
        Clutter.Stage.__init__(self)
        # ClutterGst
        self.tx = ClutterGst.VideoTexture()
        self.tx.set_uri("file:///home/sasakima-nao/movie/bike/ninjya1000.flv")
        self.tx.set_playing(True)
        self.add_actor(self.tx)
        # self
        self.connect("destroy", self.quit)
        self.set_title("ClutterGst Test")
        # Not linked to the window size
        self.set_size(400, 400)
        self.show_all()

    def quit(self, widget):
        Clutter.main_quit()

if __name__ == '__main__':
    init = Clutter.init(sys.argv)
    if init[0] == Clutter.InitError.SUCCESS:
        # Param (argc, argv) ???
        ClutterGst.init(0, "")
        TestStage()
        Clutter.main()

ClutterGst も専用の初期化が必要であるようです。
パラメータが int と str だったけどもしかして C 言語方式?
sys.argv シーケンスでは展開してくれない。

pygst みたく Window 枠に合わせて描写されない。
当然 DirectShow みたくウインドウより大きな映像ははみ出す。

絶対位置描写だと又ウインドウサイズ計算が面倒くさくなる…
設定とかあるのかな、もう少し弄くってみるけど。

Update Tips page

そういえば Ubuntu 11.10 で大半のアプリが GTK+ 3 化されてるのに
私の作った Tips ページは gconf のままだった。
Fedora についても後でまとめると書いたまま放置状態ではや半年。
てゆーか本サイトをまったく更新していない…

ということで Tips ページを適当に変更することにした。

そういえば Ubuntu のボタン右寄せはどう変わったのかな?
と思って試したら以前と同じ gconf のまんまじゃねーか!
OS レベルで gconf と gsettings が混在かよ、信じられない…

しかたがないので Fedora の gsettings ページに少し追記してリンクだけにした。
どうでもいいけど gnome-tweak-tool 大人気だね。
dconf-editor の機能限定版でしかないのに何故そんなのを使うんだろう?

Gedit のページに Gedit3 プラグインの作り方を前より詳しく書いたつもり。
けど日本語で検索しても自作した人が増えた気配はまったく無い…
スクショの為に作り直ししてみて気がついたけど __init__() 初期化が有効に切り替えする毎に行われるようになっていた。
作り直してよかった、嘘を書くところだったわい。

ついでに Linux ページだけ HTML5 化!
Linux なら問題ない、Windows だと IE6 の可能性があるのが怖い。
IE6 を抹殺するには XP のサポート終了しか手段が無いのに世間は…

Gedit と Nautilus ページを分離して凄く更新したように見せかける。
そんなこんなで、あまり追記することが無かった。
Fedora 16 が出たらまた何か見つけよう。

以上 Tips ページ更新のお知らせのみでした。

しかし Unity なんて本当に使っている人いるのか?
ランチャの右クリックメニューから多重起動が選択できない、ビックリした。
GNOME 3 なら右クリックメニューでも Ctrl + クリックでも多重起動できるのに。

Alt+F2 でわざわざ Dash が開く、というか Tab キー保管が Alt+F2 からではできないなんてマジで信じられない…
naut まで打ち込んで Tab キーを叩くと nautilus まで保管されるみたいな機能ですよ。
Linux 屋でコレを使わない人なんて絶対にいないと思うのだが…
マウスでもキーボードでも不満、タブレット専用 OS かよみたいな。
Aero も GNOME3 もすぐに慣れたけど Unity には殺意しか感じないよ。

GNOME seed

何を今頃 seed というものを知った。
Ubuntu 11.10 は後で入れないと使えないので Fedora 15 で試す。

Seed – GNOME Live!

gi の動的バインディングは色々な言語から利用できる。
海外を探せば vala とかの方法も見つかる、私は vala をやるつもりはないけど。

Seed Tutorial : Standalone

ようするに JavaScript なので PyGi ベースで考えると
var new 及びセミコロンが増えて JSON でパラメータを書けばいいようだ。

#!/usr/bin/env seed

Gtk = imports.gi.Gtk;
Gtk.init (null, null);

var window = new Gtk.Window();
//window.connect("delete-event", Gtk.main_quit);
window.signal.hide.connect(Gtk.main_quit);

var check = new Gtk.CheckButton({label:"seed check"});
//check.set_property("active", true);
check.active = true;

window.add(check);
window.show_all();

Gtk.main();

シグナルは signal メソッドから辿る、プロパティはドットでアクセス。
プロパティのハイフンはアンダースコアに変換、どの言語も同じだね。
GType でサブクラスが作れコンストラクタも利用できる。
公開メンバは var を使わず this に付加して作成する、なるほど。
GTK+ も Clutter も利用できる。

これなら PyGi と同等に扱えるかも。
ということでダイアログを出してテキストを変更するテストコードを。

#!/usr/bin/env seed

Gtk = imports.gi.Gtk;

SeedWindow = new GType({
    parent: Gtk.Window.type,
    name: "SeedWindow",
    init: function (){
        var messagebox = function(text) {
            var dlg = new Gtk.MessageDialog({buttons:Gtk.ButtonsType.OK_CANCEL});
            dlg.set_title("title");
            dlg.text = "first";
            dlg.secondary_text = text;
            var r = dlg.run();
            dlg.destroy();
            return r;
        };
        var on_clicked = function(widget){
            var res = messagebox("Message Text");
            if (res == Gtk.ResponseType.OK) {
                label.set_text("OK");
            } else {
                label.set_text("Cancel");
            };
        };
        var button = new Gtk.Button({label:"button test"});
        button.signal.clicked.connect(on_clicked);
        var label = new Gtk.Entry();
        var vbox = new Gtk.VBox();
        vbox.pack_start(button);
        vbox.pack_start(label);
        this.add(vbox);
        this.signal.hide.connect(Gtk.main_quit);
        this.show_all();
    }
});

Gtk.init (null, null);
var w = new SeedWindow();
Gtk.main();

Gtk.MessageDialog のパラメータが buttons しか適用されない…
parent や flags とかはガン無視される、なんだかよく解らない。
造り込みが甘いのか、それとも何か特殊な指定方法が必要なのか?
まあもっと情報が出ないと普段利用にはまだチト厳しいかな。

とにかく seed は JavaScript が大好きでかつ Python の文法に「なんじゃこりゃ!」とか「self いらないだろ?」とか「唖然…」とかつぶやくような Python が嫌いで嫌いでしかたがない人にはもってこいかもしれません。

私は var と new とセミコロンと中括弧が面倒くさいですw