Ubuntu 13.04 gst

第270回 Ubuntu 13.04とGNOME:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社

どうやら Ubuntu 13.04 の Nautilus は 3.6 になるようだ。

ということは Ubuntu の GStreamer も 1.0 になるということだ!
Nautilus 3.6 は動画サムネイルに GStreamer 1.0 を使っている。

これは Y901x を早々に GStreamer 1.0 仕様に変更しなければ。
まだ 0.3.9 で動くからと PyGtk のまま放置のままもどうかと思うし。
作った本人、つまり筆者以外に使っている人はいないと思うけど。

Novacut/GStreamer1.0 – Ubuntu Wiki

大方はこのとおりに変更すればイケた。
playbin2 を playbin にするのを忘れないようにと。

しかし

playbin.get_property("uri") # All None

set_property(uri) は OK だが get は何をやっても None しか得られない。
既知のバグみたいなので修正を待つしかない、それまで別の手段で URI を保存しよう。

Gst.State.CHANGE_FAILURE に相当するものが見つからない。
PlayState 変更失敗はどうやって見分けるのだろう?

#self.p_position = self.player.query_position(gst.FORMAT_TIME)[0] # 0.10 PyGtk
self.p_position = self.player.query_position(Gst.Format.TIME)[1]  # 1.0 PyGI

ココでかなり苦しんだ、[0] だと bool 値だと気がつくのに時間が掛かった。
シークバーが全然動かなくて悩んだけどそういうことだった。

ボリューム変更の手段がいまだに解らない!
PyGst で gst.interfaces 以下の部分はどう変更になったのだろう?

で、
GStreamer とは関係ないところでも多々発見。

gtk.keysyms.Return が Gdk.KEY_Return と Gdk のアトリビュートになっていた。
gobject.timeout_add が GLib.timeout_add となったのも解り難い。

''' PyGtk
pixmap = gtk.gdk.Pixmap(None, 1, 1, 1)
color = gtk.gdk.Color()
blank_cursor = gtk.gdk.Cursor(pixmap, pixmap, color, color, 0, 0)
'''
blank_cursor = Gdk.Cursor.new(Gdk.CursorType.BLANK_CURSOR)

透明マウスカーソルはこんなに簡単に作れるようになった、嬉しいぜ。
PyGtk でも実は同じような手段があったのかな?

何より一番困ったこと。

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

from gi.repository import Gtk, GdkPixbuf, Gdk

class CToolBox(Gtk.Box):
    """
        Inheritance GtkBox is HORIZONTAL
    """
    def __init__(self):
        Gtk.Box.__init__(self, Gtk.Orientation.VERTICAL, 0)
        self.pack_start(Gtk.Label("Orientation"), False, False, 0)
        self.pack_start(Gtk.Label("VERTICAL"), False, False, 0)

class Win(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        self.add(CToolBox())
        self.show_all()

Win()
Gtk.main()

vertical

これができないみたい。
GtkVBox から継承ならイケるんだけど、この場合は下記みたくするしか無いかな…

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

from gi.repository import Gtk, GdkPixbuf, Gdk

class CToolBox(Gtk.Box):
    """
        OK
    """
    def __init__(self):
        Gtk.Box.__init__(self)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(Gtk.Label("Orientation"), False, False, 0)
        vbox.pack_start(Gtk.Label("VERTICAL"), False, False, 0)
        self.pack_start(vbox, True, True, 0)

class Win(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        self.add(CToolBox())
        self.show_all()

Win()
Gtk.main()

設定ダイアログは GtkTable を使っているので GtkGrid に書き換えだ。
面倒だから今度!

他にも何かあった気がするけど、気がついたら又今度書く。
とりあえずまだまともに動かないけど Blog にバックアップ。
もし明日筆者が死んでも誰かが続きをやってくれるのを期待して。
y901x-0.99.0.tar.gz

しかしやはり実際にアプリケーションを作ってみないと気がつかないことが多いと実感。
作った本人しか使わないと解っていても何か作り続けるといいことがある。

g_convert

最近の Gedit は Windows から持ってきた Shift-JIS のファイルを普通に読み込める。
ように思えますが実はチルダがバケる。

932

と秀丸で Shift-JIS 保存したものを Fedora に持ってくる。
ついでに iconv で CP932 及び SJIS 変換した例を下記に。

iconv

つまり Gedit は CP932 ではなく Shift-JIS から変換しているのですね。
Linux の持っていく場合は Windows 上で BOM 無し UTF-8 に変換しよう。
もし持ってきた後で気がついたら iconv で変換。

しかし天下の秀丸様でさえ CP932 を Shift-JIS なんて表記しているから困る。
Windows システムデフォルトのまま保存すると CP932 であるというのに。
この事実って Windows しか使えない人のほとんどが知らないという…

ということで。

Linux ユーザーにはお馴染みの iconv ですがプログラムから変換するにはどうする?
Python なら普通に文字コード変換関数があるけど Vala 等を使いたい時に困るので。

調べると、どうやら g_convert 関数で変換できるようだ。

Python

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

import sys
from gi.repository import GLib

try:
    result, contents = GLib.file_get_contents(sys.argv[1])
    if result:
        try:
            text, bytes_read, bytes_written = GLib.convert(contents, len(contents), "UTF-8", "CP932")
            print text
        except Exception, e:
            print "ConvertError: {0}".format(e)
except Exception, e:
    print "FileError: {0}".format(e)

Vala

using GLib;

public class Conv {
    public static int main(string[] args) {
        try {
            string contents;
            bool result = GLib.FileUtils.get_contents(args[1], out contents);
            if (result) {
                try {
                    string text = GLib.convert(contents, contents.length, "UTF-8", "CP932");
                    stdout.printf(text);
                } catch (GLib.ConvertError e) {
                    stdout.printf ("ConvertError: %s\n", e.message);
		            return 1;
                }
            }
        } catch (GLib.FileError e) {
		    stdout.printf ("FileError: %s\n", e.message);
		    return 1;
        }
        return 0;
    }
}

g_convert

こんな感じでいいみたい、Python でも Vala でも問題なく g_convert で変換できる。
Vala は例外処理を書かないとコンパイルで警告になるのが少し面倒だよね。
valadoc.org とニラメッコしなきゃ書けないよ。

g_file_get_contents

テキストファイルの一期読み込みに今まで Gio を利用していた。

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

from gi.repository import Gio

# Create GLocalFile
f = Gio.File.new_for_path("test.txt")
# load_contents(GCancellable)
result, contents, length = f.load_contents(None)
if result:
    print contents

のだけど g_file_get_contents という関数が GLib にあった。
File Utilities

コチラの関数なら GLocalFile を介さず一発で読み込み完了ができるみたい。
g_file_set_contents で書き込みも一発でイケるようだし便利そうだ。

ただ PyGI ではどう書く?
ということで実験。

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

import sys
from gi.repository import GLib

TEXT = """KAWASAKI
Ninja 250
Z250"""

# Text file Write
try:
    if GLib.file_test("write.txt", GLib.FileTest.EXISTS):
        print "'write.txt' is EXISTS"
        sys.exit()
    result = GLib.file_set_contents("write.txt", TEXT)
    if result:
        print "Write Success"
except Exception, e:
    print "Error @ {0}".format(e)
    sys.exit()

# Text file Read
try:
    result, contents = GLib.file_get_contents("write.txt")
    if result:
        print contents
except Exception, e:
    print "Error @ {0}".format(e)
    sys.exit()

g_file_set_contents は無条件で上書きしてしまうようです。
g_file_test 関数で存在確認を行ってから相応の処理を行ったほうがいい。

引数の GError は Python の例外として渡ってくるようです。

# Exception intentional
GLib.file_set_contents("/write.txt", TEXT)

のように root 権限位置に指定等を行うと例外が出力されることが解ります。

g_file_get_contents は存在しないファイル名指定なら例外になる。
戻り値を if で振り分ける必要は無いかも。

load_contents にある GCancellable というあまり必要を感じない指定も不要で簡単。
ストリーミング I/O で行う必要の無い少量の読み書きならコチラのほうが簡単ですね。

Python なんだから組み込みの open を使う人がほとんどなんだろうけど。
せっかく GLib が丸々使える環境なんだからもったいないじゃないか。

MSBuild

Visual C#がインストールされていない環境で、WindowsだけでC#の開発を行う方法について

からなんかウチのネタ元ページにチビチビと人が来ている。
いや、プログラミングに興味を持つ人が増えるのならキッカケなんて何でもいいと思うけーが…
しかし画像だらけで私的にはゲンナリするけど今時の人はこんな感じの解説を望んでいるのかな?
まあそれは関係なくて。

つまり
カレントディレクトリに sln か csproj があれば msbuild コマンドでビルドができるわけです。

単発小物なら csc コマンドに直渡しのほうが簡単だけど少し複雑になるとコッチのほうが楽。
csc コマンドでは XAML のビルドはできないけど csproj を使えば可能になる。
絶対に Visual Studio なんか使いたくないという意地っ張りなところが素敵な人もいる。
GNU make のように利用したい Linux 脳丸出しな人もいる。

ということで、実は MSBuild ならもっとイイ方法がある。

.NETビルド・エンジン「MSBuild」使いこなし術 ? @IT

上記に手段が書いているけど環境変数は単一インスタンス内で追加できる。
何かする毎に環境変数を書き換えるなんて面倒だからその方法を利用する。

実は msbuild コマンドのみでカレントディレクトリの sln, csproj を勝手に見つけてくれる。
GNU make の Makefile と同じ、つまり引数は不要。

MSBuildToolsPath って何?
MSBuild で特定の .NET Framework を対象にする
よく解らないけど WPF はこの指定が無いとビルドできなかった。

と、これだけ理解できれば EmEditor 等の外部ツールで MSBuild が使えると解る。

GNOME 上で Gedit を使い C, Makefile を作成し Ctrl+F8 を行うのと同じことができます。
解説が逆だろと言わない、筆者のメインマシンは Fedora です(Windows7 はミニノート)

残念なことに秀丸や EmEditor は複数行の外部ツールは使えないので bat を作って利用する。
複数行コマンドが利用できるエディタ(あるのか?)なら bat の内容を直書きでいいと思う。
で Windows7,8 に最初から入っている .NET 3.5 を使う手段まで。

一応書くとこのミニノートに Visual Studio は入れていません。
環境変数もデフォルトの状態に戻し再起動を行った状態で以下をやってみる。

@set PATH=%PATH%;%WINDIR%\Microsoft.Net\Framework\v3.5
@set MSBuildToolsPath=%WINDIR%\Microsoft.NET\Framework\v3.5
msbuild
pause

という内容で build35.bat みたいな名前でバッチファイルをまず作成。
.NET 4.0 を使うなら 3.5 を 4.0.30319 に変えて build40.bat なんかに。
これをテキストエディタの外部ツールに登録する。
下記は EmEditor の例、カレントディレクトリの指定に注意。

emediter_set

秀丸なら [プログラム実行] に bat へのフルパスを書き込むだけ。
フルパス取得には minipoli でも使ってくださいw
その他エディタは知らない、まともなプログラマーならこの二択もしくは両方だし。

登録したら MSDN のサンプルコードで試してみよう。
チュートリアル: MSBuild プロジェクト ファイルのゼロからの作成

コピペで helloworld.cs と test.csproj を作成。
helloworld.cs をエディタで開いている状態で外部ツールを実行。

build

普通に exe が作成されるのが解りますね。
日本語を使うなら cs, xaml ファイルはすべて BOM 付き UTF-8 で保存してください。
csc は BOM が無い場合はローケルと同じ文字コードとみなすはずですけど一応。

WPF だと構成ファイルや csproj が超複雑になるので zip で置いておく。
[SDK が見つからない] 警告を出さない方法は残念ながら解らない…
wpf_csproj.zip

VC# を持っているなら csproj と同じディレクトリにある C# コードを開いて外部ツールを実行すればビルドできると確認できる。
これで環境変数すら弄くらなくてもテキストエディタから一発ビルドできる環境の完成。

MSBuild
しかしそのプロジェクトファイルが複雑すぎて手書きで作るのが面倒くさい!
proj ファイルを簡単に作るジェネレータとかどこかに無いかな。

Microsoft としては Visual Studio を買ってほしいのだろうけどさ。
プログラミングに慣れると IDE なんて鬱陶しいだけなんだって。
普段使っているテキストエディタのみ、かつ環境変数すら弄くらないことに意義がある。

それって…
結論、やっぱり Linux で Python のほうがイイ。

clipoli 2.0.0

よく考えたら半年以上もアプリの更新をしていなかった。
ということで前回の適用を行い clipolix を clipoli と名前を変えて更新!

せっかくなので PyGI 化だけでなく気になっていた部分をチマチマ。

・Windows 版と名前を変える必要は無かったということでで名前変更
・GNOME はドットファイルをヤメたいようなので ~/.config に設定位置変更
・GLib.spawn_command_line_async はチルダを展開しないので自力変換
・GTK+ 必須なのだから gvfs を遠慮なく利用

それと Python の open や subprocess ではなく全部 GLib, Gio で処理。
そうしておけば Vala,Gjs 等の gir を利用する他の言語からでも参考にできるはず。

例の Unity の糞みたいなパネル追加制限は以下のように回避

UNITY = "com.canonical.Unity.Panel"
APPNAME = "appname"

if UNITY in Gio.Settings.list_schemas():
    setting = Gio.Settings.new(UNITY)
    value = setting.get_strv("systray-whitelist")
    if not "all" in value:
        if not APPNAME in value:
            value.append(APPNAME)
            setting.set_strv("systray-whitelist", value)

GStrv は PyGI では list のごとく append で文字列を追加できるようです。
こんなにアッサリと制限突破が可能だしまったく無意味だと思う。
つか Unity のためだけにこんな処理を入れるのメンドイぞ!

ついでに。
GtkMenu って for-in 文で GtkMenuItem を取り出せるのね。

#! /usr/bin/python
# -*- encoding: utf-8 -*-

from gi.repository import Gtk

menu = Gtk.Menu()

for label in ("HAYABUSA1300", "ZZR1400", "VMAX"):
    menuitem = Gtk.MenuItem.new_with_label(label)
    menu.append(menuitem)

#for menuitem in menu.get_children():
for menuitem in menu:
    print menuitem.get_label()

menu.get_children() と結果は同じなのでそうバインドしているのだろう。
実際にアプリケーションを作ってみないと気がつかないことって多いなと。

ということで追加機能とかは何もない。
GNOME3 で使いにくいのは GNOME 3.8 に期待で済ませることにする…