自分宛てメモ

 

比較的新しめのインクルードファイル

/usr/lib/gcc/x86_64-linux-gnu/5.4.0/include

自分宛てメモ

 

simple-libmpd.c の void parse_playlistinfo_answer(MpdObj *mo, void *param) にて

下から4行目を以下に変更。

// 既存の領域が使われていたら次を用意する
      if (ms->id >= 1) md->nb++;

 

こうしないとプレイリスト用に確保した配列の要素の一部がNULLで初期化されたままになってしまう。

 

 

プレイリスト表示の改善

マウスカーソル位置に表示するよう変更

xfce4-mpc-plugin.c のstatic void show_playlist (t_mpc* mpc)に、下記を追加。

gtk_window_set_position(GTK_WINDOW(mpc->playlist),GTK_WIN_POS_MOUSE);

 

承前。

 

ラッパーでバグっているかどうかはっきりさせるため、ソースからsimple-libmpd.cを抜き出し、xfce4依存部分(といってもDBG()を使うためだけ)を取り除いて突き回してみたところ、取り敢えず動くようになった。

 

症状


UI上でマウスのセンターボタンをクリックするとプレイリストを表示する仕様だが、エラー終了してしまう。

 

 

原因


構文解析エラー。
mpdとmpcのやりとりはsocketを使っているが、mpc側のバッファは有限なので溢れた分は次回に持ち越される。
プレイリストを格納するにあたり、このバッファをちまちまと読みつつ、改行や:で区切りつつ必要なフィールドを埋めている。
問題はプレイリストの終端の検出方法にあった。ソースを見ればわかるが、どう考えても検出できない。検出できないまま、存在しないトラックを処理しようとして格納場所以外を破壊しているようだ。
void paese_playlistinfo_answer(MpdObj *mo, void *param)  にある、mpd_Song* msのメンバをNULLで埋めているあたりが怪しい。


エラーそのものはこの関数の出口側の g_strfreev(lines) で発生する。エラーメッセージによれば二重にfreeしようとした、とのこと。

 

 

 

 

対策

 

このライブラリ(simple-libmpd.c)の使い方は、

 

  1. コネクトして、
  2. ステータスをアップデートして、
  3. プレイリスト上のトラック数を得て、
  4. それを格納するに必要最小限の格納場所を確保し、
  5. 改めてプレイリストを取り寄せて上記のように読み込んでいく

 

である。

 

プレイリスト解析時点でトラック数は判明しているので、この数だけ読み込んだら処理を終了するように変更したところ改善をみた。

 

void paese_playlistinfo_answer(MpdObj *mo, void *param) 内の最初のwhile ループ

 

    lines = g_strsplit(mo->buffer, "¥n", 0);
    //~ while(lines[i] && strcmp(lines[i],"OK"))
    while(lines[i] && strcmp(lines[i],"OK") && md->nb < mo->playlistlength)   

 

 

0.5.0以前のバージョンも同様の問題を抱えているのではなかろうか。

しかし、こんな初歩的なバグが放置されているあたり、このプラグインの不人気ぶりがうかがえる。おそらくプレイリストが短ければ生じない不具合であり、テスト不十分なのではなかろうか。

 

 

その他


上記改変箇所にある、lines[i] && strcmp(lines[i],"OK") は g_strcmp0(lines[i],"OK")で置き換えできそう、である。g_strcmp0 は GLib2.16で導入された(らしい)。

 

今回はプログラムの構造に一切手を付けずに対症療法に徹したが、このプラグインはお世辞にも出来が良いとは思えないのでいずれ自分で書いてみようと思う。デバッグしにくいのでプラグインにはしないと思うけど。

 

 

実行画面。曲はSpotifyより。なお、テストしたmpdはmopidyのみ。

 

自分宛てメモ

 

outputsで得られるデバイスの取り扱い例

 

echo -e "command_list_begin¥noutputs¥ncommand_list_end"|nc localhost 6600
OK MPD 0.19.0
outputid: 0
outputname: Mute
outputenabled: 0
OK

id 0 には Mute が割り当てられている。

Muteなのでenableすることで音が止まる。
echo -e "command_list_begin¥nenableoutput 0¥ncommand_list_end"|nc localhost 6600
OK MPD 0.19.0
OK

解除
echo -e "command_list_begin¥ndisableoutput 0¥ncommand_list_end"|nc localhost 6600
OK MPD 0.19.0
OK

 


アクセス可能コマンドの一覧


commands

echo -e "command_list_begin¥ncommands¥ncommand_list_end"|nc localhost 6600
OK MPD 0.19.0
command: add
command: addid
command: addtagid
command: channels
command: clear
command: clearerror
command: cleartagid
command: close
command: commands
command: consume
command: count
command: crossfade
command: currentsong
command: decoders
command: delete
command: deleteid
command: disableoutput
command: enableoutput
command: find
command: findadd
command: list
command: listall
command: listallinfo
command: listfiles
command: listmounts
command: listneighbors
command: listplaylist
command: listplaylistinfo
command: listplaylists
command: load
command: lsinfo
command: mixrampdb
command: mixrampdelay
command: mount
command: move
command: moveid
command: next
command: notcommands
command: outputs
command: password
command: pause
command: ping
command: play
command: playid
command: playlist
command: playlistadd
command: playlistclear
command: playlistdelete
command: playlistfind
command: playlistid
command: playlistinfo
command: playlistmove
command: playlistsearch
command: plchanges
command: plchangesposid
command: previous
command: prio
command: prioid
command: random
command: rangeid
command: readmessages
command: rename
command: repeat
command: replay_gain_mode
command: replay_gain_status
command: rescan
command: rm
command: save
command: search
command: searchadd
command: searchaddpl
command: seek
command: seekcur
command: seekid
command: sendmessage
command: setvol
command: shuffle
command: single
command: stats
command: status
command: stop
command: subscribe
command: swap
command: swapid
command: tagtypes
command: toggleoutput
command: unmount
command: unsubscribe
command: update
command: urlhandlers
command: volume
OK

 

アクセス不可能なコマンド一覧

 

notcommands

echo -e "command_list_begin¥nnotcommands¥ncommand_list_end"|nc localhost 6600
OK MPD 0.19.0
command: config
command: kill
OK

 

自分宛てメモ

 

mpdとのやり取りは平文なので、仮想端末から操作できる。

echo -e "command_list_begin¥nplaylistinfo¥ncommand_list_end"|nc localhost 6600


注意点
mpd互換のサーバーはいろいろあると思うが、それらが常にmpdの上位互換とは限らない。例えば、mopidy(2.1.0)はcrossfadeやmixrampdbをサポートしない。

 

xfce4での公式メディアプレイヤー。gstreamerベース。
LinuxMint18ではgtk+3.0のバージョンが間に合わずビルドできない。
debian9ではビルドできる。が、事前にいろいろと追加インストールしなくてはならない。
以下、ハードはCF-R2(PenM1GHz,RAM512MB)

 

ネットを漁ったところ、コーデックが必要らしいのでリポジトリを追加して導入してみた。これが必須かどうかは未検証。(なお、試したPCにはsudoをインストールしてある)
deb http://www.deb-multimedia.org stretch main non-free

sudo apt-get update
sudo apt-get install deb-multimedia-keyring
sudo apt-get update

 

./configure --prefix=/usr/local --sysconfdir=/etc --localstatedir=/var --enable-clutter

 

追加した主なもの(試行錯誤で入れたので確定できず。他にもあるかも知れない。)
libgstreamer1.0-dev
libgstreamer-plugins-base1.0-dev (これがないとgstreamer-videoが見つからない、と言われる。gstreamer-video-dev等というパッケージは無いので、わかっていないとハマる)
libtag1-dev
gstreamer1.0-libav
ffmpeg
x264

 

コーデックが不足しているとその旨を表示し、「自動でインストールできます」と言うのだけれどインストールされない。debianだからかしらん。

 

ハードが貧弱なので動画(720)はコマ送りになった。但しブロックノイズで画面が破綻することはなかった。VLCではフレーム落ちする上に画面破綻がしばしば生じる。
オーディオファイル(mp4)は問題なく再生できた。ボリュームコントロールに難があり、スライダが途中で引っかかることがある。

 

比較のためmplayer (1.3,debianのリポジトリより)でも再生してみたが、フレーム数は一番多く滑らか。但し、サウンドトラックの遅延が生じる(-ao pulse, -vo xv, framedrop=hard,全画面表示)。

 

paroleはちょっと微妙かも知れない。UIのデザインがシンプルで当たり前だがxfce4にマッチしているので処理能力のあるハードであれば使っていいのかも知れない。

 

 

自分宛てメモ

 

設定欄に「ディレクトリの編集」というのがあるが、ここで ~ や $HOME を指定しても展開されない。存在しないディレクトリを参照したことにされて、アプリケーションの起動時に無視される。

 

以前からうまく動かないプラグインの一つ。具体的にはプレイリストを表示しようとするとクラッシュする。

 

プラグインなのでそのままだとgeanyからデバッグしにくい。printデバッグで根気よく追うしか無いかも知れない。

 

こんなメッセージが出る。

*** Error in `/usr/lib/x86_64-linux-gnu/xfce4/panel/wrapper-2.0': free(): invalid pointer: 0x00005568feb52af0 ***

 

ラッパーで何か間違っているのだろうか。xfce4 は長く使われているDEであり、何を今更、と思うのだが。ここに問題があると修正は結構大変だけど、他のプラグインはそれなりに動作しているので可能性は低いと思われる。というか、そう思いたい。願いたい。信じたい。

 

mpcプラグイン側には問題がありそうである(バッファオーバーをひとつ見つけた)。書いた人には申し訳ないが、Cのコーディングスタイルとして参考にしてはならないものの一つ、だと思う。xfce4の流儀なのかも知れないけれど。

Geanyでプログラムコードの管理をしているのだが、古くなるといったい何を作っていたかが分からなくなることがあります。

 

一応、統合環境なのでプロジェクトファイルには説明書きを残せるようになっているのですが、それらを一覧できる機能が備わっていないのですね。プロジェクトを開く、とやっても呼び出されるのはgtkのダイアログだけです。

 

ということで、一覧表示させるものを作ってみました。

 

最初、Geanyのプラグイン拡張を使おうとしたのですが、調べるのが面倒になったのでパス。次にGeanyそのものを直接いじってメニューに組み込んでしまおうかと思ったのですが、もっと面倒なのでパス。


結局、「独立したプログラムで一覧表示して、そこで選んだものを引数にしてGeanyを起動する」ことにしました。2段階に分かれてしまいますが、頻繁に行き来して使うものではないので実用上の問題は少ないはずです。

 

Geanyの起動はexec系の関数を使うことにしました。で、ここでちょっとした問題が発生したのですね。

exec系の関数に渡す引数の内、"geany" と "-i"(新規インスタンスでプロジェクトを開くよう指示)は定数なので良いのですが、選択したプロジェクト名(具体的には「プロジェクト名.geany」というファイルへの絶対パス)は当然変数になります。
この変数データの格納場所をどこにするか。

 

読みだした、Geanyのプロジェクトファイルに関する情報は UI(gtk)上の格納場所(GtkListStore)にありますが、これはgeanyの呼び出しに遷移する直前にUIを破壊するので失われ、execに渡せません。

 

ということで、ここから取り出してどこかにコピーを持たなくてはいけません。今回、execの呼び出しをgtkのコールバックから行う(メインウインドウのdestroyイベントのデフォルト動作の直後に仕掛ける)ので、スタック上の自動変数には置けません。

 

こんな場合は、一つ外側のスコープの変数にg_strdupとかでコピーをとって渡すのが早いのですが、g_strdupなのでg_freeで開放しなくてはなりません。開放するのは exec 関数の呼出し後ですが、その時、この「プロジェクトの一覧表示プログラム」は上書きされて消えているはずです。

 

まあ、実用上は開放しなくても問題ないと思いますが、やはり気分的に宜しくないので別の手段を考える訳です。

 

で、他に手っ取り早くグローバルに使える領域、ということで環境を使うことにしました。gtkListStoreから取り出した値をsetenvで書き出しておいてUIのdestroyイベントに遷移、その最終段階でgetenvして使う、という方法です。環境ってプロセス間での引き継ぎに使うのが本来で、プロセス内部でのデータ退避に使うものではないでしょうから、例外的な使い方だと思います。

 

何か、他にもっと良い方法があるような気がするのですが、気がするだけで思い至らない自分が情けないです。

 

ちなみにシェルスクリプト以外で環境を弄ったのはMS-DOS以来でした。DOSの環境ってものすごく小さかったような気がするのですが、環境に常駐するプログラムというのもあったので、わかる人は使っていたのでしょう。私は中間ファイル(或いは設定ファイル)ばかり使っていました。さっぱり使わないPC-9801のVRAM(グラフィックRAM)をRAMディスクにしてそこに書き出したりとか。

 

Cで書いて400行弱。やっていることの割には大きい。「プロジェクト名.geany」ファイルはgeanyでプロジェクトを開く度に更新されるようで、内容に変更が無くてもタイムスタンプは新しくなる。

 

自分宛てメモ

 

設定ファイル内の各項目についての詳しい説明
man pulse-daemon.conf
man default.pa

 


Search

Calendar

S M T W T F S
     12
3456789
10111213141516
17181920212223
24252627282930
<< June 2018 >>

Archive

Mobile

qrcode

Selected Entry

Link

Profile

Search

Other

Powered

無料ブログ作成サービス JUGEM