mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-31 11:35:24 +01:00
Precache the first and last parts of Google Drive MP3s to reduce the
number of requests when using accurate tagging.
This commit is contained in:
parent
fd1d70c644
commit
08286102da
@ -25,7 +25,11 @@
|
||||
|
||||
#include <taglib/id3v2framefactory.h>
|
||||
#include <taglib/mpegfile.h>
|
||||
using TagLib::ByteVector;
|
||||
|
||||
namespace {
|
||||
static const int kTaglibPrefixCacheBytes = 64 * 1024; // Should be enough.
|
||||
static const int kTaglibSuffixCacheBytes = 2 * 1024;
|
||||
}
|
||||
|
||||
GoogleDriveStream::GoogleDriveStream(
|
||||
const QUrl& url, const QString& filename, const long length,
|
||||
@ -37,7 +41,8 @@ GoogleDriveStream::GoogleDriveStream(
|
||||
auth_(auth),
|
||||
cursor_(0),
|
||||
network_(network),
|
||||
cache_(length) {
|
||||
cache_(length),
|
||||
num_requests_(0) {
|
||||
}
|
||||
|
||||
TagLib::FileName GoogleDriveStream::name() const {
|
||||
@ -68,6 +73,25 @@ TagLib::ByteVector GoogleDriveStream::GetCached(int start, int end) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GoogleDriveStream::Precache() {
|
||||
// For reading the tags of an MP3, TagLib tends to request:
|
||||
// 1. The first 1024 bytes
|
||||
// 2. Somewhere between the first 2KB and first 60KB
|
||||
// 3. The last KB or two.
|
||||
// 4. Somewhere in the first 64KB again
|
||||
//
|
||||
// So, if we precache the first 64KB and the last 2KB we should be sorted :-)
|
||||
// Ideally, we would use bytes=0-655364,-2048 but Google Drive does not seem
|
||||
// to support multipart byte ranges yet so we have to make do with two
|
||||
// requests.
|
||||
|
||||
seek(0, TagLib::IOStream::Beginning);
|
||||
readBlock(kTaglibPrefixCacheBytes);
|
||||
seek(kTaglibSuffixCacheBytes, TagLib::IOStream::End);
|
||||
readBlock(kTaglibSuffixCacheBytes);
|
||||
clear();
|
||||
}
|
||||
|
||||
TagLib::ByteVector GoogleDriveStream::readBlock(ulong length) {
|
||||
const uint start = cursor_;
|
||||
const uint end = qMin(cursor_ + length - 1, length_ - 1);
|
||||
@ -89,6 +113,7 @@ TagLib::ByteVector GoogleDriveStream::readBlock(ulong length) {
|
||||
"Range", QString("bytes=%1-%2").arg(start).arg(end).toUtf8());
|
||||
|
||||
QNetworkReply* reply = network_->get(request);
|
||||
++num_requests_;
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
@ -103,11 +128,11 @@ TagLib::ByteVector GoogleDriveStream::readBlock(ulong length) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void GoogleDriveStream::writeBlock(const ByteVector&) {
|
||||
void GoogleDriveStream::writeBlock(const TagLib::ByteVector&) {
|
||||
qLog(Debug) << Q_FUNC_INFO << "not implemented";
|
||||
}
|
||||
|
||||
void GoogleDriveStream::insert(const ByteVector&, ulong, ulong) {
|
||||
void GoogleDriveStream::insert(const TagLib::ByteVector&, ulong, ulong) {
|
||||
qLog(Debug) << Q_FUNC_INFO << "not implemented";
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,17 @@ class GoogleDriveStream : public TagLib::IOStream {
|
||||
virtual long length();
|
||||
virtual void truncate(long);
|
||||
|
||||
google::sparsetable<char>::size_type cached_bytes() const {
|
||||
return cache_.num_nonempty();
|
||||
}
|
||||
|
||||
int num_requests() const {
|
||||
return num_requests_;
|
||||
}
|
||||
|
||||
// Use educated guess to request the bytes that TagLib will probably want.
|
||||
void Precache();
|
||||
|
||||
private:
|
||||
bool CheckCache(int start, int end);
|
||||
void FillCache(int start, TagLib::ByteVector data);
|
||||
@ -63,6 +74,7 @@ class GoogleDriveStream : public TagLib::IOStream {
|
||||
QNetworkAccessManager* network_;
|
||||
|
||||
google::sparsetable<char> cache_;
|
||||
int num_requests_;
|
||||
};
|
||||
|
||||
#endif // GOOGLEDRIVESTREAM_H
|
||||
|
@ -616,10 +616,11 @@ void TagReaderWorker::ReadGoogleDrive(const QUrl& download_url,
|
||||
|
||||
GoogleDriveStream* stream = new GoogleDriveStream(
|
||||
download_url, title, size, access_token, network_);
|
||||
stream->Precache();
|
||||
TagLib::MPEG::File tag(
|
||||
stream, // Takes ownership.
|
||||
TagLib::ID3v2::FrameFactory::instance(),
|
||||
TagLib::AudioProperties::Fast);
|
||||
TagLib::AudioProperties::Accurate);
|
||||
if (tag.tag()) {
|
||||
song->set_title(tag.tag()->title().toCString(true));
|
||||
song->set_artist(tag.tag()->artist().toCString(true));
|
||||
@ -631,6 +632,10 @@ void TagReaderWorker::ReadGoogleDrive(const QUrl& download_url,
|
||||
if (tag.audioProperties()) {
|
||||
song->set_length_nanosec(tag.audioProperties()->length() * kNsecPerSec);
|
||||
}
|
||||
qLog(Debug) << "Google Drive Tagging Stats for:"
|
||||
<< song->title().c_str();
|
||||
qLog(Debug) << "Downloaded bytes:" << stream->cached_bytes()
|
||||
<< "Number of requests:" << stream->num_requests();
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GOOGLE_DRIVE
|
||||
|
Loading…
x
Reference in New Issue
Block a user