Perl 小品集 ─ mplay2

#!/usr/bin/perl
# multi-media player
# needs mpg123, timidity, mtvp

# global value @list, $sum, $root, $pages

# 現在のディレクトリとそのファイル情報を得る
($root) = `pwd`;
chomp $root;
&get_list;
# ディレクトリとファイルを表示し、選択を待つ
$page = 1;
&select_media ($page);
exit 0;

# 指定したディレクトリのファイル情報を得る
sub get_list {
    local (@p_list, @file_list, $entry);
    @file_list = glob "$root/*";
    @p_list [0] = "..";
    $sum = 1;
    # ディレクトリの場合
    foreach $entry (@file_list) {
        if (-d $entry) {
            $entry =~ /([^\/]+)$/;
            @p_list [$sum] = &check_name ($1);
            $sum++;
            }
        }
    # 音楽ファイルの場合
    foreach $entry (@file_list) {
        if (($entry =~ /\.mid/i) or ($entry =~ /\.rmi/i) or ($entry =~ /\.mp3/i)) {
            $entry =~ /([^\/]+)$/;
            @p_list [$sum] = &check_name ($1);
            $sum++;
            }
        }
    # 動画ファイルの場合
    foreach $entry (@file_list) {
        if (($entry =~ /\.mpeg/i) or ($entry =~ /\.mpg/i)) {
            $entry =~ /([^\/]+)$/;
            @p_list [$sum] = &check_name ($1);
            $sum++;
            }
        }
    # ファイルのリストが多い場合、複数ページにわける
    if ($sum > 40){
        $pages = int ($sum / 40);
        if ($sum % 40 > 0) {
            $pages = $pages + 1;
            }
        }
    else {
        $pages = 1;
        }
    # リストの初期化
    @list = @p_list;
}

# ファイル名に空白があるかどうかチェックする
sub check_name {
    local $temp;
    local ($name) = @_;
    # ファイル名に空白があるばあいアンダースコアで置き換える
    if ($name =~ / /) {
        $temp = $name;
        $name =~ tr/ /_/;
        # ファイル名の変更をこころみ、失敗した場合もとにもどす
        if ((system "mv '$root/$temp' '$root/$name'") != 0) {
            $name = $temp;
            }
        }
    return $name;
    }

# ディレクトリの移動、ファイルの再生などを選択する
sub select_media {
    local ($input, $file, @selected, @randfiles, @entries, $entry, $i, $number, $number_2, $start, $end);
    local ($page) = @_;
    &show_list ($page);
    print "Input (#,a,r,n,p,q) => ";
    $input = <STDIN>;
    chomp $input;
    # 終了
    if ($input eq "q") {
        exit 0;
        }
    # 次のページ
    elsif ($input eq "n") {
        $page = $page + ($page < $pages);
        }
    # 前のページ
    elsif ($input eq "p") {
        $page = $page - ($page > 1);
        }
    # すべてのファイルの再生
    elsif ($input eq "a") {
        foreach $file (@list) {
            if ($file ne "..") {
                &play_media ("$file");
                }
            }
        }
    # すべてのファイルのランダム再生
    elsif ($input eq "r") {
        $i = 0;
        while ($i < $sum) {
            $randfiles [$i] = " ";
            $i++;
            }
        # ランダムデータの作成
        foreach $file (@list) {
            while(1){
                # 乱数発生 0<=$number<$sum
                $number = int (rand $sum);
                if($randfiles [$number] eq " "){
                    $randfiles [$number] = $file;
                    last;
                    }
                }
            }
        # ランダムデータの再生
        foreach $file (@randfiles) {
            if ($file ne "..") {
                &play_media ("$file");
                }
            $i++;
            }
        }
    # 上位ディレクトリへの移動
    elsif ($input eq ".." or $input eq "0" or $input eq "") {
        @entries = split /\//, $root;
        $max = scalar (@entries) -1;
        $i = 0;
        foreach $entry (@entries) {
            if ($i == $max) {
                last;
                }
            elsif ($i == 0) {
                $root = $entry;
                }
            else {
                $root = "$root/$entry";
                }
            $i++;
            }
        &get_list;
        $page = 1;
        }
    # 下位ディレクトリへの移動
    elsif (-d "$root/$input") {
        $root = "$root/$input";
        &get_list;
        $page = 1;
        }
    # 複数ファイルの再生
    elsif ($input =~ /,/){
        @selected = split /,/, $input;
        foreach $number (@selected) {
            # 複数ファイルの中の連続ファイルの再生
            if ($number =~ /-/) {
                ($start, $end) = split /-/, $number;
                if ($end eq "") {
                    $end = $sum;
                    }
                $number_2 = $start;
                while ($number_2 <= $end) {
                    $file = @list [$number_2];
                    &play_media ("$file");
                    $number_2++;
                    }
                }
            else {
                $file = @list [$number];
                &play_media ("$file");
                }
            }
        }
    # 連続ファイルの再生
    elsif ($input =~ /-/) {
        ($start, $end) = split /-/, $input;
        if ($end eq "") {
            $end = $sum;
            }
        $number_2 = $start;
        while ($number_2 <= $end) {
            $file = @list [$number_2];
            &play_media ("$file");
            $number_2++;
            }
        }
    # 単一ファイル、またはディレクトリの再生
    else {
        $file = @list [$input];
        if ($file ne "..") {
            &play_media ("$file");
            }
        }
    # 選択メニューにもどる
    &select_media ($page);
}

# ディレクトリ、ファイルのページごとのリスト
sub show_list {
    local ($line, $i, $row, $col, $number, $p_sum, $p_root, $title_name, $name, $last);
    local ($page) = @_;
    # 二列に表示するため、最初の列の長さを計算
    if ($page < $pages) {
        $p_sum = 40 * $page;
        $last = $p_sum - 20;
        }
    else {
        $p_sum = $sum;
        if ($p_sum % 2 == 0) {
            $last = 40 * ($page -1) + int (($p_sum - 40 * ($page -1)) / 2);
            }
        else {
            $last = 40 * ($page -1) + int (($p_sum - 40 * ($page -1)) / 2) + 1;
            }
        }
    # スクリーンの初期化とタイトルの表示
    if ($root eq "") {
        $p_root = "/";
        }
    else {
        $p_root = $root;
        }
    if ($pages > 1) {
        $title_name = " MutiMedia Player ($p_root) $page/$pages ";
        }
    else {
        $title_name = " MutiMedia Player ($p_root) ";
        }
    print "\033[2J\033[1;0H";
    $line = int((80 - length ($title_name)) / 2);
    $i = 0;
    while ($i < $line){
        print '=';
        $i++;
        }
    print $title_name;
    $i = $i + length ($title_name);
    while ($i < 80){
        print '=';
        $i++;
        }
    # 左のリストの表示
    $i = 40 * ($page -1);
    $row = 2;
    $col = 0;
    while ($i < $last){
        if($i < 10){
            $number = " [0$i] ";}else{
            $number = " [$i] ";
            }
        ($name) = &print_name (@list [$i]);
        print "\033[$row;$col\H$number$name";
        $row++;
        $i++;
        }
    # 右リストの表示
    $row = 2;
    $col = 40;
    while ($i < $p_sum){
        if($i < 10){
            $number = " [0$i] ";}else{
            $number = " [$i] ";
            }
        $name = &print_name (@list [$i]);
        print "\033[$row;$col\H$number$name";
        $row++;
        $i++;
        }
    if($p_sum % 2 == 0){
        print "\n";}else{
        print "\n\n";
        }
}

# 表示名の調整
sub print_name {
    local (@letters, $i, $p_name);
    local ($name) = @_;
    # ファイル名が長い場合、それを短くして表示する
    if ((length ($name)) > 30) {
        @letters = split //, $name;
        $p_name = "";
        $i = 0;
        while ($i < 30){
            $p_name = "$p_name$letters[$i++]";
            }
        $p_name = "$p_name...";
        }
    else {
        $p_name = $name;
        }
    # ターゲットファイルのカラー表示
    if (($name =~ /\.mid/i) or ($name =~ /\.rmi/i) or ($name =~ /\.mp3/i)) {
        $p_name = "\033[34m$p_name\033[0m";
        }
    elsif (($name =~ /\.mpeg/i) or ($name =~ /\.mpg/i)) {
        $p_name = "\033[32m$p_name\033[0m";
        }
    return $p_name;
    }

# ファイルまたはディレクトリの再生
sub play_media {
    local @entries;
    local ($file) = @_;
    # ディレクトリーを指定した場合、そのファイルをすべて再生
    if (-d "$root/$file") {
        @entries = glob "$root/$file/*";
        foreach $file (@entries) {
            &play_one ("$file");
            }
        }
    else {
        &play_one ("$root/$file");
        }
}

# 再生プログラムの選択
sub play_one {
    local ($file) = @_;
    if (($file =~ /\.mpg/i) or ($file =~ /\.mpeg/i)) {
        system "mtvp '$file'";
        }
    elsif ($file =~ /\.mp3/i){
        system "mpg123 '$file'";
        }
    elsif (($file =~ /\.mid/i) or ($file =~ /\.rmi/i)) {
        system "timidity '$file'";
        }
}



[INDEX]