Andrew Bedno    Andrew@Bedno.com • 773-442-2386
 History   Kudos   Samples 

Perl
2005
Perl

Web-Based Media Manager

Comprehensive program for managing media files written in Perl. Includes library scan, search, tag and playlist maintenance features and more.
Also download my library of Perl date, CRC, logging, redirection and text utility functions.

#! /usr/bin/perl
# Above line may need installation specific customization.
# Requires Perl language interpreter and an HTTP server.

# Media Collection Manager - Collection Browser.
# "mmgr.pl" created by Andrew Bedno, 2005-2006, Andrew@Bedno.com, All Rights Reserved.
# See associated readme file for details.

# Arguments:
#   l = Library.
#   s = Seach target.
#   n = Name for playlist save.
#   w = Name for playlist load.
#   v = Name for playlist append.
#   b = Playlist text.
#   c = Append playlist from category.
#   o = Output style.
#   g = SubDir search target.

# To install the Perl MP3 module run "ppm install MP3-Info"
use MP3::Info;
use MP3::Info qw(:genres);

$PAGE_CODE = 'mmgr';
require("mcomm.pl");

# Various internal constants.
$playlist_rows = 15;
$playlist_cols = 40;
$playlist_rows_used = 0;
$playlist_cols_used = 0;
$ta_col_exp_fact = 125/100;
$ta_row_exp_add = 3;

$LIBS_TTL{'dirs'} = 0;
$LIBS_TTL{'files'} = 0;
$LIBS_TTL{'media'} = 0;
$LIBS_TTL{'links'} = 0;
$LIBS_TTL{'notes'} = 0;
$LIBS_TTL{'seconds'} = 0;
$LIBS_TTL{'gb'} = 0;
$libs_cnt = 0;

# Various formatting constants.
$html_end = "\n"."<!-- END -->\n"."<a name='bottom'></a>\n".$html_foot;

$Arg_Cat = lc($field{'C'});
$Arg_SubDirSearch = lc($field{'G'});
$SubDirSearch_len = length($Arg_SubDirSearch);

$Arg_Name = $field{'N'};
$Arg_Submit = lc($field{'SUBMITSAVE'});
&clean($Arg_Name);
$Arg_Name =~ s/\s/\_/g;
$Arg_Name =~ s/[^A-Za-z0-9\-\_]//gi;
if (! $Arg_Name) { $Arg_Name = 'default'; }

$Arg_Load = $field{'W'};
&clean($Arg_Load);
$Arg_Load =~ s/\s/\_/g;
$Arg_Load =~ s/[^A-Za-z0-9\-\_]//gi;

$Arg_Append = $field{'V'};
&clean($Arg_Append);
$Arg_Append =~ s/\s/\_/g;
$Arg_Append =~ s/[^A-Za-z0-9\-\_]//gi;
if ( ($Arg_Load) and ($Arg_Append) ) { $Arg_Load = ''; }

$Arg_Body = $field{'B'};
$Arg_Body =~ s/\r//gm;
&clean($Arg_Body);
if (length($Arg_Body) > 0) { $Arg_Body .= "\n"; }

$field{'INCOFS'} =~ s/false//i;
$field{'INCDIR'} =~ s/false//i;
if ( (! $field{'SRCDIR'}) and (! $field{'SRCFILE'}) and (! $field{'SRCTRACK'}) and (! $field{'SRCTITLE'}) and
     (! $field{'SRCARTIST'}) and (! $field{'SRCALBUM'}) and (! $field{'SRCDATES'}) and
     (! $field{'SRCGENRE'}) and (! $field{'SRCTEXT'}) ) {
  $field{'SRCDIR'} = 'on';
  $field{'SRCFILE'} = 'on';
  $field{'SRCTRACK'} = 'on';
  $field{'SRCTITLE'} = 'on';
  $field{'SRCARTIST'} = 'on';
  $field{'SRCALBUM'} = 'on';
  $field{'SRCDATES'} = 'on';
  $field{'SRCGENRE'} = 'on';
  $field{'SRCTEXT'} = 'on';
}

# Initialize hashes, etc.
$html_head_sent = 0;
$toc_links = '';
$LIB_sum = '';
%subdir_shown = ();

WriteLog("Started.");

if ($cmdline_argcnt < 1) {
  syswrite STDOUT, "Content-type: text/html; charset=UTF-8\n\n";
}

if (! $Arg_Libs) {
  $error_msg = 'No libraries specified.';
}

&ConfirmDir($SERVER_DIR_ARR{'sys'});
&ConfirmDir($SYS_DIR{'pl'});
&ConfirmDir($SYS_DIR{'m3u'});

# Playlist delete.
if (! $error_msg) {
  if ( ($Arg_Name) and ($field{'CHKDEL'}) ) {
    $m3u_delname = $SYS_DIR{'pl'}.$Arg_Name.$m3u_ext;
    unlink($m3u_delname);
    if (-e $m3u_delname) {
      $error_msg = 'Error on PlayList delete: "'.$m3u_delname.'"';
    }
    $Arg_Body = '';  $Arg_Name = '';
  }
}  # Playlist delete.

# Possible playlist load.
if (! $error_msg) {
  if ( ($Arg_Load) or ($Arg_Append) ) {
    if ($Arg_Load) { $Arg_Body = ''; }
    $m3u_loadfrom = $SYS_DIR{'pl'}.$Arg_Load.$Arg_Append.$m3u_ext;
    if (! -e $m3u_loadfrom) {
      $error_msg = 'Error on PlayList load: "'.$m3u_loadfrom.'"';
    } else {
      open(PL_IN, "< ".$m3u_loadfrom);
      while (<PL_IN>) {
        $pl_in_line = $_;
        $pl_in_line =~ s/\r//gm;
        $pl_in_line =~ s/\/\//igm;
        # $pl_in_line =~ s/$Arg_Folder//igm;
        &clean($pl_in_line);
        if ($pl_in_line) { $Arg_Body .= $pl_in_line."\n"; }
      }
      close(PL_IN);
    }
    $Arg_Name = $Arg_Load.$Arg_Append;
  }
}  # Playlist load.

# Possible section playlist create/append.
if (! $error_msg) {
  if ($Arg_Cat) {
    $M_DAT_IDX = $SERVER_DIR_ARR{'sys'}.$Arg_Folder.'.idx';
    if (! -e $M_DAT_IDX) {
      $error_msg = 'Media search index not found: "'.$M_DAT_IDX.'"';
    } else {
      # Loop through index file capturing matches.
      $cat_playlist_out = "";
      open(IDX_DAT, "< ".$M_DAT_IDX);
      %idx_head_part = ();
      $idx_line_cnt = 0;
      while (<IDX_DAT>) {
        $idx_line_in = $_;
        chomp($idx_line_in);
        $idx_line_cnt++;
        %idx_part = ();
        if ($idx_line_cnt == 1) {
          # Read header.
          @idx_head_parts = split(/$search_delim/, substr($idx_line_in,2,length($idx_line_in)-2) );
          $idx_head_part_last = $#idx_head_parts;
        } else {
          # Read data.
          if (substr($idx_line_in,0,1) ne '#') {
            @idx_line_parts = split(/$search_delim/, $idx_line_in);
            for ($idx_field_idx = 0; $idx_field_idx <= $idx_head_part_last; $idx_field_idx++) {
              $idx_part{$idx_head_parts[$idx_field_idx]} = $idx_line_parts[$idx_field_idx];
            }
            # syswrite STDOUT, 'file='.$idx_part{'file'}.'; subdir='.$idx_part{'subdir'}.'; line="'.$idx_line_in.'"<br>'."\n";
            if ($idx_part{'file'}) {
              if ( substr(lc('/'.$idx_part{'subdir'}.'/'),0,length($Arg_Cat)) eq lc($Arg_Cat) ) {
                if ( length($cat_playlist_out) < $max_playlist_create_size ) {
                  $cat_playlist_out .= &FormatLink($Arg_Folder, 'a', $idx_part{'subdir'}, $idx_part{'file'}, $idx_part{'m3uname'}, $idx_part{'url'})."\n";
                  if ( length($cat_playlist_out) >= $max_playlist_create_size ) {
                    $cat_playlist_out .= "# truncated\n";
                  }
                }
              }
            }
          }
        }
      }  # Read idx.
      close(IDX_DAT);
      if ($cat_playlist_out) {
        $Arg_Body .= $cat_playlist_out;
        @section_playlist_parts = split(/\//, lc($Arg_Cat));
        $section_playlist_parts_last = $#section_playlist_parts;
        if (! $Arg_Name) {
          for ($section_playlist_parts_idx = 0; $section_playlist_parts_idx <= $section_playlist_parts_last; $section_playlist_parts_idx++) {
            if ($section_playlist_parts[$section_playlist_parts_idx]) {
              $Arg_Name = $section_playlist_parts[$section_playlist_parts_idx];
              while ($Arg_Name =~ /[^a-z0-9\_]/) { $Arg_Name =~ s/[^a-z0-9\_]/\_/g; }
              while ($Arg_Name =~ /\_\_/) { $Arg_Name =~ s/\_\_/\_/g; }
              while ($Arg_Name =~ /\_$/) { $Arg_Name =~ s/\_$//g; }
              while ($Arg_Name =~ /^\_/) { $Arg_Name =~ s/^\_//g; }
            }
          }
        }
      }
    }  # Index exists.
  }  # Cat arg present.
}  # Playlist create from section.

# Validate current playlist.
$playlist_sec = 0;
$playlist_bytes = 0;
$playlist_lines_ttl = 0;
$playlist_lines_valid = 0;
if ($Arg_Body) {
  $playlist_out = '';
  $playlist_out_line = '';
  @pl_check_lines = split(/\n/, $Arg_Body);
  foreach $pl_check_line (@pl_check_lines) {
    &clean($pl_check_line);
    $pl_check_line =~ s/^[\#\ ]+//;
    if ($pl_check_line) {
      $playlist_lines_ttl++;
      $pl_check_file = $pl_check_line;
      if ($pl_check_file !~ /^http/) {
        if (! -e $pl_check_file) {
          $playlist_out_line = '# '.$pl_check_line;
        } else {
          $playlist_lines_valid++;
          if ( ($pl_check_line =~ /\.mp3$/i) or
               ($pl_check_line =~ /\.mpg$/i) or
               ($pl_check_line =~ /\.mpeg$/i) ) {
            $pl_check_fields = MP3::Info->new($pl_check_file);
            # Fetch the mp3 info fields, especially the duration.
            if ( ($pl_check_fields->{"SS"} > 0) or ($pl_check_fields->{"MM"} > 0) ) {
              $playlist_sec += (($pl_check_fields->{"MM"}*60)+$pl_check_fields->{"SS"});
            }
          }
          @pl_file_stats = stat($pl_check_file);
          $playlist_bytes += $pl_file_stats[7];
          $playlist_out_line = $pl_check_line;
        }
      } else {
        $playlist_out_line = $pl_check_line;
      }
      if ($playlist_out_line) {
        $playlist_rows_used++;
        if (length($pl_check_line) > $playlist_cols_used) {
          if (length($pl_check_line) <= $max_playlist_cols) {
            $playlist_cols_used = length($pl_check_line);
          } else {
            $playlist_cols_used = $max_playlist_cols;
          }
        }
        $playlist_out .= $playlist_out_line."\n";
      }
    }
  }
  if (int($playlist_cols_used*$ta_col_exp_fact) > $playlist_cols) { $playlist_cols = int($playlist_cols_used*$ta_col_exp_fact); }
  if (($playlist_rows_used+$ta_row_exp_add) > $playlist_rows) { $playlist_rows = ($playlist_rows_used+$ta_row_exp_add); }
  if ($playlist_rows > $max_playlist_rows) { $playlist_rows = $max_playlist_rows; }
  $Arg_Body = $playlist_out;
}

# Possible playlist save.
if (! $error_msg) {
  if ( ( ($Arg_Submit =~ /save/i) and ($Arg_Name) and ($Arg_Body) ) or
       ( ($Arg_Name eq 'default') and ($Arg_Body) ) ) {
    $m3u_saveas = $SYS_DIR{'pl'}.$Arg_Name.$m3u_ext;
    if (-f $m3u_saveas) { unlink($m3u_saveas); }
    open(PL_OUT, "> ".$m3u_saveas);
    $playlist_out = $Arg_Body;
    $playlist_out =~ s/\r//gm;
    &clean($playlist_out);
    # $playlist_out =~ s/^/$Arg_Folder/gmi;
    $playlist_out =~ s/\//\/igm;
    print PL_OUT $playlist_out."\n";
    close(PL_OUT);
    chmod(0666,$m3u_saveas);
    if (! -e $m3u_saveas) {
      $error_msg = 'Error on PlayList save: "'.$m3u_saveas.'"';
    } else {
      $Arg_Load = $Arg_Name;
    }
  }
}  # Playlist save.

# Render output.

CLIPPED...


 DOWNLOAD         < NEWER    OLDER >