public function scanMusicFileTags() { # TODO: handle orphaned records # TODO: displaying itemsChecked / itemsProcessed is incorrect # TODO: which speed-calculation makes sense? itemsChecked/minutute or itemsProcessed/minute or both? $this->jobPhase = 2; $this->beginJob(array('msg' => 'collecting tracks to scan from mysql database'), __FUNCTION__); $app = \Slim\Slim::getInstance(); $phpThumb = Bitmap::getPhpThumb(); $phpThumb->setParameter('config_cache_directory', APP_ROOT . 'embedded'); $getID3 = new \getID3(); // make sure that a single directory will not be scanned twice $scannedDirectories = array(); // get timestamps of all images from mysql database $imageTimestampsMysql = array(); //////////////////////////////////////////////////////////////// // TEMP reset database status for testing purposes #$query = "UPDATE rawtagdata SET importStatus=1, lastScan=0;"; #$app->db->query($query); #$query = "DELETE FROM bitmap WHERE trackId > 0;"; #$app->db->query($query); //////////////////////////////////////////////////////////////// if ($app->config['images']['look_cover_directory'] == TRUE) { $this->pluralizeCommonArtworkDirectoryNames($app->config['images']['common_artwork_dir_names']); } $query = "\n\t\t\tSELECT COUNT(*) AS itemCountTotal\n\t\t\tFROM rawtagdata WHERE lastScan < filemtime"; $this->itemCountTotal = (int) $app->db->query($query)->fetch_assoc()['itemCountTotal']; $query = "\n\t\t\tSELECT id,\n\t\t\t\trelativePath, relativePathHash, filemtime,\n\t\t\t\trelativeDirectoryPath, relativeDirectoryPathHash, directoryMtime \n\t\t\tFROM rawtagdata \n\t\t\tWHERE lastScan < filemtime"; // LIMIT 200000,1000;"; $result = $app->db->query($query); $extractedImages = 0; while ($record = $result->fetch_assoc()) { $this->itemCountChecked++; cliLog($record['id'] . ' ' . $record['relativePath'], 2); $this->updateJob(array('msg' => 'processed ' . $this->itemCountChecked . ' files', 'currentItem' => $record['relativePath'], 'extractedImages' => $extractedImages)); $t = new Rawtagdata(); $t->setId($record['id']); $t->setLastScan(time()); $t->setImportStatus(2); // TODO: handle not found files if (is_file($app->config['mpd']['musicdir'] . $record['relativePath']) === TRUE) { $t->setFilesize(filesize($app->config['mpd']['musicdir'] . $record['relativePath'])); } else { $t->setError('invalid file'); $t->update(); continue; } // skip very large files // TODO: how to handle this? if ($t->getFilesize() > 1000000000) { $t->setError('invalid filesize ' . $t->getFilesize() . ' bytes'); $t->update(); continue; } $tagData = $getID3->analyze($app->config['mpd']['musicdir'] . $record['relativePath']); \getid3_lib::CopyTagsToComments($tagData); $this->mapTagsToRawtagdataInstance($t, $tagData); $t->update(); if (!$app->config['images']['read_embedded']) { continue; } if (isset($tagData['comments']['picture']) === FALSE) { continue; } if (is_array($tagData['comments']['picture']) === FALSE) { continue; } // loop through all embedded images foreach ($tagData['comments']['picture'] as $bitmapIndex => $bitmapData) { if (isset($bitmapData['image_mime']) === FALSE) { // skip unspecifyable datachunk continue; } if (isset($bitmapData['data']) === FALSE) { // skip missing datachunk continue; } $rawImageData = $bitmapData['data']; if (strlen($rawImageData) < 20) { // skip obviously invalid imagedata continue; } if (strlen($rawImageData) > 40000) { // skip huge imagedata // got errormessage "Maximum supported image dimension is 65500 pixels" from ??? continue; } # TODO: delete tmp files of php thumb - shouldn't phpThumb handle that itself? $phpThumb->resetObject(); $phpThumb->setSourceData($rawImageData); $phpThumb->setParameter('config_cache_prefix', $record['relativePathHash'] . '_' . $bitmapIndex . '_'); $phpThumb->SetCacheFilename(); $phpThumb->GenerateThumbnail(); \phpthumb_functions::EnsureDirectoryExists(dirname($phpThumb->cache_filename)); $phpThumb->RenderToFile($phpThumb->cache_filename); $extractedImages++; if (is_file($phpThumb->cache_filename) === FALSE) { // there had been an error // TODO: how to handle this? continue; } # TODO: general handling of permissions of created directories and files chmod($phpThumb->cache_filename, 0777); $relativePath = str_replace(APP_ROOT, '', $phpThumb->cache_filename); $relativePathHash = getFilePathHash($relativePath); $imageSize = GetImageSize($phpThumb->cache_filename); $bitmap = new Bitmap(); $bitmap->setRelativePath($relativePath); $bitmap->setRelativePathHash($relativePathHash); $bitmap->setFilemtime(filemtime($phpThumb->cache_filename)); $bitmap->setFilesize(filesize($phpThumb->cache_filename)); $bitmap->setRawTagDataId($record['id']); # TODO: is there any more need for both ID's? $bitmap->setTrackId($record['id']); # TODO: is there any more need for both ID's? $bitmap->setEmbedded(1); // setAlbumId() will be applied later because at this time we havn't any albumId's but tons of bitmap-record-dupes if ($imageSize !== FALSE) { $bitmap->setWidth($imageSize[0]); $bitmap->setHeight($imageSize[1]); $bitmap->setMimeType($imageSize['mime']); } else { $bitmap->setError(1); } # TODO: can we call insert() immediatly instead of letting check the update() function itself? # this could save performance... $bitmap->update(); } } $this->finishJob(array('extractedImages' => $extractedImages), __FUNCTION__); return; }