#!/usr/bin/perl

# Copyright (c) 2000 Kveton.com
# All rights reserved.

# $Id: filefind,v 1.8 2001/07/23 05:37:17 scott Exp $
# $Source: /data/cvsroot/www/tunes/bin/filefind,v $

# Find and file away MP3's.  Run multiple times and will
#  ignore addition of duplicates in db (based on MD5 hash
#  of full file path.

use File::Find;
use DBI;
use MPEG::MP3Info;
use Digest::MD5;
use Getopt::Long;

$MAJOR_VERSION = '1.0';
$VERSION = '1.21';

my $usage = qq{
  filefind [--help] --path <path> ...
    
    --path  The path to the root of your MP3 store.  Can 
              specify multiple paths.
    --help  This help message.

    filefind v.$VERSION, 2001
    Part of the Ampache v.$VERSION distribution.

};

# get any vars from the command line
use vars qw(@opt_path $opt_help);
GetOptions( qw( path=s@ help+ ) );

if ( $opt_help or (not @opt_path) ) {
  die $usage;
}

# User, pass and database names
my $user = 'musac';
my $pass = '<your password here>';
my $db_name = 'music';
my $db_host = 'db.kveton.com';

# statement handle cache
my %sth_cache = ();

$dbh = DBI->connect("dbi:mysql:database=$db_name;host=$db_host;port=3306", $user, $pass);

# the meat of the script
foreach my $path (@opt_path) {
  find( \&catalog, $path );
}

sub catalog {
  my $file = "$File::Find::name";

  # if you use netatalk you understand this line
  if ( ($file =~ /.*\.mp3$/) and ($file !~ /AppleDouble/) ) {
    if ( my $md5 = select_mp3( $file ) ) {
      insert_mp3( $file, $md5 ); 
    }
  }
}

sub insert_mp3 {
  my ($file, $md5) = @_; 

  use_winamp_genres();

  %info = %{get_mp3info($file)};
  %tag  = %{get_mp3tag($file)};

  my $sth = $sth_cache->{_insert_mp3};

  if ( not $sth ) {
    my $sql = qq{INSERT INTO song (file, album, artist, title, layer, bitrate, rate, mode, size, md5, time, genre, track) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)};  
    $sth = $dbh->prepare($sql);
    $sth_cache->{_insert_mp3} = $sth;
  }

  my $artist_id = 0;

  # get the artist if any
  if ( $tag{ARTIST} ) {
    $artist_id = select_artist($tag{ARTIST});

    if ( !$artist_id ) {
      $artist_id = insert_artist($tag{ARTIST});
    }
  }

  my $album_id = 0;

  # get the album if any
  if ( $tag{ALBUM} ) {
    $album_id = select_album($tag{ALBUM});

    if ( !$album_id ) {
      $album_id = insert_album($tag{ALBUM});
    }
  }

  # Since MPEG::MP3Info only returns the name and not id associated with the GENRE we
  #  have to ferret it out of our list of genres stored in the database.  If somebody knows
  #  a better way to do this (or how to get it out of MPEG::MP3Info) I will gladly fix it.
  my $genre_sth = $sth_cache->{_genre_cache};

  if ( not $genre_sth ) {
    my $sql = qq{SELECT id FROM genre WHERE name=?};
    $genre_sth = $dbh->prepare($sql);
    $sth_cache->{_genre_cache} = $genre_sth;
  }

  $genre_sth->execute($tag{GENRE});
  my ($genre_id) = $genre_sth->fetchrow();

  # if we don't have the title, set to name of the file. 
  $sth->execute($file, $album_id ||= 0, $artist_id ||= 0, $tag{TITLE} ||= $file, $info{LAYER}, $info{BITRATE},
                 $info{FREQUENCY}, $info{MODE}, (stat($file))[7], $md5, (($info{MM}*60)+$info{SS}), $genre_id ||= 255, $tag{TRACKNUM} );
}

sub select_mp3 {
  my ($file) = @_;

  my $file_md5 = scalar ((Digest::MD5->new)->add($file))->hexdigest;

  my $sth = $sth_cache->{_select_mp3};

  if ( not $sth ) {
    my $sql = qq{SELECT md5 FROM song WHERE md5=?};
    $sth = $dbh->prepare($sql);
    $sth_cache->{_select_mp3} = $sth;
  }
  
  $sth->execute($file_md5);

  my ($search_md5) = $sth->fetchrow();

  if ( $file_md5 eq $search_md5 ) {
    return 0;
  }
  else {
    return $file_md5;
  }
}

sub select_artist {
  my ($artist) = @_;

  my $sth = $sth_cache->{_select_artist};

  if ( not $sth ) {
    my $sql = qq{SELECT id FROM artist WHERE name=?};
    $sth = $dbh->prepare($sql);
    $sth_cache->{_select_artist} = $sth;
  }

  $sth->execute($artist);

  my ($artist_id) = $sth->fetchrow();
  return ($artist_id);
}


sub insert_artist {
  my ($artist) = @_;

  my $sth = $sth_cache->{_insert_artist};

  if ( not $sth ) {
    my $sql = qq{INSERT INTO artist (name) VALUES (?)};
    $sth = $dbh->prepare($sql);
    $sth_cache->{_insert_artist} = $sth;
  }

  $sth->execute($artist);

  return ($dbh->{mysql_insertid});
}


sub select_album {
  my ($album) = @_;

  my $sth = $sth_cache->{_select_album};

  if ( not $sth ) {
    my $sql = qq{SELECT id FROM album WHERE name=?};
    $sth = $dbh->prepare($sql);
    $sth_cache->{_select_album} = $sth;
  }

  $sth->execute($album);
  my ($id) = $sth->fetchrow();

  return ($id);
}


sub insert_album {
  my ($album) = @_;

   my $sth = $sth_cache->{_insert_album};

  if ( not $sth ) {
    my $sql = qq{INSERT INTO album (name) VALUES (?)};
    $sth = $dbh->prepare($sql);
    $sth_cache->{_insert_album} = $sth;
  }

  $sth->execute($album);
  
  return ($dbh->{mysql_insertid});
}

1;
