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

Perl (click for next photo)

Web-Based Media Manager

Comprehensive program for managing media files; 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 >