preparing for loading photos from local in other thread

This commit is contained in:
John Preston 2015-09-29 18:29:21 +03:00
parent d5e5ef2d26
commit 592e3f7ae2
9 changed files with 168 additions and 114 deletions

View File

@ -327,29 +327,6 @@ inline bool operator!=(const FileLocation &a, const FileLocation &b) {
return !(a == b);
}
enum LocationType {
UnknownFileLocation = 0,
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
};
inline LocationType mtpToLocationType(mtpTypeId type) {
switch (type) {
case mtpc_inputDocumentFileLocation: return DocumentFileLocation;
case mtpc_inputAudioFileLocation: return AudioFileLocation;
case mtpc_inputVideoFileLocation: return VideoFileLocation;
default: return UnknownFileLocation;
}
}
inline mtpTypeId mtpFromLocationType(LocationType type) {
switch (type) {
case DocumentFileLocation: return mtpc_inputDocumentFileLocation;
case AudioFileLocation: return mtpc_inputAudioFileLocation;
case VideoFileLocation: return mtpc_inputVideoFileLocation;
case UnknownFileLocation:
default: return 0;
}
}
typedef QPair<uint64, uint64> MediaKey;
inline uint64 mediaMix32To64(int32 a, int32 b) {
return (uint64(*reinterpret_cast<uint32*>(&a)) << 32) | uint64(*reinterpret_cast<uint32*>(&b));

View File

@ -2272,6 +2272,14 @@ namespace Local {
}
}
bool startImageLoad(const StorageKey &location) {
StorageMap::iterator j = _imagesMap.find(location);
if (j == _imagesMap.cend()) {
return false;
}
return true;
}
StorageImageSaved readImage(const StorageKey &location) {
StorageMap::iterator j = _imagesMap.find(location);
if (j == _imagesMap.cend()) {
@ -2325,6 +2333,14 @@ namespace Local {
}
}
bool startStickerImageLoad(const StorageKey &location) {
StorageMap::iterator j = _stickerImagesMap.find(location);
if (j == _stickerImagesMap.cend()) {
return false;
}
return true;
}
QByteArray readStickerImage(const StorageKey &location) {
StorageMap::iterator j = _stickerImagesMap.find(location);
if (j == _stickerImagesMap.cend()) {
@ -2377,6 +2393,14 @@ namespace Local {
}
}
bool startAudioLoad(const StorageKey &location) {
StorageMap::iterator j = _audiosMap.find(location);
if (j == _audiosMap.cend()) {
return false;
}
return true;
}
QByteArray readAudio(const StorageKey &location) {
StorageMap::iterator j = _audiosMap.find(location);
if (j == _audiosMap.cend()) {

View File

@ -120,16 +120,19 @@ namespace Local {
void writeImage(const StorageKey &location, const ImagePtr &img);
void writeImage(const StorageKey &location, const StorageImageSaved &jpeg, bool overwrite = true);
bool startImageLoad(const StorageKey &location);
StorageImageSaved readImage(const StorageKey &location);
int32 hasImages();
qint64 storageImagesSize();
void writeStickerImage(const StorageKey &location, const QByteArray &data, bool overwrite = true);
bool startStickerImageLoad(const StorageKey &location);
QByteArray readStickerImage(const StorageKey &location);
int32 hasStickers();
qint64 storageStickersSize();
void writeAudio(const StorageKey &location, const QByteArray &data, bool overwrite = true);
bool startAudioLoad(const StorageKey &location);
QByteArray readAudio(const StorageKey &location);
int32 hasAudios();
qint64 storageAudiosSize();

View File

@ -45,8 +45,9 @@ namespace {
}
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size) : prev(0), next(0),
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), locationType(0), volume(volume), local(local), secret(secret),
priority(0), inQueue(false), complete(false),
_localStatus(LocalNotTried), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), _locationType(UnknownFileLocation), volume(volume), local(local), secret(secret),
id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown) {
LoaderQueues::iterator i = queues.find(dc);
if (i == queues.cend()) {
@ -55,20 +56,10 @@ id(0), access(0), fileIsOpen(false), size(size), type(mtpc_storage_fileUnknown)
queue = &i.value();
}
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size) : prev(0), next(0),
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), locationType(locType), volume(0), local(0), secret(0),
id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(false), size(size), type(mtpc_storage_fileUnknown) {
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
if (i == queues.cend()) {
i = queues.insert(MTP::dld[0] + dc, mtpFileLoaderQueue());
}
queue = &i.value();
}
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata) : prev(0), next(0),
priority(0), inQueue(false), complete(false), triedLocal(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), locationType(locType), volume(0), local(0), secret(0),
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata) : prev(0), next(0),
priority(0), inQueue(false), complete(false),
_localStatus(LocalNotTried), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
dc(dc), _locationType(type), volume(0), local(0), secret(0),
id(id), access(access), file(to), fname(to), fileIsOpen(false), duplicateInData(todata), size(size), type(mtpc_storage_fileUnknown) {
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
if (i == queues.cend()) {
@ -150,11 +141,20 @@ bool mtpFileLoader::loadPart() {
int32 limit = DocumentDownloadPartSize;
MTPInputFileLocation loc;
switch (locationType) {
case 0: loc = MTP_inputFileLocation(MTP_long(volume), MTP_int(local), MTP_long(secret)); limit = DownloadPartSize; break;
case mtpc_inputVideoFileLocation: loc = MTP_inputVideoFileLocation(MTP_long(id), MTP_long(access)); break;
case mtpc_inputAudioFileLocation: loc = MTP_inputAudioFileLocation(MTP_long(id), MTP_long(access)); break;
case mtpc_inputDocumentFileLocation: loc = MTP_inputDocumentFileLocation(MTP_long(id), MTP_long(access)); break;
switch (_locationType) {
case UnknownFileLocation:
loc = MTP_inputFileLocation(MTP_long(volume), MTP_int(local), MTP_long(secret));
limit = DownloadPartSize;
break;
case VideoFileLocation:
loc = MTP_inputVideoFileLocation(MTP_long(id), MTP_long(access));
break;
case AudioFileLocation:
loc = MTP_inputAudioFileLocation(MTP_long(id), MTP_long(access));
break;
case DocumentFileLocation:
loc = MTP_inputDocumentFileLocation(MTP_long(id), MTP_long(access));
break;
default:
finishFail();
return false;
@ -188,7 +188,7 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
Requests::iterator i = requests.find(req);
if (i == requests.cend()) return loadNext();
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
int32 dcIndex = i.value();
_dataRequested[dc].v[dcIndex] -= limit;
@ -254,24 +254,26 @@ void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRe
App::app()->killDownloadSessionsStart(dc);
}
if (!locationType && triedLocal && (fname.isEmpty() || duplicateInData)) {
Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(mtpToStorageType(type), data));
} else if (locationType && triedLocal) {
if (!fname.isEmpty()) {
Local::writeFileLocation(mediaKey(mtpToLocationType(locationType), dc, id), FileLocation(mtpToStorageType(type), fname));
}
if (duplicateInData) {
if (locationType == mtpc_inputDocumentFileLocation) {
Local::writeStickerImage(mediaKey(mtpToLocationType(locationType), dc, id), data);
} else if (locationType == mtpc_inputAudioFileLocation) {
Local::writeAudio(mediaKey(mtpToLocationType(locationType), dc, id), data);
if (_localStatus == LocalNotFound || _localStatus == LocalFailed) {
if (_locationType != UnknownFileLocation) { // audio, video, document
MediaKey mkey = mediaKey(_locationType, dc, id);
if (!fname.isEmpty()) {
Local::writeFileLocation(mkey, FileLocation(mtpToStorageType(type), fname));
}
if (duplicateInData) {
if (_locationType == DocumentFileLocation) {
Local::writeStickerImage(mkey, data);
} else if (_locationType == AudioFileLocation) {
Local::writeAudio(mkey, data);
}
}
} else {
Local::writeImage(storageKey(dc, volume, local), StorageImageSaved(mtpToStorageType(type), data));
}
}
}
emit progress(this);
loadNext();
// LOG(("Part loaded, handle time: %1").arg(getms() - ms));
}
bool mtpFileLoader::partFailed(const RPCError &error) {
@ -303,54 +305,65 @@ void mtpFileLoader::pause() {
removeFromQueue();
}
void mtpFileLoader::start(bool loadFirst, bool prior) {
if (complete) return;
if (!triedLocal) {
if (!locationType) {
triedLocal = true;
StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local));
if (cached.type != StorageFileUnknown) {
data = cached.data;
type = mtpFromStorageType(cached.type);
}
} else if (locationType) {
if (!fname.isEmpty()) {
triedLocal = true;
}
if (duplicateInData) {
if (locationType == mtpc_inputDocumentFileLocation) {
triedLocal = true;
data = Local::readStickerImage(mediaKey(mtpToLocationType(locationType), dc, id));
if (!data.isEmpty()) type = mtpc_storage_filePartial;
} else if (locationType == mtpc_inputAudioFileLocation) {
triedLocal = true;
data = Local::readAudio(mediaKey(mtpToLocationType(locationType), dc, id));
if (!data.isEmpty()) type = mtpc_storage_filePartial;
}
}
bool mtpFileLoader::tryLoadLocal() {
if (_localStatus == LocalNotFound || _localStatus == LocalLoaded || _localStatus == LocalFailed) {
return false;
}
if (_localStatus == LocalLoading) {
return true;
}
if (_locationType == UnknownFileLocation) {
StorageImageSaved cached = Local::readImage(storageKey(dc, volume, local));
if (cached.type != StorageFileUnknown) {
data = cached.data;
type = mtpFromStorageType(cached.type);
}
if (triedLocal && !data.isEmpty()) {
if (!fname.isEmpty() && duplicateInData) {
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
if (!fileIsOpen) {
return finishFail();
}
if (file.write(data) != qint64(data.size())) {
return finishFail();
}
} else {
if (duplicateInData) {
MediaKey mkey = mediaKey(_locationType, dc, id);
if (_locationType == DocumentFileLocation) {
data = Local::readStickerImage(mkey);
if (!data.isEmpty()) type = mtpc_storage_filePartial;
} else if (_locationType == AudioFileLocation) {
data = Local::readAudio(mkey);
if (!data.isEmpty()) type = mtpc_storage_filePartial;
}
complete = true;
if (fileIsOpen) {
file.close();
fileIsOpen = false;
psPostprocessFile(QFileInfo(file).absoluteFilePath());
}
emit App::wnd()->imageLoaded();
emit progress(this);
return loadNext();
}
}
if (data.isEmpty()) {
_localStatus = LocalNotFound;
return false;
}
_localStatus = LocalLoaded;
if (!fname.isEmpty() && duplicateInData) {
if (!fileIsOpen) fileIsOpen = file.open(QIODevice::WriteOnly);
if (!fileIsOpen) {
finishFail();
return true;
}
if (file.write(data) != qint64(data.size())) {
finishFail();
return true;
}
}
complete = true;
if (fileIsOpen) {
file.close();
fileIsOpen = false;
psPostprocessFile(QFileInfo(file).absoluteFilePath());
}
emit App::wnd()->imageLoaded();
emit progress(this);
loadNext();
return true;
}
void mtpFileLoader::start(bool loadFirst, bool prior) {
if (complete || tryLoadLocal()) return;
if (!fname.isEmpty() && !duplicateInData && !fileIsOpen) {
fileIsOpen = file.open(QIODevice::WriteOnly);
if (!fileIsOpen) {
@ -464,7 +477,7 @@ void mtpFileLoader::cancel() {
void mtpFileLoader::cancelRequests() {
if (requests.isEmpty()) return;
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
int32 limit = (_locationType == UnknownFileLocation) ? DownloadPartSize : DocumentDownloadPartSize;
DataRequested &dr(_dataRequested[dc]);
for (Requests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
MTP::cancel(i.key());

View File

@ -21,6 +21,38 @@ namespace MTP {
void clearLoaderPriorities();
}
enum LocationType {
UnknownFileLocation = 0,
DocumentFileLocation = 0x4e45abe9, // mtpc_inputDocumentFileLocation
AudioFileLocation = 0x74dc404d, // mtpc_inputAudioFileLocation
VideoFileLocation = 0x3d0364ec, // mtpc_inputVideoFileLocation
};
inline LocationType mtpToLocationType(mtpTypeId type) {
switch (type) {
case mtpc_inputDocumentFileLocation: return DocumentFileLocation;
case mtpc_inputAudioFileLocation: return AudioFileLocation;
case mtpc_inputVideoFileLocation: return VideoFileLocation;
default: return UnknownFileLocation;
}
}
inline mtpTypeId mtpFromLocationType(LocationType type) {
switch (type) {
case DocumentFileLocation: return mtpc_inputDocumentFileLocation;
case AudioFileLocation: return mtpc_inputAudioFileLocation;
case VideoFileLocation: return mtpc_inputVideoFileLocation;
case UnknownFileLocation:
default: return 0;
}
}
enum LocalLoadStatus {
LocalNotTried,
LocalNotFound,
LocalLoading,
LocalLoaded,
LocalFailed,
};
struct mtpFileLoaderQueue;
class mtpFileLoader : public QObject, public RPCSender {
Q_OBJECT
@ -28,8 +60,7 @@ class mtpFileLoader : public QObject, public RPCSender {
public:
mtpFileLoader(int32 dc, const uint64 &volume, int32 local, const uint64 &secret, int32 size = 0);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata);
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, LocationType type, const QString &to, int32 size, bool todata = false);
bool done() const;
mtpTypeId fileType() const;
const QByteArray &bytes() const;
@ -60,8 +91,10 @@ signals:
private:
mtpFileLoaderQueue *queue;
bool inQueue, complete, triedLocal;
bool inQueue, complete;
LocalLoadStatus _localStatus;
bool tryLoadLocal();
void cancelRequests();
typedef QMap<mtpRequestId, int32> Requests;
@ -80,7 +113,7 @@ private:
bool partFailed(const RPCError &error);
int32 dc;
mtpTypeId locationType; // 0 or mtpc_inputVideoFileLocation / mtpc_inputAudioFileLocation / mtpc_inputDocumentFileLocation
LocationType _locationType;
uint64 volume; // for photo locations
int32 local;

View File

@ -646,7 +646,7 @@ id(id), access(access), date(date), duration(duration), w(w), h(h), thumb(thumb)
void VideoData::save(const QString &toFile) {
cancel(true);
loader = new mtpFileLoader(dc, id, access, mtpc_inputVideoFileLocation, toFile, size);
loader = new mtpFileLoader(dc, id, access, VideoFileLocation, toFile, size);
loader->connect(loader, SIGNAL(progress(mtpFileLoader*)), App::main(), SLOT(videoLoadProgress(mtpFileLoader*)));
loader->connect(loader, SIGNAL(failed(mtpFileLoader*, bool)), App::main(), SLOT(videoLoadFailed(mtpFileLoader*, bool)));
loader->start();
@ -754,7 +754,7 @@ id(id), access(access), date(date), mime(mime), duration(duration), dc(dc), size
void AudioData::save(const QString &toFile) {
cancel(true);
loader = new mtpFileLoader(dc, id, access, mtpc_inputAudioFileLocation, toFile, size, (size < AudioVoiceMsgInMemory));
loader = new mtpFileLoader(dc, id, access, AudioFileLocation, toFile, size, (size < AudioVoiceMsgInMemory));
loader->connect(loader, SIGNAL(progress(mtpFileLoader*)), App::main(), SLOT(audioLoadProgress(mtpFileLoader*)));
loader->connect(loader, SIGNAL(failed(mtpFileLoader*, bool)), App::main(), SLOT(audioLoadFailed(mtpFileLoader*, bool)));
loader->start();
@ -940,7 +940,7 @@ void DocumentData::setattributes(const QVector<MTPDocumentAttribute> &attributes
void DocumentData::save(const QString &toFile) {
cancel(true);
bool isSticker = (type == StickerDocument) && (dimensions.width() > 0) && (dimensions.height() > 0) && (size < StickerInMemory);
loader = new mtpFileLoader(dc, id, access, mtpc_inputDocumentFileLocation, toFile, size, isSticker);
loader = new mtpFileLoader(dc, id, access, DocumentFileLocation, toFile, size, isSticker);
loader->connect(loader, SIGNAL(progress(mtpFileLoader*)), App::main(), SLOT(documentLoadProgress(mtpFileLoader*)));
loader->connect(loader, SIGNAL(failed(mtpFileLoader*, bool)), App::main(), SLOT(documentLoadFailed(mtpFileLoader*, bool)));
loader->start();

View File

@ -94,7 +94,6 @@ TitleWidget::TitleWidget(Window *window)
void TitleWidget::paintEvent(QPaintEvent *e) {
QPainter p(this);
LOG(("TITLE"));
p.fillRect(QRect(0, 0, width(), st::titleHeight), st::titleBG->b);
if (!_cancel.isHidden()) {
p.setPen(st::titleTextButton.color->p);

View File

@ -7,13 +7,11 @@
<key>CFBundleGetInfoString</key>
<string>Telegram Desktop messaging app</string>
<key>CFBundleIdentifier</key>
<string>com.tdesktop.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.9.2</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -31,6 +29,8 @@
</array>
</dict>
</array>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NOTE</key>
<string></string>
<key>NSPrincipalClass</key>

View File

@ -1340,7 +1340,7 @@
6DB9C3763D02B1415CD9D565 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
LastUpgradeCheck = 0700;
TargetAttributes = {
7CCA95B9FCAD34D929431AD6 = {
DevelopmentTeam = 63FLR8MQA9;
@ -1703,6 +1703,7 @@
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
OBJROOT = ./../Mac/DebugIntermediate;
PRODUCT_BUNDLE_IDENTIFIER = "com.tdesktop.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "Meta Compile";
QT_LIBRARY_SUFFIX = _debug;
SDKROOT = macosx;
@ -1721,6 +1722,7 @@
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
LLVM_LTO = YES;
OBJROOT = ./../Mac/ReleaseIntermediate;
PRODUCT_BUNDLE_IDENTIFIER = "com.tdesktop.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "Meta Compile";
QT_LIBRARY_SUFFIX = "";
SDKROOT = macosx;
@ -1880,6 +1882,7 @@
DYLIB_COMPATIBILITY_VERSION = 0.9;
DYLIB_CURRENT_VERSION = 0.9.2;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO;
@ -2005,6 +2008,7 @@
LLVM_LTO = YES;
MACOSX_DEPLOYMENT_TARGET = 10.8;
OBJROOT = ./../Mac/ReleaseIntermediate;
PRODUCT_BUNDLE_IDENTIFIER = "com.tdesktop.$(PRODUCT_NAME:rfc1034identifier)";
QT_LIBRARY_SUFFIX = "";
SDKROOT = macosx;
SYMROOT = ./../Mac;
@ -2020,6 +2024,7 @@
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
MACOSX_DEPLOYMENT_TARGET = 10.8;
OBJROOT = ./../Mac/DebugIntermediate;
PRODUCT_BUNDLE_IDENTIFIER = "com.tdesktop.$(PRODUCT_NAME:rfc1034identifier)";
QT_LIBRARY_SUFFIX = _debug;
SDKROOT = macosx;
SYMROOT = ./../Mac;