この連載のLXCの構築・
LXCでコンテナを使うときは、
Linuxにおける主なサウンドシステム・サウンドサーバ
まず、
- Open Sound System
(OSS) - UNIXベースのプラットフォームで使うことができるサウンドシステムで、
ハードウェアを直接制御するOSSドライバを含んでいます。 - Advanced Linux Sound Architecture
(ALSA) - OSSを置き換えるために開発されたLinuxにおける高機能なサウンドシステムで、
現在はALSAが主流となっています。ALSAドライバとOSSエミュレーション機能を含んでいます。 - Enlightened Sound Daemon
(ESD、 EsounD) - GNOMEで使われていたサウンドサーバで、
実行中の各種アプリケーションが出力するサウンドを取りまとめて、 ローカルデバイスやネットワーク先のデバイスに送り出します。 - PulseAudio
- ESDの置き換えとして、
クロスプラットフォームでネットワークに対応したサウンドサーバで、 現在はPulseAudioが主流となっています。ESDエミュレーション機能を含んでいます。
これらのサウンドシステム・/dev/
、/dev/
など/dev/
aplay
コマンドなどのALSA APIを使用したアプリケーションやesdplay
コマンドなどのESD APIを使用したアプリケーションは、paplay
コマンドなどのPulseAudio APIを使用したアプリケーションとともに、padsp
コマンド
![図1 サウンドシステム・サウンドサーバの関係 図1 サウンドシステム・サウンドサーバの関係](/assets/images/admin/serial/01/linux_containers/0015/thumb/TH800_001.jpg)
OSSを経由してサウンドを出力する
まず、/dev/
にリダイレクトすることにより、
taro@host:~$ cat pipipipi.au > /dev/audio
一般的なWAVファイルのような、/dev/
を使います。このとき、/dev/
をオープンしてから音声ファイル形式を設定し、
ここで、dsptest.
)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/soundcard.h>
#include <sys/ioctl.h>
#include <unistd.h>
static unsigned char buf[2048];
int main(void)
{
int fdi, fdo, arg, len;
fdi = open("geragerapo-no-uta.wav", O_RDONLY);
if ((fdo = open("/dev/dsp", O_WRONLY)) == -1) {
perror("/dev/dsp");
close(fdi);
return 1;
}
arg = AFMT_S16_LE, ioctl(fdo, SNDCTL_DSP_SETFMT, &arg);
arg = 2, ioctl(fdo, SNDCTL_DSP_CHANNELS, &arg);
arg = 44100, ioctl(fdo, SNDCTL_DSP_SPEED, &arg);
lseek(fdi, 44, SEEK_SET);
while ((len = read(fdi, buf, 2048)) > 0)
write(fdo, buf, len);
close(fdi), close(fdo);
return 0;
}
以下のようにコンパイルして実行することにより、
taro@host:~$ make dsptest cc dsptest.c -o dsptest taro@host:~$ ./dsptest
コンテナ内でサウンドを出力する(OSS)
それでは、taro
ユーザがroot権限でdefault
バリアントのPlamoコンテナct01
を作成し、hanako
ユーザが音を出すことを試みます。
hanako@ct01:~$ cat pipipipi.au > /dev/audio -bash: /dev/audio: 許可がありません hanako@ct01:~$ ./dsptest /dev/dsp: No such file or directory
コンテナ内に/dev/
や/dev/
が存在しないため、taro
ユーザが以下のコマンドを実行して、
taro@host:~$ sudo lxc-attach -n ct01 -e -- \ > mknod -m 660 /dev/mixer c 14 0 taro@host:~$ sudo lxc-attach -n ct01 -e -- \ > mknod -m 660 /dev/sequencer c 14 1 taro@host:~$ sudo lxc-attach -n ct01 -e -- \ > mknod -m 660 /dev/dsp c 14 3 taro@host:~$ sudo lxc-attach -n ct01 -e -- \ > mknod -m 660 /dev/audio c 14 4 taro@host:~$ sudo lxc-attach -n ct01 -e -- \ > mknod -m 660 /dev/sequencer2 c 14 8 taro@host:~$ sudo lxc-attach -n ct01 -- \ > chmod +t /dev/{mixer,sequencer{,2},dsp,audio} taro@host:~$ sudo lxc-attach -n ct01 -- \ > chgrp audio /dev/{mixer,sequencer{,2},dsp,audio}
また、/var/
)
# Audio configuration
lxc.cgroup.devices.allow = c 14:* rwm
これらの設定により、
hanako@ct01:~$ cat pipipipi.au > /dev/audio hanako@ct01:~$ ./dsptest
これで音が出るようになりました。
コンテナ内でサウンドを出力する(ALSA)
次に、aplay
コマンドを使って音を出してみましょう。実行したところ、
hanako@ct01:~$ aplay pipipipi.au ALSA lib confmisc.c:768:(parse_card) cannot find card '0' ALSA lib conf.c:4246:(_snd_config_evaluate) function snd_func_card_driver returned error: \ そのようなファイルやディレクトリはありません ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings ALSA lib conf.c:4246:(_snd_config_evaluate) function snd_func_concat returned error: \ そのようなファイルやディレクトリはありません ALSA lib confmisc.c:1251:(snd_func_refer) error evaluating name ALSA lib conf.c:4246:(_snd_config_evaluate) function snd_func_refer returned error: \ そのようなファイルやディレクトリはありません ALSA lib conf.c:4725:(snd_config_expand) Evaluate error: \ そのようなファイルやディレクトリはありません ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default aplay: main:696: audio open error: \ そのようなファイルやディレクトリはありません
はい、/dev/
が存在しないためですね。ホストにいるtaro
ユーザが以下のコマンドを実行して、/dev/
ディレクトリを作成します。
taro@host:~$ sudo lxc-attach -n ct01 -- mkdir -m 755 /dev/snd
また、/dev/
をバインドマウントする処理を含めた以下の設定を、/var/
)
# Audio configuration
lxc.mount.entry = /dev/snd dev/snd none bind 0 0
lxc.cgroup.devices.allow = c 14:* rwm
lxc.cgroup.devices.allow = c 116:* rwm
これらの設定により、
hanako@ct01:~$ aplay pipipipi.au 再生中 Sparc オーディオ 'pipipipi.au' : Mu-Law, レート 8000 Hz, モノラル hanako@ct01:~$ aplay geragerapo-no-uta.wav 再生中 WAVE 'geragerapo-no-uta.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
これで音が出るようになりました。
非特権コンテナ内でサウンドを出力する
一般ユーザ権限で利用するコンテナ
あらかじめ、taro
ユーザが一般ユーザ権限でdefault
バリアントのPlamoコンテナct01
hanako
ユーザを作成しておきます。非特権コンテナでは、mknod
は実行できないので、/var/
)
# Audio configuration
lxc.mount.entry = /dev/mixer dev/mixer none bind,create=file 0 0
lxc.mount.entry = /dev/sequencer dev/sequencer none bind,create=file 0 0
lxc.mount.entry = /dev/dsp dev/dsp none bind,create=file 0 0
lxc.mount.entry = /dev/audio dev/audio none bind,create=file 0 0
lxc.mount.entry = /dev/sequencer2 dev/sequencer2 none bind,create=file 0 0
lxc.mount.entry = /dev/snd dev/snd none bind 0 0
lxc.cgroup.devices.allow = c 14:* rwm
lxc.cgroup.devices.allow = c 116:* rwm
また、hanako
ユーザは、audio
グループ権限を持っていないので、hanako
ユーザが、
taro@host:/dev$ sudo find . -group audio -exec chmod o+rw {} \;
これらの設定により、
hanako@ct01:~$ cat pipipipi.au > /dev/audio hanako@ct01:~$ ./dsptest hanako@ct01:~$ aplay pipipipi.au 再生中 Sparc オーディオ 'pipipipi.au' : Mu-Law, レート 8000 Hz, モノラル hanako@ct01:~$ aplay geragerapo-no-uta.wav 再生中 WAVE 'geragerapo-no-uta.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
これで、
サウンドサーバを使ってコンテナ内のサウンドを出力する
ここまでの節で説明した方法は、taro
ユーザとコンテナ内のhanako
ユーザが、
そこで、default
バリアントのPlamoコンテナに含まれていないので、pulseaudio
パッケージを追加するか、large
バリアントのPlamoコンテナを作成して、
あらかじめ、taro
ユーザが一般ユーザ権限でlarge
バリアントのPlamoコンテナct02
hanako
ユーザを作成しておきます。
taro@host:~$ lxc-create -n ct02 -t download -- -d plamo -r 5.x -a amd64 \ > --variant=large --server=repository.plamolinux.org --keyid=0xC0B578C84772EC0D
なお、/dev/
ディレクトリが存在せず、shm_
システムコールが使えない状態になっているので、/usr/
と/usr/
を修正してから、
- ※)
- 執筆時点では、
lxc-1. 0.7はまだリリースされていません。
さて、
ホストOSと同一セグメント192.
)taro
ユーザは、/etc/
を~/.config/
にコピーしてから、
load-module module-esound-protocol-tcp auth-ip-acl=192.168.1.0/24
load-module module-native-protocol-tcp auth-ip-acl=192.168.1.0/24
ESDとPulseAudioのサウンドサーバが同居する場合、module-native-protocol-tcp
のモジュールだけでなく、module-esound-protocol-tcp
のモジュールもロードしておく必要があります。
また、192.
)hanako
ユーザは、/etc/
を~/.config/
にコピーしてから、
default-server = 192.168.1.2
このように設定すると、
![図2 PulseAudioサウンドサーバの共有 図2 PulseAudioサウンドサーバの共有](/assets/images/admin/serial/01/linux_containers/0015/thumb/TH800_002.jpg)
それでは、
以下は、paplay
コマンドを実行する例です。
hanako@ct02:~$ paplay -v geragerapo-no-uta.wav サンプル仕様 '再生' と チャンネルマップ 's16le 2ch 44100Hz' で \ front-left,front-right ストリームを開いています。 接続が確立 ストリームは正常に作成完了 バッファメトリックス: maxlength=4194304, tlength=352800, prebuf=349276, minreq=3528 サンプル仕様 's16le 2ch 44100Hz' 、チャンネルマップ 'front-left,front-right' を使用。 デバイス alsa_output.pci-0000_00_1b.0.analog-stereo に接続 (0, not suspended) ストリーム開始 ストリームアンダーラン 排出したストリームを再生 サーバーへの排出接続
以下は、aplay
コマンドを実行する例です。PulseAudioを経由して処理されています。
hanako@ct02:~$ aplay geragerapo-no-uta.wav 再生中 WAVE 'geragerapo-no-uta.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
以下は、esdplay
コマンドを実行する例です。ホストOSのIPアドレス192.
)ESPEAKER
の環境変数を設定しておきます。
hanako@ct02:~$ export ESPEAKER=192.168.1.2 hanako@ct02:~$ esdplay geragerapo-no-uta.wav
以下は、dsptest
コマンドを実行する例です。dsptest
コマンドを、padsp
コマンド
hanako@ct02:~$ padsp ./dsptest
このように、
また、
まとめ
今回は、
コンテナ内でサウンドを出力する方法として、default
バリアントやmini
バリアントのPlamoコンテナでは、large
バリアントやfull
バリアントのPlamoコンテナでは、
前々回から3回にわたって連載したLXCの構築・