// static MusicMetadata* MetaIO::readMetadata(const QString &filename) { MusicMetadata *mdata = NULL; MetaIO *tagger = MetaIO::createTagger(filename); bool ignoreID3 = (gCoreContext->GetNumSetting("Ignore_ID3", 0) == 1); if (tagger) { if (!ignoreID3) mdata = tagger->read(filename); if (ignoreID3 || !mdata) mdata = tagger->readFromFilename(filename); delete tagger; } if (!mdata) { LOG(VB_GENERAL, LOG_ERR, QString("MetaIO::readMetadata(): Could not read '%1'") .arg(filename)); } return mdata; }
void EditAlbumartDialog::doRemoveImageFromTag(bool doIt) { if (!doIt) return; MythUIButtonListItem *item = m_coverartList->GetItemCurrent(); if (item) { AlbumArtImage *image = qVariantValue<AlbumArtImage*> (item->GetData()); if (image) { MetaIO *tagger = m_metadata->getTagger(); if (!tagger->supportsEmbeddedImages()) { LOG(VB_GENERAL, LOG_ERR, "EditAlbumartDialog: asked to remove an image from the tag " "but the tagger doesn't support it!"); return; } if (!tagger->removeAlbumArt(m_metadata->Filename(), image)) LOG(VB_GENERAL, LOG_ERR, "EditAlbumartDialog: failed to remove album art from tag"); else LOG(VB_GENERAL, LOG_INFO, "EditAlbumartDialog: album art removed from tag"); removeCachedImage(image); rescanForImages(); } } }
void EditMetadataCommon::saveAll() { if (GetMythDB()->GetNumSetting("AllowTagWriting", 0)) { MetaIO *tagger = m_metadata->getTagger(); if (tagger) tagger->write(m_metadata); } saveToDatabase(); cleanupAndClose(); }
void EditMetadataCommon::scanForImages(void) { // clear the original images AlbumArtList *imageList = m_metadata->getAlbumArtImages()->getImageList(); while (!imageList->isEmpty()) { delete imageList->back(); imageList->pop_back(); } // scan the directory for images QFileInfo fi(m_metadata->Filename()); QDir dir = fi.absoluteDir(); QString nameFilter = gCoreContext->GetSetting("AlbumArtFilter", "*.png;*.jpg;*.jpeg;*.gif;*.bmp"); dir.setNameFilters(nameFilter.split(";")); QStringList files = dir.entryList(); for (int x = 0; x < files.size(); x++) { AlbumArtImage *image = new AlbumArtImage(); //image->id = 0; image->filename = dir.absolutePath() + '/' + files.at(x); image->embedded = false; image->imageType = AlbumArtImages::guessImageType(image->filename); image->description = ""; m_metadata->getAlbumArtImages()->addImage(image); } // scan the tracks tag for any images MetaIO *tagger = m_metadata->getTagger(); if (tagger->supportsEmbeddedImages()) { AlbumArtList art = tagger->getAlbumArtList(m_metadata->Filename()); for (int x = 0; x < art.count(); x++) { AlbumArtImage image = art.at(x); m_metadata->getAlbumArtImages()->addImage(image); } } }
void EditAlbumartDialog::doCopyImageToTag(const AlbumArtImage *image) { MetaIO *tagger = m_metadata->getTagger(); if (!tagger->supportsEmbeddedImages()) { LOG(VB_GENERAL, LOG_ERR, "EditAlbumartDialog: asked to write album art to the tag " "but the tagger does't support it!"); return; } if (!tagger->writeAlbumArt(m_metadata->Filename(), image)) LOG(VB_GENERAL, LOG_ERR, "EditAlbumartDialog: failed to write album art to tag"); else LOG(VB_GENERAL, LOG_INFO, "EditAlbumartDialog: album art written to tag"); removeCachedImage(image); rescanForImages(); }
/*! * \brief Insert file details into database. * If it is an audio file, read the metadata and insert * that information at the same time. * * If it is an image file, just insert the filename and * type. * * \param filename Full path to file. * * \returns Nothing. */ void FileScanner::AddFileToDB(const QString &filename) { QString extension = filename.section( '.', -1 ) ; QString directory = filename; directory.remove(0, m_startdir.length()); directory = directory.section( '/', 0, -2); QString nameFilter = gCoreContext->GetSetting("AlbumArtFilter", "*.png;*.jpg;*.jpeg;*.gif;*.bmp"); // If this file is an image, insert the details into the music_albumart table if (nameFilter.indexOf(extension.toLower()) > -1) { QString name = filename.section( '/', -1); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("INSERT INTO music_albumart SET filename = :FILE, " "directory_id = :DIRID, imagetype = :TYPE;"); query.bindValue(":FILE", name); query.bindValue(":DIRID", m_directoryid[directory]); query.bindValue(":TYPE", AlbumArtImages::guessImageType(name)); if (!query.exec() || query.numRowsAffected() <= 0) { MythDB::DBError("music insert artwork", query); } return; } Decoder *decoder = Decoder::create(filename, NULL, NULL, true); if (decoder) { LOG(VB_FILE, LOG_INFO, QString("Reading metadata from %1").arg(filename)); Metadata *data = decoder->readMetadata(); if (data) { QString album_cache_string; // Set values from cache int did = m_directoryid[directory]; if (did > 0) data->setDirectoryId(did); int aid = m_artistid[data->Artist().toLower()]; if (aid > 0) { data->setArtistId(aid); // The album cache depends on the artist id album_cache_string = data->getArtistId() + "#" + data->Album().toLower(); if (m_albumid[album_cache_string] > 0) data->setAlbumId(m_albumid[album_cache_string]); } int gid = m_genreid[data->Genre().toLower()]; if (gid > 0) data->setGenreId(gid); // Commit track info to database data->dumpToDatabase(); // Update the cache m_artistid[data->Artist().toLower()] = data->getArtistId(); m_genreid[data->Genre().toLower()] = data->getGenreId(); album_cache_string = data->getArtistId() + "#" + data->Album().toLower(); m_albumid[album_cache_string] = data->getAlbumId(); // read any embedded images from the tag MetaIO *tagger = data->getTagger(); if (tagger && tagger->supportsEmbeddedImages()) { AlbumArtList artList = tagger->getAlbumArtList(data->Filename()); data->setEmbeddedAlbumArt(artList); data->getAlbumArtImages()->dumpToDatabase(); } delete data; } delete decoder; } }
void EditAlbumartDialog::customEvent(QEvent *event) { if (event->type() == DialogCompletionEvent::kEventType) { DialogCompletionEvent *dce = (DialogCompletionEvent*)(event); // make sure the user didn't ESCAPE out of the menu if (dce->GetResult() < 0) return; QString resultid = dce->GetId(); QString resulttext = dce->GetResultText(); if (resultid == "changetypemenu") { int type = dce->GetData().toInt(); if ((type >= IT_UNKNOWN) && (type < IT_LAST)) { // get selected image in list MythUIButtonListItem *item = m_coverartList->GetItemCurrent(); if (item) { item->SetText(m_albumArt->getTypeName((ImageType) type)); AlbumArtImage *image = qVariantValue<AlbumArtImage*> (item->GetData()); if (image) { AlbumArtImage oldImage = *image; image->imageType = (ImageType) type; if (image->imageType == oldImage.imageType) return; // rename any cached image to match the new type if (image->embedded) { // update the new cached image filename image->filename = QString(GetConfDir() + "/MythMusic/AlbumArt/%1-%2.jpg") .arg(m_metadata->ID()) .arg(AlbumArtImages::getTypeFilename(image->imageType)); if (image->filename != oldImage.filename && QFile::exists(oldImage.filename)) { // remove any old cached file with the same name as the new one QFile::remove(image->filename); // rename the old cached file to the new one QFile::rename(oldImage.filename, image->filename); // force the theme image cache to refresh the image GetMythUI()->RemoveFromCacheByFile(image->filename); } // change the image type in the tag if it supports it MetaIO *tagger = m_metadata->getTagger(); if (tagger && tagger->supportsEmbeddedImages()) { if (!tagger->changeImageType(m_metadata->Filename(), &oldImage, image->imageType)) LOG(VB_GENERAL, LOG_INFO, "EditAlbumartDialog: failed to change image type"); } } else { QFileInfo fi(oldImage.filename); // get the new images filename image->filename = QString(fi.absolutePath() + "/%1.jpg") .arg(AlbumArtImages::getTypeFilename(image->imageType)); if (image->filename != oldImage.filename && QFile::exists(oldImage.filename)) { // remove any old cached file with the same name as the new one QFile::remove(image->filename); // rename the old cached file to the new one QFile::rename(oldImage.filename, image->filename); // force the theme image cache to refresh the image GetMythUI()->RemoveFromCacheByFile(image->filename); } } m_albumArtChanged = true; gridItemChanged(item); } } } } else if (resultid == "asktypemenu") { int type = dce->GetData().toInt(); if ((type >= IT_UNKNOWN) && (type < IT_LAST)) copyImageToTag((ImageType) type); } else if (resultid == "optionsmenu") { if (resulttext == tr("Edit Metadata")) switchToMetadata(); else if (resulttext == tr("Rescan For Images")) rescanForImages(); else if (resulttext == tr("Search Internet For Images")) searchForAlbumImages(); else if (resulttext == tr("Change Image Type")) showTypeMenu(); else if (resulttext == tr("Copy Selected Image To Tag")) copySelectedImageToTag(); else if (resulttext == tr("Remove Selected Image From Tag")) removeSelectedImageFromTag(); else if (resulttext == tr("Copy Image To Tag")) startCopyImageToTag(); } else if (resultid == "imagelocation") { m_imageFilename = resulttext; // save directory location for next time QFileInfo fi(m_imageFilename); gCoreContext->SaveSetting("MusicLastImageLocation", fi.canonicalPath()); showTypeMenu(false); } } else if (event->type() == MythEvent::MythEventMessage) { MythEvent *me = (MythEvent *)event; QStringList tokens = me->Message().split(" ", QString::SkipEmptyParts); if (!tokens.isEmpty()) { if (tokens[0] == "BROWSER_DOWNLOAD_FINISHED") rescanForImages(); } } }
void ImportMusicDialog::addPressed() { if (m_tracks->size() == 0) return; Metadata *meta = m_tracks->at(m_currentTrack)->metadata; // is the current track a new file? if (m_tracks->at(m_currentTrack)->isNewTune) { // get the save filename - this also creates the correct directory stucture QString saveFilename = Ripper::filenameFromMetadata(meta); // we need to manually copy the file extension QFileInfo fi(meta->Filename()); saveFilename += "." + fi.suffix(); // copy the file to the new location if (!copyFile(meta->Filename(), saveFilename)) { ShowOkPopup(tr("Copy Failed\nCould not copy file to: %1") .arg(saveFilename)); return; } meta->setFilename(saveFilename); // do we need to update the tags? if (m_tracks->at(m_currentTrack)->metadataHasChanged) { Decoder *decoder = Decoder::create(saveFilename, NULL, NULL, true); if (decoder) { decoder->commitMetadata(meta); delete decoder; } } // update the database meta->dumpToDatabase(); // read any embedded images from the tag MetaIO *tagger = meta->getTagger(); if (tagger && tagger->supportsEmbeddedImages()) { AlbumArtList artList = tagger->getAlbumArtList(meta->Filename()); meta->setEmbeddedAlbumArt(artList); meta->getAlbumArtImages()->dumpToDatabase(); } m_somethingWasImported = true; m_tracks->at(m_currentTrack)->isNewTune = Ripper::isNewTune( meta->Artist(), meta->Album(), meta->Title()); // update the UI fillWidgets(); } else ShowOkPopup(tr("This track is already in the database")); }
static int ExtractImage(const MythUtilCommandLineParser &cmdline) { if (cmdline.toString("songid").isEmpty()) { LOG(VB_GENERAL, LOG_ERR, "Missing --songid option"); return GENERIC_EXIT_INVALID_CMDLINE; } if (cmdline.toString("imagetype").isEmpty()) { LOG(VB_GENERAL, LOG_ERR, "Missing --imagetype option"); return GENERIC_EXIT_INVALID_CMDLINE; } int songID = cmdline.toInt("songid"); ImageType type = (ImageType)cmdline.toInt("imagetype"); MusicMetadata *mdata = MusicMetadata::createFromID(songID); if (!mdata) { LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID)); return GENERIC_EXIT_NOT_OK; } AlbumArtImage *image = mdata->getAlbumArtImages()->getImage(type); if (!image) { LOG(VB_GENERAL, LOG_ERR, QString("Cannot find image of type: %1").arg(type)); return GENERIC_EXIT_NOT_OK; } MetaIO *tagger = mdata->getTagger(); if (!tagger) { LOG(VB_GENERAL, LOG_ERR, QString("Cannot find a tagger for this file: %1").arg(mdata->Filename(false))); return GENERIC_EXIT_NOT_OK; } if (!image->embedded || !tagger->supportsEmbeddedImages()) { LOG(VB_GENERAL, LOG_ERR, QString("Either the image isn't embedded or the tagger doesn't support embedded images")); return GENERIC_EXIT_NOT_OK; } // find the tracks actual filename StorageGroup musicGroup("Music", gCoreContext->GetHostName(), false); QString trackFilename = musicGroup.FindFile(mdata->Filename(false)); // where are we going to save the image QString path; StorageGroup artGroup("MusicArt", gCoreContext->GetHostName(), false); QStringList dirList = artGroup.GetDirList(); if (dirList.size()) path = artGroup.FindNextDirMostFree(); if (!QDir(path).exists()) { LOG(VB_GENERAL, LOG_ERR, "Cannot find a directory in the 'MusicArt' storage group to save to"); return GENERIC_EXIT_NOT_OK; } path += "/AlbumArt/"; QDir dir(path); QString filename = QString("%1-%2.jpg").arg(mdata->ID()).arg(AlbumArtImages::getTypeFilename(image->imageType)); if (QFile::exists(path + filename)) QFile::remove(path + filename); if (!dir.exists()) dir.mkpath(path); QImage *saveImage = tagger->getAlbumArt(trackFilename, image->imageType); if (saveImage) { saveImage->save(path + filename, "JPEG"); delete saveImage; } delete tagger; // tell any clients that the albumart for this track has changed gCoreContext->SendMessage(QString("MUSIC_ALBUMART_CHANGED %1 %2").arg(songID).arg(type)); return GENERIC_EXIT_OK; }
static int UpdateMeta(const MythUtilCommandLineParser &cmdline) { bool ok = true; int result = GENERIC_EXIT_OK; if (cmdline.toString("songid").isEmpty()) { LOG(VB_GENERAL, LOG_ERR, "Missing --songid option"); return GENERIC_EXIT_INVALID_CMDLINE; } int songID = cmdline.toInt("songid"); MusicMetadata *mdata = MusicMetadata::createFromID(songID); if (!mdata) { LOG(VB_GENERAL, LOG_ERR, QString("Cannot find metadata for trackid: %1").arg(songID)); return GENERIC_EXIT_NOT_OK; } if (!cmdline.toString("title").isEmpty()) mdata->setTitle(cmdline.toString("title")); if (!cmdline.toString("artist").isEmpty()) mdata->setArtist(cmdline.toString("artist")); if (!cmdline.toString("album").isEmpty()) mdata->setAlbum(cmdline.toString("album")); if (!cmdline.toString("genre").isEmpty()) mdata->setGenre(cmdline.toString("genre")); if (!cmdline.toString("trackno").isEmpty()) mdata->setTrack(cmdline.toInt("trackno")); if (!cmdline.toString("year").isEmpty()) mdata->setYear(cmdline.toInt("year")); if (!cmdline.toString("rating").isEmpty()) mdata->setRating(cmdline.toInt("rating")); if (!cmdline.toString("playcount").isEmpty()) mdata->setPlaycount(cmdline.toInt("playcount")); if (!cmdline.toString("lastplayed").isEmpty()) mdata->setLastPlay(cmdline.toDateTime("lastplayed")); mdata->dumpToDatabase(); MetaIO *tagger = mdata->getTagger(); if (tagger) { ok = tagger->write(mdata->getLocalFilename(), mdata); if (!ok) LOG(VB_GENERAL, LOG_ERR, QString("Failed to write to tag for trackid: %1").arg(songID)); } // tell any clients that the metadata for this track has changed gCoreContext->SendMessage(QString("MUSIC_METADATA_CHANGED %1").arg(songID)); if (!ok) result = GENERIC_EXIT_NOT_OK; return result; }
/*! * \brief Insert file details into database. * If it is an audio file, read the metadata and insert * that information at the same time. * * If it is an image file, just insert the filename and * type. * * \param filename Full path to file. * * \returns Nothing. */ void MusicFileScanner::AddFileToDB(const QString &filename, const QString &startDir) { QString extension = filename.section( '.', -1 ) ; QString directory = filename; directory.remove(0, startDir.length()); directory = directory.section( '/', 0, -2); QString nameFilter = gCoreContext->GetSetting("AlbumArtFilter", "*.png;*.jpg;*.jpeg;*.gif;*.bmp"); // If this file is an image, insert the details into the music_albumart table if (nameFilter.indexOf(extension.toLower()) > -1) { QString name = filename.section( '/', -1); MSqlQuery query(MSqlQuery::InitCon()); query.prepare("INSERT INTO music_albumart " "SET filename = :FILE, directory_id = :DIRID, " "imagetype = :TYPE, hostname = :HOSTNAME;"); query.bindValue(":FILE", name); query.bindValue(":DIRID", m_directoryid[directory]); query.bindValue(":TYPE", AlbumArtImages::guessImageType(name)); query.bindValue(":HOSTNAME", gCoreContext->GetHostName()); if (!query.exec() || query.numRowsAffected() <= 0) { MythDB::DBError("music insert artwork", query); } ++m_coverartAdded; return; } if (extension.isEmpty() || !MetaIO::ValidFileExtensions.contains(extension.toLower())) { LOG(VB_GENERAL, LOG_WARNING, QString("Ignoring filename with unsupported filename: '%1'").arg(filename)); return; } LOG(VB_FILE, LOG_INFO, QString("Reading metadata from %1").arg(filename)); MusicMetadata *data = MetaIO::readMetadata(filename); if (data) { data->setFileSize((quint64)QFileInfo(filename).size()); data->setHostname(gCoreContext->GetHostName()); QString album_cache_string; // Set values from cache int did = m_directoryid[directory]; if (did > 0) data->setDirectoryId(did); int aid = m_artistid[data->Artist().toLower()]; if (aid > 0) { data->setArtistId(aid); // The album cache depends on the artist id album_cache_string = QString::number(data->getArtistId()) + "#" + data->Album().toLower(); if (m_albumid[album_cache_string] > 0) data->setAlbumId(m_albumid[album_cache_string]); } int gid = m_genreid[data->Genre().toLower()]; if (gid > 0) data->setGenreId(gid); // Commit track info to database data->dumpToDatabase(); // Update the cache m_artistid[data->Artist().toLower()] = data->getArtistId(); m_genreid[data->Genre().toLower()] = data->getGenreId(); album_cache_string = QString::number(data->getArtistId()) + "#" + data->Album().toLower(); m_albumid[album_cache_string] = data->getAlbumId(); // read any embedded images from the tag MetaIO *tagger = MetaIO::createTagger(filename); if (tagger) { if (tagger->supportsEmbeddedImages()) { AlbumArtList artList = tagger->getAlbumArtList(data->Filename()); data->setEmbeddedAlbumArt(artList); data->getAlbumArtImages()->dumpToDatabase(); } delete tagger; } delete data; ++m_tracksAdded; } }