Phonon
もうすぐKDE4安定版がリリースされる。
KDE4といえばPlasmaや、Dolphinに注目が集まりがちだが、個人的にはPhononに注目している。
なんだかんだで今までKDEはマルチメディアフレームワークが貧弱だった。KDE2で実装されたaRtsは最低限のサウンド再生しか面倒を見てくれず、しかも遅延が酷かったためKDE3末期はGStreamer等他のライブラリを通して音を出したり、デバイスファイルに直接アクセスしているものが目立った。
だがそんな状況もPhononの登場で解決するかもしれない。PhononはKDE4のマルチメディアフレームワークである。Phononはサウンドの再生だけでなく録音、映像の再生とキャプチャ、エフェクト、様々なフォーマットのエンコードとデコードまで面倒を見てくれる。混沌としていたKDEのマルチメディア事情がこんなにスッキリしてしまうのだから驚きだ(簡単なメディアプレイヤーのサンプル)。
KDE4といえばPlasmaや、Dolphinに注目が集まりがちだが、個人的にはPhononに注目している。
なんだかんだで今までKDEはマルチメディアフレームワークが貧弱だった。KDE2で実装されたaRtsは最低限のサウンド再生しか面倒を見てくれず、しかも遅延が酷かったためKDE3末期はGStreamer等他のライブラリを通して音を出したり、デバイスファイルに直接アクセスしているものが目立った。
だがそんな状況もPhononの登場で解決するかもしれない。PhononはKDE4のマルチメディアフレームワークである。Phononはサウンドの再生だけでなく録音、映像の再生とキャプチャ、エフェクト、様々なフォーマットのエンコードとデコードまで面倒を見てくれる。混沌としていたKDEのマルチメディア事情がこんなにスッキリしてしまうのだから驚きだ(簡単なメディアプレイヤーのサンプル)。
汎用スタック
作成中のライブラリの一部だからよくわからないネーミングになってるけど、コレ単体でも色々使えるかもしれない。
少なくともvoid enable()とvoid disable()の2つのpublicなメンバ関数を持つクラスを積むスタック。積むクラスはテンプレート第一引数で指定する。テンプレート第一引数でどういった時にenableとdisableを呼び出すかを柔軟に設定できる。具体的にはスタックに最初の値が積まれたときのenable、スタックに値が積まれた時のenable、上に積まれていた値が無くなった時の下の値のenable、スタックの最後の要素を捨てるときのdisable、スタックの要素を捨てるときのdisable、上に新しい値が積まれたときの下の値のdisable、ロックの有無が選択可能。
値が積まれたときに下の値をdisableし、値が捨てられたときに下の値をenableする事が出来るので、もともと入れ子にできない関数のペアを擬似的に入れ子にしてスタックで管理することができる。
当初はフラグは分岐を使って処理していたが、スタックをpush/popするたびにフラグを評価するのはオーバーヘッドが過ぎるのではないかと思い、テンプレートメタプログラムで書き直した。が、gcc-4.1の定数畳み込みは想像以上に優秀なようでパフォーマンスに差が出ることは無かった。
#ifndef SGLSTACK_HEADER
#define SGLSTACK_HEADER
#include <boost/thread/recursive_mutex.hpp>
#include <vector>
namespace streamgl {
namespace utility {
namespace stack {
enum {
BEGIN = 0x01,
END = 0x02,
RECURSIVE_BEGIN = 0x04,
RECURSIVE_END = 0x08,
SWITCH_BEGIN = 0x10,
SWITCH_END = 0x20,
LOCK = 0x40
};
template< int type > struct SGLStackType {
enum {
begin = type & BEGIN,
end = type & END,
recursive_begin = type & RECURSIVE_BEGIN,
recursive_end = type & RECURSIVE_END,
switch_begin = type & SWITCH_BEGIN && recursive_begin,
switch_end = type & SWITCH_END && recursive_end,
need_vector = recursive_begin || recursive_end,
lock = type & LOCK
};
};
template< bool, bool, typename element_type > struct SGLStackBegin {
static void call( std::vector< element_type* > &_arg_stack ) {
}
};
template< bool status, typename element_type > struct SGLStackBegin< true, status, element_type > {
static void call( std::vector< element_type* > &_arg_stack ) {
_arg_stack.back()->enable();
}
};
template< typename element_type > struct SGLStackBegin<false, true, element_type > {
static void call( std::vector< element_type* > &_arg_stack ) {
if( _arg_stack.size() == 1 )
_arg_stack.back()->enable();
}
};
template< bool, typename element_type > struct SGLStackSwitchBegin {
static void call( std::vector< element_type* > &_arg_stack ) {
}
};
template< typename element_type > struct SGLStackSwitchBegin< true, element_type > {
static void call( std::vector< element_type* > &_arg_stack ) {
if( !_arg_stack.empty() ) {
_arg_stack.back()->disable();
}
}
};
template< bool, bool, typename element_type > struct SGLStackEnd {
static void call( std::vector< element_type* > &_arg_stack ) {
}
};
template< bool status, typename element_type > struct SGLStackEnd<true, status, element_type> {
static void call( std::vector< element_type* > &_arg_stack ) {
_arg_stack.back()->disable();
}
};
template< typename element_type > struct SGLStackEnd<false, true, element_type> {
static void call( std::vector< element_type* > &_arg_stack ) {
if( _arg_stack.size() == 1 )
_arg_stack.back()->disable();
}
};
template< bool, typename element_type > struct SGLStackSwitchEnd {
static void call( std::vector< element_type* > &_arg_stack ) {
}
};
template< typename element_type > struct SGLStackSwitchEnd<true, element_type> {
static void call( std::vector< element_type* > &_arg_stack ) {
if( !_arg_stack.empty() ) {
_arg_stack.back()->enable();
}
}
};
template< int type, bool lock, typename element_type > class SGLStackCore {
public:
SGLStackCore() {
}
SGLStackCore( const SGLStackCore &_arg_src ) {
}
void push( std::vector< element_type* > &_arg_stack, element_type *_arg_ptr ) {
SGLStackSwitchBegin< SGLStackType< type >::switch_begin, element_type >::call( _arg_stack );
_arg_stack.push_back( _arg_ptr );
SGLStackBegin< SGLStackType< type >::recursive_begin, SGLStackType< type >::begin, element_type
>::call( _arg_stack );
}
void pop( std::vector< element_type* > &_arg_stack ) {
SGLStackEnd< SGLStackType< type >::recursive_end, SGLStackType< type >::end, element_type >::call(
_arg_stack );
_arg_stack.pop_back();
SGLStackSwitchEnd< SGLStackType< type >::switch_end, element_type >::call( _arg_stack );
}
};
template< int type, typename element_type > class SGLStackCore<type,true,element_type> {
public:
SGLStackCore() {
}
SGLStackCore( const SGLStackCore &_arg_src ) {
}
void push( std::vector< element_type* > &_arg_stack, element_type *_arg_ptr ) {
boost::recursive_mutex::scoped_lock lock( stack_guard );
SGLStackSwitchBegin< SGLStackType< type >::switch_begin, element_type >::call( _arg_stack );
_arg_stack.push_back( _arg_ptr );
SGLStackBegin< SGLStackType< type >::recursive_begin, SGLStackType< type >::begin, element_type
>::call( _arg_stack );
}
void pop( std::vector< element_type*> &_arg_stack ) {
boost::recursive_mutex::scoped_lock lock( stack_guard );
SGLStackEnd< SGLStackType< type >::recursive_end, SGLStackType< type >::end, element_type >::call(
_arg_stack );
_arg_stack.pop_back();
SGLStackSwitchEnd< SGLStackType< type >::switch_end, element_type >::call( _arg_stack );
}
private:
boost::recursive_mutex stack_guard;
};
template< int type, typename element_type > class SGLStackInterface {
public:
virtual ~SGLStackInterface() {
}
void push( element_type *_arg_ptr ) {
core.push( stack, _arg_ptr );
}
void pop() {
core.pop( stack );
}
unsigned int getLength() {
return stack.size();
}
private:
std::vector< element_type*> stack;
SGLStackCore< type, SGLStackType< type >::lock, element_type > core;
};
}
}
}
#endif
少なくともvoid enable()とvoid disable()の2つのpublicなメンバ関数を持つクラスを積むスタック。積むクラスはテンプレート第一引数で指定する。テンプレート第一引数でどういった時にenableとdisableを呼び出すかを柔軟に設定できる。具体的にはスタックに最初の値が積まれたときのenable、スタックに値が積まれた時のenable、上に積まれていた値が無くなった時の下の値のenable、スタックの最後の要素を捨てるときのdisable、スタックの要素を捨てるときのdisable、上に新しい値が積まれたときの下の値のdisable、ロックの有無が選択可能。
値が積まれたときに下の値をdisableし、値が捨てられたときに下の値をenableする事が出来るので、もともと入れ子にできない関数のペアを擬似的に入れ子にしてスタックで管理することができる。
当初はフラグは分岐を使って処理していたが、スタックをpush/popするたびにフラグを評価するのはオーバーヘッドが過ぎるのではないかと思い、テンプレートメタプログラムで書き直した。が、gcc-4.1の定数畳み込みは想像以上に優秀なようでパフォーマンスに差が出ることは無かった。
コンストラクタはいつ呼ばれるのか
C++においてstaticなインスタンスのコンストラクタがいつ呼び出されるかはややこしいことに何処でインスタンスを作ったかによって変化する。
このようにグローバル変数としてstaticなインスタンスを作ると
コンストラクタはmain関数が呼ばれる前に実行されるが、
このソースはC++におけるシングルトンの実装のひとつとして有名なものだが、このようにローカル変数としてstaticなインスタンスを作ると
コンストラクタは最初にそのローカル変数を持つ関数を呼び出した時に実行される。
staticなのだからどちらも必要なメモリ領域が割り当てられたタイミングは同じで、破棄されるタイミングも同じである。しかしコンストラクタが呼ばれるタイミングが違う。うまく使い分けてスマートな実装に活用したいところ。
#include <iostream>
class Hoge {
public:
Hoge() {
std::cout << "Hoge was constructed." << std::endl;
}
};
static Hoge instance;
int main() {
std::cout << "main() was called." << std::endl;
}
このようにグローバル変数としてstaticなインスタンスを作ると
Hoge was constructed.
main() was called.
main() was called.
コンストラクタはmain関数が呼ばれる前に実行されるが、
#include <iostream>
class Hoge {
public:
Hoge() {
std::cout << "Hoge was constructed." << std::endl;
}
static Hoge *getHoge() {
static Hoge singleton;
return &singleton;
}
};
int main() {
std::cout << "main() was called." << std::endl;
Hoge *singleton = Hoge::getHoge();
}
このソースはC++におけるシングルトンの実装のひとつとして有名なものだが、このようにローカル変数としてstaticなインスタンスを作ると
main() was called.
Hoge was constructed.
Hoge was constructed.
コンストラクタは最初にそのローカル変数を持つ関数を呼び出した時に実行される。
staticなのだからどちらも必要なメモリ領域が割り当てられたタイミングは同じで、破棄されるタイミングも同じである。しかしコンストラクタが呼ばれるタイミングが違う。うまく使い分けてスマートな実装に活用したいところ。
Linux用X-Fiプロプリドライバ
ずいぶん前にCreativeがLinux用のX-Fiプロプリドライバをリリースすると言っていたのを思い出したので調べてみた。
ぉー本当に出てるー!
って
64bit...?
x86_64専用!な、何考えてるんだ。なんでx86版が無いんだ。その他ページの説明によるとGCC4ではドライバソースをコンパイルできないらしい。これはもう少しまともになるまで待った方が良さそうだ。
X-Fi 64bit BETA Linux drivers are now available.
ぉー本当に出てるー!
って
X-Fi 64bit BETA Linux drivers are now available.
64bit...?
Requirements:
Linux x86_64 OS
Creative Sound Blaster X-Fi audio devices listed above.
Linux x86_64 OS
Creative Sound Blaster X-Fi audio devices listed above.
x86_64専用!な、何考えてるんだ。なんでx86版が無いんだ。その他ページの説明によるとGCC4ではドライバソースをコンパイルできないらしい。これはもう少しまともになるまで待った方が良さそうだ。
パンドラ
Engadget japaneseによるとLinuxベースのゲーム/メディアプレイヤーGP2Xの後継機が出るらしい。これだけならさして興味も湧かなかったのだが、そのスペックを見て唖然。
ハードウェア
ARM Cortex A8プロセッサ搭載
DDR-SDRAM 128MB搭載
PowerVR SGXグラフィックプロセッサ(OpenGL ES2.0準拠 数百万ポリゴン毎秒)搭載
800x480 ワイドVGAタッチスクリーン液晶搭載
S端子/コンポジットビデオ出力搭載
qwertyキーボード搭載
SDHCカードスロットx2搭載
802.11g WiFi搭載
USBホストコントローラ搭載
リチウムイオンバッテリー内蔵
ソフトウェア
Open2X-type Linuxファームウェア搭載だけど多分Debian ARMもいける
デフォルトでX11を走らせてウィンドウマネージャやデスクトップ環境を動かせる予定
$320くらいの予定
2008年春リリース予定
ありがちなARMプロセッサ搭載のSBCと比べてプロセッサがやけに速くて(Cortex A8は最低でも650MHz)、グラフィックチップがやけにパワフルで(ドリームキャストくらい)、ケースまで付いてやけに安い。Cortex A8を実際に積んでる機器なんて初めて見たヨ...
この構成で本当に$320で出せるのだろうか。qwertyキーボードも付いていることだし、X11が普通に動くとなれば自作PDAの素に最適かもしれない。
ハードウェア
ARM Cortex A8プロセッサ搭載
DDR-SDRAM 128MB搭載
PowerVR SGXグラフィックプロセッサ(OpenGL ES2.0準拠 数百万ポリゴン毎秒)搭載
800x480 ワイドVGAタッチスクリーン液晶搭載
S端子/コンポジットビデオ出力搭載
qwertyキーボード搭載
SDHCカードスロットx2搭載
802.11g WiFi搭載
USBホストコントローラ搭載
リチウムイオンバッテリー内蔵
ソフトウェア
Open2X-type Linuxファームウェア搭載だけど多分Debian ARMもいける
デフォルトでX11を走らせてウィンドウマネージャやデスクトップ環境を動かせる予定
$320くらいの予定
2008年春リリース予定
ありがちなARMプロセッサ搭載のSBCと比べてプロセッサがやけに速くて(Cortex A8は最低でも650MHz)、グラフィックチップがやけにパワフルで(ドリームキャストくらい)、ケースまで付いてやけに安い。Cortex A8を実際に積んでる機器なんて初めて見たヨ...
この構成で本当に$320で出せるのだろうか。qwertyキーボードも付いていることだし、X11が普通に動くとなれば自作PDAの素に最適かもしれない。