목차
라즈베리 파이로 라디오 듣기
개요
라즈베리 파이를 이용해 Digitally Imported의 라디오를 듣도록 한다. 간단하게 재생/멈춤을 지원하며 웹서버의 특정 URL을 이용해 재생을 제어한다고 생각한다.
작업 내용
라즈베리에 패키지 설치
라즈베리에 mplayer와 sudo를 설치한다. 웹서버 및 PHP는 이미 동작하고 있다고 가정한다.
$ sudo apt-get install sudo mplayer
라즈베리 파이에서 소리가 나도록 조정
라즈베리 파이로 스피커 출력이 되도록 명령어를 입력해 조절한다.
$ sudo amixer cset numid=3 1
라디오를 위한 유저 생성
그리고 라디오만 전담하는 유저를 하나 생성한다. 그리고 이 유저는 사운드를 이용할 수 있어야 한다.
$ sudo useradd -M -N -g nogroup -G audio radio $ sudo passwd -l radio
웹서버는 www-data
계정으로 동작한다. 그러므로 www-data
가 자유롭게 mplayer를 radio
계정을 사용할 수 있도록 조작할 수 있어야 한다. visudo
명령을 내린 후 다음을 추가한다.
$ sudo visudo # www-data can run mplayer as radio www-data ALL=(radio) NOPASSWD: /usr/bin/mplayer, /usr/bin/pkill
그리고 일단 radio 계정으로 mplayer가 동작하고, 스피커로 음악이 출력되는지 확인해본다.
$ wget http://robtowns.com/music/blind_willie.mp3 # 테스트 음원입니다. 저작권 걱정없이 쓸 수 있습니다. $ sudo -s # user -> root # su radio # root -> radio $ mplayer blind_willie.mp3 # 소리가 나와야 합니다!
Ctrl+C
를 눌러 일단 종료한다. 이제 같은 방법으로 웹서버가 음악을 실행할 수 있는지도 재차 테스트한다.
$ exit # radio -> root # su www-data # root -> www-data $ sudo -u radio mplayer blind_willie.mp3 # 소리가 나와야 합니다!
재생 중에 터미널 하나를 더 이용해 임의로 mplayer를 멈출 수 있는지도 확인합니다.
$ sudo -s # user -> root # su www-data # root -> www-data $ sudo -u radio pkill mplayer # 음악이 연주되는 중에 이 명령을 입력합니다. mplayer가 종료되면서 음악이 멈추어야 한다.
명령이 모두 동작하면 이제 동작시킬 준비가 된다.
플레이리스트 받기
- http://www.di.fm 에 접속하고 로그인한다.
- 'My Account'에 들어가 'Player Settings'를 선택한다. http://www.di.fm/settings 로도 들어갈 수 있다.
- 'Preferred Player'에서 'Hardware Player'를 선택한다.
- 'Server Information'에서 적당한 장르를 선택한다. 선택된 장르에 따라 'Playlist'와 'Servers' 항목이 달라진다. mplayer는 playlist 파일을 잘 지원하므로 Playlist 파일만 받아오면 된다. 이후 설명에선느 'Ambient' 장르를 가져와 작업하는 것으로 가정한다.
- pls 파일을
ambient.pls
로 고치고, 라즈베리 파이로 옮긴다.
제어 구문 작성 (PHP)
일단 아주 간단하게 PHP 스크립트 몇 줄을 이용하여 재생/정지 기능을 구현한다.
# cd /usr/share/nginx/www # 웹서버의 루트로 이동. 서버마다, 설정마다 달라지므로 각자 확인 # mkdir difm # difm 이라는 디렉토리에서 작업
이 difm 디렉토리에 ambient.pls
파일을 옮긴다. 그리고 웹서버의 difm에 다음과 같은 간단한 두 가지 스크립트를 작성한다.
- ambient.php
<?php $cmd = 'sudo -u radio mplayer -playlist ambient.pls 1>/dev/null 2>&1 &'; echo exec($cmd); echo "playing ambient"; ?>
웹서버의 주소를 통해 음악이 재생되는지 확인해본다!
개선안
위 방법은 테스트이고, 그나마 조금 쓰기 편하게 하려면 다음과 같은 PHP 구문으로 대체하는 것이 좋다. 이번의 PHP는 difm이라는 디렉토리 내부의 모든 PLS 파일을 순서대로 목록화하여 보여준다.
아래 스크립트에서 각 방송국(스테이션)은 하위 디렉토리 하나를 점유하고 있으며 각 하위 디렉토리에는 각 채널의 그림 파일과 pls 파일을 보유하고 있다.
- ipcheck.php
<?php function ipcheck() { $allow = array("^192.168.0.*"); foreach($allow as $ip) if(eregi($ip, $_SERVER['REMOTE_ADDR'])) return; die('Unauthorized'); } ?>
- index.php
<?php include('ipcheck.php'); ipcheck(); function get_channels($sitename) { $handle = opendir("./$sitename"); $channels = array(); while(false !== ($entry = readdir($handle))) { $path = pathinfo($entry); $name = $path['filename']; $ext = $path['extension']; if($ext == 'pls') array_push($channels, $name); } sort($channels); return $channels; } function get_img($channel) { $exts = array('.png', '.jpg'); foreach($exts as $e) { $imgfile = $channel.$e; if(file_exists($imgfile)) return $imgfile; } return ""; } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>di.fm@PI-0 Server!</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style type="text/css"> .station {margin-right:10px; float:left; } </style> </head> <body> <h1>Radio at Raspberry Pi Server!</h1> <h2>Choose your channel!</h2> <h3><a href="control.php?action=stop">Just stop playing!</a><br></h3> <div class="station"> <h3>Digitally Imported</h3> <ul> <?php // print all .pls file in the current directory $difm = get_channels('di.fm'); foreach($difm as $ch) { $url = urlencode("di.fm/".$ch); $img = get_img("di.fm/".$ch); echo "<li><a href=\"control.php?action=play&channel=$url\"><img src=\"$img\" width=\"48\"> $ch</a>\n"; } ?> </ul> </div> <div class="station"> <h3>SKY.FM</h3> <ul> <?php $skyfm = get_channels('sky.fm'); foreach($skyfm as $ch) { $url = urlencode("sky.fm/".$ch); $img = get_img("sky.fm/".$ch); echo "<li><a href=\"control.php?action=play&channel=$url\"><img src=\"$img\" width=\"48\"> $ch</a>\n"; } ?> </ul> </div> </body> </html>
- control.php
<?php include('ipcheck.php'); ipcheck(); ?> <html> <head> </head> <body> <?php function play($channel) { $filename = str_replace(' ', '\\ ', $channel); $cmd = "sudo -u radio mplayer -playlist $filename.pls 1>/dev/null 2>&1 &"; exec($cmd); echo "<p>Playing ".$channel."... Request from ".$_SERVER["REMOTE_ADDR"]."</p>"; } function stop() { exec('sudo -u radio pkill mplayer > /dev/null 2>&1'); echo "<p>Music stopped</p>"; } if($_GET["action"]=="play") { $channel = $_GET['channel']; echo "Channel name: ".$channel; if(file_exists($channel.".pls")) { stop(); play($channel); } else { echo "Channel ".$channel." not found!"; } } else if($_GET["action"]=="stop") { stop(); } else { echo "Unknown action!"; } ?> <h1><a href="index.php">Go to index</a></h1> </body> </html>
이제는 각 스테이션 별 디렉토리 내부에 pls 파일만 채워 주면 알아서 웹페이지가 갱신되는 편리함이 추가되었다.
또다른 개선안
pls 파일과 같은 이름의 png 파일이 있으면 로딩할 수도 있을 것이다.각 채널의 png, jpg 그림 파일을 같이 보여주도록 추가하였다.사실 이 주소가 외부에서 노출되면 안된다. 외부 IP의 요청인 경우 작동하지 않도록 프로그램을 수정.내부망에서만 동작하도록 프로그램 수정.- 일지 중지 (pause)
- 볼륨 조정 (up, down, mute)