月別アーカイブ: 2021年5月

kiji

今日の大口町。

Hibari

ヒバリさん、ストーップストップひばり君(古い)
高く飛んでピーチクパーチクするのは威嚇だと思っていた。
アレ求愛だったのね、鳥の世界はよくワカラン。

Kawasemi

カワセミ君、ひっさしぶり。
いやココ水を張った田んぼだよ、魚いないよ?
調べたらカエルやザリガニも食うのか、へー知らなんだ。

Kiji

キジの夫婦、ちょっとブレた。
てかここらにマジでいるんだな、初めて見つけたよ。
こんなにデカくて目立つビジュアルなのにね。

ここ最近休日は小牧山に行っていたんだけど。
コマドリ等のさえずりは聴こえるけど姿は見えず。。。。。
が続いていたのでキジ発見は嬉しい。

Eye of Mac

筆者は Fedora と Mac を併用しています。
写真関連は現在全部 Mac でやっている。
そして思う、Eye of GNOME(eog) を Mac で使いたい。

大量画像の Exif 情報をサクッと確認したくなる場合が多い。
eog は左右矢印キーでディレクトリ内を巡回できるのがいい。
Finder のギャラリー表示はなんかもどかしくて。

Photo management | Paepoi Blog

Mac にインスト、、、、、いや Gedit でやって劇遅だったじゃん。
だから Atom を Gedit 風にカスタムして使っているのだし。
コレも似たようなビューアを探す?いやどうせなら自分で作ろうかなって。
カスタムするくらいなら最初から自分好みに作ったほうがいいので。

まて、その前に RAW 画像を NSImage は表示できるのか?
ということで試してみた。

#!/usr/bin/env python3

from AppKit import *

PATH = 'P1012925.RW2' # LUMIX(Panasonic) RAW image
RECT = NSMakeRect(0, 0, 600, 400)
wins = []

class RawView(NSView):
    def initWithFrame_(self, rect):
        objc.super(RawView, self).initWithFrame_(RECT)
        self.image = NSImage.alloc().initWithContentsOfFile_(PATH)
        return self

    def drawRect_(self, rect):
        NSColor.blackColor().set()
        NSRectFill(rect)
        aw = rect.size.width
        ah = rect.size.height
        w = self.image.size().width
        h = self.image.size().height
        if w - h > 0:
            if aw * h > ah * w:
                width = w * ah / h
                height = ah
                x = (aw - width) / 2
                y = 0
            else:
                width = aw
                height = h * aw / w
                x = 0
                y = (ah - height) / 2
            r1 = NSMakeRect(x, y, width, height)
            self.image.drawInRect_(r1)

class MyWindow(NSWindow):
    def init(self):
        objc.super(MyWindow, self).initWithContentRect_styleMask_backing_defer_(
            RECT,
            NSTitledWindowMask | NSClosableWindowMask |
            NSResizableWindowMask | NSMiniaturizableWindowMask,
            NSBackingStoreBuffered, False)
        # NSView
        view = RawView.alloc().initWithFrame_(RECT)
        self.contentView().addSubview_(view)
        # self
        self.setTitle_('RAW image Viewer')
        return self

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        window = MyWindow.new()
        window.makeKeyAndOrderFront_(window)
        # save
        wins.append(window)
        # Activate
        NSApp.activateIgnoringOtherApps_(True)

class AppMenu(NSMenu):
    def init(self):
        objc.super(AppMenu, self).init()
        item_app  = NSMenuItem.new().autorelease()
        self.addItem_(item_app)
        menu_app = NSMenu.new().autorelease()
        item_app.setSubmenu_(menu_app)
        # quit menu
        item_quit = NSMenuItem.new().autorelease()
        item_quit.initWithTitle_action_keyEquivalent_('Quit App', 'terminate:', 'q')
        menu_app.addItem_(item_quit)
        return self

pool = NSAutoreleasePool.new()

NSApplication.sharedApplication()
NSApp.setMainMenu_(AppMenu.new().autorelease())
NSApp.setDelegate_(AppDelegate.new().autorelease())
NSApp.run()

rw2_view

普通に表示できるじゃん。
macOS が対応している RAW は全部表示できると思う。
RAW 対応は「システムレポート」で見ることができる。

mac_raw

EXIF は以下の方法で RAW でも取得できるようだ。

PyObjC Exif | Paepoi Blog

これは思ったより簡単に作れそうだぞ。
GTK4 もやらなきゃだけど今はこっちをやりたいかな。

Gst

Fedora 34 にしてから我が Y901x がおかしい。
動画再生はできるけど画面が止まったりシークで暴走したり等々。
GTK4 に変更すれば大丈夫なのかなと軽く書き換えしてみた。

not_gtk3

どうやってもこのエラーが出てしまう、ちっとも進まない。
GTK4 に書き替えたし細かい所は例外で逃がしているはずなのに。
色々弄くり回して絶望的な原因を発見してしまった。

GtkClutter が GTK3 専用だ!

GTK4 化するには GtkClutter を使わない手段に変更するしか手が無い。
つまり丸ごと作り替えか、わーい。

とりあえず他の手段を探してみよう。

gst-plugins-bad/main.c at master ? GStreamer/gst-plugins-bad ? GitHub

gtk_widget_get_window は GTK4 で削除されている。
他サイトで GdkWindow は GdkSurface に変わったと見つかる。
Wayland では xid が得られないけど GdkWaylandSurface 指定できるようで。
どっちにせよこれらを GtkWidget から得る手段は見つからない。
GdkWayland の gir は 4.0 用しか Fedora 34 には入っていない
えっと、どうしろと。。。。。

#!/usr/bin/env python3

'''
# run of X11 
GDK_BACKEND=x11 python x11gtk3.py
'''

import gi, sys
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, Gio, Gst, GstVideo

FILENAME = 'video.mp4'

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        try:
            self.video_area = Gtk.DrawingArea()
            self.add(self.video_area)
            # uri
            f = Gio.file_new_for_path(FILENAME)
            uri = f.get_uri()
            # Gst
            self.pipeline = Gst.parse_launch ('playbin')# video-sink=waylandsink')
            self.pipeline.props.uri = uri
            self.bus = self.pipeline.get_bus()
            self.bus.add_signal_watch()
            self.bus.set_sync_handler(self.bus_sync_handler)
            #
            self.video_area.realize()
            self.resize(640, 480)
            self.show_all()
            #
            self.pipeline.set_state(Gst.State.PLAYING)
        except Exception as e:
            print(f'@@@Error@@@@: ${e}', file=sys.stderr)

    def bus_sync_handler(self, bus, message):
        if GstVideo.is_video_overlay_prepare_window_handle_message (message):
            al = self.video_area.get_allocation()
            gdkwindow = self.video_area.get_window() # GTK3
            message.src.set_window_handle(gdkwindow.get_xid()) # No Wayland
            message.src.set_render_rectangle(al.x, al.y, al.width, al.height)
        return Gst.BusSyncReply.PASS

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.gixxer')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

Gst.init()
app = TestApplication()
app.run()

最低限を抜き出し。
GDK_BACKEND を X11 にして GTK3 を使うならコレでいいけどさ。
Wayland かつ GTK4 では手段がわかりません。

てか。

Celluloid でサイズ固定ができたらもう自作しないかも。
とか以前書いたような気がするけど、現行はできるんです。

celluloid

この一番上のチェックを外すだけ、原寸は Alt+1 でイケる。
筆者がずっと後回しにしているスマホ動画の回転も普通にやってくれる。
もうコレだけでいいジャン、みたいな。

でも何か作り続けていないと浦島太郎になるのが困る。
comipoli は逆に何も問題なく動いているので GTK4 化するの面倒。
うーんどうしよう、もう完全な野鳥ブログに変更しようかなとか。

Fedora 34 gir

PyGObject が Fedora 34 では例外になってもプロセスが続くようになった。
GTK4 だからかと思ったら GTK3 でやっても同じだった。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        try:
            btn = Gtk.Button(label='SUZUKI')
            btn.connect('clicked', self.on_button_clicked)
            self.label = Gtk.Label(label='Motor Cycle')
            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            self.add(box)
            box.pack_start(btn, False, False, 0)
            box.pack_start(self.label, False, False, 0)
            # err
            box.pack_start(null_widget, False, False, 0)
        except Exception as e:
            print(f'@@@Error@@@@: ${e}', file=sys.stderr)

    def on_button_clicked(self, widget):
        # err
        self.label.null_func()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.sv')

    def do_activate(self):
        w = TestWindow(self)
        w.show_all()

app = TestApplication()
app.run()

ところで前回は例外を受け取っても pass するコードだった。
これだと何も出力されなくなってしまうね。
stderr に出力するようにしたらアプリを実行中でも表示される。
Gedit の外部ツールなら色が着くというおまけ付き。

この仕様変更は gir 側なのか PyGObject 独自なのか。
ということで Gjs で同じことをやってみる。

GNOME Javascript

いつのまにかこんなサイトができていたのね。
ガイドを見るとまだ GTK3 での解説だけどね。

Legacy Class Syntax | GNOME Javascript

ES6 以降でクラスにする方法が筆者がよく使っている方法に。
コレだ!って解説が無かったから動いたのを書いていただけですが。
こういうサイトがこう書いてくれると以後安心して書けますね。

ただ、PyGObject と比べるとちょっと面倒臭いよね。
ただでさえ let と new とセミコロンとブレースが面倒なのに。
それはいいとして、とっとと上記を GTK4 で Gjs に書き換え。

#!/usr/bin/gjs

imports.gi.versions.Gtk = '4.0';
const {GObject, Gtk} = imports.gi;

var TestWindow = GObject.registerClass({
    GTypeName: 'TestWindow'
}, class TestWindow extends Gtk.ApplicationWindow {
    _init(app) {
        super._init({
            application: app
        });
        try {
            let btn = new Gtk.Button({label: 'SUZUKI'});
            btn.connect('clicked', ()=> {
                // err
                this.label.null_func();
            });
            this.label = new Gtk.Label({label: 'Motor Cycle'});
            let box = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL});
            this.set_child(box);
            box.append(btn);
            box.append(this.label);
            // err
            box.append(null_widget);
        } catch(e) {
            printerr(`@@@Error@@@@: ${e.message}`);
        }
    }
});

var TestApplication = GObject.registerClass({
    GTypeName: 'TestApplication'
}, class TestApplication extends Gtk.Application {
    _init() {
        super._init({
            application_id: 'org.suzuki.bandit'
        });
    }
    vfunc_activate() {
        let w = new TestWindow(this);
        w.present();
    }
});

let app = new TestApplication();
app.run(null);

gjs_gedit4

うん完全に同じだ、gir 側の仕様変更だったようです。
プロセスの終了を待たずに printf debug ができるのは嬉しいね。

Fedora 34 etc…

Fedora 34 をしばらく使ってみて。

ibus-anthy には困った。
変換候補のページ切り替えで PageDown が動作しない。
設定を見るとキチンと指定されているのだが。

Fedora 側の不具合なのかと試しに ibus-kkc を入れてみる。
kana kanji って奴、Fedora 33 までのデフォルトインプットメソッド。

設定で切り替えようとしたら出てこない、なんでや!
dconf-editor で org.gnome.desktop.input-sources に自力追加。

[('xkb', 'us'), ('ibus', 'anthy'), ('ibus', 'kkc')]

それでも切り替えできない、まじでなんでや!
もしかしてと再起動、普通に切り替えできるようになった。
てか入れた後で再起動すれば多分 GUI で設定できたんだろうな。

まあいい切り替え、普通に PageDown が使えるや。
つまり anthy だめだこりゃ、削除して kkc にします。
相変わらず初期状態はバカだなぁ、そのうち学習するからいいけど。

それと先日 Gedit プラグイン更新分の配布のためアーカイブした。
そのとき気が付く、file-roller が無くなっていたのね。
今は Nautilus にアーカイブ機能があるからだろうね、ショボいけど。
筆者は必須だから入れる、おいらは tar.gz と cbz を作りたいんや。

それと make は今回は最初から入っていた。
gcc があって make が無いとか変だったもんね。

それと Gedit から PyGObject のアプリを起動の件。
__init__ で例外になった時に勝手に死んでくれなくなっている。
でもシグナルの例外等は即時 stdout に表示されるようになった。
つまりどこでどう例外になってもプロセスは続くということね。
どうにか present させれば後はなんとかなるかも。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        try:
            btn = Gtk.Button(label='SUZUKI')
            btn.connect('clicked', self.on_button_clicked)
            self.label = Gtk.Label(label='Motor Cycle')
            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            self.set_child(box)
            box.append(btn)
            box.append(self.label)
            # err
            box.append(null_widget)
        except Exception as e:
            pass

    def on_button_clicked(self, widget):
        self.label.null_func()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.sv')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run()

うん、これなら例外になってもどうにでもできるぞ。
もっといい方法があるかもしれないのでとりあえずということで。