diff --git a/app/commands/ClassifyMLPMA.php b/app/commands/ClassifyMLPMA.php index 3f2ab684..782ea61e 100644 --- a/app/commands/ClassifyMLPMA.php +++ b/app/commands/ClassifyMLPMA.php @@ -21,7 +21,14 @@ class ClassifyMLPMA extends Command { * * @var string */ - protected $description = 'Add Pony.fm-specific metadata to imported MLPMA tracks.'; + protected $description = 'Adds Pony.fm-specific metadata to imported MLPMA tracks.'; + + /** + * A counter for the number of processed tracks. + * + * @var int + */ + protected $currentTrack = 0; /** * Create a new command instance. @@ -42,11 +49,26 @@ class ClassifyMLPMA extends Command { { // Get the list of tracks that need classification $tracks = DB::table('mlpma_tracks') - ->orderBy('id') + ->orderBy('mlpma_tracks.id') + ->join('tracks', 'tracks.id', '=', 'mlpma_tracks.track_id') + ->whereNull('tracks.published_at') ->get(); + $this->comment('Importing tracks...'); + + $totalTracks = sizeof($tracks); + + $fileToStartAt = (int) $this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files..." . PHP_EOL); + + $tracks = array_slice($tracks, $fileToStartAt); + $this->currentTrack = $fileToStartAt; + foreach ($tracks as $track) { - $parsedTags = json_decode($track->parsed_tags); + $this->currentTrack++; + $this->comment('[' . $this->currentTrack . '/' . $totalTracks . '] Classifying track [' . $track->filename . ']...'); + + $parsedTags = json_decode($track->parsed_tags, true); //========================================================================================================== @@ -69,14 +91,14 @@ class ClassifyMLPMA extends Command { // If it has "Ingram" in the name, it's definitely an official song remix. if (Str::contains(Str::lower($track->filename), 'ingram')) { - $this->comment('This is an official song remix!'); + $this->info('This is an official song remix!'); list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs, true); // If it has "remix" in the name, it's definitely a remix. } else if (Str::contains(Str::lower($sanitizedTrackTitle), 'remix')) { - $this->comment('This is some kind of remix!'); + $this->info('This is some kind of remix!'); list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs); } @@ -96,6 +118,7 @@ class ClassifyMLPMA extends Command { $track->showSongs()->attach($linkedSongIds); } + echo PHP_EOL; } } @@ -107,9 +130,7 @@ class ClassifyMLPMA extends Command { */ protected function getArguments() { - return array( - array('example', InputArgument::REQUIRED, 'An example argument.'), - ); + return array(); } /** @@ -120,7 +141,7 @@ class ClassifyMLPMA extends Command { protected function getOptions() { return array( - array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null), + array('startAt', null, InputOption::VALUE_OPTIONAL, 'Track to start importing from. Useful for resuming an interrupted import.', 1), ); } @@ -143,11 +164,12 @@ class ClassifyMLPMA extends Command { $this->comment('=> Matched official song: [' . $song->id . '] ' . $song->title); } + if ($isRemixOfOfficialTrack && sizeof($officialSongs) === 1) { $linkedSongIds = [$officialSongs[0]->id]; } else { - if ($isRemixOfOfficialTrack) { + if ($isRemixOfOfficialTrack && sizeof($officialSongs) > 1) { $this->question('Multiple official songs matched! Please enter the ID of the correct one.'); } else if (sizeof($officialSongs) > 0) { diff --git a/app/commands/ImportMLPMA.php b/app/commands/ImportMLPMA.php index bf31c5ee..8e0ab371 100644 --- a/app/commands/ImportMLPMA.php +++ b/app/commands/ImportMLPMA.php @@ -7,9 +7,7 @@ use Illuminate\Support\Facades\File; use Entities\Album; use Entities\Image; use Entities\User; -use Entities\ShowSong; use Entities\Track; -use Entities\TrackType; use Commands\UploadTrackCommand; use Symfony\Component\HttpFoundation\File\UploadedFile; use Carbon\Carbon; @@ -40,6 +38,20 @@ class ImportMLPMA extends Command { */ protected $ignoredExtensions = ['db', 'jpg', 'png']; + /** + * Used to stop the import process when a SIGINT is received. + * + * @var bool + */ + protected $isInterrupted = false; + + /** + * A counter for the number of processed tracks. + * + * @var int + */ + protected $currentFile; + /** * Create a new command instance. * @@ -50,6 +62,12 @@ class ImportMLPMA extends Command { parent::__construct(); } + public function handleInterrupt($signo) { + $this->error('Import aborted!'); + $this->error('Resume it from here using: --startAt='.$this->currentFile); + $this->isInterrupted = true; + } + /** * Execute the console command. * @@ -57,6 +75,8 @@ class ImportMLPMA extends Command { */ public function fire() { + pcntl_signal(SIGINT, [$this, 'handleInterrupt']); + $mlpmaPath = Config::get('app.files_directory').'mlpma'; $tmpPath = Config::get('app.files_directory').'tmp'; @@ -72,14 +92,25 @@ class ImportMLPMA extends Command { $artists = File::directories($mlpmaPath); $this->info(sizeof($artists).' artists found!'); - $this->comment('Importing tracks...'.PHP_EOL); + $this->comment('Importing tracks...'); $totalFiles = sizeof($files); - $currentFile = 0; + + $fileToStartAt = (int) $this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files...".PHP_EOL); + + $files = array_slice($files, $fileToStartAt); + $this->currentFile = $fileToStartAt; foreach($files as $file) { - $currentFile++; - $this->comment('['.$currentFile.'/'.$totalFiles.'] Importing track ['. $file->getFilename() .']...'); + $this->currentFile++; + + pcntl_signal_dispatch(); + if ($this->isInterrupted) { + break; + } + + $this->comment('['.$this->currentFile.'/'.$totalFiles.'] Importing track ['. $file->getFilename() .']...'); if (in_array($file->getExtension(), $this->ignoredExtensions)) { $this->comment('This is not an audio file! Skipping...'.PHP_EOL); @@ -143,7 +174,7 @@ class ImportMLPMA extends Command { } // This is later used by the classification/publishing script to determine the publication date. - $parsedTags['released_at'] = $releasedAt; + $parsedTags['released_at'] = $releasedAt->toDateTimeString(); //========================================================================================================== // Does this track have vocals? @@ -178,12 +209,14 @@ class ImportMLPMA extends Command { $artist->slug = $artist->slug.'-'.Str::random(4); } - $artist = $artist->save(); + $artist->save(); } //========================================================================================================== // Extract the cover art, if any exists. //========================================================================================================== + + $this->comment('Extracting cover art!'); $coverId = null; if (array_key_exists('comments', $allTags) && array_key_exists('picture', $allTags['comments'])) { $image = $allTags['comments']['picture'][0]; @@ -213,7 +246,7 @@ class ImportMLPMA extends Command { $coverId = $cover->id; } else { - $this->error('No cover art found!'); + $this->comment('No cover art found!'); } @@ -246,13 +279,9 @@ class ImportMLPMA extends Command { //========================================================================================================== // Save this track. //========================================================================================================== - $title = $parsedTags['title']; -// -// $track = Track::where('user_id', '=', $artist->id) -// ->where('title', '=', $title) -// ->first(); - // "upload" the track to Pony.fm + // "Upload" the track to Pony.fm + $this->comment('Transcoding the track!'); Auth::loginUsingId($artist->id); $trackFile = new UploadedFile($file->getPathname(), $file->getFilename(), $allTags['mime_type']); @@ -261,14 +290,29 @@ class ImportMLPMA extends Command { $upload = new UploadTrackCommand(true); $result = $upload->execute(); -// var_dump(null); - if ($result->didFail()) { $this->error(json_encode($result->getValidator()->messages()->getMessages(), JSON_PRETTY_PRINT)); + } else { + // Save metadata. + $track = Track::find($result->getResponse()['id']); + + $track->title = $parsedTags['title']; + $track->cover_id = $coverId; + $track->album_id = $albumId; + $track->track_number = $parsedTags['track_number']; + $track->released_at = $releasedAt; + $track->description = $parsedTags['comments']; + $track->is_downloadable = true; + $track->lyrics = $parsedTags['lyrics']; + $track->is_vocal = $isVocal; + $track->license_id = 2; + $track->save(); + + // If we made it to here, the track is intact! Log the import. DB::table('mlpma_tracks') ->insert([ - 'track_id' => $result['id'], + 'track_id' => $result->getResponse()['id'], 'path' => $file->getRelativePath(), 'filename' => $file->getFilename(), 'extension' => $file->getExtension(), @@ -276,20 +320,8 @@ class ImportMLPMA extends Command { 'parsed_tags' => json_encode($parsedTags), 'raw_tags' => json_encode($rawTags), ]); - - $track = Track::find($result['id']); - var_dump($track); - - $track->title = $parsedTags['title']; - $track->cover_id = $coverId; - $track->album_id = $albumId; - $track->track_number = $parsedTags['track_number']; - $track->released_at = $releasedAt; - $track->is_vocal = $isVocal; - $track->save(); } - echo PHP_EOL.PHP_EOL; } } @@ -311,7 +343,9 @@ class ImportMLPMA extends Command { */ protected function getOptions() { - return array(); + return array( + array('startAt', null, InputOption::VALUE_OPTIONAL, 'Track to start importing from. Useful for resuming an interrupted import.', 1), + ); } diff --git a/app/models/Commands/UploadTrackCommand.php b/app/models/Commands/UploadTrackCommand.php index c241b980..17467db7 100644 --- a/app/models/Commands/UploadTrackCommand.php +++ b/app/models/Commands/UploadTrackCommand.php @@ -78,7 +78,6 @@ $isLossyUpload = !in_array($audioObject->getAudioCodec(), $this->_losslessFormats); if ($isLossyUpload) { - if ($audioObject->getAudioCodec() === 'mp3') { $masterFormat = 'MP3'; @@ -93,10 +92,11 @@ $trackFile = new TrackFile(); $trackFile->is_master = true; $trackFile->format = $masterFormat; + $trackFile->track_id = $track->id; + $trackFile->save(); // Lossy masters are copied into the datastore - no re-encoding involved. - File::copy($source, $trackFile->getFilename()); - $track->trackFiles()->save($trackFile); + File::copy($source, $trackFile->getFile()); } foreach (Track::$Formats as $name => $format) { diff --git a/app/models/Entities/Track.php b/app/models/Entities/Track.php index 337b6b8f..8edf51bb 100644 --- a/app/models/Entities/Track.php +++ b/app/models/Entities/Track.php @@ -448,8 +448,7 @@ $command .= '--genre ' . escapeshellarg($this->genre != null ? $this->genre->name : '') . ' '; $command .= '--copyright ' . escapeshellarg('© '.$this->year.' '.$this->user->display_name).' '; $command .= '--comment "' . 'Downloaded from: https://pony.fm/' . '" '; - $command .= '--encodingTool "' . 'Pony.fm' . '" '; - $command .= '--encodedBy "' . 'Pony.fm - https://pony.fm/' . '" '; + $command .= '--encodingTool "' . 'Pony.fm - https://pony.fm/' . '" '; if ($this->album_id !== NULL) { $command .= '--album ' . escapeshellarg($this->album->title) . ' ';