[Database] restored id on Artist, Genre and Release tables. Added basic MusicBrainz ID support. Improved search filters a bit
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "database/DatabaseHandler.hpp"
|
||||
|
||||
static const std::string trackMBID = "123e4567-e89b-12d3-a456-426655440000";
|
||||
static const std::string artistMBID = "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx";
|
||||
static const std::string releaseMBID = "xxxxxxxx-xxxx-9877-Nxxx-xxxxxxxxxxxx";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
boost::filesystem::remove("test.db");
|
||||
|
||||
Handler db("test.db");
|
||||
|
||||
// Create
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
Track::pointer track = Track::create(db.getSession(), "test.mp2");
|
||||
|
||||
track.modify()->setName("track01");
|
||||
track.modify()->setMBID(trackMBID);
|
||||
|
||||
Artist::pointer artist = Artist::create(db.getSession(), "artist01", artistMBID);
|
||||
Release::pointer release = Release::create(db.getSession(), "release01", releaseMBID);
|
||||
Genre::pointer genre = Genre::create(db.getSession(), "genre01");
|
||||
|
||||
track.modify()->setArtist(artist);
|
||||
track.modify()->setRelease(release);
|
||||
track.modify()->setGenres( { genre });
|
||||
}
|
||||
|
||||
// Search
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
Track::pointer track = Track::getByMBID(db.getSession(), trackMBID);
|
||||
assert(track);
|
||||
assert(track->getArtist()->getMBID() == artistMBID);
|
||||
|
||||
Track::pointer trackNotFound = Track::getByMBID(db.getSession(), "foobar");
|
||||
assert(!trackNotFound);
|
||||
|
||||
Artist::pointer artist = Artist::getByMBID(db.getSession(), artistMBID);
|
||||
assert(artist);
|
||||
}
|
||||
|
||||
// Search Filters
|
||||
// Select track by track name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].push_back("track");
|
||||
std::vector<Track::pointer> res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].clear();
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].push_back("not-found");
|
||||
res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 0 );
|
||||
}
|
||||
|
||||
// Select track by artist name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.nameLikeMatch[SearchFilter::Field::Artist].push_back("artist");
|
||||
std::vector<Track::pointer> res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
}
|
||||
|
||||
// Select track by artist id
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.idMatch[SearchFilter::Field::Artist].push_back(1);
|
||||
std::vector<Track::pointer> res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
}
|
||||
|
||||
// Select track by track name + artist id
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.idMatch[SearchFilter::Field::Artist].push_back(1);
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].push_back("track");
|
||||
std::vector<Track::pointer> res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "track01" );
|
||||
}
|
||||
|
||||
// Select track by genre name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter = SearchFilter::NameLikeMatch({{SearchFilter::Field::Genre, {"genre"}}});
|
||||
std::vector<Track::pointer> res = Track::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "track01" );
|
||||
}
|
||||
|
||||
// Select artist by track name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].push_back("track");
|
||||
std::vector<Artist::pointer> res = Artist::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].clear();
|
||||
filter.nameLikeMatch[SearchFilter::Field::Track].push_back("badtrack");
|
||||
res = Artist::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 0);
|
||||
}
|
||||
|
||||
// Select artist by track id
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.idMatch[SearchFilter::Field::Track].push_back(1);
|
||||
std::vector<Artist::pointer> res = Artist::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
}
|
||||
|
||||
// Select Artist by name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.nameLikeMatch[SearchFilter::Field::Artist].push_back("artist");
|
||||
std::vector<Artist::pointer> res = Artist::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
}
|
||||
|
||||
// Select Release by name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter;
|
||||
filter.nameLikeMatch[SearchFilter::Field::Release].push_back("release");
|
||||
|
||||
std::vector<Release::pointer> res = Release::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
}
|
||||
|
||||
// Select Release by track name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter = SearchFilter::NameLikeMatch({{SearchFilter::Field::Track, {"track"}}});
|
||||
std::vector<Release::pointer> res = Release::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "release01");
|
||||
}
|
||||
|
||||
// Select genre by name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter = SearchFilter::NameLikeMatch({{SearchFilter::Field::Genre, {"genre"}}});
|
||||
std::vector<Genre::pointer> res = Genre::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "genre01");
|
||||
}
|
||||
|
||||
// Select genre by track name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter = SearchFilter::NameLikeMatch({{SearchFilter::Field::Track, {"track"}}});
|
||||
std::vector<Genre::pointer> res = Genre::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "genre01");
|
||||
}
|
||||
|
||||
// Select genre by track name and artist name
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(db.getSession());
|
||||
|
||||
SearchFilter filter = SearchFilter::NameLikeMatch({{SearchFilter::Field::Track, {"track"}},
|
||||
{SearchFilter::Field::Artist, {"artist"}}});
|
||||
std::vector<Genre::pointer> res = Genre::getByFilter(db.getSession(), filter, -1, -1);
|
||||
assert(res.size() == 1);
|
||||
assert(res.front().id() == 1);
|
||||
assert(res.front()->getName() == "genre01");
|
||||
}
|
||||
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << "Caught exception " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
+25
-2
@@ -1,7 +1,24 @@
|
||||
|
||||
TESTS = database-integrity sql-query database-user remote-client
|
||||
TESTS = database-basics database-integrity sql-query database-user remote-client
|
||||
|
||||
check_PROGRAMS = database-basics database-integrity sql-query database-user remote-client
|
||||
|
||||
database_basics_SOURCES = \
|
||||
$(srcdir)/CheckDbBasics.cpp \
|
||||
$(top_srcdir)/src/logger/Logger.cpp \
|
||||
$(top_srcdir)/src/database/Artist.cpp \
|
||||
$(top_srcdir)/src/database/DatabaseHandler.cpp \
|
||||
$(top_srcdir)/src/database/MediaDirectory.cpp \
|
||||
$(top_srcdir)/src/database/Playlist.cpp \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/SearchFilter.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
$(top_srcdir)/src/database/Video.cpp
|
||||
|
||||
database_basics_CXXFLAGS=-std=c++11 -Wall -Wextra -DBOOST_LOG_DYN_LINK -I$(top_srcdir)/src
|
||||
|
||||
check_PROGRAMS = database-integrity sql-query database-user remote-client
|
||||
|
||||
remote_client_SOURCES = \
|
||||
$(srcdir)/RemoteClient.cpp \
|
||||
@@ -30,10 +47,13 @@ remote_client_CXXFLAGS=-std=c++11 -Wall -Wextra -DBOOST_LOG_DYN_LINK -I$(top_src
|
||||
database_user_SOURCES = \
|
||||
$(srcdir)/CheckDatabaseUser.cpp \
|
||||
$(top_srcdir)/src/logger/Logger.cpp \
|
||||
$(top_srcdir)/src/database/Artist.cpp \
|
||||
$(top_srcdir)/src/database/Playlist.cpp \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/DatabaseHandler.cpp \
|
||||
$(top_srcdir)/src/database/MediaDirectory.cpp \
|
||||
$(top_srcdir)/src/database/SearchFilter.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
$(top_srcdir)/src/database/Video.cpp
|
||||
@@ -44,10 +64,13 @@ database_user_CXXFLAGS=-std=c++11 -Wall -Wextra -DBOOST_LOG_DYN_LINK -I$(top_src
|
||||
database_integrity_SOURCES = \
|
||||
$(srcdir)/DatabaseIntegrity.cpp \
|
||||
$(top_srcdir)/src/logger/Logger.cpp \
|
||||
$(top_srcdir)/src/database/Artist.cpp \
|
||||
$(top_srcdir)/src/database/Playlist.cpp \
|
||||
$(top_srcdir)/src/database/Track.cpp \
|
||||
$(top_srcdir)/src/database/DatabaseHandler.cpp \
|
||||
$(top_srcdir)/src/database/MediaDirectory.cpp \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
$(top_srcdir)/src/database/SearchFilter.cpp \
|
||||
$(top_srcdir)/src/database/SqlQuery.cpp \
|
||||
$(top_srcdir)/src/database/User.cpp \
|
||||
$(top_srcdir)/src/database/Video.cpp
|
||||
|
||||
+129
-82
@@ -34,40 +34,52 @@
|
||||
|
||||
struct GenreInfo
|
||||
{
|
||||
uint64_t id;
|
||||
std::string name;
|
||||
|
||||
GenreInfo() : id(0) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const GenreInfo& info)
|
||||
{
|
||||
os << "name = '" << info.name << "'";
|
||||
os << "name = '" << info.name << "'(" << info.id << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct ArtistInfo
|
||||
{
|
||||
uint64_t id;
|
||||
std::string mbid;
|
||||
std::string name;
|
||||
|
||||
ArtistInfo() :id(0) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ArtistInfo& info)
|
||||
{
|
||||
os << "name = '" << info.name << "'";
|
||||
os << "name = '" << info.name << "'(" << info.id << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct ReleaseInfo
|
||||
{
|
||||
uint64_t id;
|
||||
std::string mbid;
|
||||
std::string name;
|
||||
|
||||
ReleaseInfo() : id(0) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ReleaseInfo& info)
|
||||
{
|
||||
os << "name = '" << info.name;
|
||||
os << "name = '" << info.name << "'(" << info.id << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
struct TrackInfo
|
||||
{
|
||||
uint64_t id;
|
||||
std::string mbid;
|
||||
|
||||
uint64_t release_id;
|
||||
uint64_t artist_id;
|
||||
@@ -103,8 +115,30 @@ struct Cover
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
// Ugly class for testing purposes
|
||||
struct SearchFilter
|
||||
{
|
||||
std::vector<uint64_t> artistIds;
|
||||
std::vector<uint64_t> genreIds;
|
||||
std::vector<uint64_t> releaseIds;
|
||||
std::vector<uint64_t> trackIds;
|
||||
};
|
||||
|
||||
void SearchFilterToRequest(const SearchFilter& filter, Remote::AudioCollectionRequest_SearchFilter& request)
|
||||
{
|
||||
for (uint64_t id : filter.artistIds)
|
||||
request.add_artist_id(id);
|
||||
|
||||
for (uint64_t id : filter.genreIds)
|
||||
request.add_genre_id(id);
|
||||
|
||||
for (uint64_t id : filter.releaseIds)
|
||||
request.add_release_id(id);
|
||||
|
||||
for (uint64_t id : filter.trackIds)
|
||||
request.add_track_id(id);
|
||||
}
|
||||
|
||||
// Ugly class for testing purposes
|
||||
class TestClient
|
||||
{
|
||||
public:
|
||||
@@ -122,8 +156,7 @@ class TestClient
|
||||
_socket.handshake(boost::asio::ssl::stream_base::client);
|
||||
}
|
||||
|
||||
void getArtists(std::vector<ArtistInfo>& artists,
|
||||
const std::vector<std::string>& genres = std::vector<std::string>())
|
||||
void getArtists(std::vector<ArtistInfo>& artists, const SearchFilter& filter = SearchFilter())
|
||||
{
|
||||
|
||||
const std::size_t requestedBatchSize = 128;
|
||||
@@ -131,12 +164,12 @@ class TestClient
|
||||
std::size_t res = 0;
|
||||
|
||||
|
||||
while ((res = getArtists(artists, genres, offset, requestedBatchSize) ) > 0)
|
||||
while ((res = getArtists(artists, filter, offset, requestedBatchSize) ) > 0)
|
||||
offset += res;
|
||||
|
||||
}
|
||||
|
||||
std::size_t getArtists(std::vector<ArtistInfo>& artists, const std::vector<std::string>& genres, std::size_t offset, std::size_t size)
|
||||
std::size_t getArtists(std::vector<ArtistInfo>& artists, const SearchFilter& filter, std::size_t offset, std::size_t size)
|
||||
{
|
||||
std::size_t nbArtists = 0;
|
||||
|
||||
@@ -148,8 +181,7 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest_Type_TypeGetArtistList);
|
||||
request.mutable_audio_collection_request()->mutable_get_artists()->mutable_batch_parameter()->set_size(size);
|
||||
request.mutable_audio_collection_request()->mutable_get_artists()->mutable_batch_parameter()->set_offset(offset);
|
||||
BOOST_FOREACH(const std::string& genre, genres)
|
||||
request.mutable_audio_collection_request()->mutable_get_artists()->add_genre(genre);
|
||||
SearchFilterToRequest(filter, *request.mutable_audio_collection_request()->mutable_get_artists()->mutable_search_filter());
|
||||
|
||||
sendMsg(request);
|
||||
|
||||
@@ -166,11 +198,18 @@ class TestClient
|
||||
|
||||
for (int i = 0; i < response.audio_collection_response().artist_list().artists_size(); ++i)
|
||||
{
|
||||
if (!response.audio_collection_response().artist_list().artists(i).has_name())
|
||||
const Remote::AudioCollectionResponse_Artist& respArtist = response.audio_collection_response().artist_list().artists(i);
|
||||
|
||||
if (!respArtist.has_id())
|
||||
throw std::runtime_error("no id!");
|
||||
if (!respArtist.has_name())
|
||||
throw std::runtime_error("no artist name!");
|
||||
|
||||
ArtistInfo artist;
|
||||
artist.name = response.audio_collection_response().artist_list().artists(i).name();
|
||||
artist.name = respArtist.name();
|
||||
artist.id = respArtist.id();
|
||||
if (respArtist.has_mbid())
|
||||
artist.mbid = respArtist.mbid();
|
||||
|
||||
artists.push_back( artist );
|
||||
nbArtists++;
|
||||
@@ -179,19 +218,19 @@ class TestClient
|
||||
return nbArtists;
|
||||
}
|
||||
|
||||
void getGenres(std::vector<GenreInfo>& genres)
|
||||
void getGenres(std::vector<GenreInfo>& genres, const SearchFilter& filter = SearchFilter())
|
||||
{
|
||||
|
||||
const std::size_t requestedBatchSize = 8;
|
||||
std::size_t offset = 0;
|
||||
std::size_t res = 0;
|
||||
|
||||
while ((res = getGenres(genres, offset, requestedBatchSize) ) > 0)
|
||||
while ((res = getGenres(genres, filter, offset, requestedBatchSize) ) > 0)
|
||||
offset += res;
|
||||
|
||||
}
|
||||
|
||||
std::size_t getGenres(std::vector<GenreInfo>& genres, std::size_t offset, std::size_t size)
|
||||
std::size_t getGenres(std::vector<GenreInfo>& genres, const SearchFilter& filter, std::size_t offset, std::size_t size)
|
||||
{
|
||||
std::size_t nbAdded = 0;
|
||||
|
||||
@@ -203,6 +242,7 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest_Type_TypeGetGenreList);
|
||||
request.mutable_audio_collection_request()->mutable_get_genres()->mutable_batch_parameter()->set_size(size);
|
||||
request.mutable_audio_collection_request()->mutable_get_genres()->mutable_batch_parameter()->set_offset(offset);
|
||||
SearchFilterToRequest(filter, *request.mutable_audio_collection_request()->mutable_get_genres()->mutable_search_filter());
|
||||
|
||||
sendMsg(request);
|
||||
|
||||
@@ -219,11 +259,16 @@ class TestClient
|
||||
|
||||
for (int i = 0; i < response.audio_collection_response().genre_list().genres_size(); ++i)
|
||||
{
|
||||
if (!response.audio_collection_response().genre_list().genres(i).has_name())
|
||||
const Remote::AudioCollectionResponse_Genre& respGenre = response.audio_collection_response().genre_list().genres(i);
|
||||
|
||||
if (!respGenre.has_id())
|
||||
throw std::runtime_error("no genre id!");
|
||||
if (!respGenre.has_name())
|
||||
throw std::runtime_error("no genre name!");
|
||||
|
||||
GenreInfo genre;
|
||||
genre.name = response.audio_collection_response().genre_list().genres(i).name();
|
||||
genre.id = respGenre.id();
|
||||
genre.name = respGenre.name();
|
||||
|
||||
genres.push_back( genre );
|
||||
nbAdded++;
|
||||
@@ -231,21 +276,19 @@ class TestClient
|
||||
return nbAdded;
|
||||
}
|
||||
|
||||
void getReleases(std::vector<ReleaseInfo>& releases,
|
||||
const std::vector<std::string>& artists = std::vector<std::string>(),
|
||||
const std::vector<std::string>& genres = std::vector<std::string>())
|
||||
void getReleases(std::vector<ReleaseInfo>& releases, const SearchFilter& filter = SearchFilter())
|
||||
{
|
||||
|
||||
const std::size_t requestedBatchSize = 256;
|
||||
std::size_t offset = 0;
|
||||
std::size_t res = 0;
|
||||
|
||||
while ((res = getReleases(releases, artists, genres, offset, requestedBatchSize) ) > 0)
|
||||
while ((res = getReleases(releases, filter, offset, requestedBatchSize) ) > 0)
|
||||
offset += res;
|
||||
|
||||
}
|
||||
|
||||
std::size_t getReleases(std::vector<ReleaseInfo>& releases, const std::vector<std::string>& artists, const std::vector<std::string>& genres, std::size_t offset, std::size_t size)
|
||||
std::size_t getReleases(std::vector<ReleaseInfo>& releases, const SearchFilter& filter, std::size_t offset, std::size_t size)
|
||||
{
|
||||
std::size_t nbAdded = 0;
|
||||
|
||||
@@ -257,11 +300,7 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest_Type_TypeGetReleaseList);
|
||||
request.mutable_audio_collection_request()->mutable_get_releases()->mutable_batch_parameter()->set_size(size);
|
||||
request.mutable_audio_collection_request()->mutable_get_releases()->mutable_batch_parameter()->set_offset(offset);
|
||||
BOOST_FOREACH(const std::string& artist, artists)
|
||||
request.mutable_audio_collection_request()->mutable_get_releases()->add_artist(artist);
|
||||
|
||||
BOOST_FOREACH(const std::string& genre, genres)
|
||||
request.mutable_audio_collection_request()->mutable_get_releases()->add_genre(genre);
|
||||
SearchFilterToRequest(filter, *request.mutable_audio_collection_request()->mutable_get_releases()->mutable_search_filter());
|
||||
|
||||
sendMsg(request);
|
||||
|
||||
@@ -284,11 +323,16 @@ class TestClient
|
||||
|
||||
for (int i = 0; i < response.audio_collection_response().release_list().releases_size(); ++i)
|
||||
{
|
||||
if (!response.audio_collection_response().release_list().releases(i).has_name())
|
||||
const Remote::AudioCollectionResponse_Release& respRelease = response.audio_collection_response().release_list().releases(i);
|
||||
|
||||
if (!respRelease.has_id())
|
||||
throw std::runtime_error("no id!");
|
||||
if (!respRelease.has_name())
|
||||
throw std::runtime_error("no release name!");
|
||||
|
||||
ReleaseInfo release;
|
||||
release.name = response.audio_collection_response().release_list().releases(i).name();
|
||||
release.id = respRelease.id();
|
||||
release.name = respRelease.name();
|
||||
|
||||
releases.push_back( release );
|
||||
nbAdded++;
|
||||
@@ -296,25 +340,17 @@ class TestClient
|
||||
return nbAdded;
|
||||
}
|
||||
|
||||
void getTracks(std::vector<TrackInfo>& tracks,
|
||||
const std::vector<std::string>& artists = std::vector<std::string>(),
|
||||
const std::vector<std::string>& releases = std::vector<std::string>(),
|
||||
const std::vector<std::string>& genres = std::vector<std::string>())
|
||||
void getTracks(std::vector<TrackInfo>& tracks, const SearchFilter& filter = SearchFilter())
|
||||
{
|
||||
const std::size_t requestedBatchSize = 0;
|
||||
std::size_t offset = 0;
|
||||
std::size_t res = 0;
|
||||
|
||||
while ((res = getTracks(tracks, artists, releases, genres, offset, requestedBatchSize) ) > 0)
|
||||
while ((res = getTracks(tracks, filter, offset, requestedBatchSize) ) > 0)
|
||||
offset += res;
|
||||
}
|
||||
|
||||
std::size_t getTracks(std::vector<TrackInfo>& tracks,
|
||||
const std::vector<std::string>& artists,
|
||||
const std::vector<std::string>& releases,
|
||||
const std::vector<std::string>& genres,
|
||||
std::size_t offset,
|
||||
std::size_t size)
|
||||
std::size_t getTracks(std::vector<TrackInfo>& tracks, const SearchFilter& filter, std::size_t offset, std::size_t size)
|
||||
{
|
||||
std::size_t nbAdded = 0;
|
||||
|
||||
@@ -326,13 +362,7 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest_Type_TypeGetTrackList);
|
||||
request.mutable_audio_collection_request()->mutable_get_tracks()->mutable_batch_parameter()->set_size(size);
|
||||
request.mutable_audio_collection_request()->mutable_get_tracks()->mutable_batch_parameter()->set_offset(offset);
|
||||
|
||||
BOOST_FOREACH(const std::string& artist, artists)
|
||||
request.mutable_audio_collection_request()->mutable_get_tracks()->add_artist(artist);
|
||||
BOOST_FOREACH(const std::string& release, releases)
|
||||
request.mutable_audio_collection_request()->mutable_get_tracks()->add_release(release);
|
||||
BOOST_FOREACH(const std::string& genre, genres)
|
||||
request.mutable_audio_collection_request()->mutable_get_tracks()->add_genre(genre);
|
||||
SearchFilterToRequest(filter, *request.mutable_audio_collection_request()->mutable_get_tracks()->mutable_search_filter());
|
||||
|
||||
sendMsg(request);
|
||||
|
||||
@@ -349,22 +379,27 @@ class TestClient
|
||||
|
||||
for (int i = 0; i < response.audio_collection_response().track_list().tracks_size(); ++i)
|
||||
{
|
||||
const Remote::AudioCollectionResponse_Track& respTrack = response.audio_collection_response().track_list().tracks(i);;
|
||||
|
||||
TrackInfo track;
|
||||
track.id = response.audio_collection_response().track_list().tracks(i).id();
|
||||
track.name = response.audio_collection_response().track_list().tracks(i).name();
|
||||
track.duration = boost::posix_time::seconds(response.audio_collection_response().track_list().tracks(i).duration_secs());
|
||||
if (response.audio_collection_response().track_list().tracks(i).has_track_number())
|
||||
track.track_number = response.audio_collection_response().track_list().tracks(i).track_number();
|
||||
track.id = respTrack.id();
|
||||
if (respTrack.has_mbid())
|
||||
track.mbid = respTrack.mbid();
|
||||
|
||||
if (response.audio_collection_response().track_list().tracks(i).has_disc_number())
|
||||
track.disc_number = response.audio_collection_response().track_list().tracks(i).disc_number();
|
||||
track.name = respTrack.name();
|
||||
track.duration = boost::posix_time::seconds(respTrack.duration_secs());
|
||||
|
||||
if (response.audio_collection_response().track_list().tracks(i).has_release_date())
|
||||
track.date = response.audio_collection_response().track_list().tracks(i).release_date();
|
||||
if (respTrack.has_track_number())
|
||||
track.track_number = respTrack.track_number();
|
||||
|
||||
if (response.audio_collection_response().track_list().tracks(i).has_original_release_date())
|
||||
track.original_date = response.audio_collection_response().track_list().tracks(i).original_release_date();
|
||||
if (respTrack.has_disc_number())
|
||||
track.disc_number = respTrack.disc_number();
|
||||
|
||||
if (respTrack.has_release_date())
|
||||
track.date = respTrack.release_date();
|
||||
|
||||
if (respTrack.has_original_release_date())
|
||||
track.original_date = respTrack.original_release_date();
|
||||
|
||||
|
||||
tracks.push_back( track );
|
||||
@@ -419,7 +454,7 @@ class TestClient
|
||||
}
|
||||
}
|
||||
|
||||
void getCoverRelease(std::vector<Cover>& coverArt, const std::string& release)
|
||||
void getCoverRelease(std::vector<Cover>& coverArt, uint64_t releaseId)
|
||||
{
|
||||
// Send request
|
||||
Remote::ClientMessage request;
|
||||
@@ -428,7 +463,7 @@ class TestClient
|
||||
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest::TypeGetCoverArt);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_type( Remote::AudioCollectionRequest::GetCoverArt::TypeGetCoverArtRelease);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_release( release );
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_release_id( releaseId );
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_size( 256 );
|
||||
|
||||
sendMsg(request);
|
||||
@@ -772,7 +807,7 @@ int main()
|
||||
TestClient client( boost::asio::ip::tcp::endpoint( boost::asio::ip::address_v4::loopback(), 5080));
|
||||
|
||||
// Use a dumb account in order to login TODO parametrize
|
||||
if (!client.login("admin", "toto"))
|
||||
if (!client.login("admin", "totoadmin"))
|
||||
throw std::runtime_error("login failed!");
|
||||
|
||||
// **** REVISION ***
|
||||
@@ -786,7 +821,7 @@ int main()
|
||||
client.getArtists(artists);
|
||||
|
||||
std::cout << "Got " << artists.size() << " artists!" << std::endl;
|
||||
BOOST_FOREACH(const ArtistInfo& artist, artists)
|
||||
for (const ArtistInfo& artist : artists)
|
||||
std::cout << "Artist: '" << artist << "'" << std::endl;
|
||||
|
||||
// ***** Genres *********
|
||||
@@ -795,14 +830,14 @@ int main()
|
||||
client.getGenres(genres);
|
||||
|
||||
std::cout << "Got " << genres.size() << " genres!" << std::endl;
|
||||
BOOST_FOREACH(const GenreInfo& genre, genres)
|
||||
for (const GenreInfo& genre : genres)
|
||||
std::cout << "Genre: '" << genre << "'" << std::endl;
|
||||
|
||||
// **** Releases ******
|
||||
std::cout << "Getting releases..." << std::endl;
|
||||
std::vector<ReleaseInfo> releases;
|
||||
client.getReleases(releases);
|
||||
BOOST_FOREACH(const ReleaseInfo& release, releases)
|
||||
for (const ReleaseInfo& release : releases)
|
||||
std::cout << "Release: '" << release << "'" << std::endl;
|
||||
|
||||
// **** Tracks ******
|
||||
@@ -811,7 +846,7 @@ int main()
|
||||
client.getTracks(tracks);
|
||||
|
||||
std::cout << "Got " << tracks.size() << " tracks!" << std::endl;
|
||||
BOOST_FOREACH(const TrackInfo& track, tracks)
|
||||
for (const TrackInfo& track : tracks)
|
||||
std::cout << "Track: '" << track << "'" << std::endl;
|
||||
|
||||
// Caution: long test!
|
||||
@@ -819,14 +854,17 @@ int main()
|
||||
{
|
||||
std::cout << "Getting artist for each genre..." << std::endl;
|
||||
// Get the artists for each genre
|
||||
BOOST_FOREACH(const GenreInfo& genre, genres)
|
||||
for (const GenreInfo& genre : genres)
|
||||
{
|
||||
std::cout << "Getting artists from genre '" << genre.name << "'... ";
|
||||
SearchFilter filter;
|
||||
filter.genreIds.push_back(genre.id);
|
||||
|
||||
std::vector<ArtistInfo> artists;
|
||||
client.getArtists(artists, std::vector<std::string>(1, genre.name));
|
||||
client.getArtists(artists, filter);
|
||||
|
||||
std::cout << "Found " << artists.size() << " artists!" << std::endl;
|
||||
BOOST_FOREACH(const ArtistInfo& artist, artists)
|
||||
for (const ArtistInfo& artist : artists)
|
||||
std::cout << "Genre '" << genre.name << "' -> Artist: " << artist << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -834,14 +872,17 @@ int main()
|
||||
if (test(Test::ReleaseFilterArtist))
|
||||
{
|
||||
std::cout << "Getting release for each artist..." << std::endl;
|
||||
BOOST_FOREACH(const ArtistInfo& artist, artists)
|
||||
for (const ArtistInfo& artist : artists)
|
||||
{
|
||||
std::cout << "Getting release from artist '" << artist.name << "'... ";
|
||||
SearchFilter filter;
|
||||
filter.artistIds.push_back(artist.id);
|
||||
|
||||
std::vector<ReleaseInfo> releases;
|
||||
client.getReleases(releases, std::vector<std::string>(1, artist.name) );
|
||||
client.getReleases(releases, filter);
|
||||
|
||||
std::cout << "Found " << releases.size() << " releases!" << std::endl;
|
||||
BOOST_FOREACH(const ReleaseInfo& release, releases)
|
||||
for (const ReleaseInfo& release : releases)
|
||||
std::cout << "Artist '" << artist.name << "' -> Release: '" << release << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -849,11 +890,14 @@ int main()
|
||||
if (test(Test::ReleaseFilterGenre))
|
||||
{
|
||||
std::cout << "Getting release for each genre..." << std::endl;
|
||||
BOOST_FOREACH(const GenreInfo& genre, genres)
|
||||
for (const GenreInfo& genre : genres)
|
||||
{
|
||||
std::cout << "Getting release from genre '" << genre.name << "'... ";
|
||||
SearchFilter filter;
|
||||
filter.genreIds.push_back(genre.id);
|
||||
|
||||
std::vector<ReleaseInfo> releases;
|
||||
client.getReleases(releases, std::vector<std::string>(), std::vector<std::string>(1, genre.name));
|
||||
client.getReleases(releases, filter);
|
||||
|
||||
std::cout << "Found " << releases.size() << " releases!" << std::endl;
|
||||
BOOST_FOREACH(const ReleaseInfo& release, releases)
|
||||
@@ -865,13 +909,16 @@ int main()
|
||||
{
|
||||
std::cout << "Getting tracks for each artist..." << std::endl;
|
||||
// Get the tracks for each artist
|
||||
BOOST_FOREACH(const ArtistInfo& artist, artists)
|
||||
for (const ArtistInfo& artist : artists)
|
||||
{
|
||||
SearchFilter filter;
|
||||
filter.artistIds.push_back(artist.id);
|
||||
|
||||
std::vector<TrackInfo> tracks;
|
||||
client.getTracks(tracks, std::vector<std::string>(1, artist.name));
|
||||
client.getTracks(tracks, filter);
|
||||
|
||||
std::cout << "Artist '" << artist.name << "', nb tracks = " << tracks.size() << std::endl;
|
||||
BOOST_FOREACH(const TrackInfo& track, tracks)
|
||||
for (const TrackInfo& track : tracks)
|
||||
std::cout << "Artist '" << artist.name << "', track: '" << track << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -880,19 +927,19 @@ int main()
|
||||
if (test(Test::CoverByRelease))
|
||||
{
|
||||
std::cout << "Getting cover for each release..." << std::endl;
|
||||
BOOST_FOREACH(const ReleaseInfo& release, releases)
|
||||
for (const ReleaseInfo& release : releases)
|
||||
{
|
||||
std::vector<Cover> coverArts;
|
||||
client.getCoverRelease(coverArts, release.name);
|
||||
client.getCoverRelease(coverArts, release.id);
|
||||
|
||||
if (writeCovers)
|
||||
{
|
||||
boost::filesystem::create_directory("cover");
|
||||
BOOST_FOREACH(const Cover coverArt, coverArts)
|
||||
for (const Cover coverArt : coverArts)
|
||||
{
|
||||
std::ostringstream oss; oss << "cover/" << release.name << ".jpeg";
|
||||
std::ofstream out(oss.str().c_str());
|
||||
BOOST_FOREACH(unsigned char c, coverArt.data)
|
||||
for (unsigned char c : coverArt.data)
|
||||
out.put(c);
|
||||
}
|
||||
}
|
||||
@@ -904,7 +951,7 @@ int main()
|
||||
if (test(Test::CoverByTrack))
|
||||
{
|
||||
std::cout << "Getting cover for each track..." << std::endl;
|
||||
BOOST_FOREACH(const TrackInfo& track, tracks)
|
||||
for (const TrackInfo& track : tracks)
|
||||
{
|
||||
std::vector<Cover> coverArt;
|
||||
client.getCoverTrack(coverArt, track.id);
|
||||
@@ -916,7 +963,7 @@ int main()
|
||||
|
||||
if (test(Test::Transcode))
|
||||
{
|
||||
BOOST_FOREACH(const TrackInfo& track, tracks)
|
||||
for (const TrackInfo& track : tracks)
|
||||
{
|
||||
std::vector<unsigned char> data;
|
||||
client.getMediaAudio(track.id, data);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user