Raspberry Pi Radiko Player(with CD-Player version)

前回のRadiko Playerラジオバージョンに暫定的(永遠に暫定的)ですがCD Playerを搭載してみました。

現状は実行中のMplayerからは再生中のトラックや終了の情報をを得ることができない(わからない)という課題がありますがそれ以外はほぼ快適に使えるかなと思っています。

Raspberry pi 3(raspbian jessie)ディスクトップの設定
パッケージのインストール

# apt install cd-discid nkf

CD-ROMドライブをwww-dataから読めるようアクセス権の変更
/etc/udev/rules.d/99-cd.rulesの新規作成
idVendorとidProductはドライブによって違うのでlsusbで調べる

/etc/udev/rules.d/99-cd.rules
ATTRS{idVendor}=="04bb", ATTRS{idProduct}=="022b", GROUP="pi",MODE="0666"

空ファイル作成

# touch /var/www/html/freedb.txt
# chown www-data:www-data freedb.txt

index.phpの編集

/var/www/html/index.php

ここで一旦再起動します。

Radiko Playerにアクセス

http://localhost/


動作確認は以下の環境で確認しています
Pi3(jessie) 内蔵(bcm2835 ALSA) IO-DATA DVRP-U8N
Pi1B(moode3.1) USB-DAC IO-DATA DVRP-U8N

アルバムのトラック数はcd-discidから取得出来ました。これでラストのトラックも指定可能になりました。

$ cd-discid /dev/sr0
550a3707 7 150 26531 49333 81025 111350 136975 160148 2617

ディスクを入れていない状態でeject以外のCD関連のボタンを押すとNo medium foundを表示します。
<>ボタンは1トラックステップ
&ボタンは3トラックステップ
>>ボタンはラストトラック
<<ボタンはトラック1に移動


CDをセットしていきなりCD PLAYを押しても再生と同時にFreeDBに問い合わせてCDDB情報を取得します。
その他のボタンを押しても同様にCDDB情報を表示します。
一度取得したCDDB情報はセッションに記憶され再利用します。
セッション情報はイジェクトするまで有効です。


トラック5を選択してトラックボタンを押すとシングルプレイモードに入ります。

曲をスキップしたい時は送りボタンでトラックを選択プレイボタンを押すという流れになります。


ここで再度プレイボタンを押すとトラック5〜ラストのモードになります。
トラック1から連続再生する時はストップボタンでトラック番号はクリアします。
テキストエリアはなにかPHP実行のボタンを押すとデフォルトの大きさに戻ります。(仕様です)


再生しないでCDDB情報をみる時はFreeDBボタンを押します。

このときセッション情報がなければ問い合わせに行きあればそれを再利用します。


CD再生中にステーション情報をみる時は上段のRadio Stationのリンクをクリックします。

戻る時はFreeDBボタンで戻ります。

以上のように現状の課題は再生中のトラックを表示できない、再生終了しても現在の表示が残っているいうことになります。

表示についてもラジオ再生中は音量ボタンを押してもステーション情報をCD再生中はCDDB情報を表示できるように苦心したつもりです。多少の不具合はあるかもしれません。


環境によってはボタンがはみ出すかもしれません。その場合はカラムを調整するといいと思います。
現在は3−6−3の構成をとっています。3−7−2とすると中央のカラムはずっと広くなります。
あとは寄せたり上げたりするといいかもしれません。(簡単なhtmlの知識が必要)

<div class="col md-7 float-center">
<div class="col md-2 float-right">

当サイトのジャンクなUSB-DACでもCDはなかなかいい音がしています。取り敢えず試すなら内臓のALSAでも問題ないと思います。mplayerなら盛大なポップノイズも出ません。

index.phpファイルは少し長くなってしまいますが動作としてはなんら問題ないと思います。(ラジオサイトの追加編集が少し面倒になるくらいです)
当サイトとしては基本index.phpのみで構成したいと思っています。

# OS起動直後Station欄に”Raspberry Pi Radiko Player”を表示させているとテキストエリアが切り替わらない不具合がありました。取り敢えず表示なしに変更
参考 index.php.pi.cd-ver2

Raspberry Pi Radiko Player(simple)

当サイトのRadiko Playerですが気が向いた時に適当に機能を追加していることもあって使い勝手が悪くなってきました。ここで一旦シンプルなRadiko Playerとして見直してみることにしました。

今回はディスクトップのPi3(jessie)にインストールしてみます。
サウンドデバイスも内蔵の(bcm2835 ALSA)を使用。
Piの設定からAudio Device Settingsで設定できます。
インストール
radiko関連

# apt install mplayer swftools libxml2-utils libav-tools rtmpdump

コマンドラインからradikoスクリプトを実行して正常に聴取できることを確認
/var/tmp/player.swf is not a valid SWF file or contains errors.
[stop] failed get keydata (/var/tmp/authkey.png)
こんなエラーが出る時はradikoの仕様変更に対策済みのスクリプトかまたは
$ rm /var/tmp/player.swfを実行
1分で停止する時は
$ /path/to/radiko.sh -t 120 -p *** とかして連続再生を確認
スクリプトは/var/www/htmlへ
web server

# apt install lighttpd php5-cgi
# lighty-enable-mod cgi
# lighty-enable-mod userdir
/etc/lighttpd/conf-available/10-cgi.conf
cgi.assign      = (
    ".pl"  => "/usr/bin/perl",
    ".py"  => "/usr/bin/python",
    ".php" => "/usr/bin/php-cgi",
)
# gpasswd -a www-data audio

SkyBlue CSS Framework
https://github.com/Stanko/skyblue/archive/gh-pages.zipをダウンロード、展開して/var/www/htmlにおきます。
Radiko Playerのindex.phpも/var/www/htmlに配置します。
以上で再起動します。

Radiko Playerの実行

http://localhost/


シンプルといってもラジオだけで今までと何も変わらないのですが今回は音量値を取得、表示してみました。
音量のデフォルト設定ボタンに現在の値を表示しています。ボタンの機能はそのままなのでこのボタンを押すことによってデフォルト値を設定、表示します。
音量値は以下のコマンドから取得しています。

$ amixer -R
Simple mixer control 'PCM',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -1312 [84%] [-13.12dB] [on]

音量値は-10239〜400の10640ステップあります。
現在の音量値は84%を表示しています。
“R”オプションはデフォルトですがもうひとつ”M”オプションがあります。

$ amixer -M
Simple mixer control 'PCM',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -1312 [52%] [-13.12dB] [on]

“M”オプションで表示すると実際の値は同じですが%表示[52%]が違っています。
こちらは人の聴感に合わせたような表示ですね。最終的には同じ100%になります。
各音量ボタンを押すとケース文を実行後ここに飛びます。

// goto vol
        vol:
            $vol = shell_exec("amixer -c 0 -R 2>&1");
            $vol_a = explode(' ',$vol,30);
            $vol_s = $vol_a[29];
            $vol_x = substr($vol_s,1,3);
            $vol_y = str_replace('%', '', $vol_x);
            $volume = str_replace(']', '', $vol_y);
            $_SESSION['volume']=$volume;
            $select = 'station';
        break;

無駄に行がある感じですが”R”オプションのコマンドから数値のみを取り出しています。
この”R”を”M”に変更するとによって”M”オプションの表示になります。
またOS起動後はこの値は空になっているので空の時のみ同じく読み取るよう先頭に別に記載しています。

テキストエリア

テキストエリアはある程度自由に記載、使い分けできるようにしてみました。

大きいボタンはTOKYO FMを仮に割り当てています。
大きいボタンを押すとphpのcase “default”を実行し末尾の変数$selectに’default’を入れます。
htmlに戻ってくるとphpのswitch文$selectのcase defaultの項を実行します。

 php
case "default";
exec("nohup killall mplayer > /dev/null 2>&1");
exec("nohup /bin/bash radiko.sh -p FMT > /dev/null &");
$_SESSION['broad']= "TOKYO FM";
$select = 'default';

html
/*
Display
}*/
switch ($select) {
case "default";
    print_r($radiko);
    print_r(PHP_EOL); print_r(PHP_EOL);
    print_r('Have a nice day');
break;

参考 index.php.pi.sample1
USBスピーカーなどを使っている場合は
amixer -c 0 –> amixer -c 1に変更する必要があります。
radikoスクリプト内も同様です。

これでベースの部分がある程度整理がついたので次回はまたCDプレーヤーを組み込んでみたいと思います。

Raspberry Pi Radiko Player 更新

今回はRadiko Playerの更新です。

UIを見なおしてみました。

CDDBに問い合わせをしてみました。

中央のカラムにステーションリストを配置

アンカーを打って左カラムのメニューから目的のリストにアクセスできます。


メニューからradikoを選択するとこの位置に表示します。

ステーションはボタンに配置してコンパクトにまとめました。


SHOUTcastとCSRA.fmはプレイリストが必要です。(/var/www/html/castに配置)

以前の記事に大体まとめているので参考にしてください。
CSRA.fmはプレイリストに誤記があるサイトがあります。(修正が必要)

CDDBに問い合わせてみる
参考 いち雑記 CDDB問い合わせ
リッピングソフトのabcdeを使っているとアルバム情報をいくつも拾ってくる場合があります。以前abcdeの設定で参考にさせてもらったサイトでコマンドからfreedbに問い合わせる方法が紹介されているので実行してみました。
以下のpackageが必要です。(abcdeがインストールされていればcd-discidは依存で入っている)

# apt install cd-discid nkf

適当なCDをセットしてCDに記録されている固有のIDや曲番号を取得

$ cd-discid /dev/sr0
46091d05 5 150 49632 81692 118825 156730 2335
$ cd-discid /dev/sr0 | tr "[:blank:]" "+"
46091d05+5+150+49632+81692+118825+156730+2335

取得したディスク情報を基に問い合わせ(freedb日本語) 1回目の問い合わせ

$ wget -q -O - "http://freedbtest.dyndns.org/~cddb/cddbeuc.cgi?cmd=cddb+query+46091d05+5+150+49632+81692+118825+156730+2335&hello=raspberrypi+localhost+wget+ver1.16.1&proto=6"
200 jazz 46091d05 Cannonball Adderley / Somethin' Else

しかしディスクによっては1回目の問い合わせで違うパターンの返答をするものがあります。
しかもディスクに記録されているIDとは違うIDにアルバム情報があります。

$ wget -q -O - "http://freedbtest.dyndns.org/~cddb/cddbeuc.cgi?cmd=cddb+query+3608d104+4+150+42467+88930+126387+2259+&hello=raspberrypi+localhost+wget+ver1.16.1&proto=6" | nkf
211 Found inexact matches, list follows (until terminating `.')
jazz 3808d104 1588 Sonny Clark / Cool Struttin'
jazz 3a08d204 Sonny Clark / Cool Struttin'
data 3608d104 Sonny Clark / Cool Struttin' 
reggae 3608d104 Sonny Clark / COOL STRUTTIN' (ジャズの100枚) 
soundtrack 3608d104 ソニー・クラーク / クール・ストラッティン 
newage 3608d104 Sonny Clark / Cool Struttin' 
country 3608d104 Sonny Clark / The Essential Jazz Collection: Cool Struttin' 
blues 3608d104 Sonny Clark / The Essential Jazz Collection: Cool Struttin' 
classical 3608d104 Sonny Clark / Cool Struttin' 
folk 3608d104 Sonny Clark / Cool Strutin 
jazz 3608d104 Sonny Clark / Blue Minor

次に必要なものはジャンルとディスクID 2回目の問い合わせ

$ wget -q -O - "http://freedbtest.dyndns.org/~cddb/cddbeuc.cgi?cmd=cddb+read+ jazz+3808d104+&hello=raspberrypi+localhost+wget+ver1.16.1&proto=6" | nkf

210 jazz 3808d104 CD database entry follows (until terminating `.')
# xmcd CD database file
#
# Track frame offsets:
#	150
#	42487
#	89002
#	126477
#
# Disc length: 2259 seconds
#
# Revision: 1
# Processed by: cddbd v1.4PL0 Copyright (c) Steve Scherf et al.
# Submitted via: Rip!AudiCO v4.10
#
DISCID=3808d104
DTITLE=1588 Sonny Clark / Cool Struttin'
DYEAR=
DGENRE=jazz
TTITLE0=Cool Struttin'
TTITLE1=Blue Minor
TTITLE2=Sippin' At Bells
TTITLE3=Deep Night
EXTD=
EXTT0=
EXTT1=
EXTT2=
EXTT3=
PLAYORDER=
.

取得できましたね。以上のようなパターンでも上位のIDに音楽情報が記載されていると期待してジャンル+ディスクIDを指定してやればRadiko Player(php)からでも取得できるだろうということでやってみました。

urlを書き出すためのファイルを準備します。

# touch /var/www/html/freedb.txt
# chown www-data:www-data /var/www/html/freedb.txt

index.phpの編集
ドライブにディスクがセットされていない状態で問い合わせ実行した場合No medium foundを返します。

$cddb = shell_exec('cd-discid /dev/sr0 2>&1');
if (preg_match("/No/", $cddb)) {
     if (stristr($cddb, 'No')) {
         $cddb = (stristr($cddb, 'No'));
         $_SESSION['cddb'] = $cddb;
         break;
     }
}

CDのディスクIDを取得(改行コード削除)

$command = ('cd-discid /dev/sr0 | tr "[:blank:]" "+"');
$diskid = shell_exec("{$command}");
$diskid = str_replace(PHP_EOL, '', $diskid);

1回目の問い合わせのurlを作成、実行
作成したurlは一旦ファイルに書き出し、wgetはそれを読み込んで実行します。

$url = "http://freedbtest.dyndns.org/~cddb/cddbeuc.cgi?cmd=cddb+query+";
$url .= $diskid;
$url .= "&hello=raspberrypi+localhost+wget+ver1.16.1&proto=6";
$fp = fopen("freedb.txt", "w");
fwrite($fp, $url);
fclose($fp);
$command = ('wget -q -O - -i freedb.txt');
$disktitle = shell_exec("{$command}");

2回目の問い合わせ
1回目で得られた結果から’inexact’の文字を検索してヒットしたら1行目に相当する箇所を制御コードを含めて削除、それ以外は最初の4文字を削除します。そこから配列にしてジャンルとディスクIDを抜き出します。
2回目の問い合わせのurlを作成、wgetで得られた結果をnkfで文字コード変換、egerepで必要な項目を抽出して出力します。

$str = $disktitle;
if(preg_match('/inexact/',$str)){
    $cut = 65;
    }else{
    $cut = 4;
}
$replace = substr( $str , $cut , strlen($str)-$cut );
$disktitle = $replace;
$disk = explode(' ',$disktitle,3);
$janru = $disk[0];
$id = $disk[1];
$url = "http://freedbtest.dyndns.org/~cddb/cddbeuc.cgi?cmd=cddb+read+";
$url .= $janru;
$url .= "+";
$url .= $id;
$url .= "+&hello=raspberrypi+localhost+wget+ver1.16.1&proto=6";
$fp = fopen("freedb.txt", "w");
fwrite($fp, $url);
fclose($fp);
$command = ('wget -q -O - -i freedb.txt | nkf | grep -i -e DTITLE -e DYEAR -e DGENRE -e TTITLE');
$cddb = shell_exec("{$command}");

freedb(日本語)で取得できなかったディスクは出力が空になっているので本家(freedb.freedb.org)に問い合わせます。url以外は上記と同じコマンドを発行することになり少々冗長になりますがループするよりも簡単になります。

if ($cddb === NULL) {
--------- snip ----------
$url = "http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+query+";
--------- snip ----------
$url = "http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+";
--------- snip ----------


以上でCDDBを実行するとアルバム情報が取得出来ました。

但し曲順がTTITLE0から始まっていますね。

こちらもビューティーなコードをかけませんが取り敢えず修正してみました。

$str = $cddb;
if(preg_match('/DTITLE=/',$str)){
    $cut = 7;
    $str = str_replace('DYEAR=', 'Year ', $str);
    $str = str_replace('DGENRE=', 'Genre ', $str);
    $str = str_replace('TTITLE0=', '01  ', $str);
    $str = str_replace('TTITLE1=', '02  ', $str);
    --------- snip ----------
    $str = str_replace('TTITLE13=', '14  ', $str);
    $str = str_replace('TTITLE14=', '15  ', $str);
}
$replace = substr( $str , $cut , strlen($str)-$cut );
$cddb = $replace;


少しは見やすくなったと思います。
日本語もOKです。

すべてのジャンルで取得できるかは不明ですが取り敢えず手元のアルバム50枚位で試した限りではすべて取得できました。


参考 index.php.sample2
もし試用する場合は現在のindex.phpのバックアップを取ってください。
なにかphp実行のボタンを押すとテキストウィンドウはデフォルトの大きさに戻ります。(仕様です)
デフォルトの状態からCDプレーヤーのシングルプレイをいきなり押すとPLAY0から始まっていた不具合を修正しました。

Raspberry Pi Blu-ray/DVD-RW Tools 更新

Blu-ray/DVD-RW Toolsを少し更新してみました。

前回のcdrdaoをメニューに追加します。

左側のカラム、メニューに追加して

表示させます。

これだけです。

Pi使いの人はこれだけで充分ですね。(^▽^;)
前回の結果をテキストファイルにして/var/www/htmlに置いて読み込んでいます。

閑話休題
以上は前置きとして、さて本題です。
現在の書式ではphpを実行すると必ずhtmlのトップに戻ります。
実行した結果をみるにはまた押したボタンの項に戻って確認する必要がありました。
そこでトップのINFO画面にテキストエリアを再度復活させることにしました。

実行した結果はResultのテキストエリアに表示されます。


実行したボタンのエリアにも今までどおり表示されているのでボタンの押し間違いなどの確認ができます。
infoボタンやclearボタンを押すとクリアしてしまいますがhtml内の移動ではクリアはしません。

この表示により通常の作業はずっと見やすくなると思います。

参考 dvd.php.sample3
growisofsはあくまでコマンドラインツールです。
日常のバックアップなどは本ツールはある程度便利に使えると思います。
但しディスクをフルに使うような記録の場合はそれなりに時間もかかります。
そんな時はあきらかにコマンドラインから実行したほうがメリットがあります。
ターミナルからtmuxを起動してそこから実行すれば寝ている間に作業が終わります。
コマンドからの挙動をよく理解して使い分ければ本ツールのようなものでも活用の幅が広がると思います。

Raspberry Pi 音楽CDを焼く(cdrdao)

今はCDを焼くことも少なくなったのですが手元にはまだCD-Rメディアが少しあったので音楽CDを焼いてみようと思います。

パッケージをインストール

# apt install cdrdao

以前DVD-RWドライブ(IODATA DVRP-U8N)では試しているので今回はBDドライブ(IODATA EX-BD03)で実行してみます。
デバイスをみてみると

シンボリックリンクがまたsr0になってますね

このシンボリックリンクもデバイスを正常に認識して初めて生えてくるのでどんな条件で決まるのかよくわかりません。

当方としてはsr0のほうが都合がいいので様子をみたいと思います。

作業はターミナルからコマンドラインで実行します。
cdrdaoは書き込みをするために最大約700MBの一時ファイルを作成します。
読み込んでから書き込みをする前に強制中止をすると一時ファイルは自動で削除されないのでわかりやすいホームディレクトリで作業をするのがいいでしょう。
基本はrootで作業をします。Piではwarningは出ますがpiユーザーでも実行可能のようです。
元ディスクを入れてコピーを実行してみます。

# cdrdao copy --eject --speed 12 --device /dev/sr1

–speed 未指定にすると書き込み可能な最大の速度で書き込もうとします。
前回DVRP-U8Nで試した時は正常に完了しますが無音(音飛び)状態になる箇所がありました。たまたまメディアが悪かったのかもしれませんが音楽CDではよくあることなのでおまじない代わりに適当な値を入れたほうがいいと思います。(読み込みには適用されません)
–eject 焼きあがった後に終わったよ!合図にいいかも
–device /dev/sr1 IODATA EX-BD03を指定

Cdrdao version 1.2.3 - (C) Andreas Mueller 
/dev/sr1: PIONEER BD-RW   BDR-UD03      Rev: 1.05
Using driver: Generic SCSI-3/MMC - Version 2.0 (options 0x0000)

Starting CD copy at speed 24...

Track   Mode    Flags  Start                Length
------------------------------------------------------------
 1      AUDIO   0      00:00:00(     0)     10:59:57( 49482)
 2      AUDIO   0      10:59:57( 49482)     07:07:35( 32060)
 3      AUDIO   0      18:07:17( 81542)     08:15:08( 37133)
 4      AUDIO   0      26:22:25(118675)     08:25:30( 37905)
 5      AUDIO   0      34:47:55(156580)     04:05:35( 18410)
Leadout AUDIO   0      38:53:15(174990)

PQ sub-channel reading (audio track) is supported, data format is BCD.
Raw P-W sub-channel reading (audio track) is supported.
Copying audio tracks 1-5: start 00:00:00, length 38:53:15 to "cddata4356.bin"...
Track 1...
Track 2...
Found pre-gap: 00:00:04
Track 3...
Found pre-gap: 00:00:21
Track 4...
Found pre-gap: 00:00:22
Track 5...
Found pre-gap: 00:00:05
Found 130 Q sub-channels with CRC errors.
Found disk catalogue number.
Please insert a recordable medium and hit enter.

CRC errorは多少は必ず出るようです。
ここでは自動でejectしてくれません。
ブランクメディアと入れ替えて enter

ERROR: Cannot determine disk status - hit enter to try again.

気にしないでもう1回エンター

Turning BURN-Proof on
Executing power calibration...
Power calibration successful.
Writing track 01 (mode AUDIO/AUDIO )...
Writing track 02 (mode AUDIO/AUDIO )....
Writing track 03 (mode AUDIO/AUDIO )....
Writing track 04 (mode AUDIO/AUDIO )....
Writing track 05 (mode AUDIO/AUDIO )....
Wrote 392 of 392 MB (Buffers 100%  96%).
Wrote 174990 blocks. Buffer fill min 93%/max 100%.
Flushing cache...
Writing finished successfully.
CD copying finished successfully.

ejectして完了、無事焼き上がりました。
一時ファイルも削除されています。
時間は正確に測っていないのですが約400MBのディスクで読み込み5〜6分、書き込みも同じか若干+気味だったと記憶しています。
IODATA EX-BD03でもCDのコピーは正常にできましたがIODATA DVRP-U8Nと比べると明らかにメカノイズ(回転音)が大きいですね。
BD,DVDでは気にならないのですが。

Top