ReadyMediaのソースを修正してインストールする

# 概要
Raspberry PiにインストールしたReadyMediaでDLNAをここ数年活用していて。
久々に気になった件がありソース修正を行ったので、
ついでにインストールからの記事を書いてみる。

# 要約
* ReadyMediaをソースからビルド・インストール
* ReadyMediaをソースを修正して挙動を修正する
  * アルバム アートのキャッシュ解像度の変更。  
    (160x160 ⇒ 500x500)
  * ARTIST情報の収集ロジックの変更  
    [ALBUM ARTIST] もしくは [BAND]が設定されている場合に、それらが優先されるのを無効化。
* 設定を変更する
  * ソート順を変更。フォルダを先にする。
* ReadyMediaの実行ユーザー
  * upnp:upnp

# 構築環境 (参考)
* Raspberry Pi 3 B+
* CentOS 7.5 (1804 armhfp Minimal image for RaspberryPi 2/3)
* minidlna-1.2.1 (※ReadyMedia)

# 手順
## 手順(1) ReadyMediaのビルド・インストール
### 手順(1-1) ライブラリのインストール
```shell:shell
# libjpeg-turbo
yum list libjpeg-turbo libjpeg-turbo-devel libjpeg-turbo-static libjpeg-turbo-utils
yum install libjpeg-turbo libjpeg-turbo-devel libjpeg-turbo-static libjpeg-turbo-utils

# sqlite3
yum list sqlite-devel
yum install sqlite-devel

# libexif
yum list libexif libexif-devel libexif-doc
yum install libexif libexif-devel libexif-doc

# libid3tag
yum list libid3tag libid3tag-devel
yum install libid3tag libid3tag-devel

#flac
yum list flac flac-devel flac-libs
yum install flac flac-devel flac-libs
```
他、不足がアレば適宜インストール。

### 手順(1-2) ReadyMediaのソースのダウンロード・展開
```shell:shell
cd /usr/local/src
wget http://jaist.dl.sourceforge.net/project/minidlna/minidlna/1.2.1/minidlna-1.2.1.tar.gz
tar zxvf minidlna-1.2.1.tar.gz
cd minidlna-1.2.1
```

### 手順(1-3) ReadyMediaのソース修正
#### 手順(1-3-1)  アルバムアートのキャッシュサイズを変更
デフォルトで最大160pxになっており、再生時に荒い表示になってしまう。
最大を500pxに引き上げる。
(もっとでかい方が良ければもっとでかくする。)

変更は2ファイル。

* albumart.c
* metadata.c

```shell:shell
vi /usr/local/src/minidlna-1.2.1/albumart.c
```
72行あたり。
160を500に書き換える。

```c:albumart.c
if( imsrc->width > imsrc->height )
{
	# dstw = 160;
	dstw = 500;
	# dsth = (imsrc->height<<8) / ((imsrc->width<<8)/160);
	dsth = (imsrc->height<<8) / ((imsrc->width<<8)/500);
}
else
{
	# dstw = (imsrc->width<<8) / ((imsrc->height<<8)/160);
	dstw = (imsrc->width<<8) / ((imsrc->height<<8)/500);
	# dsth = 160;
	dsth = 500;
}
```


```shell:shell
vi /usr/local/src/minidlna-1.2.1/metadata.c
```
594行あたり

```c:metadata.c
if( ed->size )
{
	/* We might need to verify that the thumbnail is 160x160 or smaller */
	if( ed->size > 12000 )
	{
		imsrc = image_new_from_jpeg(NULL, 0, ed->data, ed->size, 1, ROTATE_NONE);
		if( imsrc )
		{
			#if( (imsrc->width <= 160) && (imsrc->height <= 160) )
			if( (imsrc->width <= 500) && (imsrc->height <= 500) )
				thumb = 1;
			image_free(imsrc);
		}
	}
	else
		thumb = 1;
}
```

#### 手順(1-3-2) ARTIST情報の収集ロジックの変更
デフォルトのままだと、アルバム アーティストが設定されている曲の場合にそっちが優先されてしまう。
ロジック的には
　　[ALBUM ARTIST] > [BAND] > [ARTIST]
で、DBにはARTIST属性しか管理されておらず、優先度の高いもので登録される様子。

何のためかわからないけど、トラックのアーティストをCDのアーティストで潰されるのは非常に都合が悪いので、ARTISTのみにする。
処理的には[ARTIST]を取ったあと、[ALBUM ARTIST] か [BAND] で上書きしているので、
情報を上書きしている箇所をコメントアウトして、処理を無くす。


```shell:shell
vi /usr/local/src/minidlna-1.2.1/metadata.c
```
411行あたり。
if文のブロックをまるごとコメントアウト。

```c:metadata.c
/* If there is a album artist or band associated with the album,
   use it for virtual containers. */
//if( i < ROLE_ALBUMARTIST )
//{
//	for( i = ROLE_ALBUMARTIST; i <= ROLE_BAND; i++ )
//	{
//		if( song.contributor[i] && *song.contributor[i] )
//			break;
//	}
//	if( i <= ROLE_BAND )
//	{
//		m.artist = trim(song.contributor[i]);
//		if( strlen(m.artist) > 48 )
//		{
//			m.artist = strdup("Various Artists");
//			free_flags |= FLAG_ARTIST;
//		}
//		else if( (esc_tag = escape_tag(m.artist, 0)) )
//		{
//			m.artist = esc_tag;
//			free_flags |= FLAG_ARTIST;
//		}
//	}
//}
```

### 手順(1-4) ReadyMediaのビルド・インストール
```shell:shell
./configure
make -j2
make install
```

### 手順(1-5) ReadyMediaの設定
デフォルトではメディア・フォルダ関係ないソートになっているので、その設定もする。

```shell:shell
cp /usr/local/src/minidlna-1.2.1/minidlna.conf /etc/
vi /etc/minidlna.conf
```

```conf:/etc/minidlna.conf
# メディア フォルダを設定
media_dir=任意のパス

# DLNAサーバー名を入力
friendly_name=任意の名前

# ソート指定の設定。コメントアウトを外す
force_sort_criteria=+upnp:class,+upnp:originalTrackNumber,+dc:title
```


## 手順(2) サービス実行設定
### 手順(2-1) 実行ユーザーの作成とcacheフォルダの作成
```
useradd -s /sbin/nologin upnp
mkdir -R /var/cache/minidlna
chown -R upnp:upnp /var/cache/minidlna
```

### 手順(2-2) サービス用のユニットの作成
```shell:shell
touch /etc/systemd/system/minidlna.service
vi /etc/systemd/system/minidlna.service
```
```conf:/etc/systemd/system/minidlna.service
[Unit]
Description=minidlna server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
User=upnp
Group=upnp
Restart=always
RestartSec=10
ExecStart=/usr/local/sbin/minidlnad -R -d -f /etc/minidlna.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill $MAINPID

[Install]
WantedBy=multi-user.target
```
※あくまでも参考程度に。Restartなどはお好みで調整を。


### 手順(2-3) サービス用の有効化・実行
```shell:shell
# サービス有効化
systemctl enable minidlna.service
# サービス起動
systemctl start minidlna.service
# ログ確認
journalctl -f -u minidlna.service
```

## 手順(3) 確認
DLNAクライアントで確認する。
(WindowsだとまともなDLNAクライアントはMediaMonkeyくらいかと思われる。)



## 手順(9) おまけ
### inotify監視上限の変更
ReadyMediaはinotifyを用いて
ファイル システムの変更検知で自動追加されるが。
必要があればinotifyのチューニングを行う。

```shell:shell
# 1ユーザーあたりの最大監視数を確認
cat /proc/sys/fs/inotify/max_user_watches

# 1ユーザーあたりの最大監視数を変更(一時)
sysctl fs.inotify.max_user_watches=100000

# 1ユーザーあたりの最大監視数を変更(恒久)
touch /etc/sysctl.d/90-inotify.conf
vi /etc/sysctl.d/90-inotify.conf
```
```conf:/etc/sysctl.d/90-inotify.conf
# 1ユーザーあたりの最大監視数を設定
fs.inotify.max_user_watches = 100000
```

※ 『90-inotify.conf』 の確認は再起動が必要


# 感想
屋内外で家のメディアを聞くに際しここ数年試行錯誤していて。
DLNA(ReadyMedia)、BubleUPnP、SubSonic(lms)などを試してみてはいるのだけど。
ReadyMediaはファイル システムに置いたプレイリストが利用できるのが有り難く、
屋内でもBGM再生に非常に役立っている。

また、先日600曲近くも買ってしまったため、
それらを聴いて、ちゃんと曲名覚える事を考えた時に、視覚情報も非常に重要だと思ったので。
今回アーティスト名表示が修正出来てよかった。
(タグ整理頑張っているので。。。。)

![photo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72257/535ecc44-93bd-9ce8-3e26-c14d4b414ea0.jpeg)
(参考) Amazon Kindle + BubleUPnP


# 余談
## 余談① リサイズ ロジックをゆっくり読む
```C:metadata.c
if( imsrc->width > imsrc->height )
{
	dstw = 160;
	dsth = (imsrc->height<<8) / ((imsrc->width<<8)/160);
}
else
{
	dstw = (imsrc->width<<8) / ((imsrc->height<<8)/160);
	dsth = 160;
}
```
今回の修正箇所のところ。
雰囲気でリサイズ後のサイズを計算しているのだろうとは思ったけど、
なかなか理解するのが難しく、読むのを諦めてしまっていた。
しかし、ゆっくり考えてみると、やっぱりちょっと面白いコードである。

* 基本はアス比を維持するため、大きい方で縮小率を求め、もう1辺に適用する式。
* 乗除算を整数で処理するために、bit演算で値を大きくしている。
* 8bit左シフト = 2^8 = 256倍。
* 縮小率計算で256倍しているので、もう1辺にも256倍して打ち消し。

恐らく値を大きくする係数も特には根拠がないので。
だったら乗算よりもシフト演算で高速化してしまえって感じなんだろうな。
普通に小数を使わないあたりも、FPUへの配慮なのだろうと思われる。

```math:
height' = \frac{height\times 256}{(width \times 256) \div 目的のサイズ}
```

いや、まぁ算数レベルなの話なのでで、ここまで分解しなくてもだけど。
iアプリ作ってた時も小数が使えなくて、HPゲージやスクロール バーなど、
整数側での計算はよくあったので、懐かしいなぁと感じた。

## 余談② リサイズ ロジック式を最適化する算数
私も昔リサイズ処理の際に比率計算をしていたけど、
実は乗算を先に行わせることで比率計算を無く整数演算が出来た経験がある。
まぁ私の場合は単に馬鹿だったので気づくのに数年もかかったわけですが(爆)。
(態々百分率を求めていたですよ。。。)
最適化出来ないか、ちょっと頑張って算数してみた。

```math:
\begin{align}
height' &= \frac{height \times 256}{(width \times 256) \div 目的のサイズ} \\
&= \frac{height}{width \div 目的のサイズ} \\
&= \frac{height}{width \times \frac{1}{目的のサイズ}} \\
&= \frac{height}{width} \times \frac{目的のサイズ}{1} \\
&= (height \div width) \times 目的のサイズ \\
&= height \times 目的のサイズ \div width \\
\end{align}
```
という事で

```math:
height' = height \times 目的のサイズ \div width \\
```

で行ける？:thinking:
Let's 検算!
![SS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72257/d6383a38-d04f-7a19-8c42-04143d117bd1.png)
Excelで確認してみたけど、大丈夫っぽい。
(赤字が計算した箇所で、リサイズ前後のアス比の誤差で量で確認。)
桁あふれの危険性も有るけど、式がシンプルになることもあるので、
こういった制約の元での計算式の見直しもありかも知れない。

# 参考(謝辞)

* SourceForge.net: ReadyMedia - Project Web Hosting - Open Source Software  
  http://minidlna.sourceforge.net/
* ReadyMedia download | SourceForge.net  
  https://sourceforge.net/projects/minidlna/
* miniDLNAのインストール - 屑籠というかゴミ箱  
  http://d.hatena.ne.jp/teandt/20151109
* とりとめもないはなし。: CentOS 7 ベースのサーバに ReadyMedia (MiniDLNA) を導入してみた話。  
  http://karat5i.blogspot.jp/2015/11/centos-7-readymedia-minidlna.html
* DLNAサーバー構築(ReadyMedia(旧MiniDLNA)) - CentOSで自宅サーバー構築  
  https://centossrv.com/readymedia.shtml
* とあるSEの備忘録: CentOS7でDLNAサーバー(minidlna)を構築 -インストール編-  
  http://blog.developerlabs.net/2015/02/centos7-dlna.html
* ReadyMedia (miniDLNA) | katz+  
  http://katzplus.com/centos-7/readymedia-minidlna/
* miniDLNA改：Artistの取り扱い: 万象酔歩  
  http://k-hiura.cocolog-nifty.com/blog/2016/04/minidlnaartist-.html