void PodcastService::CopyToDevice(const QModelIndexList& episode_indexes, const QModelIndexList& podcast_indexes) { PodcastEpisode episode_tmp; SongList songs; PodcastEpisodeList episodes; Podcast podcast; for (const QModelIndex& index : episode_indexes) { episode_tmp = index.data(Role_Episode).value<PodcastEpisode>(); if (episode_tmp.downloaded()) episodes << episode_tmp; } for (const QModelIndex& podcast : podcast_indexes) { for (int i = 0; i < podcast.model()->rowCount(podcast); ++i) { const QModelIndex& index = podcast.child(i, 0); episode_tmp = index.data(Role_Episode).value<PodcastEpisode>(); if (episode_tmp.downloaded() && !episode_tmp.listened()) episodes << episode_tmp; } } for (const PodcastEpisode& episode : episodes) { podcast = backend_->GetSubscriptionById(episode.podcast_database_id()); songs.append(episode.ToSong(podcast)); } organise_dialog_->SetDestinationModel( app_->device_manager()->connected_devices_model(), true); organise_dialog_->SetCopy(true); if (organise_dialog_->SetSongs(songs)) organise_dialog_->show(); }
void SpotifyResolver::SearchFinished(const spotify_pb::SearchResponse& response) { QString query_string = QString::fromUtf8(response.request().query().c_str()); qLog(Debug) << query_string; QMap<QString, int>::iterator it = queries_.find(query_string); if (it == queries_.end()) { return; } int id = it.value(); queries_.erase(it); SongList songs; for (int i = 0; i < response.result_size(); ++i) { const spotify_pb::Track& track = response.result(i); Song song; SpotifyService::SongFromProtobuf(track, &song); songs << song; } qLog(Debug) << "Resolved from spotify:" << songs.length(); if (!songs.isEmpty()) { qLog(Debug) << songs[0].title() << songs[0].artist(); } emit ResolveFinished(id, songs); }
void SongLoaderInserter::AsyncLoad() { // First, quick load raw songs. int async_progress = 0; int async_load_id = task_manager_->StartTask(tr("Loading tracks")); task_manager_->SetTaskProgress(async_load_id, async_progress, pending_.count()); for (SongLoader* loader : pending_) { loader->LoadFilenamesBlocking(); task_manager_->SetTaskProgress(async_load_id, ++async_progress); songs_ << loader->songs(); } task_manager_->SetTaskFinished(async_load_id); emit PreloadFinished(); // Songs are inserted in playlist, now load them completely. async_progress = 0; async_load_id = task_manager_->StartTask(tr("Loading tracks info")); task_manager_->SetTaskProgress(async_load_id, async_progress, songs_.count()); SongList songs; for (SongLoader* loader : pending_) { loader->LoadMetadataBlocking(); songs << loader->songs(); task_manager_->SetTaskProgress(async_load_id, songs.count()); } task_manager_->SetTaskFinished(async_load_id); // Replace the partially-loaded items by the new ones, fully loaded. emit EffectiveLoadFinished(songs); deleteLater(); }
void PlaylistTest::testStatic2() { DynamicPlaylist::PlaylistParams p; p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "tallest man on earth" ) ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "bon iver" ) ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "mumford and sons" ) ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Artist, QLatin1String( "Florence + The Machine" ) ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::ArtistMaxFamiliarity, 0.4 ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::MinDanceability, 0.7 ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistType ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::SongInformation, QVariant::fromValue( Echonest::SongInformation( Echonest::SongInformation::Hotttnesss | Echonest::SongInformation::ArtistHotttnesss | Echonest::SongInformation::ArtistFamiliarity ) ) ) ); p.append( DynamicPlaylist::PlaylistParamData( DynamicPlaylist::Results, 4 ) ); QNetworkReply* reply = DynamicPlaylist::staticPlaylist( p ); qDebug() << reply->url().toEncoded(); QCOMPARE( QLatin1String( reply->url().toEncoded() ), QLatin1String( "http://developer.echonest.com/api/v4/playlist/static?api_key=JGJCRKWLXLBZIFAZB&format=xml&artist=tallest+man+on+earth&artist=bon+iver&artist=mumford+and+sons&artist=Florence+%2B+The+Machine&artist_max_familiarity=0.4&min_danceability=0.7&type=artist&bucket=song_hotttnesss&bucket=artist_hotttnesss&bucket=artist_familiarity&results=4" ) ); QEventLoop loop; loop.connect( reply, SIGNAL(finished()), SLOT(quit()) ); loop.exec(); SongList songs = DynamicPlaylist::parseStaticPlaylist( reply ); // qDebug() << "Got songs;" << songs; QVERIFY( songs.size() > 1 ); Q_FOREACH( const Song& song, songs ) { QVERIFY( !song.id().isEmpty() ); }
void SongList::AddDirectory(Directory Dir, bool VSRGActive, bool DotcurActive) { SongList* NewList = new SongList(this); ListEntry NewEntry; NewEntry.EntryName = Dir.path().substr(Dir.path().find_last_of('/')+1); NewEntry.Kind = ListEntry::Directory; NewEntry.Data = NewList; std::vector<VSRG::Song*> Songs7K; std::vector<dotcur::Song*> SongsDC; std::vector<String> Listing; Dir.ListDirectory(Listing, Directory::FS_DIR); for (std::vector<String>::iterator i = Listing.begin(); i != Listing.end(); i++) { if (VSRGActive) LoadSong7KFromDir(Dir / *i, Songs7K); if (DotcurActive) LoadSongDCFromDir(Dir / *i, SongsDC); if (!SongsDC.size() && !Songs7K.size()) NewList->AddDirectory(Dir / *i, VSRGActive, DotcurActive); if (Songs7K.size()) { for (std::vector<VSRG::Song*>::iterator j = Songs7K.begin(); j != Songs7K.end(); j++) { NewList->AddSong(*j); } Songs7K.clear(); } if (SongsDC.size()) { for (std::vector<dotcur::Song*>::iterator j = SongsDC.begin(); j != SongsDC.end(); j++) { NewList->AddSong(*j); } SongsDC.clear(); } } if (NewList->GetNumEntries()) mChildren.push_back(NewEntry); else delete NewList; }
SongMimeData* AlbumCoverManager::GetMimeDataForAlbums( const QModelIndexList& indexes) const { SongList songs = GetSongsInAlbums(indexes); if (songs.isEmpty()) return nullptr; SongMimeData* data = new SongMimeData; data->backend = library_backend_; data->songs = songs; return data; }
size_t LoadSongList( SongList &songs ) { size_t count = 0; FILE *fp = fopen( "musicdb.txt", "rt" ); if (!fp) return 0; string artist; string fullpath; string title; char line[6144], *ch; while (!feof(fp)) { fgets( line, 6144, fp ); cleanString( line ); ch = strtok( line, "\t" ); if (ch) artist = ch; else continue; ch = strtok( NULL, "\t" ); if (ch) title = ch; else continue; ch = strtok( NULL, "\t" ); if (ch) fullpath = ch; else continue; printf ("Artist: %s\nTitle: %s\nFullPath: %s\n", artist.c_str(), title.c_str(), fullpath.c_str() + 60 ); count++; SongList::iterator sli; sli = songs.find( artist ); if (sli == songs.end()) { songs[artist] = std::vector<Song>(); sli = songs.find( artist ); assert( sli != songs.end() ); } Song s; s.filename = fullpath; s.title = title; (*sli).second.push_back( s ); } fclose(fp); return count; }
void SongSender::SendAlbum(const Song& song) { // No streams! if (song.url().scheme() != "file") return; SongList album = app_->library_backend()->GetSongsByAlbum(song.album()); for (Song s : album) { DownloadItem item(s, album.indexOf(s) + 1, album.size()); download_queue_.append(item); } }
TEST_F(AsxIniParserTest, ParsesBasicTrackList) { QFile file(":/testdata/test.asxini"); file.open(QIODevice::ReadOnly); SongList songs = parser_.Load(&file, "", QDir()); ASSERT_EQ(2, songs.length()); EXPECT_EQ(QUrl("http://195.245.168.21/antena3?MSWMExt=.asf"), songs[0].url()); EXPECT_EQ(QUrl("http://195.245.168.21:80/antena3?MSWMExt=.asf"), songs[1].url()); EXPECT_TRUE(songs[0].is_valid()); EXPECT_TRUE(songs[1].is_valid()); }
SongList Library::FilterCurrentWMASong(SongList songs, Song* queued) { for (SongList::iterator it = songs.begin(); it != songs.end();) { if (it->url() == current_wma_song_url_) { *queued = *it; it = songs.erase(it); } else { ++it; } } return songs; }
TEST_F(ASXParserTest, ParsesSomaFM) { QFile somafm(":/testdata/secretagent.asx"); somafm.open(QIODevice::ReadOnly); ASXParser parser(NULL); SongList songs = parser.Load(&somafm); ASSERT_EQ(4, songs.count()); EXPECT_EQ("SomaFM: Secret Agent", songs[0].title()); EXPECT_EQ("Keep us on the air! Click Support SomaFM above!", songs[0].artist()); EXPECT_EQ(QUrl("http://streamer-ntc-aa03.somafm.com:80/stream/1021"), songs[0].url()); }
void PodcastService::CopyToDevice(const PodcastEpisodeList& episodes_list) { SongList songs; Podcast podcast; for (const PodcastEpisode& episode : episodes_list) { podcast = backend_->GetSubscriptionById(episode.podcast_database_id()); songs.append(episode.ToSong(podcast)); } organise_dialog_->SetDestinationModel( app_->device_manager()->connected_devices_model(), true); organise_dialog_->SetCopy(true); if (organise_dialog_->SetSongs(songs)) organise_dialog_->show(); }
void SongList::AddVirtualDirectory(String NewEntryName, Game::Song* List, int Count) { SongList* NewList = new SongList(this); ListEntry NewEntry; NewEntry.EntryName = NewEntryName; NewEntry.Kind = ListEntry::Directory; NewEntry.Data = NewList; for (int i = 0; i < Count; i++) NewList->AddSong(&List[Count]); mChildren.push_back(NewEntry); }
void JamendoService::ParseDirectory(QIODevice* device) const { int total_count = 0; // Bit of a hack: don't update the model while we're parsing the xml disconnect(library_backend_, SIGNAL(SongsDiscovered(SongList)), library_model_, SLOT(SongsDiscovered(SongList))); disconnect(library_backend_, SIGNAL(TotalSongCountUpdated(int)), this, SLOT(UpdateTotalSongCount(int))); // Delete the database and recreate it. This is faster than dropping tables // or removing rows. library_backend_->db()->RecreateAttachedDb("jamendo"); TrackIdList track_ids; SongList songs; QXmlStreamReader reader(device); while (!reader.atEnd()) { reader.readNext(); if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == "artist") { songs << ReadArtist(&reader, &track_ids); } if (songs.count() >= kBatchSize) { // Add the songs to the database in batches library_backend_->AddOrUpdateSongs(songs); InsertTrackIds(track_ids); total_count += songs.count(); songs.clear(); track_ids.clear(); // Update progress info app_->task_manager()->SetTaskProgress(load_database_task_id_, total_count, kApproxDatabaseSize); } } library_backend_->AddOrUpdateSongs(songs); InsertTrackIds(track_ids); connect(library_backend_, SIGNAL(SongsDiscovered(SongList)), library_model_, SLOT(SongsDiscovered(SongList))); connect(library_backend_, SIGNAL(TotalSongCountUpdated(int)), SLOT(UpdateTotalSongCount(int))); library_backend_->UpdateTotalSongCount(); }
void WplParser::Save(const SongList& songs, QIODevice* device, const QDir& dir, Playlist::Path path_type) const { QXmlStreamWriter writer(device); writer.setAutoFormatting(true); writer.setAutoFormattingIndent(2); writer.writeProcessingInstruction("wpl", "version=\"1.0\""); StreamElement smil("smil", &writer); { StreamElement head("head", &writer); WriteMeta("Generator", "Clementine -- " CLEMENTINE_VERSION_DISPLAY, &writer); WriteMeta("ItemCount", QString::number(songs.count()), &writer); } { StreamElement body("body", &writer); { StreamElement seq("seq", &writer); for (const Song& song : songs) { writer.writeStartElement("media"); writer.writeAttribute("src", URLOrFilename(song.url(), dir, path_type)); writer.writeEndElement(); } } } }
void Library::WriteAllSongsStatisticsToFiles() { const SongList all_songs = backend_->GetAllSongs(); const int task_id = app_->task_manager()->StartTask( tr("Saving songs statistics into songs files")); app_->task_manager()->SetTaskBlocksLibraryScans(task_id); const int nb_songs = all_songs.size(); int i = 0; for (const Song& song : all_songs) { TagReaderClient::Instance()->UpdateSongStatisticsBlocking(song); TagReaderClient::Instance()->UpdateSongRatingBlocking(song); app_->task_manager()->SetTaskProgress(task_id, ++i, nb_songs); } app_->task_manager()->SetTaskFinished(task_id); }
Organise::Organise(TaskManager* task_manager, boost::shared_ptr<MusicStorage> destination, const OrganiseFormat &format, bool copy, bool overwrite, const SongList& songs, bool eject_after) : thread_(NULL), task_manager_(task_manager), transcoder_(new Transcoder(this)), destination_(destination), format_(format), copy_(copy), overwrite_(overwrite), eject_after_(eject_after), task_count_(songs.count()), transcode_suffix_(1), tasks_complete_(0), started_(false), task_id_(0), current_copy_progress_(0) { original_thread_ = thread(); for (const Song& song : songs) { tasks_pending_ << Task(song); } }
void FileView::DeleteFinished(const SongList& songs_with_errors) { if (songs_with_errors.isEmpty()) return; OrganiseErrorDialog* dialog = new OrganiseErrorDialog(this); dialog->Show(OrganiseErrorDialog::Type_Delete, songs_with_errors); // It deletes itself when the user closes it }
QString PlaylistManager::GetNameForNewPlaylist(const SongList& songs) { if (songs.isEmpty()) { return tr("Playlist"); } QSet<QString> artists; QSet<QString> albums; for (const Song& song : songs) { artists << (song.artist().isEmpty() ? tr("Unknown") : song.artist()); albums << (song.album().isEmpty() ? tr("Unknown") : song.album()); if (artists.size() > 1) { break; } } bool various_artists = artists.size() > 1; QString result; if (various_artists) { result = tr("Various artists"); } else { result = artists.values().first(); } if (!various_artists && albums.size() == 1) { result += " - " + albums.toList().first(); } return result; }
TEST_F(XSPFParserTest, IgnoresInvalidLength) { QByteArray data = "<playlist><trackList><track>" "<location>http://example.com/foo.mp3</location>" "<title>Foo</title>" "<creator>Bar</creator>" "<album>Baz</album>" "<duration>60000qwerty</duration>" "<image>http://example.com/albumcover.jpg</image>" "<info>http://example.com</info>" "</track></trackList></playlist>"; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); XSPFParser parser(NULL); SongList songs = parser.Load(&buffer); ASSERT_EQ(1, songs.length()); EXPECT_EQ(-1, songs[0].length_nanosec()); }
TEST_F(ASXParserTest, ParsesOneTrackFromXML) { QByteArray data = "<asx version=\"3.0\"><title>foobar</title><entry>" "<ref href=\"http://example.com/foo.mp3\"/>" "<title>Foo</title>" "<author>Bar</author>" "<copyright>mumble mumble</copyright>" "</entry></asx>"; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); ASXParser parser(NULL); SongList songs = parser.Load(&buffer); ASSERT_EQ(1, songs.length()); const Song& song = songs[0]; EXPECT_EQ("Foo", song.title()); EXPECT_EQ("Bar", song.artist()); EXPECT_EQ(QUrl("http://example.com/foo.mp3"), song.url()); EXPECT_TRUE(song.is_valid()); }
TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) { QByteArray data = "<playlist><trackList>" "<track>" "<location>http://example.com/foo.mp3</location>" "</track>" "<track>" "<location>http://example.com/bar.mp3</location>" "</track>" "</trackList></playlist>"; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); XSPFParser parser(NULL); SongList songs = parser.Load(&buffer); ASSERT_EQ(2, songs.length()); EXPECT_EQ(QUrl("http://example.com/foo.mp3"), songs[0].url()); EXPECT_EQ(QUrl("http://example.com/bar.mp3"), songs[1].url()); EXPECT_TRUE(songs[0].is_stream()); EXPECT_TRUE(songs[1].is_stream()); }
TEST_F(ASXParserTest, ParsesMoreThanOneTrackFromXML) { QByteArray data = "<asx><entry>" "<entry>" "<ref href=\"http://example.com/foo.mp3\"/>" "</entry>" "<entry>" "<ref href=\"http://example.com/bar.mp3\"/>" "</entry>" "</entry></asx>"; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); ASXParser parser(NULL); SongList songs = parser.Load(&buffer); ASSERT_EQ(2, songs.length()); EXPECT_EQ(QUrl("http://example.com/foo.mp3"), songs[0].url()); EXPECT_EQ(QUrl("http://example.com/bar.mp3"), songs[1].url()); EXPECT_TRUE(songs[0].is_stream()); EXPECT_TRUE(songs[1].is_stream()); }
void SpotifyService::SearchResults( const pb::spotify::SearchResponse& response) { if (QStringFromStdString(response.request().query()) != pending_search_) { qLog(Debug) << "Old search result for" << QStringFromStdString(response.request().query()) << "expecting" << pending_search_; return; } pending_search_.clear(); SongList songs; for (int i = 0; i < response.result_size(); ++i) { Song song; SongFromProtobuf(response.result(i), &song); songs << song; } qLog(Debug) << "Got" << songs.count() << "results"; ClearSearchResults(); // Fill results list for (const Song& song : songs) { QStandardItem* child = CreateSongItem(song); search_->appendRow(child); } const QString did_you_mean_suggestion = QStringFromStdString(response.did_you_mean()); qLog(Debug) << "Did you mean suggestion: " << did_you_mean_suggestion; if (!did_you_mean_suggestion.isEmpty()) { search_box_->did_you_mean()->Show(did_you_mean_suggestion); } else { // In case something else was previously displayed search_box_->did_you_mean()->hide(); } QModelIndex index = model()->merged_model()->mapFromSource(search_->index()); ScrollToIndex(index); }
void EditTagDialog::FetchTag() { const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes(); SongList songs; for (const QModelIndex& index : sel) { Song song = data_[index.row()].original_; if (!song.is_valid()) { continue; } songs << song; } if (songs.isEmpty()) return; results_dialog_->Init(songs); tag_fetcher_->StartFetch(songs); results_dialog_->show(); }
void PLSParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const { QTextStream s(device); s << "[playlist]" << endl; s << "Version=2" << endl; s << "NumberOfEntries=" << songs.count() << endl; int n = 1; foreach (const Song& song, songs) { s << "File" << n << "=" << URLOrRelativeFilename(song.url(), dir) << endl; s << "Title" << n << "=" << song.title() << endl; s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl; ++n; }
TEST_F(ASXParserTest, ParsesBrokenXmlEntities) { QByteArray data = "<asx version = \"3.0\">" "<Title>DI.fm</Title>" "<Author>Digitally Imported Radio</Author>" "<Copyright>2006 Digitally Imported., Inc</Copyright>" "<MoreInfo href=\"http://www.di.fm/\" />" " <entry>" " <PARAM name=\"HTMLView\" value=\"http://www.di.fm/classictrance/pro/mini_playlist.html\"/>" " <ref href = \"mms://72.26.204.105/classictrance128k?user=h&pass=xxxxxxxxxxxxxxx\"/>" " <Title>Classic Trance</Title>" " <Author>Digitally Imported Premium</Author>" " </entry>" "</asx>"; QBuffer buffer(&data); buffer.open(QIODevice::ReadOnly); ASXParser parser(NULL); SongList songs = parser.Load(&buffer); ASSERT_EQ(1, songs.length()); EXPECT_EQ(QUrl("mms://72.26.204.105/classictrance128k?user=h&pass=xxxxxxxxxxxxxxx"), songs[0].url()); }
void LibraryView::SaveFocus() { QModelIndex current = currentIndex(); QVariant type = model()->data(current, LibraryModel::Role_Type); if (!type.isValid() || !(type.toInt() == LibraryItem::Type_Song || type.toInt() == LibraryItem::Type_Container || type.toInt() == LibraryItem::Type_Divider)) { return; } last_selected_path_.clear(); last_selected_song_ = Song(); last_selected_container_ = QString(); switch (type.toInt()) { case LibraryItem::Type_Song: { QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current); SongList songs = app_->library_model()->GetChildSongs(index); if (!songs.isEmpty()) { last_selected_song_ = songs.last(); } break; } case LibraryItem::Type_Container: case LibraryItem::Type_Divider: { QString text = model()->data(current, LibraryModel::Role_SortText).toString(); last_selected_container_ = text; break; } default: return; } SaveContainerPath(current); }
QVariant LibraryModel::AlbumIcon(const QModelIndex& index) { LibraryItem* item = IndexToItem(index); if (!item) return no_cover_icon_; // Check the cache for a pixmap we already loaded. const QString cache_key = AlbumIconPixmapCacheKey(index); QPixmap cached_pixmap; if (QPixmapCache::find(cache_key, &cached_pixmap)) { return cached_pixmap; } // Try to load it from the disk cache std::unique_ptr<QIODevice> cache(icon_cache_->data(QUrl(cache_key))); if (cache) { QImage cached_pixmap; if (cached_pixmap.load(cache.get(), "XPM")) { QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_pixmap)); return QPixmap::fromImage(cached_pixmap); } } // Maybe we're loading a pixmap already? if (pending_cache_keys_.contains(cache_key)) { return no_cover_icon_; } // No art is cached and we're not loading it already. Load art for the first // Song in the album. SongList songs = GetChildSongs(index); if (!songs.isEmpty()) { const quint64 id = app_->album_cover_loader()->LoadImageAsync( cover_loader_options_, songs.first()); pending_art_[id] = ItemAndCacheKey(item, cache_key); pending_cache_keys_.insert(cache_key); } return no_cover_icon_; }
void GetSongNamesForCurrentArtist() { string aname = artistNames[currArtistNdx]; SongList::iterator ai = songs.find( aname ); if (ai == songs.end() ) { printf("Could not find %s\n", aname.c_str() ); return; } std::vector<Song> &asongs = (*ai).second; printf("GetSongNamesForCurrentArtist---\n" ); printf("%d songs... \n", asongs.size() ); songNames.clear(); songPath.clear(); for ( std::vector<Song>::iterator si = asongs.begin(); si != asongs.end(); ++si ) { songNames.push_back( (*si).title ); songPath.push_back( (*si).filename ); } }