スマートフォンなどの音源を、Bluetooth経由でラズベリーパイ3からならす。
OSはいつもどおりyoctoprojectを使用して作成。
BluetoothではA2DPを使用し、sinkとなるようにする。
実際に音を鳴らすのはpulseaudioで、ラズベリーパイ3が他の端末からオーディオに見えるようにするための設定も
pulseaudioのbluetooth-discoverモジュールで行う。
そのため、bluez5自体の設定ファイルはいらない。
ラズベリーパイ3上でBluetoothで接続された音源と音を鳴らすためのデバイスをloopbackしたり、経路を作る必要があり、
よそのサイトではこの部分にudevのルールを書いたりpythonでスクリプトを書いたりしているのを見かけたが、
これもpulseaudioのbluetooth-policyモジュールで行うため今回は不要。
使用するyoctoprojectのバージョンはpyro(2.3)
すでにrocko(2.4)が出ているが、今回は古いので行く。
環境構築
ソースの取得
$ git clone git://git.yoctoproject.org/poky.git -b pyro
$ git clone git://git.openembedded.org/meta-openembedded -b pyro
$ git clone git://git.yoctoproject.org/meta-raspberrypi -b pyro
環境変数の読み込みとビルドディレクトリの作成
$ cd ..
$ source poky/oe-init-build-env
ビルド対象のレイヤを追加
$ bitbake-layers add-layer ../poky/meta-raspberrypi
$ bitbake-layers add-layer ../poky/meta-openembedded/meta-oe
$ bitbake-layers add-layer ../poky/meta-openembedded/meta-python
local.confの変更
下記をlocal.confに追加する
MACHINE = "raspberrypi3"
# systemd
DISTRO_FEATURES_append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
IMAGE_INSTALL_append = " systemd-bash-completion \
"
# pulseaudio
DISTRO_FEATURES_append = " pulseaudio pam"
IMAGE_INSTALL_append = " pulseaudio \
pulseaudio-server \
pulseaudio-misc \
pulseaudio-module-systemd-login \
pulseaudio-module-bluez5-discover \
pulseaudio-module-bluez5-device \
pulseaudio-module-bluetooth-policy \
pulseaudio-module-bluetooth-discover \
pulseaudio-module-loopback \
pulseaudio-bash-completion \
"
# bluez5
IMAGE_INSTALL_append = " bluez5"
IMAGE_INSTALL_append = " bluez5-testtools"
# connman
IMAGE_INSTALL_append = " connman connman-client"
# avahi
IMAGE_INSTALL_append = " avahi-daemon"
FETCHCMD_wget = "/usr/bin/env wget -t 2 -T 3000 -nv --passive-ftp --no-check-certificate"
# automount
DISTRO_FEATURES_append = " automount"
# util-linux
IMAGE_INSTALL_append = " util-linux-bash-completion \
util-linux-lsblk"
# Enable UART for debug console
ENABLE_UART = "1"
# ALSA
IMAGE_INSTALL_append = " alsa-utils \
alsa-utils-speakertest \
"
# sudo
IMAGE_INSTALL_append = " sudo"
若干不要なパッケージや設定も含まれているが気にしない。
pulseaudioのbluetoothモジュールのロード設定
/etc/pulse/system.pa
に下記を追加
### Automatically load driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
load-module module-bluetooth-policy
.endif
.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
.endif
今回のケースでは、module-bluetooth-discoverはBluetoothの設定を自動化し
module-bluetooth-policyはa2dp_sourceとsinkのloopbackを自動化する。
pulseaudioのシステムサーバ化
/etc/systemd/system/pulseaudio.service
を下記の内容で作成
[Unit]
Description=PulseAudio system server
[Service]
Type=notify
ExecStart=/usr/bin/pulseaudio --daemonize=no --system --realtime --log-target=journal
[Install]
WantedBy=multi-user.target
サービスの登録、起動
$ systemctl --system enable pulseaudio.service
$ systemctl --system start pulseaudio.service
/etc/dbus-1/system.d/pulseaudio-system.conf
に下記の行を追加
<busconfig>
<!-- System-wide PulseAudio runs as 'pulse' user. This fragment is
not necessary for user PulseAudio instances. -->
<policy user="pulse">
<allow own="org.pulseaudio.Server"/>
+ <allow send_destination="org.bluez"/>
+ <allow send_interface="org.bluez.Manager"/>
</policy>
</busconfig>
pactlの使い方
sudo でpulseユーザーを指定して実行する
$ sudo -u pulse pactl list short sinks
blueoothの設定
discoverableを有効にする。
$ connmanctl enable bluetooth
$ bluetoothctl
> power on
> discoverable on
> agent on
> quit
ここまででペアリング可能になる。
このままではAccessDeniedが発生し接続できないが、相手のデバイスをtrustすることで接続できるようになる。
自動化
bluetoothctlではバッチ処理に不向であることと、相手のデバイスをtrustする手順が煩雑になるため、
bluez5-testtoolsに含まれるスクリプトを使用し、ある程度自動化できるようにする。
まずはバグフィックス
$ cd /usr/lib/bluez/test/
$ find -type f | xargs sed -i 's/iteritems/items/g'
次のコマンドを実行する。
$ cd /usr/lib/bluez/test
$ ./test-adapter discoverable on
$ ./simple-agent -c NoInputNoOutput
simple-agentがtrustまで行ってくれるので、bluetoothctlの手順よりも多少は簡略化できる。
これでも、相手とのペアリングのタイミングでプロンプトがでるため、完全にヘッドレスでの運用はできない。
一度、接続が成功し相手の端末に接続設定が保存されてしまえば、ヘッドレス運用もできると思う。
その場合はシステム起動時にsimple-agentを起動し、
GPIOで物理ボタンなどをつけて、押されたタイミングでdiscoverable onを行うなど工夫が必要になる。
内蔵オーディオについて
ラズベリーパイ内蔵のオーディオを使用するためにはsnd_bcm2835
ドライバを組み込む必要がある。
SDカードのブートパーティションにあるconfig.txtに下記を追加すると、ブート時にドライバが組み込まれるようになる。
dtparam=audio=on
まとめ
ここまでの設定を行った後で再起動してsimple-agentを立ち上げると、
スマートフォンやipodなどとBluetoothで接続して、音源を鳴らすことが出来るようになる。