徒然なる日々を送るソフトウェアデベロッパーの記録(2)

技術上思ったことや感じたことを気ままに記録していくブログです。さくらから移設しました。

Pi3でインターネットラジオ選局機能を作る(2)

昨日はプレイヤーを作成したので、ここに情報を流すための web サーバを作成します。
今回も折角なので perl と HTTP::Daemon を使うことにします。
そのため、libwww-perl パッケージをインストールしておく必要があります。

  • 仕様

ポート 8066 で listen する。
*.cgi という URL だったら内蔵のサブルーティンを動かす。
サブルーティンが定義されていなければ RC_NOTFOUND を返す。
その他の拡張子はその名称のファイルがあれば、ファイルを読み込んで返す。
なければ RC_FORBIDDEN を返す。
ついでにスマホ対応にする。

  • プログラム
#!/usr/biin/perl
use HTTP::Daemon;
use HTTP::Date;
use HTTP::Status;
use IO::Socket::UNIX;
use Proc::Daemon;
use Cwd;


my $port = shift || 8066;
my $rootdir = cwd;
my %cgi;
$cgi{'stop'} = \&stop_cgi;
$cgi{'katsushika'} = \&katsushika_cgi;
$cgi{'venice-classic'} = \&venice_classic_cgi;

# daemonize
Proc::Daemon::Init;

my $d = HTTP::Daemon->new(LocalAddr => '0.0.0.0', LocalPort => $port);
my $client = IO::Socket::UNIX->new (
  Type => SOCK_STREAM(), Peer => "/tmp/player.sock"
);

while (my $c = $d->accept) {
  if (my $r = $c->get_request) {
    my $path = $r->url->path;
    $path = "/index.html" if $path eq "/";
    $path = trim_path($path);
    if ($r->method eq "GET" and $path =~ /^(.*)\.cgi$/) {
      my $cgi = $cgi{$1};
      if ($cgi ne undef) {
        $cgi->($c, $r);
      } else {
        $c->send_error(RC_NOTFOUND);
      }
    } else  {
      my $file = $rootdir . "/" . $path;
      if (-f $file) {
        $c->send_file_response($file);
      } else {
        $c->send_error(RC_FORBIDDEN);
      }
    }
  }
  $c->close;
  undef($c);
}

sub trim_path {
  local ($p) = @_;
  my @sp = split(/\//, $p);
  my @r;

  for (my $i = 0; $i <= $#sp; ++$i) {
    my $r = $sp[$i];
    if ($r eq "..") {
      my $len = @r;
      if ($len > 0) {
        pop(@r);
      }
    } elsif ($r ne "." and $r ne "") {
      push(@r, $r);
    }
  }
  return join("/", @r);
}

sub stop_cgi {
  my ($c, $r) = @_;
  my $cmd = "stop\n";
  $client->write($cmd);
  $client->flush();
  my $file = $rootdir . "/response-stop.html";
  $c->send_file_response($file);
}

sub katsushika_cgi {
  my ($c, $r) = @_;
  my $cmd = "play --cache=256 http://hdv3.nkansai.tv/katsushika\n";
  $client->write($cmd);
  $client->flush();
  my $file = $rootdir . "/response-select.html";
  $c->send_file_response($file);
}

sub venice_classic_cgi {
  my ($c, $r) = @_;
  my $cmd = "play http://109.123.116.202:8020/stream\n";
  $client->write($cmd);
  $client->flush();
  my $file = $rootdir . "/response-select.html";
  $c->send_file_response($file);
}
  • index.html ファイル
<!DOCTYPE html>
<html lang="ja">
<head>
<link rel="stylesheet" type="text/css" href="text.css" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>インターネットラジオ選局</title>
</head>
<body>
<h1>インターネットラジオ選局</h1><hr />
<ul>
<li><a href="katsushika.cgi">かつしかFM</a></li>
<li><a href="venice-classic.cgi">Venice Classic Radio</a></li>
</ul>
<ul>
<li><a href="stop.cgi">受信をやめる</a></li>
</ul>
</body>
</html>

そう言えば、shoutcast.com の仕様が大幅に変更されていました。
playlist 指定ができなくなった??