#!/usr/bin/perl -w # SqueezeCenter Copyright 2001-2007 Logitech. # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License, # version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # require 5.008_001; use strict; use warnings; use FindBin qw($Bin); use lib $Bin; use constant SLIM_SERVICE => 0; # Tell PerlApp to bundle these modules if (0) { require Encode::CN; require Encode::JP; require Encode::KR; require Encode::TW; } BEGIN { use Slim::bootstrap; use Slim::Utils::OSDetect; Slim::bootstrap->loadModules([qw(version Time::HiRes DBD::mysql DBI HTML::Parser XML::Parser::Expat YAML::Syck)], []); }; use Getopt::Long; use File::Path; use File::Spec::Functions qw(:ALL); use Slim::Utils::Log; use Slim::Utils::Prefs; use Slim::Music::Import; use Slim::Music::Info; use Slim::Music::MusicFolderScan; use Slim::Music::PlaylistFolderScan; use Slim::Player::ProtocolHandlers; use Slim::Utils::Misc; use Slim::Utils::MySQLHelper; use Slim::Utils::OSDetect; use Slim::Utils::PluginManager; use Slim::Utils::Progress; use Slim::Utils::Scanner; use Slim::Utils::Strings qw(string); use Slim::Control::Request; sub main { our ($rescan, $playlists, $wipe, $itunes, $musicip, $force, $cleanup, $prefsFile, $progress, $priority); our ($quiet, $logfile, $logdir, $logconf, $debug, $help); our $LogTimestamp = 1; my $prefs = preferences('server'); my $musicmagic; $prefs->readonly; GetOptions( 'force' => \$force, 'cleanup' => \$cleanup, 'rescan' => \$rescan, 'wipe' => \$wipe, 'playlists' => \$playlists, 'itunes' => \$itunes, 'musicip' => \$musicip, 'musicmagic' => \$musicmagic, 'prefsfile=s' => \$prefsFile, # prefsdir parsed by Slim::Utils::Prefs 'progress' => \$progress, 'priority=i' => \$priority, 'logfile=s' => \$logfile, 'logdir=s' => \$logdir, 'logconfig=s' => \$logconf, 'debug=s' => \$debug, 'quiet' => \$quiet, 'LogTimestamp!'=> \$LogTimestamp, 'help' => \$help, ); if (defined $musicmagic && !defined $musicip) { $musicip = $musicmagic; } Slim::Utils::Log->init({ 'logconf' => $logconf, 'logdir' => $logdir, 'logfile' => $logfile, 'logtype' => 'scanner', 'debug' => $debug, }); if ($help || (!$rescan && !$wipe && !$playlists && !$musicip && !$itunes && !scalar @ARGV)) { usage(); exit; } # Redirect STDERR to the log file. if (!$progress) { tie *STDERR, 'Slim::Utils::Log::Trapper'; } STDOUT->autoflush(1); my $log = logger('server'); # Bring up strings, database, etc. initializeFrameworks($log); # Set priority, command line overrides pref if (defined $priority) { Slim::Utils::Misc::setPriority($priority); } else { Slim::Utils::Misc::setPriority( $prefs->get('scannerPriority') ); } if (!$force && Slim::Music::Import->stillScanning) { msg("Import: There appears to be an existing scanner running.\n"); msg("Import: If this is not the case, run with --force\n"); msg("Exiting!\n"); exit; } if ($playlists) { Slim::Music::PlaylistFolderScan->init; Slim::Music::Import->scanPlaylistsOnly(1); } else { Slim::Music::PlaylistFolderScan->init; Slim::Music::MusicFolderScan->init; } # Various importers - should these be hardcoded? if ($itunes) { initClass('Slim::Plugin::iTunes::Importer'); } if ($musicip) { initClass('Slim::Plugin::MusicMagic::Importer'); } #checkDataSource(); $log->info("SqueezeCenter done init...\n"); # Take the db out of autocommit mode - this makes for a much faster scan. Slim::Schema->storage->dbh->{'AutoCommit'} = 0; # Flag the database as being scanned. Slim::Music::Import->setIsScanning(1); if ($cleanup) { Slim::Music::Import->cleanupDatabase(1); } if ($wipe) { eval { Slim::Schema->txn_do(sub { Slim::Schema->wipeAllData }) }; if ($@) { logError("Failed when calling Slim::Schema->wipeAllData: [$@]"); logError("This is a fatal error. Exiting"); exit(-1); } # Clear the artwork cache, since it will contain cached items with IDs # that are no longer valid. Just delete the directory because clearing the # cache takes too long my $artworkCacheDir = catdir( $prefs->get('cachedir'), 'Artwork' ); eval { rmtree( $artworkCacheDir ); }; } # Don't wrap the below in a transaction - we want to have the server # periodically update the db. This is probably better than a giant # commit at the end, but is debatable. # # NB: Slim::Schema::throw_exception really isn't right now - it's just # printing an error and bt(). Once the server can handle & log # exceptions properly, it should croak(), so the exception is # propagated to the higher levels. # # We've been passed an explict path or URL - deal with that. if (scalar @ARGV) { for my $url (@ARGV) { eval { Slim::Utils::Scanner->scanPathOrURL({ 'url' => $url }) }; } } else { # Otherwise just use our Importers to scan. eval { if ($wipe) { Slim::Music::Import->resetImporters; } Slim::Music::Import->runScan; }; } if ($@) { logError("Failed when running main scan: [$@]"); logError("Skipping post-process & Not updating lastRescanTime!"); } else { # Run mergeVariousArtists, artwork scan, etc. eval { Slim::Schema->txn_do(sub { Slim::Music::Import->runScanPostProcessing }) }; if ($@) { logError("Failed when running scan post-process: [$@]"); logError("Not updating lastRescanTime!"); } else { Slim::Music::Import->setLastScanTime; if ($@) { logError("Failed to update lastRescanTime: [$@]"); logError("You may encounter problems next rescan!"); } } } # Wipe templates if they exist. rmtree( catdir($prefs->get('cachedir'), 'templates') ); } sub initializeFrameworks { my $log = shift; $log->info("SqueezeCenter OSDetect init..."); Slim::Utils::OSDetect::init(); Slim::Utils::OSDetect::initSearchPath(); # initialize SqueezeCenter subsystems $log->info("SqueezeCenter settings init..."); Slim::Utils::Prefs::init(); Slim::Utils::Prefs::makeCacheDir(); $log->info("SqueezeCenter strings init..."); Slim::Utils::Strings::init(catdir($Bin,'strings.txt'), "EN"); # $log->info("SqueezeCenter MySQL init..."); # Slim::Utils::MySQLHelper->init(); $log->info("SqueezeCenter Info init..."); Slim::Music::Info::init(); # Bug 6721 # The ProtocolHandlers class won't have all our handlers registered, # and this can cause problems scanning playlists that contain URLs # that use a protocol handler, i.e. rhapd:// my @handlers = qw( live365 loop pandora rhapd slacker source ); for my $handler ( @handlers ) { Slim::Player::ProtocolHandlers->registerHandler( $handler => 1 ); } } sub usage { print < Command line options: --force Force a scan, even if we think a scan is already taking place. --cleanup Run a database cleanup job at the end of the scan --rescan Look for new files since the last scan. --wipe Wipe the DB and start from scratch --playlists Only scan files in your playlistdir. --itunes Run the iTunes Importer. --musicip Run the MusicIP Importer. --progress Show a progress bar of the scan. --prefsdir Specify alternative preferences directory. --priority set process priority from -20 (high) to 20 (low) --logfile Send all debugging messages to the specified logfile. --logdir Specify folder location for log file --logconfig Specify pre-defined logging configuration file --debug various debug options --quiet keep silent Examples: $0 --rescan /Users/dsully/Music $0 http://www.somafm.com/groovesalad.pls EOF } sub initClass { my $class = shift; Slim::bootstrap::tryModuleLoad($class); if ($@) { logError("Couldn't load $class: $@"); } else { $class->initPlugin; } } sub cleanup { # Make sure to flush anything in the database to disk. if ($INC{'Slim/Schema.pm'} && Slim::Schema->storage) { Slim::Music::Import->setIsScanning(0); Slim::Schema->forceCommit; Slim::Schema->disconnect; } } sub END { Slim::bootstrap::theEND(); } sub idleStreams {} main(); __END__