BlueZ CLI を使って Bluetooth 接続したデバイスの音楽を Linux PC 上で操作する

Bluetooth 接続したデバイスの音楽を CLI によって操作することは

* 簡素なデスクトップ作業環境の場合[^env]
* ノート PC から(ハイスペックサウンドカード搭載[^quality]の)デスクトップ PC に
  ssh 接続して操作する場合

重宝するはずです[^key][^true]。

# 1. 構成

ここで説明するのは、BlueZ を使った以下の構成になります。

```
 .---------------------.               .--------------.
 | PC                  |               | Device       |
 | .------------------.|-- Bluetooth --| .-----------.|
 | | bluetoothd       ||   connection  | | music app ||
 | '------------------'|               | '-----------'|
 |    |                |               '--------------'
 |  D-Bus connection   |
 |    |                |
 | .------------------.|
 | | bluetoothctl     ||
 | | bluetooth-player ||
 | '------------------'|
 '---------------------'
     |
   sound
     |
     V
   (=_= @)
```

# 2. ソフトウェアの準備

## 2.1. BlueZ パッケージのインストール

```
dnf install bluez
```

もしくは

```
aptitude install bluez
```

## 2.2. bluetooth-player の用意

BlueZ にある `bluetooth-player` を使いますが、ディストリビュータのパッケージに標準で含まれていない[^dest]ので、コミュニティ版を使います。

### 2.2.1. コミュニティ版のダウンロード

```
git clone https://git.kernel.org/pub/scm/bluetooth/bluez.git
```

### 2.2.2. Makefile の生成

```
cd bluez
./bootstrap
# bootstrap により configure が生成されます。
./configure
```

`configure` 実行時に必要なライブラリ等が足りなければ、以下のように足りないライブラリ情報が出力されますので、適宜インストールします。

```
configure: error: readline header files are required
```

上記の場合は、readline ヘッダファイルを要求しているので、libreadline-dev をインストールします。

### 2.2.3 bluetooth-player の生成

Makefile が生成されていれば、以下を実行します。

```
make
```

# 3. bluetooth 接続

## 3.1. bluetooth サービスの開始

以下で bluetoothd を起動させます。

```
systemctl start bluetooth.service
```

## 3.2. デバイスとの接続

`bluetoothctl` 実行し、その上でインタラクティブに以下を実行します。

```
bluetoothctl
```

1. `power on` (PC 上の bluetooth への電源投下)
2. `scan on` (対象デバイスのスキャン)
3. 対象デバイスが見つかったら `scan off` (スキャンの停止)
4. `pair <bluetooth address>` (対象デバイスとのペアリング)
5. `connect <bluetooth address>` (対象デバイスとの接続)
6. 自動接続したいなどの場合に `trust <bluetooth address>` (信頼できるデバイスとして登録)
7. `quit` (`bluetoothctl` を終了する)

# 4. bluetooth-player の操作

tools ディレクトリ配下に `bluetooth-player` が生成されているので、
実行してインタラクティブモードで起動します。

```
./tools/bluetooth-player
[NEW] Player /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0 [default]
[NEW] Folder /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/NowPlaying /NowPlaying
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem /Filesystem
[bluetooth]#
```

ここで、XX_XX_XX_XX_XX_XX は接続したデバイスの bluetooth address になります。

`bluetooth-player` 上で `play` (再生)/`pause` (一時停止)/`stop` (停止)/`next` (次の曲)/`previous` (前の曲)/`fast-forward` (早送り)/`rewind` (巻き戻し) などのコマンドを実行してプレーヤーを操作します。

なお、音量を変更する場合は `pactl` などを使うと良いでしょう。

# 5. 操作する音楽の指定

上記の `[NEW] Item ... /Filesystem` が表示される場合は、曲/フォルダ(以降、アイテム)を指定して操作することができます[^opt]。
なお、表示されない場合は再接続すると表示されることがあります。ただ、デバイスおよびアプリによってはどんなに頑張っても表示されないことがあります。

## 5.1. 対象アイテムの探索

対象アイテムが見つかるまで操作可能なアイテムへの移動(`change-folder <アイテムのパス>`)と列挙(`list-items`)を繰り返します。

以下の例では、まずアイテムを列挙し、列挙された中の `最近再生した曲` フォルダに移動しています。
その後に、そのフォルダ内を再度列挙しています。

```
[bluetooth]# list-items
Attempting to list items
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1 /Filesystem/最近再生した曲
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item2 /Filesystem/プレイリスト
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item3 /Filesystem/アーティスト
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item4 /Filesystem/アルバム
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item5 /Filesystem/曲
ListItems successful
```

```
[bluetooth]# change-folder /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1
Attempting to change folder
[CHG] Folder /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0 Name: /Filesystem/最近再生した曲
ChangeFolder successful
```

```
[bluetooth]# list-items
Attempting to list items
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item6 Freekwen-z
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item7 Erica Sunn
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item8 Missquerada
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item9 Tranzpotter
[NEW] Item /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item10 Brett5000
ListItems successful
```

## 5.2. 対象アイテムの再生

`play <アイテムのパス>` で対象アイテムを再生します。

```
[bluetooth]# play /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item7
Attempting to play /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0/Filesystem/item1/item7
Play successful
```

[^env]: 自分は以下のデスクトップ作業環境を使用し、仮想端末分割を用いて作業しています。
 - [Openbox](https://ja.wikipedia.org/wiki/Openbox) (簡素なウィンドウマネージャ) 
 - tmux (ターミナルマルチプレクサ)

[^quality]: 音質を気にするなら他に良い方法があるはずです。

[^key]: 色々ユースケースを挙げましたが、キーボードから指を極力離したくない人ぐらいしか必要としないでしょう。

[^true]: スマホなどから直接音を出すか、ヘッドフォン/イヤフォン接続するか、スマホのアプリを直接操作するか等で大抵はこと足りると思います。

[^dest]: Fedora 26、Ubuntu 17.10 での BlueZ パッケージ内には存在しないことを確認しています。

[^opt]: `bluetooth-player` で `next`/`previous` を複数回実行してもできます。さらに言えば、(本末転倒ですが、)スマホ上からアプリを操作すれば良いでしょう。