Y901x」タグアーカイブ

GtkMenuButton F10

Y901x 1.1.2 公開、日は変わってしまったけど。

y901x112

メニューバーを取り払ったよ。
ラジオメニューじゃ解りづらい再生速度アスペクト比切り替えもステータスバーに移した。

GtkHeaderBar and GStreamer | PaePoi
Mini GtkButton | PaePoi

つーか、今頃になってやっと上記を実装した、半年も前だったのか。
使い道の例だと思ってください、多分作った本人しか使っていないアプリなので。

所で F10 キーでメインメニューがドロップするのは知っているよね。
GtkMenuButton ではこれを自分で実装しないといけないみたい。
こんな感じでいいみたい、F10 ってシステム管理じゃなかったんだ。
ちょっと具体的に追記

#!/usr/bin/env python3

class Win(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # GtkAccelGroup
        accelgroup = Gtk.AccelGroup.new()
        self.add_accel_group(accelgroup)
        # Preference button
        preferencebutton = Gtk.MenuButton.new()
        image_gear = Gtk.Image.new_from_icon_name("emblem-system-symbolic", Gtk.IconSize.MENU)
        preferencebutton.set_image(image_gear)
        # Set F10 Accel
        preferencebutton.add_accelerator("clicked", accelgroup, Gdk.KEY_F10, 0, Gtk.AccelFlags.VISIBLE)
        # HeaderBar
        headerbar = Gtk.HeaderBar()
        headerbar.pack_end(preferencebutton)

ついでに今頃気が付いた。
Alt+F10 で最大化切り替えできる、これは便利だ。
まあシステム設定で変更できるんだけど。

後 Y901 伝統の Z キーでフルスクリーンは実装できなかった。
一応強引な手段もあるけど GNOME デフォルトの F11 のみでいいかなと。

次は Alt+Enter でプロパティ表示を実装したいな。
一度弄り始めると急に色々思い付くんだよね。

Ubuntu での動作確認は明日やろう(ぉい!
個人的には超有名な某ゲームエンジンと同じ名前であるあの糞デスクトップ環境はガン無視したいんだけどユーザー数がなぁ…

gst direction next frame

JavaScript でスマホゲームもいいけどメインの GTK+ もやらねば。
久々に Y901x の更新、ポーズからコマ戻しが上手くいく方法を見つけたので。

# self.player @ playbin
# self.settingwin @ My Setting

def set_next_frame(self, rate):
    """
        1 frame up down (rate 1.0 or -1.0)
    """
    if self.settingwin.direction != rate:
        self.settingwin.direction = rate
        self.set_playback_direction(rate)
    event = Gst.Event.new_step(Gst.Format.BUFFERS, 1, 1.0, True, False)
    self.player.send_event(event)

def set_playback_direction(self, rate):
    """
        Change direction
    """
    pos = self.player.query_position(Gst.Format.TIME)[1]
    if rate >= 0.0:
        self.player.seek(
                rate,
                Gst.Format.TIME,
                Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
                Gst.SeekType.SET, pos,
                Gst.SeekType.SET, -1)
    else:
        self.player.seek(
                rate,
                Gst.Format.TIME,
                Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
                Gst.SeekType.SET, 0,
                Gst.SeekType.SET, pos)

def on_play(self, widget, data=None):
    if self.settingwin.direction == -1.0:
        self.settingwin.direction = 1.0
        self.set_playback_direction(1.0)
    if self.player.get_state(1)[1] == Gst.State.PLAYING:
        self.player.set_state(Gst.State.PAUSED)
    else:
        self.player.set_state(Gst.State.PLAYING)

逆転させる手続きを分離して send_event するだけだった。
GLib.idle_add とか色々試したのに実はこんなに簡単だった…

これなら関数を抜けるので逆転した後で 1 コマ移動ということになるのかな。
再生開始で正転に戻すのを忘れないようにと。

それと手段が全然解らず困り果てていたシークバー上のマウスホイール。
event.direction 引数が Gdk.ScrollDirection.SMOOTH になるのよ。
Gdk.ScrollDirection.UP, DOWN になる記事以外見当たらなかったし。

http://nullege.com/codes/show/src%40p%40i%40pitivi-HEAD%40pitivi%40utils%40widgets.py/1035/gi.repository.Gdk.ScrollDirection.UP/python

そういうことだったのか!
やっぱり GPL のコードを見たほうが圧倒的に参考になるね。
何も作品を作っていなさそうな人って何故勉強しているのか、日本人に多過ぎ。

def on_seek_scroll_event(self, widget, event):
    """
        Mouse Wheel event
        widget @ GtkScale
    """
    delta = 0
    if event.direction in [Gdk.ScrollDirection.UP, Gdk.ScrollDirection.RIGHT]:
        delta = 1
    elif event.direction in [Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.LEFT]:
        delta = -1
    elif event.direction in [Gdk.ScrollDirection.SMOOTH]:
        unused_res, delta_x, delta_y = event.get_scroll_deltas()
        if delta_x:
            delta = math.copysign(1, delta_x)
        elif delta_y:
            delta = math.copysign(1, -delta_y)
    if delta:
        location = widget.get_value() - (delta * 10000000000)
        if location > 0 and location < self.playinfo.duration:
            self.set_play_position(location)
            self.put_time_status(location)

これで約 10 秒送りなホイールスクロールが可能になった。
Fedora 20 でしか試していないけど多分 GNOME なら大丈夫だろう。
次バージョン早く出ないかなぁ、20 が安定しているからいいけど半年サイクルに慣れ過ぎた。

Gst step

Y901x 1.1.0 を公開。
多重起動防止は行わないけど GtkApplicationWindow 化。
アプリケーションメニューに About を移動、新しいウインドウ追加。

つまり今の GNOME アプリっぽくしたかっただけ。
次でメニューバーを取っ払う予定、どうにでもなれ。

おまけでポーズ時のみ左右矢印キーでコマ送りできるように。
しかし Gst.Event.new_step() 関数ではゼロ以下の指定ができない。
ようするにコマ送りはできるけどコマ戻しはできない。

self.player.seek() の第一引数をマイナスにすると逆転再生できる。
実はその状態でコマ送りするとコマ戻しになる、なんとも変な感じだけど。

なので一度逆転させて送った後に元に戻せばイケるはず。
なんだけどちっとも上手く動作してくれないんだな、これが。

tinbergen/tinbergen.py at master ? biogeo/tinbergen ? GitHub

PyGtk の頃から同じだったみたい。
やっぱりみんな最初はそうしようとするよね。

しかたがないのでフレームレートから自力計算でシーク処理。
したんだけど上手く動くファイルがほとんどないや。
GstSeekFlags をどう変更しても変わらないってどうよ。

二秒送りとかなら少しはマシだけどソレさえ綺麗に動かない場合がある。
Avidemux くらいの細かいコマ戻しが理想なんだけど、どうすれば…

ちなみに上記をまんま PyGI 化してもフレームレートは取得できない。

framerate = 0

vsink = self.player.props.video_sink
if vsink:
    for pad in vsink.pads:
        caps = pad.get_current_caps()
        success, num, denom = caps.get_structure(0).get_fraction('framerate')
        framerate = num

こんな方法を使ったけどもっとイイ方法があるかも。

Change in Python3

Y901x を Python3 化してみた。
Python3 って pyc キャッシュは __pycache__ ディレクトリに入るのね。

言語としての一貫性を重視したPython 3の進化 ? @IT

Y901x は gir 以外は sys, os, time の標準モジュールしか使っていない。
多分文字列と割り算さえ気を付ければそれほど変更点は無いだろう。

Python3 はデフォルトが UTF-8 なので coding 指定が不要に。
これで海外の Python 製アプリの動作が変という場合は減ると思う。

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

to

#!/usr/bin/env python3

例外はカンマから as に変わり raise も関数(?)になった。

#except Exception, e:
except Exception as e:

#raise ValueError, "hoge"
raise ValueError("hoge")

忘れちゃいけない unicode 関数を使っていた部分は str にして。

#s = unicode(entry.get_text()) # Python2
s = entry.get_text()
i = s.rindex(".")

割り算で整数にならないと困る部分は / を // に書き換えて。
/= も //= にしないといけないのか。
逆に float にキャストしていた部分はキャストを外して。

Python 歴があるなら誰でも知っていることはこれくらいで。

他 Fedora 19 の gir を色々試してみると
GLib.filename_from_uri 関数の動作が Ubuntu 13.04 と同じになった。
Gio.ApplicationFlags.HANDLES_OPEN も使えるようになった。

しかし Gio.ActionEntry が作れず ApplicationMenu は使えないまま。
使えるなら多重起動防止の設定を追加しようと思ったけどまだムリっぽい。
pygobject のバージョンに今後も振り回されるんだろうな。

今頃気が付いたけど inifile8.py に古いものを使っていた。
Python3 互換の文字列フォーマッタ版を随分前に作ったのにアホだ。

思ったより簡単だと変更していたけど問題は文字列や割り算ではなかった。
自然順ソートを行う numsort.py だった。

Python3 には cmp 関数が無い、いやコレの自作だけなら簡単だけど。
sort(), sorted() の引数が違う、てか比較関数が使えない。

ソート HOW TO ? Python 3.3 documentation

自力でクイックソートを作るか cmp_to_key をコピペするかだね。
cmp_to_key 関数を使うとなるとこんな感じでいいようです。

#! /usr/bin/env python3

from gi.repository import GLib, Gio

def sort_func(str1, str2):
    """
        str1.encode("utf8") is not required.
        Not 'cmp' function in Python3
    """
    cmpstr1 = GLib.utf8_collate_key_for_filename(str1, -1)
    cmpstr2 = GLib.utf8_collate_key_for_filename(str2, -1)
    # cmp function
    if cmpstr1 < cmpstr2:
        return -1
    elif cmpstr1 > cmpstr2:
        return 1
    return 0

def cmp_to_key(mycmp):
    """
        http://docs.python.org/3.3/howto/sorting.html # en
        http://docs.python.jp/3.3/howto/sorting.html # Japanese
        Convert a cmp= function into a key= function
    """
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

def get_file_numsort_list(dirname):
    """
        param dirname: Directory Full Path Name
        return: List in Numeric Order
    """
    files = []
    d = Gio.file_new_for_path(dirname)
    enum = d.enumerate_children(
            Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
            Gio.FileQueryInfoFlags.NONE,
            None )
    for info in enum:
        if info.get_file_type() == Gio.FileType.REGULAR:
            s = info.get_name()
            if not s.startswith("."):
                if not s.endswith("~"):
                    files.append(s)
    # Python2
    #files.sort(lambda x, y : cmp(GLib.utf8_collate_key_for_filename(x, -1), 
    #            GLib.utf8_collate_key_for_filename(y, -1)))
    #
    # Python3
    files.sort(key=cmp_to_key(sort_func))
    return files

これじゃラムダ式にできない、別にいいけど。
随分コードが長くなってしまったけどアプリケーションは動けばいいのさ。
アーカイブサイズが減った理由がワカラナイ…

GLib.utf8_collate_key_for_filename は str のままイケた。
GLib で文字列として扱う場合は UTF-8 で得られるということみたい。
でも Python 文字列として扱う場合は UCS-4 であるのを意識する必用あり。
でいいのだろうか、いつか落とし穴にはまりそうな気もする。

ついでに PyGI で今更気が付いたこと。

class CToolBox(Gtk.Box):
    def __init__(self):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)

GtkBox は GtkOrientable をインプリメントしているから orientation property がある。
なのでこの指定で GtkBox のサブクラスを作れば GtkVBox と同様になる。
いやプロパティは全部 __init__ の引数にできるのを知ったのは最近だし。

y901x101

とりあえず Python3 化した Y901x 1.0.1 公開。
memopoli の更新をやるべきなんだろうけど、実はもう使っていないのだがどうしよう。

1.0.1 Download (34.0kb)

blog にもリンクを今回から貼ることにする。
需要は無いだろうけど何かの参考になればいいや。

Y901x 1.0.0

この連休中にどうしても Y901x を正式版にしたい。
Boxes 仮想マシンにした Ubuntu 13.04 で映像が出ない原因を色々と調べてみる。

Xubuntu の Parole で動画再生できない件はアッサリ見つかった。
[xubuntu] gstreamer videosink error

$ parole --xv false

コマンドを打ち込めば以降再生できるようになる。
つまり、関係無かった。

やっぱり OpenGL 関係なんだろうな。
あれ、Ubuntu には glxinfo が入っていないじゃないの。

$ sudo apt-get install mesa-utils

んでレンダラの確認

$ glxinfo | grep renderer

次のように出力された

OpenGL renderer string: Gallium 0.4 on llvmpipe (LLVM 3.2, 128 bits)

Gallium3D – Wikipedia

なので OpenGL レンダラ自体は Boxes 上でも動いているわけだ。
そりゃ 3D デスクトップが動くし、ソフトウエアエミュレートだから激遅なりに。

gst-launch-1.0 での再生は上手くいった。
Raspberry Pi ? View topic – Gstreamer 1.0 for raspbian

でもコッチだと音しか出ない。
gst-launch-1.0 playbin uri=file:///path/to/file

つまり playbin だとダメだということか。
playbin が OpenGL 関係のものを読み込もうとしてコケているっぽい。
そこを作り替えれば、ってソレだと全部作り替えジャン!

いや、これって Boxes つか qemu-kvm 側がコケているのかも。

仮想マシンではなく通常インストールだと動くのかな?
でも我がミニノートは Ubuntu 12.10 が起動できなかったんだよなぁ…

ということで 19,800 円の激安中古ノートを勢いで買ってきた。
Core2Duo P8700, GM45, 2G メモリの今でも充分なノートがこんな値段とは。
無線 LAN が付いていない事に気がつかず後で USB 子機を買いに走ったのは内緒。

Windows XP はいらなかったが、というか XP の使い方を忘れたw
ライブ DVD を入れるためだけに起動したが IE6 で笑った。
Ubuntu 13.04 x86_64 ライブ起動、64bit でも問題なく動いた。

USB 無線 LAN も問題なく認識、接続して XP に上書きインストール。
Fedora もそうだが別途ドライバ不要で全部認識してしまう今の Linux 凄すぎる。
この超まっさらな状態で Y901x をインストールしてみる。

ubuntu_y901x

普通に動いちゃった、やっぱり qemu-kvm 側の不具合だったのか。
parole もネイティブなら問題無かったのかもしれない。
あんなに悩んだのにこんなにアッサリ…
まあ充分使えるノートパソコンを激安で手に入れたし満足。

ということで Y901x 1.0.0 はめでたく公開となりました。
仮想マシン上 OS で動画を見る人なんていないはずだ。

しかしネイティブで使うと当然だが Unity は 3D でもサクサク動く。

ただ GNOME3 では Alt+F1 からはコマンドを全部打たずとも選択状態になった時点で Enter すれば起動できるという動作をするのでイチイチクリックするか全部打ち込む必要があるのが面倒くさいぞ。
Alt+F2 で Tab キー保管ができないのも面倒くさいぞ。
ランチャはどこかをクリックするまで隠れているほうがウザくないぞ。
メニューバー位置を勝手に変えるのはアプリ作り手としてイラッとするぞ。
端末は Fedora みたくカレントディレクトリのみ表示にしてくれよ。
Monospace の半角空白が等幅ではないって何だよ。
デフォルトアイコンは人によるんだろうけど…

サクサク動いても Unity はやっぱり気に入りそうにないな。