mirror of https://github.com/procxx/kepka.git
Use Media::Streaming in EditCaptionBox.
This commit is contained in:
parent
3d431a27cb
commit
581a21dbd9
|
@ -22,13 +22,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_photo.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_streaming.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "media/streaming/media_streaming_loader_local.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
|
@ -47,6 +52,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <QtCore/QMimeData>
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace ::Media::Streaming;
|
||||
|
||||
} // namespace
|
||||
|
||||
EditCaptionBox::EditCaptionBox(
|
||||
QWidget*,
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
@ -70,14 +81,13 @@ EditCaptionBox::EditCaptionBox(
|
|||
} else if (const auto document = media->document()) {
|
||||
_documentMedia = document->createMediaView();
|
||||
_documentMedia->thumbnailWanted(_msgId);
|
||||
// #TODO optimize + streamed GIF view
|
||||
image = _documentMedia->thumbnail();
|
||||
dimensions = image
|
||||
? image->size()
|
||||
: document->dimensions;
|
||||
if (document->isAnimation()) {
|
||||
_gifw = document->dimensions.width();
|
||||
_gifh = document->dimensions.height();
|
||||
_gifw = style::ConvertScale(document->dimensions.width());
|
||||
_gifh = style::ConvertScale(document->dimensions.height());
|
||||
_animated = true;
|
||||
} else if (document->isVideoFile()) {
|
||||
_animated = true;
|
||||
|
@ -161,7 +171,7 @@ EditCaptionBox::EditCaptionBox(
|
|||
maxW,
|
||||
maxH);
|
||||
};
|
||||
prepareGifPreview();
|
||||
prepareStreamedPreview();
|
||||
} else {
|
||||
maxW = dimensions.width();
|
||||
maxH = dimensions.height();
|
||||
|
@ -243,22 +253,25 @@ EditCaptionBox::EditCaptionBox(
|
|||
|
||||
_thumbnailImageLoaded = _thumbnailImage
|
||||
? _thumbnailImage->loaded()
|
||||
: _documentMedia
|
||||
? !_documentMedia->owner()->hasThumbnail()
|
||||
: true;
|
||||
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
||||
if (!_thumbnailImageLoaded
|
||||
&& _thumbnailImage
|
||||
&& _thumbnailImage->loaded()) {
|
||||
_thumbnailImageLoaded = true;
|
||||
_refreshThumbnail();
|
||||
update();
|
||||
}
|
||||
if (_documentMedia && _documentMedia->owner()->isAnimation()) {
|
||||
if (_documentMedia->loaded() && !_gifPreview) {
|
||||
prepareGifPreview();
|
||||
if (!_thumbnailImageLoaded) {
|
||||
subscribe(_controller->session().downloaderTaskFinished(), [=] {
|
||||
if (_thumbnailImageLoaded) {
|
||||
return;
|
||||
} else if (!_thumbnailImage
|
||||
&& _documentMedia
|
||||
&& _documentMedia->owner()->hasThumbnail()) {
|
||||
_thumbnailImage = _documentMedia->thumbnail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (_thumbnailImage && _thumbnailImage->loaded()) {
|
||||
_thumbnailImageLoaded = true;
|
||||
_refreshThumbnail();
|
||||
update();
|
||||
}
|
||||
});
|
||||
}
|
||||
_field.create(
|
||||
this,
|
||||
st::confirmCaptionArea,
|
||||
|
@ -293,6 +306,8 @@ EditCaptionBox::EditCaptionBox(
|
|||
}, _wayWrap->lifetime());
|
||||
}
|
||||
|
||||
EditCaptionBox::~EditCaptionBox() = default;
|
||||
|
||||
void EditCaptionBox::emojiFilterForGeometry(not_null<QEvent*> event) {
|
||||
const auto type = event->type();
|
||||
if (type == QEvent::Move || type == QEvent::Resize) {
|
||||
|
@ -311,78 +326,86 @@ void EditCaptionBox::updateEmojiPanelGeometry() {
|
|||
local.x() + _emojiToggle->width() * 3);
|
||||
}
|
||||
|
||||
void EditCaptionBox::prepareGifPreview() {
|
||||
void EditCaptionBox::prepareStreamedPreview() {
|
||||
const auto isListEmpty = _preparedList.files.empty();
|
||||
if (_gifPreview) {
|
||||
if (_streamed) {
|
||||
return;
|
||||
} else if (!_documentMedia && isListEmpty) {
|
||||
return;
|
||||
}
|
||||
const auto callback = [=](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
};
|
||||
if (_documentMedia && _documentMedia->owner()->isAnimation()) {
|
||||
if (_documentMedia->loaded()) {
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
_documentMedia.get(),
|
||||
_msgId,
|
||||
callback);
|
||||
}
|
||||
const auto document = _documentMedia
|
||||
? _documentMedia->owner().get()
|
||||
: nullptr;
|
||||
if (document && document->isAnimation()) {
|
||||
setupStreamedPreview(
|
||||
document->owner().streaming().sharedDocument(
|
||||
document,
|
||||
_msgId));
|
||||
} else if (!isListEmpty) {
|
||||
const auto file = &_preparedList.files.front();
|
||||
if (file->path.isEmpty()) {
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
file->content,
|
||||
callback);
|
||||
} else {
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
file->path,
|
||||
callback);
|
||||
}
|
||||
}
|
||||
if (_gifPreview) {
|
||||
_gifPreview->setAutoplay();
|
||||
auto loader = file->path.isEmpty()
|
||||
? MakeBytesLoader(file->content)
|
||||
: MakeFileLoader(file->path);
|
||||
setupStreamedPreview(std::make_shared<Document>(std::move(loader)));
|
||||
}
|
||||
}
|
||||
|
||||
void EditCaptionBox::clipCallback(Media::Clip::Notification notification) {
|
||||
using namespace Media::Clip;
|
||||
switch (notification) {
|
||||
case NotificationReinit: {
|
||||
if (_gifPreview && _gifPreview->state() == State::Error) {
|
||||
_gifPreview.setBad();
|
||||
}
|
||||
void EditCaptionBox::setupStreamedPreview(std::shared_ptr<Document> shared) {
|
||||
if (!shared) {
|
||||
return;
|
||||
}
|
||||
_streamed = std::make_unique<Instance>(
|
||||
std::move(shared),
|
||||
[=] { update(); });
|
||||
_streamed->lockPlayer();
|
||||
_streamed->player().updates(
|
||||
) | rpl::start_with_next_error([=](Update &&update) {
|
||||
handleStreamingUpdate(std::move(update));
|
||||
}, [=](Error &&error) {
|
||||
handleStreamingError(std::move(error));
|
||||
}, _streamed->lifetime());
|
||||
|
||||
if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) {
|
||||
const auto calculateGifDimensions = [&]() {
|
||||
const auto scaled = QSize(
|
||||
_gifPreview->width(),
|
||||
_gifPreview->height()).scaled(
|
||||
st::sendMediaPreviewSize * cIntRetinaFactor(),
|
||||
st::confirmMaxHeight * cIntRetinaFactor(),
|
||||
Qt::KeepAspectRatio);
|
||||
_thumbw = _gifw = scaled.width();
|
||||
_thumbh = _gifh = scaled.height();
|
||||
_thumbx = _gifx = (st::boxWideWidth - _gifw) / 2;
|
||||
updateBoxSize();
|
||||
};
|
||||
// If gif file is not mp4,
|
||||
// Its dimension values will be known only after reading.
|
||||
if (_gifw <= 0 || _gifh <= 0) {
|
||||
calculateGifDimensions();
|
||||
}
|
||||
const auto s = QSize(_gifw, _gifh);
|
||||
_gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, RectPart::None);
|
||||
}
|
||||
if (_streamed->ready()) {
|
||||
streamingReady(base::duplicate(_streamed->info()));
|
||||
}
|
||||
checkStreamedIsStarted();
|
||||
}
|
||||
|
||||
update();
|
||||
} break;
|
||||
void EditCaptionBox::handleStreamingUpdate(Update &&update) {
|
||||
update.data.match([&](Information &update) {
|
||||
streamingReady(std::move(update));
|
||||
}, [&](const PreloadedVideo &update) {
|
||||
}, [&](const UpdateVideo &update) {
|
||||
this->update();
|
||||
}, [&](const PreloadedAudio &update) {
|
||||
}, [&](const UpdateAudio &update) {
|
||||
}, [&](const WaitingForData &update) {
|
||||
}, [&](MutedByOther) {
|
||||
}, [&](Finished) {
|
||||
});
|
||||
}
|
||||
|
||||
case NotificationRepaint: {
|
||||
if (_gifPreview && !_gifPreview->currentDisplayed()) {
|
||||
update();
|
||||
}
|
||||
} break;
|
||||
void EditCaptionBox::handleStreamingError(Error &&error) {
|
||||
}
|
||||
|
||||
void EditCaptionBox::streamingReady(Information &&info) {
|
||||
const auto calculateGifDimensions = [&]() {
|
||||
const auto scaled = QSize(
|
||||
info.video.size.width(),
|
||||
info.video.size.height()
|
||||
).scaled(
|
||||
st::sendMediaPreviewSize * cIntRetinaFactor(),
|
||||
st::confirmMaxHeight * cIntRetinaFactor(),
|
||||
Qt::KeepAspectRatio);
|
||||
_thumbw = _gifw = scaled.width();
|
||||
_thumbh = _gifh = scaled.height();
|
||||
_thumbx = _gifx = (st::boxWideWidth - _gifw) / 2;
|
||||
updateBoxSize();
|
||||
};
|
||||
// If gif file is not mp4,
|
||||
// Its dimension values will be known only after reading.
|
||||
if (_gifw <= 0 || _gifh <= 0) {
|
||||
calculateGifDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +423,7 @@ void EditCaptionBox::updateEditPreview() {
|
|||
_animated = false;
|
||||
_photo = false;
|
||||
_doc = false;
|
||||
_gifPreview = nullptr;
|
||||
_streamed = nullptr;
|
||||
_thumbw = _thumbh = _thumbx = 0;
|
||||
_gifw = _gifh = _gifx = 0;
|
||||
|
||||
|
@ -479,7 +502,7 @@ void EditCaptionBox::updateEditPreview() {
|
|||
_gifw = _thumbw;
|
||||
_gifh = _thumbh;
|
||||
_gifx = _thumbx;
|
||||
prepareGifPreview();
|
||||
prepareStreamedPreview();
|
||||
}
|
||||
}
|
||||
updateEditMediaButton();
|
||||
|
@ -694,6 +717,31 @@ int EditCaptionBox::errorTopSkip() const {
|
|||
return (st::defaultBox.buttonPadding.top() / 2);
|
||||
}
|
||||
|
||||
void EditCaptionBox::checkStreamedIsStarted() {
|
||||
if (!_streamed) {
|
||||
return;
|
||||
}
|
||||
if (_streamed->paused()) {
|
||||
_streamed->resume();
|
||||
}
|
||||
if (!_streamed->active() && !_streamed->failed()) {
|
||||
startStreamedPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
void EditCaptionBox::startStreamedPlayer() {
|
||||
auto options = ::Media::Streaming::PlaybackOptions();
|
||||
options.audioId = _documentMedia
|
||||
? AudioMsgId(_documentMedia->owner(), _msgId)
|
||||
: AudioMsgId();
|
||||
options.waitForMarkAsShown = true;
|
||||
//if (!_streamed->withSound) {
|
||||
options.mode = ::Media::Streaming::Mode::Video;
|
||||
options.loop = true;
|
||||
//}
|
||||
_streamed->play(options);
|
||||
}
|
||||
|
||||
void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
||||
BoxContent::paintEvent(e);
|
||||
|
||||
|
@ -707,16 +755,27 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) {
|
|||
if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) {
|
||||
p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, th, st::confirmBg);
|
||||
}
|
||||
if (_gifPreview && _gifPreview->started()) {
|
||||
checkStreamedIsStarted();
|
||||
if (_streamed
|
||||
&& _streamed->player().ready()
|
||||
&& !_streamed->player().videoSize().isEmpty()) {
|
||||
const auto s = QSize(_gifw, _gifh);
|
||||
const auto paused = _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Layer);
|
||||
const auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, RectPart::None, paused ? 0 : crl::now());
|
||||
p.drawPixmap(_gifx, st::boxPhotoPadding.top(), frame);
|
||||
|
||||
auto request = ::Media::Streaming::FrameRequest();
|
||||
request.outer = s * cIntRetinaFactor();
|
||||
request.resize = s * cIntRetinaFactor();
|
||||
p.drawImage(
|
||||
QRect(_gifx, st::boxPhotoPadding.top(), _gifw, _gifh),
|
||||
_streamed->frame(request));
|
||||
if (!paused) {
|
||||
_streamed->markFrameShown();
|
||||
}
|
||||
} else {
|
||||
const auto offset = _gifh ? ((_gifh - _thumbh) / 2) : 0;
|
||||
p.drawPixmap(_thumbx, st::boxPhotoPadding.top() + offset, _thumb);
|
||||
}
|
||||
if (_animated && !_gifPreview) {
|
||||
if (_animated && !_streamed) {
|
||||
QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (th - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
|
|
@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/abstract_box.h"
|
||||
#include "storage/storage_media_prepare.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "mtproto/mtproto_rpc_sender.h"
|
||||
|
||||
namespace ChatHelpers {
|
||||
|
@ -37,6 +36,16 @@ namespace Window {
|
|||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
class Instance;
|
||||
class Document;
|
||||
struct Update;
|
||||
enum class Error;
|
||||
struct Information;
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
||||
|
||||
class EditCaptionBox
|
||||
: public Ui::BoxContent
|
||||
, public RPCSender
|
||||
|
@ -46,6 +55,7 @@ public:
|
|||
QWidget*,
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<HistoryItem*> item);
|
||||
~EditCaptionBox();
|
||||
|
||||
protected:
|
||||
void prepare() override;
|
||||
|
@ -57,8 +67,14 @@ protected:
|
|||
|
||||
private:
|
||||
void updateBoxSize();
|
||||
void prepareGifPreview();
|
||||
void clipCallback(Media::Clip::Notification notification);
|
||||
void prepareStreamedPreview();
|
||||
void checkStreamedIsStarted();
|
||||
void setupStreamedPreview(
|
||||
std::shared_ptr<::Media::Streaming::Document> shared);
|
||||
void handleStreamingUpdate(::Media::Streaming::Update &&update);
|
||||
void handleStreamingError(::Media::Streaming::Error &&error);
|
||||
void streamingReady(::Media::Streaming::Information &&info);
|
||||
void startStreamedPlayer();
|
||||
|
||||
void setupEmojiPanel();
|
||||
void updateEmojiPanelGeometry();
|
||||
|
@ -96,7 +112,7 @@ private:
|
|||
bool _doc = false;
|
||||
|
||||
QPixmap _thumb;
|
||||
Media::Clip::ReaderPointer _gifPreview;
|
||||
std::unique_ptr<::Media::Streaming::Instance> _streamed;
|
||||
|
||||
object_ptr<Ui::InputField> _field = { nullptr };
|
||||
object_ptr<Ui::EmojiButton> _emojiToggle = { nullptr };
|
||||
|
|
|
@ -888,7 +888,6 @@ void SingleMediaPreview::prepareAnimatedPreview(
|
|||
_gifPreview = Media::Clip::MakeReader(
|
||||
animatedPreviewPath,
|
||||
std::move(callback));
|
||||
if (_gifPreview) _gifPreview->setAutoplay();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,8 +66,8 @@ std::shared_ptr<Streaming::Reader> Streaming::sharedReader(
|
|||
return nullptr;
|
||||
}
|
||||
auto result = std::make_shared<Reader>(
|
||||
&_owner->cacheBigFile(),
|
||||
std::move(loader));
|
||||
std::move(loader),
|
||||
&_owner->cacheBigFile());
|
||||
if (!PruneDestroyedAndSet(_readers, document, result)) {
|
||||
_readers.emplace_or_assign(document, result);
|
||||
}
|
||||
|
|
|
@ -145,7 +145,6 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
|||
that->_gif = Media::Clip::MakeReader(_dataMedia.get(), FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
}
|
||||
|
||||
const auto animating = (_gif && _gif->started());
|
||||
|
@ -1360,7 +1359,6 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con
|
|||
that->_gif = Media::Clip::MakeReader(_dataMedia.get(), FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
}
|
||||
|
||||
bool animating = (_gif && _gif->started());
|
||||
|
|
|
@ -67,13 +67,6 @@ public:
|
|||
// Reader can be already deleted.
|
||||
static void callback(Reader *reader, qint32 threadIndex, qint32 notification);
|
||||
|
||||
void setAutoplay() {
|
||||
_autoplay = true;
|
||||
}
|
||||
bool autoplay() const {
|
||||
return _autoplay;
|
||||
}
|
||||
|
||||
AudioMsgId audioMsgId() const {
|
||||
return _audioMsgId;
|
||||
}
|
||||
|
@ -172,8 +165,6 @@ private:
|
|||
QAtomicInt _videoPauseRequest = 0;
|
||||
int32 _threadIndex;
|
||||
|
||||
bool _autoplay = false;
|
||||
|
||||
friend class Manager;
|
||||
|
||||
ReaderPrivate *_private = nullptr;
|
||||
|
|
|
@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/streaming/media_streaming_document.h"
|
||||
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_loader.h"
|
||||
#include "media/streaming/media_streaming_reader.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
|
@ -32,22 +34,29 @@ constexpr auto kGoodThumbnailQuality = 87;
|
|||
Document::Document(
|
||||
not_null<DocumentData*> document,
|
||||
std::shared_ptr<Reader> reader)
|
||||
: _player(&document->owner(), reader)
|
||||
: Document(std::move(reader), document) {
|
||||
_player.fullInCache(
|
||||
) | rpl::start_with_next([=](bool fullInCache) {
|
||||
_document->setLoadedInMediaCache(fullInCache);
|
||||
}, _player.lifetime());
|
||||
}
|
||||
|
||||
Document::Document(std::unique_ptr<Loader> loader)
|
||||
: Document(std::make_shared<Reader>(std::move(loader)), nullptr) {
|
||||
}
|
||||
|
||||
Document::Document(std::shared_ptr<Reader> reader, DocumentData *document)
|
||||
: _document(document)
|
||||
, _player(std::move(reader))
|
||||
, _radial(
|
||||
[=] { waitingCallback(); },
|
||||
st::defaultInfiniteRadialAnimation)
|
||||
, _document(document) {
|
||||
[=] { waitingCallback(); },
|
||||
st::defaultInfiniteRadialAnimation) {
|
||||
_player.updates(
|
||||
) | rpl::start_with_next_error([=](Update &&update) {
|
||||
handleUpdate(std::move(update));
|
||||
}, [=](Streaming::Error &&error) {
|
||||
handleError(std::move(error));
|
||||
}, _player.lifetime());
|
||||
|
||||
_player.fullInCache(
|
||||
) | rpl::start_with_next([=](bool fullInCache) {
|
||||
_document->setLoadedInMediaCache(fullInCache);
|
||||
}, _player.lifetime());
|
||||
}
|
||||
|
||||
Player &Document::player() {
|
||||
|
@ -62,9 +71,9 @@ const Information &Document::info() const {
|
|||
return _info;
|
||||
}
|
||||
|
||||
not_null<DocumentData*> Document::data() const {
|
||||
return _document;
|
||||
}
|
||||
//not_null<DocumentData*> Document::data() const {
|
||||
// return _document;
|
||||
//}
|
||||
|
||||
void Document::play(const PlaybackOptions &options) {
|
||||
_player.play(options);
|
||||
|
@ -145,10 +154,12 @@ void Document::handleUpdate(Update &&update) {
|
|||
}
|
||||
|
||||
void Document::handleError(Error &&error) {
|
||||
if (error == Error::NotStreamable) {
|
||||
_document->setNotSupportsStreaming();
|
||||
} else if (error == Error::OpenFailed) {
|
||||
_document->setInappPlaybackFailed();
|
||||
if (_document) {
|
||||
if (error == Error::NotStreamable) {
|
||||
_document->setNotSupportsStreaming();
|
||||
} else if (error == Error::OpenFailed) {
|
||||
_document->setInappPlaybackFailed();
|
||||
}
|
||||
}
|
||||
waitingChange(false);
|
||||
}
|
||||
|
@ -194,7 +205,9 @@ void Document::waitingChange(bool waiting) {
|
|||
}
|
||||
|
||||
void Document::validateGoodThumbnail() {
|
||||
if (_info.video.cover.isNull() || _document->goodThumbnailChecked()) {
|
||||
if (_info.video.cover.isNull()
|
||||
|| !_document
|
||||
|| _document->goodThumbnailChecked()) {
|
||||
return;
|
||||
}
|
||||
const auto document = _document;
|
||||
|
|
|
@ -18,12 +18,14 @@ namespace Media {
|
|||
namespace Streaming {
|
||||
|
||||
class Instance;
|
||||
class Loader;
|
||||
|
||||
class Document {
|
||||
public:
|
||||
Document(
|
||||
not_null<DocumentData*> document,
|
||||
std::shared_ptr<Reader> reader);
|
||||
explicit Document(std::unique_ptr<Loader> loader);
|
||||
|
||||
void play(const PlaybackOptions &options);
|
||||
void saveFrameToCover();
|
||||
|
@ -31,13 +33,15 @@ public:
|
|||
[[nodiscard]] Player &player();
|
||||
[[nodiscard]] const Player &player() const;
|
||||
[[nodiscard]] const Information &info() const;
|
||||
[[nodiscard]] not_null<DocumentData*> data() const;
|
||||
// [[nodiscard]] not_null<DocumentData*> data() const;
|
||||
|
||||
[[nodiscard]] bool waitingShown() const;
|
||||
[[nodiscard]] float64 waitingOpacity() const;
|
||||
[[nodiscard]] Ui::RadialState waitingState() const;
|
||||
|
||||
private:
|
||||
Document(std::shared_ptr<Reader> reader, DocumentData *document);
|
||||
|
||||
friend class Instance;
|
||||
|
||||
void registerInstance(not_null<Instance*> instance);
|
||||
|
@ -54,6 +58,7 @@ private:
|
|||
|
||||
void validateGoodThumbnail();
|
||||
|
||||
DocumentData *_document = nullptr;
|
||||
Player _player;
|
||||
Information _info;
|
||||
|
||||
|
@ -63,8 +68,6 @@ private:
|
|||
base::Timer _timer;
|
||||
base::flat_set<not_null<Instance*>> _instances;
|
||||
|
||||
not_null<DocumentData*> _document;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -390,9 +390,7 @@ void File::Context::stopStreamingAsync() {
|
|||
_reader->stopStreamingAsync();
|
||||
}
|
||||
|
||||
File::File(
|
||||
not_null<Data::Session*> owner,
|
||||
std::shared_ptr<Reader> reader)
|
||||
File::File(std::shared_ptr<Reader> reader)
|
||||
: _reader(std::move(reader)) {
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include <thread>
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
} // namespace Data
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
|
||||
|
@ -27,7 +23,7 @@ class FileDelegate;
|
|||
|
||||
class File final {
|
||||
public:
|
||||
File(not_null<Data::Session*> owner, std::shared_ptr<Reader> reader);
|
||||
explicit File(std::shared_ptr<Reader> reader);
|
||||
|
||||
File(const File &other) = delete;
|
||||
File &operator=(const File &other) = delete;
|
||||
|
|
|
@ -79,10 +79,8 @@ void SaveValidStartInformation(Information &to, Information &&from) {
|
|||
|
||||
} // namespace
|
||||
|
||||
Player::Player(
|
||||
not_null<Data::Session*> owner,
|
||||
std::shared_ptr<Reader> reader)
|
||||
: _file(std::make_unique<File>(owner, std::move(reader)))
|
||||
Player::Player(std::shared_ptr<Reader> reader)
|
||||
: _file(std::make_unique<File>(std::move(reader)))
|
||||
, _remoteLoader(_file->isRemoteLoader())
|
||||
, _renderFrameTimer([=] { checkNextFrameRender(); }) {
|
||||
}
|
||||
|
|
|
@ -12,10 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/weak_ptr.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
} // namespace Data
|
||||
|
||||
namespace Media {
|
||||
namespace Player {
|
||||
struct TrackState;
|
||||
|
@ -34,7 +30,7 @@ class Instance;
|
|||
class Player final : private FileDelegate {
|
||||
public:
|
||||
// Public interfaces is used from the main thread.
|
||||
Player(not_null<Data::Session*> owner, std::shared_ptr<Reader> reader);
|
||||
explicit Player(std::shared_ptr<Reader> reader);
|
||||
|
||||
// Because we remember 'this' in calls to crl::on_main.
|
||||
Player(const Player &other) = delete;
|
||||
|
|
|
@ -845,11 +845,11 @@ Reader::SerializedSlice Reader::Slices::unloadToCache() {
|
|||
}
|
||||
|
||||
Reader::Reader(
|
||||
not_null<Storage::Cache::Database*> cache,
|
||||
std::unique_ptr<Loader> loader)
|
||||
: _cache(cache)
|
||||
, _loader(std::move(loader))
|
||||
, _cacheHelper(InitCacheHelper(_loader->baseCacheKey()))
|
||||
std::unique_ptr<Loader> loader,
|
||||
Storage::Cache::Database *cache)
|
||||
: _loader(std::move(loader))
|
||||
, _cache(cache)
|
||||
, _cacheHelper(cache ? InitCacheHelper(_loader->baseCacheKey()) : nullptr)
|
||||
, _slices(_loader->size(), _cacheHelper != nullptr) {
|
||||
_loader->parts(
|
||||
) | rpl::start_with_next([=](LoadedPart &&part) {
|
||||
|
@ -1122,6 +1122,7 @@ std::shared_ptr<Reader::CacheHelper> Reader::InitCacheHelper(
|
|||
|
||||
// 0 is for headerData, slice index = sliceNumber - 1.
|
||||
void Reader::readFromCache(int sliceNumber) {
|
||||
Expects(_cache != nullptr);
|
||||
Expects(_cacheHelper != nullptr);
|
||||
Expects(!sliceNumber || !_slices.headerModeUnknown());
|
||||
|
||||
|
@ -1182,6 +1183,7 @@ bool Reader::readFromCacheForDownloader(int sliceNumber) {
|
|||
}
|
||||
|
||||
void Reader::putToCache(SerializedSlice &&slice) {
|
||||
Expects(_cache != nullptr);
|
||||
Expects(_cacheHelper != nullptr);
|
||||
Expects(slice.number >= 0);
|
||||
|
||||
|
@ -1375,6 +1377,7 @@ void Reader::finalizeCache() {
|
|||
if (!_cacheHelper) {
|
||||
return;
|
||||
}
|
||||
Assert(_cache != nullptr);
|
||||
if (_cacheHelper->waiting != nullptr) {
|
||||
QMutexLocker lock(&_cacheHelper->mutex);
|
||||
_cacheHelper->waiting.store(nullptr, std::memory_order_release);
|
||||
|
|
|
@ -33,9 +33,9 @@ enum class Error;
|
|||
class Reader final : public base::has_weak_ptr {
|
||||
public:
|
||||
// Main thread.
|
||||
Reader(
|
||||
not_null<Storage::Cache::Database*> cache,
|
||||
std::unique_ptr<Loader> loader);
|
||||
explicit Reader(
|
||||
std::unique_ptr<Loader> loader,
|
||||
Storage::Cache::Database *cache = nullptr);
|
||||
|
||||
void setLoaderPriority(int priority);
|
||||
|
||||
|
@ -228,8 +228,10 @@ private:
|
|||
static std::shared_ptr<CacheHelper> InitCacheHelper(
|
||||
std::optional<Storage::Cache::Key> baseKey);
|
||||
|
||||
const not_null<Storage::Cache::Database*> _cache;
|
||||
const std::unique_ptr<Loader> _loader;
|
||||
Storage::Cache::Database * const _cache = nullptr;
|
||||
|
||||
// shared_ptr is used to be able to have weak_ptr.
|
||||
const std::shared_ptr<CacheHelper> _cacheHelper;
|
||||
|
||||
base::thread_safe_queue<LoadedPart, std::vector> _loadedParts;
|
||||
|
|
|
@ -270,7 +270,6 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
|||
that->_gif = Media::Clip::MakeReader(_documentMedia.get(), FullMsgId(), [=](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
}
|
||||
}
|
||||
if (_gif && _gif->started()) {
|
||||
|
|
Loading…
Reference in New Issue