GStreamer Change Volume

GStreamer Player のボリュームを直線的に変更したい。
GtkHScale の値を直で渡すと曲線になって使いにくい、DirectShow はもっと酷かったけど。

dBデシベルの話し 音の大きさ

音量のデシベルは非常にややこしい。
GStreamer マニュアルの GstStreamVolumeFormat 以下にも 20 * log10 (val) とある。

gststreamvolume

実は私の Cinema という Windows 用 DirectShow プレイヤーは手抜きをしていて…
DirectShow ボリュームは最大 0、無音 -10,000 をデシベル単位でということなのですが…

void CDirectA::SetVolume(int nVolume)
{
	double d = pow((double)(nVolume * 2), 2.0);
	m_nVolume =  static_cast(-d);
	if (pBasicAudio)
		pBasicAudio->put_Volume(m_nVolume);
}

というベキ乗を利用してなんとなく似たようなカーブにしている。
ぶっちゃけ WMP とは全然カーブが違うんだが面倒だということで(ぉい!

GStreamer ボリュームは最大 100.0、無音 0.0 なのでコレを Y901x で真似るには

def on_volume_value_changed(self, widget, event=None):
    val = widget.get_value()**2 / 10000.0
    self.player.set_property("volume", val)

とやってみたけど完全に違う、GStreamer では同じ手は使えないようだ。
キチンと調べないといけないみたい、Totem はどうやっているかコードを漁る。

bacon-video-widget-gst-0.10.c の bacon_video_widget_set_volume 関数で
GST_STREAM_VOLUME_FORMAT_CUBIC を指定している、この型と相互変換が必要か。

gststreamvolume を pygst から利用するには c ヘッダが gst/interfaces 以下にあるので

import gst
dir(gst.interfaces)

みたいにやれば関数が一覧されるので探ってみる。
stream_volume_set_volume は流石に使えないようだけど convert はできるようだ。
CLAMP 関数も必要かな C言語でCLAMP(a,b,c) | OKWave
一行なのでラムダ式を使えと言われそうだが CLAMP という関数名も覚書に使いたい。

def set_volume(self, value):
    v = gst.interfaces.stream_volume_convert_volume(
            gst.interfaces.STREAM_VOLUME_FORMAT_CUBIC,
            gst.interfaces.STREAM_VOLUME_FORMAT_LINEAR,
            value)
    def clamp(a,b,c): return min(max(a,b),c)
    v = clamp(v, 0.0, 1.0)
    self.player.set_property("volume", v)

def on_volume_value_changed(self, widget, event=None):
    self.set_volume(widget.get_value() / 100.0)

おっし、これで Totem とまったく同じ音量カーブになった。
CUBIC を LINEAR に変換すればいいのね、実はいまいちよく解っていなかったり(ぉい!

もう少し Debug して Y901x の Playbin2 化 version 0.3 はなんとかなりそう。

playbin2

Totem は

gst_stream_volume_set_volume

でボリューム調節を行っているということだけ理解した。
その関数ってもしかして playbin の volume Property とリンクしているんじゃないの?

米国の Google でコードを探し試しまくったけどさっぱり解らない…
3. Pipeline
自前でパイプラインを構築するか、しかし情報少なすぎ!

いや、そういえば playbin は古いので新しい PulseAudio に対応しているはずがない。
だから playbin2 に移行しろということなのか…

playbin2

playbin

Y901x の GstPipeline を playbin2 に書き換えて試す。

self.player = gst.element_factory_make("playbin2", "player")

エラーが出る場所をとにかくコメントアウトしてボリュームを試す。

あーあ、マジでそんだけだった、しかも mute Property にて簡単にミュート。
しかし DirectShow 同様に非線形カーブなので GtkHScale 値をそのまま使えないみたい。
ミュートも「サウンドの設定」の「アプリケーション」タブと見事連動。

これではもう playbin2 に移行するしか選択肢が無いようだ。

# Get GstStreamInfo List
info_arr = self.player.get_property("stream-info-value-array")

の所で例外になる、そりゃ playbin2 にそんなプロパティは無い。
本当はもの凄い遠回りをしたけど一応こう書き換えたら上手く動いた。

def gst_on_message(self, bus, message):
    t = message.type
    if t == gst.MESSAGE_EOS:
        self.clear()
        # Repeat
        if self.settingwin["repeat"] > 1:
            self.on_next(self)
        elif self.settingwin["repeat"] == 1:
            self.set_play_position(0)
            self.player.set_state(gst.STATE_PLAYING)
    elif t == gst.MESSAGE_ERROR:
        self.clear()
        err, debug = message.parse_error()
        self.messagebox(str(err) + "\n" + str(debug))  
        self.toolbox.change_img(0)
    elif t == gst.MESSAGE_STATE_CHANGED:
        if gst.STATE_PLAYING == message.parse_state_changed()[1]:
            self.toolbox.change_img(0)
            # This is First Play
            if not self.is_playing:
                try:
                    self.p_duration = self.player.query_duration(gst.FORMAT_TIME)[0]
                except:
                    self.p_duration = gst.CLOCK_TIME_NONE
                if self.p_duration != gst.CLOCK_TIME_NONE:
                    self.toolbox.seekadj.upper = self.p_duration
                    self.is_playing = True
                    # toolbox Buttons Enabled
                    self.toolbox.set_enable_ctrl(True)
                    # Timer on
                    self.timer_id = gobject.timeout_add(200, self.on_timer)
                    # File Names Listup
                    self.listup_change()
                    #
                    # playbin2
                    #
                    vsink = self.player.get_property("video-sink")
                    # vsink == None @ Music File
                    if vsink:
                        for pad in vsink.pads():
                            # print pad.get_caps()[0].get_name() # is Check
                            # W Buffer Off
                            self.video_window.unset_flags(gtk.DOUBLE_BUFFERED)
                            # caps[0] @ GstStructure
                            caps = pad.get_negotiated_caps()
                            self.video["width"] = caps[0]["width"]
                            self.video["height"] = caps[0]["height"]
                            #
                            flt = float(self.video["width"]) / float(self.video["height"])
                            self.aframe.set(xalign=0.5, yalign=0.5, ratio=flt, obey_child=False)
                            self.change_video_size()
                    """ under Old PlayBin src
                    # Get GstStreamInfo List
                    info_arr = self.player.get_property("stream-info-value-array")
                    if len(info_arr) == 1:
                        # Music
                        pass
                    else:
                        # W Buffer Off
                        self.video_window.unset_flags(gtk.DOUBLE_BUFFERED)
                    for info in info_arr:
                        # Get Video Size
                        pad = info.get_property("object")
                        #print pad
                        caps = pad.get_negotiated_caps()
                        if caps != None and "video" in caps.to_string():
                            # caps[0] @ GstStructure
                            self.video["width"] = caps[0]["width"]
                            self.video["height"] = caps[0]["height"]
                            #
                            flt = float(self.video["width"]) / float(self.video["height"])
                            self.aframe.set(xalign=0.5, yalign=0.5, ratio=flt, obey_child=False)
                            self.change_video_size()"""
        else:
            self.toolbox.change_img(1)

GstStreamInfo のリストからの情報で設定するより短くなってもーたw
video-sink なんてテキトーだったのにビンゴだったのは自分で驚いたマジで。

これで playbin2 化はなんとかなりそうだ、後はボリューム値の線形化だ。
って以前のように動かせるだけで見た目は何も進化していないのが少し悲しい…

Mandriva to Ubuntu p3

Ubuntu 10.04 の「外観の設定」を開くと何か足りない。
9.10 まではあったツールバーやメニューのアイコン設定が無くなっている。

まあこれは gconf で弄くれるので覚書。
gconf-editor にて

/desktop/gnome/interface/toolbar_style
を icons にするとツールバーテキストを消せる。

/desktop/gnome/interface/menus_have_icons
を On にするとメニューにアイコンを全部付けられる。

ついでに Nautilus で場所バーが GtkEntry に変更できなくなったと書いたができた。

Ubuntu日本語フォーラム / [Lucid] Nautilus 2.30.0でディレクトリの絶対パスを表示&コピーしたい

場所バーで直接入力切り替えボタンが無くなったのは私も一瞬困ったと思ったけど…
端末で cd 移動するのが面倒な時と Blog に長いフルパスを書く時以外は必要無いわ。

cd 移動が面倒な時はボタンを端末にドロップすればいい。
ファイルも一旦端末にドロップした後でコピーすればフルパスも簡単にコピペ完了。
今までと少し手段を変えればいいだけ、それならやっぱり切り替えボタンはいらないや。

つーかコマンドが解っているなら

~/.gnome2/nautilus-scripts

に登録すればいいのにと思うんだが、どうしてもボタンでやりたいのだろうか…

それより今頃気がついたのだが。
Y901x でボリューム調節ができなくなってしまった!
Totem はできる、Y901x とは違う方法でボリューム調節しているようだ。

Totem と同時起動してサウンドの設定を開き本体ボリュームバーを動かしてみる。
Y901x は何も起こらないが Totem は見事に連動、Totem は PulseAudio を直で変更?
環境も糞も Mandriva で使っていた頃とまったくマシンは同じだ。

VirtualBox 仮想マシン上の 9.10 でも結果は同じだが Y901x でボリューム調節できる。
何かの仕様が変わったのだろうけど PulseAudio 自体を弄くるようにしないとダメか。
Windows の Vista 以降同様にアプリ毎に指定できるんだからそのほうが自然か。

あーあ、いつまでたってもやらなきゃいけないことが無くならない。
というかミュートボタンを付けたいんだが上手い方法が思いつかない…

しかし OS 乗り換えを思い切って行うと色々なことを発見するもんだ。

.NET 4.0 on IronPython

.NET Framework 4.0 の日本語版が出たようだ。

窓の杜 – 【NEWS】マイクロソフト、“.NET Framework”の最新版「.NET Framework 4」を公開

そういえば Windows 7 を立ち上げるのは一ヶ月ぶりくらいのような…
もう Windows に対しては .NET がどうなった?以外に興味が無いのかも…
せっかく買ったんだから使いたいんだけど Linux のほうが圧倒的に便利だし…

とにかく早速インストール。
二十分くらいで終わった、以外に早かった。

早速 4.0 を動かして…
ってアプリが無い。

そういえば IronPython 2.6.1 の .NET 4.0 版ってのがあった。
.NET 2.0 版を削除して入れ替えて使ってみよう。
普通にダウンロードすると 4.0 版が落ちてくるんだね。

IronPython.net /

4.0 版のデフォルトインストール位置は以下になる。

C:\Program Files (x86)\IronPython 2.6 for .NET 4.0

2.0 版から入れ替える人は環境変数の変更なんかを忘れずに。

それから、これは IronPython が悪いわけではないけど。
私は IronPython 関連の関連付けをこうしていた。

ぱぇぽぃ2 ? Blog Archive ? IronPython への関連付け

んでこんなのを作ってスタートアップ登録して利用していた。

ぱぇぽぃ2 ? Blog Archive ? NotifyIcon to use from IronPython

ファイルの右クリでプロパティから新しい ipyw64.exe に関連付け変更ができない!
2.0 時の情報がレジストリに残っていて存在しない exe 扱いになっちまったようだ。

HKEY_CLASSES_ROOT\pyw_auto_file
HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\MuiCache

なんかの関連するものを丸ごと削除したけど EXE 情報が空になる。

HKEY_CLASSES_ROOT\Applications\ipyw64.exe\shell\open\command

を書き換えて、まあコレで関連付けはなんとかなったが…

なんだこりゃ、これはレジストリのドコを弄くれば修正できるのだ?
とにかく何でもかんでもキャッシュするのは迷惑なだけだ、特にアイコンキャッシュが。
Linux のほうがイイや、こういう細かいところで Windows を使う気が失せる。

ってコレは Windows への不満だし、気を取り直して実行。

さて ipy64.exe の初期化速度は、全然変わっておらずスゲェ遅い。
予想していたけど DLR はもう少しなんとかならないものか。
初期化さえ終われば実行速度も不満が無いし 2.0 版と同様に使えるのだけど。

上記の自作トレイアイコンもそのまんま動いた。

ぱぇぽぃ2 ? Blog Archive ? WPF Simple TextEditor example

も問題なく動く、3.5 までのコードはほとんど弄くらないまま 4.0 で動きそう。
新機能は知らないので後で調べる。

Mandriva 2010.1 Spring Beta

気がついたらもう四月後半、半年毎に Linux の新版がワンサカ出る季節である。
Mandriva One 2010.0 GNOME で何一つ不満が無いので見送りも考えているけど一応調べる。
クリアールックスにミストアイコン、更に VL ゴシックにして Fedora 臭い見た目だけど。

DistroWatch.com: Put the fun back into computing. Use Linux, BSD.

あらら、次の mandriva は 6/3 とチト遠いのですね。
ならばベータを VirtualBox で試してみよう、今回も One の GNOME 版を。

ftp://ftp.kddlabs.co.jp/Linux/distributions/Mandrake/devel/iso/2010.1/beta1/

から mandriva-linux-one-2010-spring-beta1-GNOME-africa-asia-cdrom-i586.iso をば。
md5sum –check コマンドも成功、仮想 HDD を作ってライブ CD を iso から起動。

あれ、one africa-asia を選んだのに Japanese が選択肢に無いぞ?
とりあえずデフォルトの英語を選んで進めてみる。
タイムゾーンは Asia 内に Tokyo が、キーボード選択には japanesee106 があったけど。

やっぱり Japanese は無い、入れ忘れなのかそれとも完全に見限られたのか…
ベータなせいか壁紙やテーマが 2010.0 と同じで変な気分。
Live CD 状態では追加もできないし、とりあえず細かいところを見てみよう。

やはり今回も Guest Additional は最初から適用済み状態で Live CD を起動できる。
Flash も入っているのでそのまま YouTube 観覧可能である。
このプロプライエタリ・ソフトウエアにも柔軟な姿勢は他の Linux もやってほしい。
だって結局デスクトップ用途ではみんな入れるんだもの。

日本語入力できないけど SCIM の設定があった、iBus にはしないのかな?
Font には UmePlus がしっかりあった、VL ゴシックは無いです。
Ubuntu はデフォルト状態では Gimp を外すとか見かけたけどコイツはしっかりある。
gnome-screenshot のアイコンがカッチョよくなっているけど得に変わっていないっぽい。

というか標準搭載アプリは 2010.0 と同じ。
というより KDE メインのディストリビューションだし、正式版では解らないけど。

Python が 2.6.5 に、mono が 2.6.3 に、まぁ mono は今となってはどうでもいい。
Python 依存度が低い部類のディストリなんだから 3.0 系でも…企業ユーザーが困るか。

Epiphany 2.30.0 の WebKit が普通に使える、仮想環境での試用だから何ともいえないが。
私の現環境の 2.28.1 では起動するだけで OS が不安定になる、ATI と相性が悪いのだろうか。

Nautilus のデフォルトディレクトリには Fedora 等と同じくアイコンが付くように。
GNOME の仕様なのかな?何にせよ解りやすくなったのは嬉しい。
デザインも Ubuntu の「何故こんなにダサいの…」なアイコンとは違い大人しめでイイ。
それでもウザいなら user-dirs.dirs で全部無効にすればいいだけだ。

他、Nautilus は F3 キーでもう一つペインが出せるようになった、タブより使いやすい。
しかし一覧とアイコン表示切り替えがツールバーに移動してしまった。
ツールバー非表示で使いたいのに、他に場所バーが直接入力できなくなっていたり。
新機能は嬉しいけどバー追加の結果としてこれらが犠牲になった感じ。

チビッと使ってみて気がついたのはこんなところ。
とにかくデフォルト状態は 2010.0 とあまり代わり映えしない、個々が地味に更新されただけ。

ものは試しとインストールしてそのままアップデートしてみたら日本語 local が。

africa-asia を選ぶ意味無いジャン!
と思ったけど /etc/sysconfig/i18n 編集して再起動しても適用できん…
つか、ということは最初からあったのに適用されないってことなのかな?
次版は Ubuntu を選ぶほうが正解なんだろうけど、あの超ダサいアイコンがなぁ…

続く、かも。