festival command

Linux で Mac OS の say コマンドのようなことをやりたい。
筆者は Mac を持っていないのだが検索すると面白そう。

厳密には GTK+ アプリ等で選択した文字列なんかを喋るようにしたい。

この英語スペルはどう発音するか等の簡易チェックに使いたい。
頻繁に使うわけではないので組み込みではなく単独アプリのほうがいい。
chrome 等から DnD で文字列を受け取ると読み上げるみたいな感じで。

GNOME3 には orca というアプリがある。
フォーカスのあるウインドウ文字列を読み上げる。
だけなのか。
つまり全部読み上げるので超鬱陶しい、求めているのはコレじゃない!
PyGI がエラーを吐いているし、日本語部はチャイニーズうんたらって何よ。

orca

というか、検索すると皆日本語を読ませようと四苦八苦しているみたい。
業務用途なら当然そうなるけど個人利用なら必要性をまったく感じないんだが。
英語の発音チェックに使いたいと考える筆者みたいな人はあまりいないのね。

ということで。

探してみると festival というコマンドがあるようだ。
Festival

私の Fedora 18 には最初から入っていた。

# stdout
echo "Read and Write" | festival --tts
# Read file
festival --tts read.txt

こんな感じで使える、これは使えそうだ。
英語で一定速しか読み上げできないけど私的には充分だ。

文字列のドロップで読み上げる PyGI ウインドウを作ってみる。
ついでにファイルドロップでも中身を読み上げできるように。

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

from gi.repository import Gtk, Gdk, GLib
import subprocess

class SayWin(Gtk.Window):
    def __init__(self):
        """
            Speech at the Drop string
        """
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        self.set_title("Say")
        # DnD
        dnd_list = [Gtk.TargetEntry.new("text/plane", 0, 0),
                    Gtk.TargetEntry.new("text/uri-list", 0, 1) ]
        self.drag_dest_set(
                Gtk.DestDefaults.MOTION |
                Gtk.DestDefaults.HIGHLIGHT |
                Gtk.DestDefaults.DROP,
                dnd_list,
                Gdk.DragAction.COPY )
        self.drag_dest_add_uri_targets()
        self.drag_dest_add_text_targets()
        self.connect("drag-data-received", self.on_drag_data_received)
        # GtkLabel
        self.label = Gtk.Label("Please drop your Selection Text or File")
        self.add(self.label)
        self.show_all()

    def on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
        if info == 0:
            # text/plane
            p1 = subprocess.Popen(['echo', data.get_data()], stdout=subprocess.PIPE)
            p2 = subprocess.Popen(['festival', '--tts'], stdin=p1.stdout)
            p1.stdout.close()
            p2.communicate()[0]
        elif info == 1:
            # text/uri-list
            uris = data.get_uris()
            filename = GLib.filename_from_uri(uris[0], None)
            subprocess.call(['festival', '--tts', filename])

SayWin()
Gtk.main()

say_app

GLib.spawn_command_line_async でパイプを使う方法が解らなかった。
subprocess モジュールでマニュアルどおりにしたけど何か冗長な感じ。
もう少しスマートにできそうだけど。

イマイチな感じもするけど目的どおりにはなった。
orca のほうが発音が解りやすいのでソッチが利用できればなと思うけど。

File manager for Xubuntu and Lubuntu 13.04

Nautilus は USB メモリ、デジカメ、スマートフォンを自動マウントできる。
携帯音楽プレイヤーの接続なら Rhythmbox、又は選択肢になるはず。

別途ドライバは一切不要、何も考えず USB ケーブルを差し込むだけで自動認識。
Windows のようにウザいだけのユーティリティアプリを導入する必要が無いのが嬉しい。

nautilus

余談だがファイルマネージャは GUI だけでなく実際のファイル管理も行っている。
つまり Nautilus 採用のディストリビューションであればマウントは保証できる。
筆者は Fedora で GNOME3 を愛用しているが当然 Ubuntu も同様である。

はて?
Xubuntu や Lubuntu では自動マウントはどうなるのかな?

五年以上 GNOME しか常用していない、というかメインは Fedora だし。
常用するデスクトップなら最低デジカメくらい自動マウントしてほしいし。

ということで。
せっかく Ubuntu の動作確認マシンを買ったのだから試してみることにする。
KDE 及びその他デスクトップ環境については他の人にまかせる。
メニューが超カオスになるので後から KDE 化するのだけは勘弁して。

sudo apt-get install lubuntu-desktop
sudo apt-get install xubuntu-desktop

起動して切り替えて USB メモリ、デジカメ、スマホを接続してみる。

Lubuntu @ PCManFM

pcmanfm

Xubuntu @ Thunar

thunar

あれ、コレらどのデスクトップでもマウント可能だったのか。
Ubuntu からコマンドで導入したので単体インストールの場合は保証できないけど。
PCManFM は何故か2つづつ表示されるけど。
Thunar は USB メモリ以外はアンマウントボタンが出ないけど。

とにかく素の Ubuntu からの変更であればスマホもデジカメも自動マウントできます。
常用可能なデスクトップ環境の選択肢が増えた、やったね。

ユーティリティアプリが必要ない人ならパソコンは Linux にしたほうがいいよ。
特にデジカメ画像で拡張子のみ小文字に変更したい場合に Linux は普通にできるし。
うっかり画像の拡張子を消してしまっても普通に画像と認識してくれるし。

********************

ついでに Alt+F1, Alt+F2 動作のチェック。

Lubuntu, Xubuntu 共 GNOME2 とまったく同じ。
具体的には Alt+F1 でメニュー、Alt+F2 で一行コマンドランチャ。

alt_f2

コマンドランチャは自動保管があり選択肢が残り一つになると全部コマンドが流し込まれる。
そのまま Enter で実行、そういえば GNOME2 はそうだったと思い出す。

ちなみに GNOME3 の Alt+F2 は端末と同様に Tab キーを叩くと保管に変わっています。
Alt+F1 は選択状態になった時点で Enter するだけで実行できる。

Unity だけ一切保管できない、何故クリックすることを強要する UI なのだと。
(Amazon 広告をクリックさせるため意図的なのだろうと憶測できるが)
筆者が Unity を避ける最大の理由でもあります。
コレに言及している人が少ないというより見たことが無いのが本当に不思議。

ただ私の環境だけかもしれないけど Xubuntu の Alt+F2 は異様に遅い。
もしかして保管用 GtkListStore を都度作成しているのだろうか?

しかし XFCE, LXDE 共 GNOME2 を参考にしているので操作性はほとんど変わらない。
Xubuntu は合成処理が使えるのが利点だが上記のように少し重い場面が多々ある。

というか Lubuntu が軽すぎる、軽くしたいのなら Lubuntu だけでいい。
両方入れるとメニューがカオスなことになるのでなるべく増えないようにしたいし。
それと XFCE は Ubuntu アプリとランチャが共通名な場合が多いので混乱しそう。

削除は下記でイケるようです。
Getting Back to a Pure Gnome on Ubuntu

********************

ついでに GNOME3 化もやってみる。

sudo apt-get install ubuntu-gnome-desktop ubuntu-gnome-default-settings

インストール途中で gdm の選択になる。
lightdm だと Ubuntu デフォルトのログイン画面、名前のとおりチョッピリ軽い。
gdm を選択だと Fedora と同じ GNOME デフォルトのログイン画面になるようだ。

gdm を選択して再起動、あぁ完全な GNOME3 になった。
SE Linux が無いので Fedora より軽い、ソレをどう見るかだが。

ただ Unity に色々と干渉してしまう、今の Unity は GTK3 ベースだから当然か。
なので完全に GNOME3 化してしまいたい場合以外は行わないほうが良さそう。
強制フォールバックの選択肢が無いことに笑える。

Xubuntu, Lubuntu は GTK2 ベースなので完全な別物として共存できる。
それぞれメリットとデメリットがあるので後はお好みで。

しかし Fedora なら GNOME3 一択で他を試そうとは全然思わないのだが。
筆者の場合は GTK3 と Python 使いだからというのが一番の理由だけど。
xubuntu の検索ワードでイッパイ人が来ている現実を見るとやっぱりみんな…

Empty the trash from PyGI

我が公開 Linux アプリでまだ PyGI 化していないものがあった。
trash だ、しょーもないアプリだと思って作ったが意外に本人は結構使う。

PyGI 化だけだと二分で終わるし何かないかな。
そうだ、ゴミ箱を空にするオプションを付けちゃえ!
実際にそんな機能を使うかどうかは別の話。

Nautilus のソースを参考にすれば多分手段は解るだろう。
ということでソレっぽい名前で grep しまくる。

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

"""
    Empty the trash.
"""

from gi.repository import Gio

# Get Trash URI
trash_uri = Gio.file_new_for_uri("trash:")
# Get Child
enum = trash_uri.enumerate_children(
        "{0},{1}".format(
            Gio.FILE_ATTRIBUTE_STANDARD_NAME,
            Gio.FILE_ATTRIBUTE_STANDARD_TYPE ),
        Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
        None )
# Delete
for info in enum:
    f = trash_uri.get_child(info.get_name())
    f.delete(None)

こんな感じでやっていた。
当然元の C 言語はもっと複雑だったけど Python は楽だ。
普通に g_file_delete しているだけなんだな。

Nautilus から Ctrl+L でロケーションバーを表示させる。
んで trash: と打ち込んで Enter するとゴミ箱が開くんだね。
Explorer の sendto みたいなことができたのか、知らなかった。

んでファイルリスト作成と同様に enum を得る。
g_file_get_child でゴミ箱内の GFile を個別で得る。
既に GFile なのでそのまま g_file_delete できる。

パス名に変換して rm コマンドに渡すとか最初は考えていたけど不要だった。
Nautilus のゴミ箱アイコンは監視しているようでしっかり連動する。
何かメッセージを送らないといけないかと思ったけどコレも不要だった。

より手段は解った。
あとはコマンドラインオプションをどう実装するか。

15.4. optparse ? より強力なコマンドラインオプション解析器 ? Python 2.6ja2 documentation

こんな便利なモンが標準モジュールにあったのか!
使わないと損だ、ということで適用。

ただバージョン情報を -V, –version にしようと思ったけど手段が無い。
書くまでもなく Python と同じにしたかっただけですけど。
自前で –version を定義するとコンフリクトしていると怒られる。
素直にあきらめよう。

ということで trash-1.0.0 公開。
全アプリの PyGI 化完了、去年からの目標だったけど長かった。

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 はやっぱり気に入りそうにないな。

Xubuntu 13.04 and GtkApplication

Ubuntu 13.04 は少し軽くなったとはいえ相変わらず 3D しか使えない。
テスト用途にしか使わない仮想とはいえ重すぎる。
しかも操作性最悪、何故カスタマイズしてまで Unity を使う人がいるのか?

なので今回も LXDE…
では芸が無いので Xubuntu にしてみた、実は初めてです。

sudo apt-get install xubuntu-desktop

ってなんだこれ、ちっとも軽くないというより重すぎ!

XFCE は GTK2 ベースだけど 3D 表示しているんだな。
[ウインドウマネージャ(詳細)]で合成処理の有無を切り替えできるようだ。
ということは有効状態なら下記で背景が透けるはず。
Transparent GtkWindow | PaePoi

xubuntu_visual

off にすると Lubuntu ほどではない気がするけど充分軽くなった。
コレなら継続利用できそうだ、ということで気になる部分をチェック。

デフォルトプレイヤーの parole で動画が再生できないぞ!
しかしコイツもやはり GStreamer なのか。

xubuntu_video

gnome-session-properties に何も無い。
あれ?と思い 12.04 LTS のを見ても何もない、独自処理だったのか。
キーリングとかはどうしているんだろう、便利なのに。

ub_session

つまりディレクトリ名監視なんかしていない。
普通に不要なデフォルトディレクトリを削除したり F2 キーで変名できる。
何故かデスクトップだけは変名できなかったけど。

GTK+ のバージョンは 3.6.4 って今の Fedora と同じかい。
でも pygobject が変わっているのだからもしかして。

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

from gi.repository import Gtk, Gio
import sys

class Win(Gtk.Window):
    """
        Test "HANDLES_OPEN"
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        swin = Gtk.ScrolledWindow()
        self.view = Gtk.TextView()
        swin.add(self.view)
        self.add(swin)
        self.resize(320, 240)
        self.show_all()

    def add_uri(self, uris):
        buf = self.view.get_buffer()
        buf.set_text(uris)

class AppClass(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(
                self,
                application_id="org.gnome.test_id",
                flags=Gio.ApplicationFlags.HANDLES_OPEN )
        self.connect("startup", self.on_startup)
        self.connect("activate", self.on_activate)
        self.connect("open", self.on_open)

    def on_startup(self, data=None):
        self.window = Win()
        self.add_window(self.window)

    def on_activate(self, data=None):
        self.window.present()

    def on_open(self, application, files, n_file, hint, data=None):
        """
            Ubuntu 13.04 @ SUCSESS!
            Fedora 18    @ FAILED...
        """
        s = ""
        for f in files:
            s += "{0}\n".format(f.get_uri())
        if s == "":
            s = "FAILED..."
        self.window.add_uri(s)
        self.window.present()

if __name__ == "__main__":
    app = AppClass()
    app.run(sys.argv)

gtkapplication

ついに HANDLES_OPEN に対応してくれたようだ。
コレで多重起動防止アプリを Python で作るのが簡単になったね。
Fedora 19 が待ち遠しいぜ!

clipoli も動く、よしコイツはこのままでいいな。
memopoli も動く、いや初期状態に問題があることは解っているんだが。
とりあえず我がアプリは Y901x 以外は大丈夫であるようだ。

肝心の使い勝手は Lubuntu とたいして変わらない。
しかし標準テキストエディタはショボすぎだろ、GtkSourceView なのに。

Xubuntu は合成オフ可能なことに気がつくまではキレそうだったけど悪くない。
別に GTK2 ベースのデスクトップでも GTK3 開発は可能なわけだし。
ただ 3.6 なので Fedora 18 から乗り換える理由は何も無いけど。

FTP やスマホ接続で Nautilus が絶対にファイルマネージャである必要があるのでホスト OS は今後も GNOME にしますが。