void Ripper::switchTitlesAndArtists() { if (!m_compilationCheck->GetBooleanCheckState()) return; Metadata *data; // Switch title and artist for each track QString tmp; if (m_tracks->size() > 0) { for (int track = 0; track < m_tracks->size(); ++track) { data = m_tracks->at(track)->metadata; if (data) { tmp = data->Artist(); data->setArtist(data->Title()); data->setTitle(tmp); } } updateTrackList(); } }
void ImportMusicDialog::metadataChanged(void) { Metadata *editMeta = m_tracks->at(m_currentTrack)->metadata; m_tracks->at(m_currentTrack)->metadataHasChanged = true; m_tracks->at(m_currentTrack)->isNewTune = Ripper::isNewTune(editMeta->Artist(), editMeta->Album(), editMeta->Title()); fillWidgets(); }
void Ripper::updateTrackList(void) { if (m_tracks->isEmpty()) return; QString tmptitle; if (m_trackList) { m_trackList->Reset(); int i; for (i = 0; i < (int)m_tracks->size(); i++) { if (i >= m_tracks->size()) break; RipTrack *track = m_tracks->at(i); Metadata *metadata = track->metadata; MythUIButtonListItem *item = new MythUIButtonListItem(m_trackList,""); item->setCheckable(true); item->SetData(qVariantFromValue(track)); if (track->isNew) item->DisplayState("new", "yes"); else item->DisplayState("new", "no"); if (track->active) item->setChecked(MythUIButtonListItem::FullChecked); else item->setChecked(MythUIButtonListItem::NotChecked); item->SetText(QString::number(metadata->Track()), "track"); item->SetText(metadata->Title(), "title"); item->SetText(metadata->Artist(), "artist"); int length = track->length / 1000; if (length > 0) { int min, sec; min = length / 60; sec = length % 60; QString s; s.sprintf("%02d:%02d", min, sec); item->SetText(s, "length"); } else item->SetText("", "length"); // if (i == m_currentTrack) // m_trackList->SetItemCurrent(i); } } }
/*! * \copydoc MetaIO::read() */ Metadata* MetaIOFLACVorbis::read(QString filename) { TagLib::FLAC::File *flacfile = OpenFile(filename); if (!flacfile) return NULL; TagLib::Ogg::XiphComment *tag = flacfile->xiphComment(); if (!tag) { delete flacfile; return NULL; } Metadata *metadata = new Metadata(filename); ReadGenericMetadata(tag, metadata); bool compilation = false; if (tag->contains("COMPILATION_ARTIST")) { QString compilation_artist = TStringToQString( tag->fieldListMap()["COMPILATION_ARTIST"].toString()).trimmed(); if (compilation_artist != metadata->Artist()) { metadata->setCompilationArtist(compilation_artist); compilation = true; } } if (!compilation && tag->contains("MUSICBRAINZ_ALBUMARTISTID")) { QString musicbrainzcode = TStringToQString( tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString()).trimmed(); if (musicbrainzcode == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID) compilation = true; } metadata->setCompilation(compilation); if (metadata->Length() <= 0) { TagLib::FileRef *fileref = new TagLib::FileRef(flacfile); metadata->setLength(getTrackLength(fileref)); // FileRef takes ownership of flacfile, and is responsible for it's // deletion. Messy. delete fileref; } else delete flacfile; return metadata; }
void ImportMusicDialog::saveDefaults(void) { Metadata *data = m_tracks->at(m_currentTrack)->metadata; m_defaultCompilation = data->Compilation(); m_defaultCompArtist = data->CompilationArtist(); m_defaultArtist = data->Artist(); m_defaultAlbum = data->Album(); m_defaultGenre = data->Genre(); m_defaultYear = data->Year(); m_defaultRating = data->Rating(); m_haveDefaults = true; }
void ImportMusicDialog::setAlbum(void) { if (!m_haveDefaults) return; Metadata *data = m_tracks->at(m_currentTrack)->metadata; data->setAlbum(m_defaultAlbum); m_tracks->at(m_currentTrack)->isNewTune = Ripper::isNewTune( data->Artist(), data->Album(), data->Title()); fillWidgets(); }
/*! * \copydoc MetaIO::read() */ Metadata* MetaIOOggVorbis::read(const QString &filename) { TagLib::Ogg::Vorbis::File *oggfile = OpenFile(filename); if (!oggfile) return NULL; TagLib::Ogg::XiphComment *tag = oggfile->tag(); if (!tag) { delete oggfile; return NULL; } Metadata *metadata = new Metadata(filename); ReadGenericMetadata(tag, metadata); bool compilation = false; if (tag->contains("COMPILATION_ARTIST")) { QString compilation_artist = TStringToQString( tag->fieldListMap()["COMPILATION_ARTIST"].toString()).trimmed(); if (compilation_artist != metadata->Artist()) { metadata->setCompilationArtist(compilation_artist); compilation = true; } } if (!compilation && tag->contains("MUSICBRAINZ_ALBUMARTISTID")) { QString musicbrainzcode = TStringToQString( tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString()).trimmed(); if (musicbrainzcode == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID) compilation = true; } metadata->setCompilation(compilation); if (metadata->Length() <= 0) metadata->setLength(getTrackLength(oggfile)); else delete oggfile; return metadata; }
void ImportMusicDialog::fillWidgets() { if (m_tracks->size() > 0) { // update current m_currentText->SetText(QString("%1 of %2") .arg(m_currentTrack + 1).arg(m_tracks->size())); Metadata *meta = m_tracks->at(m_currentTrack)->metadata; m_filenameText->SetText(meta->Filename()); m_compilationCheck->SetCheckState(meta->Compilation()); m_compartistText->SetText(meta->CompilationArtist()); m_artistText->SetText(meta->Artist()); m_albumText->SetText(meta->Album()); m_titleText->SetText(meta->Title()); m_genreText->SetText(meta->Genre()); m_yearText->SetText(QString::number(meta->Year())); m_trackText->SetText(QString::number(meta->Track())); if (m_tracks->at(m_currentTrack)->isNewTune) { m_coverartButton->SetVisible(false); m_statusText->SetText(tr("New File")); } else { m_coverartButton->SetVisible(true); m_statusText->SetText(tr("Already in Database")); } } else { // update current m_currentText->SetText(tr("Not found")); m_filenameText->Reset(); m_compilationCheck->SetCheckState(false); m_compartistText->Reset(); m_artistText->Reset(); m_albumText->Reset(); m_titleText->Reset(); m_genreText->Reset(); m_yearText->Reset(); m_trackText->Reset(); m_statusText->Reset(); m_coverartButton->SetVisible(false); } }
void ImportMusicDialog::scanDirectory(QString &directory, vector<TrackInfo*> *tracks) { QDir d(directory); if (!d.exists()) return; const QFileInfoList list = d.entryInfoList(); if (list.isEmpty()) return; QFileInfoList::const_iterator it = list.begin(); const QFileInfo *fi; while (it != list.end()) { fi = &(*it); ++it; if (fi->fileName() == "." || fi->fileName() == "..") continue; QString filename = fi->absoluteFilePath(); if (fi->isDir()) scanDirectory(filename, tracks); else { Decoder *decoder = Decoder::create(filename, NULL, NULL, true); if (decoder) { Metadata *metadata = decoder->getMetadata(); if (metadata) { TrackInfo * track = new TrackInfo; track->metadata = metadata; track->isNewTune = Ripper::isNewTune(metadata->Artist(), metadata->Album(), metadata->Title()); track->metadataHasChanged = false; tracks->push_back(track); m_sourceFiles.append(filename); } delete decoder; } } } }
/*! * \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 Ripper::ScanFinished() { delete m_scanThread; m_scanThread = NULL; m_tracks->clear(); bool isCompilation = false; bool newTune = true; if (m_decoder) { QString label; Metadata *metadata; m_artistName.clear(); m_albumName.clear(); m_genreName.clear(); m_year.clear(); bool yesToAll = false; bool noToAll = false; for (int trackno = 0; trackno < m_decoder->getNumTracks(); trackno++) { RipTrack *ripTrack = new RipTrack; metadata = m_decoder->getMetadata(trackno + 1); if (metadata) { ripTrack->metadata = metadata; ripTrack->length = metadata->Length(); ripTrack->active = true; if (metadata->Compilation()) { isCompilation = true; m_artistName = metadata->CompilationArtist(); } else if (m_artistName.isEmpty()) { m_artistName = metadata->Artist(); } if (m_albumName.isEmpty()) m_albumName = metadata->Album(); if (m_genreName.isEmpty() && !metadata->Genre().isEmpty()) m_genreName = metadata->Genre(); if (m_year.isEmpty() && metadata->Year() > 0) m_year = QString::number(metadata->Year()); QString title = metadata->Title(); newTune = Ripper::isNewTune(m_artistName, m_albumName, title); if (newTune) { m_tracks->push_back(ripTrack); } else { if (yesToAll) { deleteTrack(m_artistName, m_albumName, title); m_tracks->push_back(ripTrack); } else if (noToAll) { delete ripTrack; delete metadata; continue; } else { DialogBox *dlg = new DialogBox( GetMythMainWindow(), tr("Artist: %1\n" "Album: %2\n" "Track: %3\n\n" "This track is already in the database. \n" "Do you want to remove the existing track?") .arg(m_artistName).arg(m_albumName).arg(title)); dlg->AddButton("No"); dlg->AddButton("No To All"); dlg->AddButton("Yes"); dlg->AddButton("Yes To All"); DialogCode res = dlg->exec(); dlg->deleteLater(); dlg = NULL; if (kDialogCodeButton0 == res) { delete ripTrack; delete metadata; } else if (kDialogCodeButton1 == res) { noToAll = true; delete ripTrack; delete metadata; } else if (kDialogCodeButton2 == res) { deleteTrack(m_artistName, m_albumName, title); m_tracks->push_back(ripTrack); } else if (kDialogCodeButton3 == res) { yesToAll = true; deleteTrack(m_artistName, m_albumName, title); m_tracks->push_back(ripTrack); } else // treat cancel as no { delete ripTrack; delete metadata; } } } } else delete ripTrack; } m_artistEdit->SetText(m_artistName); m_albumEdit->SetText(m_albumName); m_genreEdit->SetText(m_genreName); m_yearEdit->SetText(m_year); m_compilationCheck->SetCheckState(isCompilation); if (!isCompilation) m_switchTitleArtist->SetVisible(false); else m_switchTitleArtist->SetVisible(true); } BuildFocusList(); updateTrackList(); CloseBusyPopup(); }
void CDRipperThread::run(void) { if (!m_tracks->size() > 0) return; Metadata *track = m_tracks->at(0)->metadata; QString tots; if (track->Compilation()) { tots = track->CompilationArtist() + " ~ " + track->Album(); } else { tots = track->Artist() + " ~ " + track->Album(); } QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kOverallTextEvent, tots)); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kOverallProgressEvent, 0)); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kTrackProgressEvent, 0)); QString textstatus; QString encodertype = gCoreContext->GetSetting("EncoderType"); bool mp3usevbr = gCoreContext->GetNumSetting("Mp3UseVBR", 0); m_totalSectors = 0; m_totalSectorsDone = 0; for (int trackno = 0; trackno < m_tracks->size(); trackno++) { m_totalSectors += getSectorCount(m_CDdevice, trackno + 1); } QApplication::postEvent(m_parent, new RipStatusEvent(RipStatusEvent::kOverallStartEvent, m_totalSectors)); if (LCD *lcd = LCD::Get()) { QString lcd_tots = QObject::tr("Importing ") + tots; QList<LCDTextItem> textItems; textItems.append(LCDTextItem(1, ALIGN_CENTERED, lcd_tots, "Generic", false)); lcd->switchToGeneric(textItems); } Metadata *titleTrack = NULL; QString outfile; std::auto_ptr<Encoder> encoder; for (int trackno = 0; trackno < m_tracks->size(); trackno++) { if (isCancelled()) break; QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kStatusTextEvent, QString("Track %1 of %2") .arg(trackno + 1).arg(m_tracks->size()))); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kTrackProgressEvent, 0)); track = m_tracks->at(trackno)->metadata; if (track) { textstatus = track->Title(); QApplication::postEvent( m_parent, new RipStatusEvent( RipStatusEvent::kTrackTextEvent, textstatus)); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kTrackProgressEvent, 0)); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kTrackPercentEvent, 0)); // do we need to start a new file? if (m_tracks->at(trackno)->active) { titleTrack = track; titleTrack->setLength(m_tracks->at(trackno)->length); outfile = Ripper::filenameFromMetadata(track); if (m_quality < 3) { if (encodertype == "mp3") { outfile += ".mp3"; encoder.reset(new LameEncoder(outfile, m_quality, titleTrack, mp3usevbr)); } else // ogg { outfile += ".ogg"; encoder.reset(new VorbisEncoder(outfile, m_quality, titleTrack)); } } else { outfile += ".flac"; encoder.reset(new FlacEncoder(outfile, m_quality, titleTrack)); } if (!encoder->isValid()) { QApplication::postEvent( m_parent, new RipStatusEvent( RipStatusEvent::kEncoderErrorEvent, "Encoder failed to open file for writing")); VERBOSE(VB_IMPORTANT, "MythMusic: Encoder failed" " to open file for writing"); return; } } if (!encoder.get()) { // This should never happen. QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kEncoderErrorEvent, "Failed to create encoder")); VERBOSE(VB_IMPORTANT, QString("MythMusic: Error: No encoder, failing")); return; } ripTrack(m_CDdevice, encoder.get(), trackno + 1); if (isCancelled()) return; // save the metadata to the DB if (m_tracks->at(trackno)->active) { titleTrack->setFilename(outfile); titleTrack->dumpToDatabase(); } } } QString PostRipCDScript = gCoreContext->GetSetting("PostCDRipScript"); if (!PostRipCDScript.isEmpty()) myth_system(PostRipCDScript); QApplication::postEvent( m_parent, new RipStatusEvent(RipStatusEvent::kFinishedEvent, "")); }
int Playlist::writeTree(GenericTree *tree_to_write_to, int a_counter) { // compute max/min playcount,lastplay for this playlist int playcountMin = 0; int playcountMax = 0; double lastplayMin = 0.0; double lastplayMax = 0.0; typedef map<QString, uint32_t> AlbumMap; AlbumMap album_map; AlbumMap::iterator Ialbum; QString album; typedef map<QString, uint32_t> ArtistMap; ArtistMap artist_map; ArtistMap::iterator Iartist; QString artist; uint idx = 0; SongList::const_iterator it = songs.begin(); for (; it != songs.end(); ++it, ++idx) { if (!(*it)->getCDFlag()) { if ((*it)->getValue() == 0) { VERBOSE(VB_IMPORTANT, LOC_ERR + kID0err); } if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { if (tmpdata->isVisible()) { if (0 == idx) { // first song playcountMin = playcountMax = tmpdata->PlayCount(); lastplayMin = lastplayMax = tmpdata->LastPlay().toTime_t(); } else { if (tmpdata->PlayCount() < playcountMin) playcountMin = tmpdata->PlayCount(); else if (tmpdata->PlayCount() > playcountMax) playcountMax = tmpdata->PlayCount(); if (tmpdata->LastPlay().toTime_t() < lastplayMin) lastplayMin = tmpdata->LastPlay().toTime_t(); else if (tmpdata->LastPlay().toTime_t() > lastplayMax) lastplayMax = tmpdata->LastPlay().toTime_t(); } } // pre-fill the album-map with the album name. // This allows us to do album mode in album order album = tmpdata->Album(); // pre-fill the artist map with the artist name and song title artist = tmpdata->Artist() + "~" + tmpdata->Title(); } if ((Ialbum = album_map.find(album)) == album_map.end()) album_map.insert(AlbumMap::value_type(album,0)); if ((Iartist = artist_map.find(artist)) == artist_map.end()) artist_map.insert(ArtistMap::value_type(artist,0)); } } } // populate the sort id into the album map uint32_t album_count = 1; for (Ialbum = album_map.begin(); Ialbum != album_map.end(); Ialbum++) { Ialbum->second = album_count; album_count++; } // populate the sort id into the artist map uint32_t count = 1; for (Iartist = artist_map.begin(); Iartist != artist_map.end(); Iartist++) { Iartist->second = count; count++; } int RatingWeight = 2; int PlayCountWeight = 2; int LastPlayWeight = 2; int RandomWeight = 2; parent->FillIntelliWeights(RatingWeight, PlayCountWeight, LastPlayWeight, RandomWeight); for (it = songs.begin(); it != songs.end(); ++it) { if (!(*it)->getCDFlag()) { if ((*it)->getValue() == 0) { VERBOSE(VB_IMPORTANT, LOC_ERR + kID0err); } if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata && tmpdata->isVisible()) { QString a_string = QString("%1 ~ %2") .arg(tmpdata->FormatArtist()) .arg(tmpdata->FormatTitle()); GenericTree *added_node = tree_to_write_to->addNode( a_string, (*it)->getValue(), true); ++a_counter; added_node->setAttribute(0, 1); added_node->setAttribute(1, a_counter); // regular order added_node->setAttribute(2, rand()); // random order // // Compute "intelligent" weighting // int rating = tmpdata->Rating(); int playcount = tmpdata->PlayCount(); double lastplaydbl = tmpdata->LastPlay().toTime_t(); double ratingValue = (double)(rating) / 10; double playcountValue, lastplayValue; if (playcountMax == playcountMin) playcountValue = 0; else playcountValue = ((playcountMin - (double)playcount) / (playcountMax - playcountMin) + 1); if (lastplayMax == lastplayMin) lastplayValue = 0; else lastplayValue = ((lastplayMin - lastplaydbl) / (lastplayMax - lastplayMin) + 1); double rating_value = (RatingWeight * ratingValue + PlayCountWeight * playcountValue + LastPlayWeight * lastplayValue + RandomWeight * (double)rand() / (RAND_MAX + 1.0)); uint32_t integer_rating = (int) (4000001 - rating_value * 10000); // "intelligent" order added_node->setAttribute(3, integer_rating); // "intellegent/album" order uint32_t album_order; album = tmpdata->Album(); if ((Ialbum = album_map.find(album)) == album_map.end()) { // we didn't find this album in the map, // yet we pre-loaded them all. we are broken, // but we just set the track order to 1, since there // is no real point in reporting an error album_order = 1; } else { album_order = Ialbum->second * 100; } album_order += tmpdata->Track(); added_node->setAttribute(4, album_order); // "artist" order, sorts by artist name then track title // uses the pre-prepared artist map to do this uint32_t integer_order; artist = tmpdata->Artist() + "~" + tmpdata->Title(); if ((Iartist = artist_map.find(artist)) == artist_map.end()) { // we didn't find this track in the map, // yet we pre-loaded them all. we are broken, // but we just set the track order to 1, since there // is no real point in reporting an error integer_order = 1; } else { integer_order = Iartist->second; } added_node->setAttribute(5, integer_order); } } if ((*it)->getValue() < 0) { // it's a playlist, recurse (mildly) Playlist *level_down = parent->getPlaylist(((*it)->getValue()) * -1); if (level_down) { a_counter = level_down->writeTree(tree_to_write_to, a_counter); } } } else { Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { QString a_string = QString("(CD) %1 ~ %2") .arg(tmpdata->FormatArtist()).arg(tmpdata->FormatTitle()); if (tmpdata->FormatArtist().length() < 1 || tmpdata->FormatTitle().length() < 1) { a_string = QString("(CD) Track %1").arg(tmpdata->Track()); } GenericTree *added_node = tree_to_write_to->addNode(a_string, (*it)->getValue(), true); ++a_counter; added_node->setAttribute(0, 1); added_node->setAttribute(1, a_counter); // regular order added_node->setAttribute(2, rand()); // random order added_node->setAttribute(3, rand()); // "intelligent" order } } } return a_counter; }
bool Ripper::deleteExistingTrack(RipTrack *track) { if (!track) return false; Metadata *metadata = track->metadata; if (!metadata) return false; QString artist = metadata->Artist(); QString album = metadata->Album(); QString title = metadata->Title(); MSqlQuery query(MSqlQuery::InitCon()); QString queryString("SELECT song_id, " "CONCAT_WS('/', music_directories.path, music_songs.filename) AS filename " "FROM music_songs " "LEFT JOIN music_artists" " ON music_songs.artist_id=music_artists.artist_id " "LEFT JOIN music_albums" " ON music_songs.album_id=music_albums.album_id " "LEFT JOIN music_directories " " ON music_songs.directory_id=music_directories.directory_id " "WHERE artist_name REGEXP \'"); QString token = artist; token.replace(QRegExp("(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"), QString(".")); queryString += token + "\' AND " + "album_name REGEXP \'"; token = album; token.replace(QRegExp("(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"), QString(".")); queryString += token + "\' AND " + "name REGEXP \'"; token = title; token.replace(QRegExp("(/|\\\\|:|\'|\\,|\\!|\\(|\\)|\"|\\?|\\|)"), QString(".")); queryString += token + "\' ORDER BY artist_name, album_name," " name, song_id, filename LIMIT 1"; query.prepare(queryString); if (!query.exec() || !query.isActive()) { MythDB::DBError("Search music database", query); return false; } if (query.next()) { int trackID = query.value(0).toInt(); QString filename = gMusicData->musicDir + query.value(1).toString(); // delete file if (!QFile::remove(filename)) { LOG(VB_GENERAL, LOG_NOTICE, QString("Ripper::deleteExistingTrack() " "Could not delete %1") .arg(filename)); return false; } // remove database entry MSqlQuery deleteQuery(MSqlQuery::InitCon()); deleteQuery.prepare("DELETE FROM music_songs" " WHERE song_id = :SONG_ID"); deleteQuery.bindValue(":SONG_ID", trackID); if (!deleteQuery.exec()) { MythDB::DBError("Delete Track", deleteQuery); return false; } return true; } return false; }
void Ripper::ScanFinished() { delete m_scanThread; m_scanThread = NULL; m_tracks->clear(); bool isCompilation = false; if (m_decoder) { QString label; Metadata *metadata; m_artistName.clear(); m_albumName.clear(); m_genreName.clear(); m_year.clear(); for (int trackno = 0; trackno < m_decoder->getNumTracks(); trackno++) { RipTrack *ripTrack = new RipTrack; metadata = m_decoder->getMetadata(trackno + 1); if (metadata) { ripTrack->metadata = metadata; ripTrack->length = metadata->Length(); if (metadata->Compilation()) { isCompilation = true; m_artistName = metadata->CompilationArtist(); } else if (m_artistName.isEmpty()) { m_artistName = metadata->Artist(); } if (m_albumName.isEmpty()) m_albumName = metadata->Album(); if (m_genreName.isEmpty() && !metadata->Genre().isEmpty()) m_genreName = metadata->Genre(); if (m_year.isEmpty() && metadata->Year() > 0) m_year = QString::number(metadata->Year()); QString title = metadata->Title(); ripTrack->isNew = isNewTune(m_artistName, m_albumName, title); ripTrack->active = ripTrack->isNew; m_tracks->push_back(ripTrack); } else delete ripTrack; } m_artistEdit->SetText(m_artistName); m_albumEdit->SetText(m_albumName); m_genreEdit->SetText(m_genreName); m_yearEdit->SetText(m_year); m_compilationCheck->SetCheckState(isCompilation); if (!isCompilation) m_switchTitleArtist->SetVisible(false); else m_switchTitleArtist->SetVisible(true); } BuildFocusList(); updateTrackList(); CloseBusyPopup(); }
int Playlist::CreateCDMP3(void) { // Check & get global settings if (!gCoreContext->GetNumSetting("CDWriterEnabled")) { VERBOSE(VB_GENERAL, "CD Writer is not enabled."); return 1; } QString scsidev = MediaMonitor::defaultCDWriter(); if (scsidev.isEmpty()) { VERBOSE(VB_GENERAL, "No CD Writer device defined."); return 1; } int disksize = gCoreContext->GetNumSetting("CDDiskSize", 2); QString writespeed = gCoreContext->GetSetting("CDWriteSpeed", "2"); bool MP3_dir_flag = gCoreContext->GetNumSetting("CDCreateDir", 1); double size_in_MB = 0.0; QStringList reclist; SongList::const_iterator it = songs.begin(); for (; it != songs.end(); ++it) { if ((*it)->getCDFlag()) continue; if ((*it)->getValue() == 0) { VERBOSE(VB_IMPORTANT, kID0err); } else if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { // check filename.. QFileInfo testit(tmpdata->Filename()); if (!testit.exists()) continue; size_in_MB += testit.size() / 1000000.0; QString outline; if (MP3_dir_flag) { if (tmpdata->Artist().length() > 0) outline += tmpdata->Artist() + "/"; if (tmpdata->Album().length() > 0) outline += tmpdata->Album() + "/"; } outline += "="; outline += tmpdata->Filename(); reclist += outline; } } else if ((*it)->getValue() < 0) { // FIXME: handle playlists } } int max_size; if (disksize == 0) max_size = 650; else max_size = 700; if (size_in_MB >= max_size) { VERBOSE(VB_GENERAL, "MP3 CD creation aborted -- cd size too big."); return 1; } // probably should tie stdout of mkisofs to stdin of cdrecord sometime QString tmptemplate("/tmp/mythmusicXXXXXX"); QString tmprecordlist = createTempFile(tmptemplate); if (tmprecordlist == tmptemplate) { VERBOSE(VB_IMPORTANT, "Unable to open temporary file"); return 1; } QString tmprecordisofs = createTempFile(tmptemplate); if (tmprecordisofs == tmptemplate) { VERBOSE(VB_IMPORTANT, "Unable to open temporary file"); return 1; } QFile reclistfile(tmprecordlist); if (!reclistfile.open(QIODevice::WriteOnly)) { VERBOSE(VB_IMPORTANT, "Unable to open temporary file"); return 1; } QTextStream recstream(&reclistfile); QStringList::Iterator iter; for (iter = reclist.begin(); iter != reclist.end(); ++iter) { recstream << *iter << "\n"; } reclistfile.close(); MythProgressDialog *progress; progress = new MythProgressDialog(QObject::tr("Creating CD File System"), 100); progress->setProgress(1); QStringList args("mkisofs"); args += "-graft-points"; args += "-path-list"; args += tmprecordlist; args += "-o"; args += tmprecordisofs; args += "-J"; args += "-R"; VERBOSE(VB_GENERAL, "Running: " + args.join(" ")); bool retval = 0; Q3Process isofs(args); if (isofs.start()) { while (1) { while (isofs.canReadLineStderr()) { QString buf = isofs.readLineStderr(); if (buf[6] == '%') { buf = buf.mid(0, 3); progress->setProgress(buf.trimmed().toInt()); } } if (isofs.isRunning()) { qApp->processEvents(); usleep(100000); } else { if (!isofs.normalExit()) { VERBOSE(VB_IMPORTANT, "Unable to run 'mkisofs'"); retval = 1; } break; } } } else { VERBOSE(VB_IMPORTANT, "Unable to run 'mkisofs'"); retval = 1; } progress->Close(); progress->deleteLater(); progress = new MythProgressDialog(QObject::tr("Burning CD"), 100); progress->setProgress(2); args = QStringList("cdrecord"); args += "-v"; //args += "-dummy"; args += "dev="; args += scsidev; if (writespeed.toInt() > 0) { args += "-speed="; args += writespeed; } args += "-data"; args += tmprecordisofs; VERBOSE(VB_GENERAL, "Running: " + args.join(" ")); Q3Process burn(args); if (burn.start()) { while (1) { while (burn.canReadLineStderr()) { QString err = burn.readLineStderr(); if (err == "cdrecord: Drive needs to reload the media" || err == "cdrecord: Input/output error." || err == "cdrecord: No disk / Wrong disk!") { VERBOSE(VB_IMPORTANT, err); burn.kill(); retval = 1; } } while (burn.canReadLineStdout()) { QString line = burn.readLineStdout(); if (line.mid(15, 2) == "of") { int mbdone = line.mid(10, 5).trimmed().toInt(); int mbtotal = line.mid(17, 5).trimmed().toInt(); if (mbtotal > 0) { progress->setProgress((mbdone * 100) / mbtotal); } } } if (burn.isRunning()) { qApp->processEvents(); usleep(10000); } else { if (!burn.normalExit()) { VERBOSE(VB_IMPORTANT, "Unable to run 'cdrecord'"); retval = 1; } break; } } } else { VERBOSE(VB_IMPORTANT, "Unable to run 'cdrecord'"); retval = 1; } progress->Close(); progress->deleteLater(); QFile::remove(tmprecordlist); QFile::remove(tmprecordisofs); return retval; }
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")); }
void DatabaseBox::entered(UIListTreeType *treetype, UIListGenericTree *item) { if (!item || !treetype) return; // Determin if this is a CD entry bool cd = false; if (dynamic_cast<CDCheckItem*>(item)) cd = true; TreeCheckItem *item_ptr = dynamic_cast<TreeCheckItem*>(item); if (item_ptr && item->childCount() == 0 && item_ptr->getLevel() == "title") { int id = item_ptr->getID(); Metadata *mdata; if (!cd) { mdata = gMusicData->all_music->getMetadata(id); if (!mdata) return; } else { // Need to allocate storage for CD Metadata mdata = new Metadata; if (!gMusicData->all_music->getCDMetadata(id, mdata)) { delete mdata; return; } } unsigned int line = 0; QString tmpstr; if (mdata->Compilation()) { tmpstr = tr("Compilation Artist:\t") + mdata->CompilationArtist(); if (m_lines.at(line)) m_lines.at(line++)->SetText(tmpstr); } tmpstr = tr("Artist:\t") + mdata->Artist(); if (m_lines.at(line)) m_lines.at(line++)->SetText(tmpstr); tmpstr = tr("Album:\t") + mdata->Album(); if (m_lines.at(line)) m_lines.at(line++)->SetText(tmpstr); tmpstr = tr("Title:\t") + mdata->Title(); if (m_lines.at(line)) m_lines.at(line++)->SetText(tmpstr); if (m_lines.at(line)) { int maxTime = mdata->Length() / 1000; int maxh = maxTime / 3600; int maxm = (maxTime / 60) % 60; int maxs = maxTime % 60; QString timeStr; if (maxh > 0) timeStr.sprintf("%02d:%02d:%02d", maxh, maxm, maxs); else timeStr.sprintf("%02d:%02d", maxm, maxs); tmpstr = tr("Length:\t") + timeStr; m_lines.at(line++)->SetText(tmpstr); } tmpstr = tr("Genre: ") + mdata->Genre(); if (m_lines.at(line)) { m_lines.at(line)->SetText(tmpstr); } else { QString prevvalue = m_lines.at(line-1)->GetText(); tmpstr = prevvalue + " " + tmpstr; m_lines.at(line-1)->SetText(tmpstr); } // Pre increment as not incremented from previous use. while (++line < (unsigned) m_lines.size()) m_lines.at(line)->SetText(""); // Don't forget to delete the mdata storage if we allocated it. if (cd) delete mdata; return; } QStringList pathto = treetype->getRouteToCurrent(); int linelen = 0; int dispat = 0; QString data; for (QStringList::Iterator it = pathto.begin(); it != pathto.end(); ++it) { if (it == pathto.begin()) continue; if (!data.isEmpty()) data += " / "; data += *it; linelen++; if (linelen == 2) { if (m_lines.at(dispat)) { m_lines.at(dispat)->SetText(data); } data.clear(); linelen = 0; dispat++; } } if (linelen != 0) { if (m_lines.at(dispat)) { m_lines.at(dispat)->SetText(data); } dispat++; } for (unsigned int i = dispat; i < (unsigned) m_lines.size(); i++) m_lines.at(i)->SetText(""); }
int Playlist::CreateCDMP3(void) { // Check & get global settings if (!gCoreContext->GetNumSetting("CDWriterEnabled")) { LOG(VB_GENERAL, LOG_ERR, "CD Writer is not enabled."); return 1; } QString scsidev = MediaMonitor::defaultCDWriter(); if (scsidev.isEmpty()) { LOG(VB_GENERAL, LOG_ERR, "No CD Writer device defined."); return 1; } int disksize = gCoreContext->GetNumSetting("CDDiskSize", 2); QString writespeed = gCoreContext->GetSetting("CDWriteSpeed", "2"); bool MP3_dir_flag = gCoreContext->GetNumSetting("CDCreateDir", 1); double size_in_MB = 0.0; QStringList reclist; SongList::const_iterator it = songs.begin(); for (; it != songs.end(); ++it) { if ((*it)->getCDFlag()) continue; if ((*it)->getValue() == 0) { LOG(VB_GENERAL, LOG_ERR, kID0err); } else if ((*it)->getValue() > 0) { // Normal track Metadata *tmpdata = all_available_music->getMetadata((*it)->getValue()); if (tmpdata) { // check filename.. QFileInfo testit(tmpdata->Filename()); if (!testit.exists()) continue; size_in_MB += testit.size() / 1000000.0; QString outline; if (MP3_dir_flag) { if (tmpdata->Artist().length() > 0) outline += tmpdata->Artist() + "/"; if (tmpdata->Album().length() > 0) outline += tmpdata->Album() + "/"; } outline += "="; outline += tmpdata->Filename(); reclist += outline; } } else if ((*it)->getValue() < 0) { // FIXME: handle playlists } } int max_size; if (disksize == 0) max_size = 650; else max_size = 700; if (size_in_MB >= max_size) { LOG(VB_GENERAL, LOG_ERR, "MP3 CD creation aborted -- cd size too big."); return 1; } // probably should tie stdout of mkisofs to stdin of cdrecord sometime QString tmptemplate("/tmp/mythmusicXXXXXX"); QString tmprecordlist = createTempFile(tmptemplate); if (tmprecordlist == tmptemplate) { LOG(VB_GENERAL, LOG_ERR, "Unable to open temporary file"); return 1; } QString tmprecordisofs = createTempFile(tmptemplate); if (tmprecordisofs == tmptemplate) { LOG(VB_GENERAL, LOG_ERR, "Unable to open temporary file"); return 1; } QFile reclistfile(tmprecordlist); if (!reclistfile.open(QIODevice::WriteOnly)) { LOG(VB_GENERAL, LOG_ERR, "Unable to open temporary file"); return 1; } QTextStream recstream(&reclistfile); QStringList::Iterator iter; for (iter = reclist.begin(); iter != reclist.end(); ++iter) { recstream << *iter << "\n"; } reclistfile.close(); progress = new MythProgressDialog(QObject::tr("Creating CD File System"), 100); progress->setProgress(1); QStringList args; QString command; command = "mkisofs"; args << "-graft-points"; args << "-path-list"; args << tmprecordlist; args << "-o"; args << tmprecordisofs; args << "-J"; args << "-R"; uint flags = kMSRunShell | kMSStdErr | kMSBuffered | kMSDontDisableDrawing | kMSDontBlockInputDevs | kMSRunBackground; proc = new MythSystem(command, args, flags); connect(proc, SIGNAL(readDataReady(int)), this, SLOT(mkisofsData(int)), Qt::DirectConnection); connect(proc, SIGNAL(finished()), this, SLOT(processExit()), Qt::DirectConnection); connect(proc, SIGNAL(error(uint)), this, SLOT(processExit(uint)), Qt::DirectConnection); procExitVal = GENERIC_EXIT_RUNNING; proc->Run(); while( procExitVal == GENERIC_EXIT_RUNNING ) usleep( 100000 ); uint retval = procExitVal; progress->Close(); progress->deleteLater(); proc->disconnect(); delete proc; if (retval) { LOG(VB_GENERAL, LOG_ERR, QString("Unable to run mkisofs: returns %1") .arg(retval)); } else { progress = new MythProgressDialog(QObject::tr("Burning CD"), 100); progress->setProgress(2); command = "cdrecord"; args = QStringList(); args << "-v"; //args << "-dummy"; args << QString("dev=%1").arg(scsidev); if (writespeed.toInt() > 0) { args << "-speed="; args << writespeed; } args << "-data"; args << tmprecordisofs; flags = kMSRunShell | kMSStdErr | kMSStdOut | kMSBuffered | kMSDontDisableDrawing | kMSDontBlockInputDevs | kMSRunBackground; proc = new MythSystem(command, args, flags); connect(proc, SIGNAL(readDataReady(int)), this, SLOT(cdrecordData(int)), Qt::DirectConnection); connect(proc, SIGNAL(finished()), this, SLOT(processExit()), Qt::DirectConnection); connect(proc, SIGNAL(error(uint)), this, SLOT(processExit(uint)), Qt::DirectConnection); procExitVal = GENERIC_EXIT_RUNNING; proc->Run(); while( procExitVal == GENERIC_EXIT_RUNNING ) usleep( 100000 ); retval = procExitVal; progress->Close(); progress->deleteLater(); proc->disconnect(); delete proc; if (retval) { LOG(VB_GENERAL, LOG_ERR, QString("Unable to run cdrecord: returns %1") .arg(retval)); } } QFile::remove(tmprecordlist); QFile::remove(tmprecordisofs); return retval; }