Support streaming of local files.

This commit is contained in:
John Preston 2019-03-04 16:26:29 +04:00
parent 2e824ace00
commit c27456277e
5 changed files with 147 additions and 9 deletions

View File

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "core/application.h"
#include "media/streaming/media_streaming_loader_mtproto.h"
#include "media/streaming/media_streaming_loader_local.h"
namespace {
@ -1214,14 +1215,14 @@ bool DocumentData::inappPlaybackFailed() const {
auto DocumentData::createStreamingLoader(Data::FileOrigin origin) const
-> std::unique_ptr<Media::Streaming::Loader> {
// #TODO streaming create local file loader
//auto &location = this->location(true);
//if (!_doc->data().isEmpty()) {
// initStreaming();
//} else if (location.accessEnable()) {
// initStreaming();
// location.accessDisable();
//}
const auto &location = this->location(true);
if (!data().isEmpty()) {
return Media::Streaming::MakeBytesLoader(data());
} else if (!location.isEmpty() && location.accessEnable()) {
auto result = Media::Streaming::MakeFileLoader(location.name());
location.accessDisable();
return result;
}
return hasRemoteLocation()
? std::make_unique<Media::Streaming::LoaderMtproto>(
&session().api(),
@ -1590,7 +1591,7 @@ void HandleUnsupportedMedia(
not_null<DocumentData*> document,
FullMsgId contextId) {
document->setInappPlaybackFailed();
auto filepath = document->filepath(
const auto filepath = document->filepath(
DocumentData::FilePathResolveSaveFromData);
if (filepath.isEmpty()) {
const auto save = [=] {

View File

@ -0,0 +1,83 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "media/streaming/media_streaming_loader_local.h"
#include "storage/cache/storage_cache_types.h"
namespace Media {
namespace Streaming {
LoaderLocal::LoaderLocal(std::unique_ptr<QIODevice> device)
: _device(std::move(device)) {
Expects(_device != nullptr);
if (!_device->open(QIODevice::ReadOnly)) {
fail();
}
}
std::optional<Storage::Cache::Key> LoaderLocal::baseCacheKey() const {
return std::nullopt;
}
int LoaderLocal::size() const {
return _device->size();
}
void LoaderLocal::load(int offset) {
if (_device->pos() != offset && !_device->seek(offset)) {
fail();
return;
}
auto result = _device->read(kPartSize);
if (result.isEmpty()
|| ((result.size() != kPartSize)
&& (offset + result.size() != size()))) {
fail();
return;
}
crl::on_main(this, [=, result = std::move(result)]() mutable {
_parts.fire({ offset, std::move(result) });
});
}
void LoaderLocal::fail() {
crl::on_main(this, [=] {
_parts.fire({ LoadedPart::kFailedOffset });
});
}
void LoaderLocal::cancel(int offset) {
}
void LoaderLocal::increasePriority() {
}
void LoaderLocal::stop() {
}
rpl::producer<LoadedPart> LoaderLocal::parts() const {
return _parts.events();
}
std::unique_ptr<LoaderLocal> MakeFileLoader(const QString &path) {
return std::make_unique<LoaderLocal>(std::make_unique<QFile>(path));
}
std::unique_ptr<LoaderLocal> MakeBytesLoader(const QByteArray &bytes) {
auto device = std::make_unique<QBuffer>();
auto copy = new QByteArray(bytes);
QObject::connect(device.get(), &QBuffer::destroyed, [=] {
delete copy;
});
device->setBuffer(copy);
return std::make_unique<LoaderLocal>(std::move(device));
}
} // namespace Streaming
} // namespace Media

View File

@ -0,0 +1,47 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "media/streaming/media_streaming_loader.h"
#include "mtproto/sender.h"
#include "data/data_file_origin.h"
class ApiWrap;
namespace Media {
namespace Streaming {
class LoaderLocal : public Loader, public base::has_weak_ptr {
public:
LoaderLocal(std::unique_ptr<QIODevice> device);
[[nodiscard]] auto baseCacheKey() const
->std::optional<Storage::Cache::Key> override;
[[nodiscard]] int size() const override;
void load(int offset) override;
void cancel(int offset) override;
void increasePriority() override;
void stop() override;
// Parts will be sent from the main thread.
[[nodiscard]] rpl::producer<LoadedPart> parts() const override;
private:
void fail();
std::unique_ptr<QIODevice> _device;
rpl::event_stream<LoadedPart> _parts;
};
std::unique_ptr<LoaderLocal> MakeFileLoader(const QString &path);
std::unique_ptr<LoaderLocal> MakeBytesLoader(const QByteArray &bytes);
} // namespace Streaming
} // namespace Media

View File

@ -1895,6 +1895,11 @@ void OverlayWidget::initStreamingThumbnail() {
const auto thumb = _doc->thumbnail();
const auto useThumb = (thumb && thumb->loaded());
const auto blurred = _doc->thumbnailInline();
if (good && !useGood) {
good->load({});
} else if (thumb && !useThumb) {
thumb->load(fileOrigin());
}
if (!useGood && !thumb && !blurred) {
return;
} else if (_doc->dimensions.isEmpty()) {

View File

@ -460,6 +460,8 @@
<(src_loc)/media/streaming/media_streaming_file_delegate.h
<(src_loc)/media/streaming/media_streaming_loader.cpp
<(src_loc)/media/streaming/media_streaming_loader.h
<(src_loc)/media/streaming/media_streaming_loader_local.cpp
<(src_loc)/media/streaming/media_streaming_loader_local.h
<(src_loc)/media/streaming/media_streaming_loader_mtproto.cpp
<(src_loc)/media/streaming/media_streaming_loader_mtproto.h
<(src_loc)/media/streaming/media_streaming_player.cpp