From 650945b5c43ef0ccdefad4f7ed2ca0351ec4c8e2 Mon Sep 17 00:00:00 2001 From: emeric Date: Wed, 11 Jun 2014 14:40:08 +0200 Subject: [PATCH] WIP, Remote Client/Server, cover art for tracks, TBT --- cover/CoverArtGrabber.cpp | 43 ++++++----- remote/messages/Header.hpp | 24 +++--- .../server/AudioCollectionRequestHandler.cpp | 20 ++++- remote/server/Connection.cpp | 13 +++- test/RemoteClientServer.cpp | 73 ++++++++++++++----- 5 files changed, 120 insertions(+), 53 deletions(-) diff --git a/cover/CoverArtGrabber.cpp b/cover/CoverArtGrabber.cpp index dd35bc07..3d59993b 100644 --- a/cover/CoverArtGrabber.cpp +++ b/cover/CoverArtGrabber.cpp @@ -9,10 +9,32 @@ namespace CoverArt { std::vector -Grabber::getFromRelease(Release::pointer release) +Grabber::getFromTrack(Track::pointer track) { std::vector res; + try + { + Av::InputFormatContext input(track->getPath()); + + std::vector< std::vector > pictures; + input.getPictures(pictures); + + BOOST_FOREACH(const std::vector& picture, pictures) + res.push_back( CoverArt("application/octet-stream", picture) ); + + } + catch(std::exception& e) + { + std::cerr << "Cannot get pictures: " << e.what(); + } + + return res; +} + +std::vector +Grabber::getFromRelease(Release::pointer release) +{ // TODO // Check if there is an image file in the directory of the release // For now, just get the cover art from the first track of the release @@ -25,23 +47,10 @@ Grabber::getFromRelease(Release::pointer release) if (firstTrack) { - try - { - Av::InputFormatContext input(firstTrack->getPath()); - - std::vector< std::vector > pictures; - input.getPictures(pictures); - - BOOST_FOREACH(const std::vector& picture, pictures) - res.push_back( CoverArt("application/octet-stream", picture) ); - } - catch(std::exception& e) - { - std::cerr << "Cannot get pictures: " << e.what(); - } + return Grabber::getFromTrack(firstTrack); } - - return res; + else + return std::vector(); } diff --git a/remote/messages/Header.hpp b/remote/messages/Header.hpp index 91b4fb74..4c909012 100644 --- a/remote/messages/Header.hpp +++ b/remote/messages/Header.hpp @@ -10,14 +10,13 @@ namespace Remote class Header { public: + static const std::size_t size = 8; // HeaderSize + static const std::size_t max_data_size = 65536*64 - size; - static const std::size_t size = 8; - - Header() : _size(0) {} - - void setSize(std::size_t size) { _size = size; } - std::size_t getSize(void) const {return _size;} + Header() : _dataSize(0) {} + void setDataSize(std::size_t size) { _dataSize = size; } + std::size_t getDataSize(void) const {return _dataSize;} bool from_istream(std::istream &is) { @@ -39,12 +38,12 @@ class Header } else { - _size = decode32(&buffer[4]); + _dataSize = decode32(&buffer[4]); - if (_size > _maxSize) - std::cerr << "Header: msg too big (" << _size << ")!" << std::endl; + if (_dataSize > max_data_size) + std::cerr << "Header: msg too big (" << _dataSize << ")!" << std::endl; - return _size <= _maxSize; + return _dataSize <= max_data_size; } } @@ -57,7 +56,7 @@ class Header void to_buffer(std::array& buffer) const { encode32(_magic, &buffer[0]); - encode32(_size, &buffer[4]); + encode32(_dataSize, &buffer[4]); } private: @@ -78,9 +77,8 @@ class Header } static const uint32_t _magic = 0xdeadbeef; - static const uint32_t _maxSize = 65536*32; - uint32_t _size; + uint32_t _dataSize; }; diff --git a/remote/server/AudioCollectionRequestHandler.cpp b/remote/server/AudioCollectionRequestHandler.cpp index 18a787d0..e1220874 100644 --- a/remote/server/AudioCollectionRequestHandler.cpp +++ b/remote/server/AudioCollectionRequestHandler.cpp @@ -290,9 +290,25 @@ AudioCollectionRequestHandler::processGetCoverArt(const AudioCollectionRequest:: break; case AudioCollectionRequest::GetCoverArt::TypeGetCoverArtTrack: - std::cerr << "TODO AudioCollectionRequest::GetCoverArt::TypeGetCoverArtTrack" < coverArts = CoverArt::Grabber::getFromTrack(track); + + BOOST_FOREACH(const CoverArt::CoverArt& coverArt, coverArts) + { + AudioCollectionResponse_CoverArt* cover_art = response.add_cover_art(); + + cover_art->set_mime_type(coverArt.getMimeType()); + cover_art->set_data( std::string( coverArt.getData().begin(), coverArt.getData().end()) ); + } + } + res = true; + break; } return res; diff --git a/remote/server/Connection.cpp b/remote/server/Connection.cpp index 319d94c3..0737f8fa 100644 --- a/remote/server/Connection.cpp +++ b/remote/server/Connection.cpp @@ -84,11 +84,11 @@ Connection::handleReadHeader(const boost::system::error_code& error, std::size_t } // Now read the real message - boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(header.getSize()); + boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(header.getDataSize()); boost::asio::async_read(_socket, bufs, - boost::asio::transfer_exactly(header.getSize()), + boost::asio::transfer_exactly(header.getDataSize()), boost::bind(&Connection::handleReadMsg, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); @@ -138,10 +138,17 @@ Connection::handleReadMsg(const boost::system::error_code& error, std::size_t by return; } + if (_outputStreamBuf.size() >= Remote::Header::max_data_size) + { + std::cerr << "output message is too big! " << _outputStreamBuf.size() << " > " << Remote::Header::max_data_size << std::endl; + _connectionManager.stop(shared_from_this()); + return; + } + std::array headerBuffer; { Remote::Header header; - header.setSize(_outputStreamBuf.size()); + header.setDataSize(_outputStreamBuf.size()); header.to_buffer(headerBuffer); } diff --git a/test/RemoteClientServer.cpp b/test/RemoteClientServer.cpp index c2407ae9..6b43d283 100644 --- a/test/RemoteClientServer.cpp +++ b/test/RemoteClientServer.cpp @@ -364,6 +364,36 @@ class TestClient mediaTerminate(); } + void getCoverTrack(std::vector& coverArt, uint64_t trackId) + { + // Send request + Remote::ClientMessage request; + + request.set_type( Remote::ClientMessage::AudioCollectionRequest ); + + request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest::TypeGetCoverArt); + request.mutable_audio_collection_request()->mutable_get_cover_art()->set_type( Remote::AudioCollectionRequest::GetCoverArt::TypeGetCoverArtTrack); + request.mutable_audio_collection_request()->mutable_get_cover_art()->set_track_id( trackId ); + sendMsg(request); + + // Receive responses + Remote::ServerMessage response; + recvMsg(response); + + // Process message + if (!response.has_audio_collection_response()) + throw std::runtime_error("not an audio_collection_response!"); + + for (int i = 0; i < response.audio_collection_response().cover_art_size(); ++i) + { + CoverArt cover; + cover.mimeType = response.audio_collection_response().cover_art(i).mime_type(); + cover.data.assign(response.audio_collection_response().cover_art(i).data().begin(), response.audio_collection_response().cover_art(i).data().end());; + + coverArt.push_back(cover); + } + } + void getCoverRelease(std::vector& coverArt, uint64_t releaseId) { // Send request @@ -536,13 +566,20 @@ class TestClient // Serialize message if (message.SerializeToOstream(&os)) { + + if (_outputStreamBuf.size() > Remote::Header::max_data_size) + { + std::ostringstream oss; oss << "Message too big = " << _outputStreamBuf.size() << " bytes! (max is " << Remote::Header::max_data_size << ")" << std::endl; + throw std::runtime_error("Message to big!"); + } + // Send message header std::array headerBuffer; // Generate header content { Remote::Header header; - header.setSize(_outputStreamBuf.size()); + header.setDataSize(_outputStreamBuf.size()); header.to_buffer(headerBuffer); } @@ -589,13 +626,13 @@ class TestClient // Read in a stream buffer { // reserve bytes in output sequence - boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(header.getSize()); + boost::asio::streambuf::mutable_buffers_type bufs = _inputStreamBuf.prepare(header.getDataSize()); std::size_t n = boost::asio::read(_socket, bufs, - boost::asio::transfer_exactly(header.getSize())); + boost::asio::transfer_exactly(header.getDataSize())); - assert(n == header.getSize()); + assert(n == header.getDataSize()); _inputStreamBuf.commit(n); if (!message.ParseFromIstream(&is)) @@ -648,23 +685,15 @@ int main() // **** Releases ****** std::vector releases; - client.getReleases(releases, std::vector(1, 1162)); + client.getReleases(releases, std::vector()); BOOST_FOREACH(const ReleaseInfo& release, releases) std::cout << "Release: '" << release << "'" << std::endl; - { - std::vector releases; - client.getReleases(releases, std::vector()); - BOOST_FOREACH(const ReleaseInfo& release, releases) - std::cout << "Release: '" << release << "'" << std::endl; - } // **** Tracks ****** - { - std::vector tracks; - client.getTracks(tracks, std::vector(), std::vector(), std::vector()); - BOOST_FOREACH(const TrackInfo& track, tracks) - std::cout << "Track: '" << track << "'" << std::endl; - } + std::vector tracks; + client.getTracks(tracks, std::vector(), std::vector(), std::vector()); + BOOST_FOREACH(const TrackInfo& track, tracks) + std::cout << "Track: '" << track << "'" << std::endl; // Caution: long test! /* if (extendedTests) @@ -684,7 +713,6 @@ int main() // ***** Covers ******* if (extendedTests) { - BOOST_FOREACH(const ReleaseInfo& release, releases) { std::vector coverArt; @@ -692,6 +720,15 @@ int main() std::cout << "Release '" << release << "', spotted " << coverArt.size() << " covers!" << std::endl; } + + BOOST_FOREACH(const TrackInfo& track, tracks) + { + std::vector coverArt; + client.getCoverTrack(coverArt, track.id); + + std::cout << "Track '" << track << "', spotted " << coverArt.size() << " covers!" << std::endl; + } + } // ****** Transcode test ********