diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index a469f48b5..49d982706 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1167,9 +1167,13 @@ std::shared_ptr<::Media::Streaming::Document> Session::documentStreamer( return result; } } + auto reader = documentStreamedReader(document, origin); + if (!reader) { + return nullptr; + } auto result = std::make_shared<::Media::Streaming::Document>( document, - origin); + std::move(reader)); if (!PruneDestroyedAndSet(_streamedDocuments, document, result)) { _streamedDocuments.emplace_or_assign(document, result); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 22519b4fc..a12ee01a1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -45,9 +45,8 @@ int gifMaxStatusWidth(DocumentData *document) { } // namespace struct Gif::Streamed { - Streamed( - not_null document, - Data::FileOrigin origin); + explicit Streamed( + std::shared_ptr<::Media::Streaming::Document> document); ~Streamed(); std::shared_ptr<::Media::Streaming::Document> shared; @@ -56,9 +55,8 @@ struct Gif::Streamed { }; Gif::Streamed::Streamed( - not_null document, - Data::FileOrigin origin) -: shared(document->owner().documentStreamer(document, origin)) + std::shared_ptr<::Media::Streaming::Document> document) +: shared(std::move(document)) , instance(shared->addInstance()) { } @@ -116,7 +114,7 @@ QSize Gif::countOptimalSize() { auto maxWidth = qMax(tw, st::minPhotoSize); auto minHeight = qMax(th, st::minPhotoSize); accumulate_max(maxWidth, _parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); - if (!activeCurrentPlayer()) { + if (!activeCurrentStreamed()) { accumulate_max(maxWidth, gifMaxStatusWidth(_data) + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); } if (_parent->hasBubble()) { @@ -171,7 +169,7 @@ QSize Gif::countCurrentSize(int newWidth) { newWidth = qMax(tw, st::minPhotoSize); auto newHeight = qMax(th, st::minPhotoSize); accumulate_max(newWidth, _parent->infoWidth() + 2 * st::msgDateImgDelta + st::msgDateImgPadding.x()); - if (!activeCurrentPlayer()) { + if (!activeCurrentStreamed()) { //const auto own = (reader->mode() == ::Media::Clip::Reader::Mode::Gif); //if (own && !reader->started()) { // auto isRound = _data->isVideoMessage(); @@ -232,8 +230,8 @@ QSize Gif::countCurrentSize(int newWidth) { } QSize Gif::videoSize() const { - if (const auto player = activeCurrentPlayer()) { - return player->videoSize(); + if (const auto streamed = activeCurrentStreamed()) { + return streamed->player().videoSize(); } else if (!_data->dimensions.isEmpty()) { return _data->dimensions; } else if (const auto thumbnail = _data->thumbnail()) { @@ -256,11 +254,11 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms //auto loaded = _data->loaded(); auto displayLoading = (item->id < 0) || _data->displayLoading(); auto selected = (selection == FullSelection); - - if (autoplayEnabled() + const auto startPlayAsync = autoplayEnabled() && !_streamed && _data->canBePlayed() - && !activeRoundPlayer()) { + && !activeRoundStreamed(); + if (startPlayAsync) { _parent->delegate()->elementAnimationAutoplayAsync(_parent); } @@ -273,16 +271,18 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms const auto isRound = _data->isVideoMessage(); auto displayMute = false; - const auto player = activeCurrentPlayer(); + const auto streamed = activeCurrentStreamed(); + const auto player = streamed ? &streamed->player() : nullptr; - if ((!player || item->id < 0) && displayLoading) { + if ((!streamed || item->id < 0) && displayLoading) { ensureAnimation(); if (!_animation->radial.animating()) { _animation->radial.start(dataProgress()); } } updateStatusText(); - const auto radial = isRadialAnimation(); + const auto radial = isRadialAnimation() + || (streamed && streamed->waitingShown()); if (bubble) { if (!_caption.isEmpty()) { @@ -313,10 +313,10 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms auto roundRadius = isRound ? ImageRoundRadius::Ellipse : inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large; auto roundCorners = (isRound || inWebPage) ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) | ((isBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); - if (player) { + if (streamed) { auto paused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any); if (isRound) { - if (activeRoundPlayer()) { + if (activeRoundStreamed()) { paused = false; } else { displayMute = true; @@ -385,8 +385,17 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms App::complexOverlayRect(p, rthumb, roundRadius, roundCorners); } - if (radial || (!player && ((_streamed && _streamed->shared->player().failed()) || (!_data->loaded() && !_data->loading()) || !autoplayEnabled()))) { - auto radialOpacity = (radial && _data->loaded() && item->id > 0) ? _animation->radial.opacity() : 1.; + if (radial + || (!player + && !startPlayAsync + && ((_streamed && _streamed->shared->player().failed()) + || (!_data->loaded() && !_data->loading()) + || !autoplayEnabled()))) { + auto radialOpacity = (radial && _data->loaded() && item->id > 0) + ? _animation->radial.opacity() + : streamed + ? streamed->waitingOpacity() + : 1.; auto inner = QRect(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); if (selected) { @@ -423,7 +432,25 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms if (radial) { p.setOpacity(1); QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); - _animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg); + const auto fg = selected + ? st::historyFileThumbRadialFgSelected + : st::historyFileThumbRadialFg; + if (streamed) { + Ui::InfiniteRadialAnimation::Draw( + p, + streamed->waitingState(), + rinner.topLeft(), + rinner.size(), + width(), + fg, + st::msgFileRadialLine); + } else { + _animation->radial.draw( + p, + rinner, + st::msgFileRadialLine, + fg); + } } if (!isRound && (!player || item->id < 0)) { @@ -763,8 +790,8 @@ void Gif::updateStatusText() const { statusSize = _data->loadOffset(); } else if (_data->loaded()) { statusSize = FileStatusSizeLoaded; - if (const auto video = activeRoundPlayer()) { - const auto state = video->prepareLegacyState(); + if (const auto streamed = activeRoundStreamed()) { + const auto state = streamed->player().prepareLegacyState(); if (state.length) { auto position = int64(0); if (::Media::Player::IsStoppedAtEnd(state.state)) { @@ -817,23 +844,23 @@ int Gif::additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply return result; } -::Media::Streaming::Player *Gif::activeRoundPlayer() const { - return ::Media::Player::instance()->roundVideoPlayer(_parent->data()); +::Media::Streaming::Document *Gif::activeRoundStreamed() const { + return ::Media::Player::instance()->roundVideoStreamed(_parent->data()); } -const ::Media::Streaming::Player *Gif::activeOwnPlayer() const { +const ::Media::Streaming::Document *Gif::activeOwnStreamed() const { return (_streamed && _streamed->shared->player().ready() && !_streamed->shared->player().videoSize().isEmpty()) - ? &_streamed->shared->player() + ? _streamed->shared.get() : nullptr; } -const ::Media::Streaming::Player *Gif::activeCurrentPlayer() const { - if (const auto player = activeRoundPlayer()) { +const ::Media::Streaming::Document *Gif::activeCurrentStreamed() const { + if (const auto player = activeRoundStreamed()) { return player; } - return activeOwnPlayer(); + return activeOwnStreamed(); } ::Media::View::PlaybackProgress *Gif::videoPlayback() const { @@ -890,7 +917,9 @@ void Gif::playAnimation(bool autoplay) { if (!autoplayEnabled()) { history()->owner().checkPlayingVideoFiles(); } - createStreamedPlayer(); + if (!createStreamedPlayer()) { + return; + } auto options = ::Media::Streaming::PlaybackOptions(); options.audioId = AudioMsgId(_data, _realParent->fullId()); //if (!_streamed->withSound) { @@ -901,8 +930,14 @@ void Gif::playAnimation(bool autoplay) { } } -void Gif::createStreamedPlayer() { - setStreamed(std::make_unique(_data, _realParent->fullId())); +bool Gif::createStreamedPlayer() { + auto shared = _data->owner().documentStreamer( + _data, + _realParent->fullId()); + if (!shared) { + return false; + } + setStreamed(std::make_unique(std::move(shared))); _streamed->shared->player().updates( ) | rpl::start_with_next_error([=](::Media::Streaming::Update &&update) { @@ -911,10 +946,10 @@ void Gif::createStreamedPlayer() { handleStreamingError(std::move(error)); }, _streamed->lifetime); - _streamed->shared->player().fullInCache( - ) | rpl::start_with_next([=](bool fullInCache) { - _data->setLoadedInMediaCache(fullInCache); - }, _streamed->lifetime); + if (_streamed->shared->player().ready()) { + streamingReady(base::duplicate(_streamed->shared->info())); + } + return true; } void Gif::setStreamed(std::unique_ptr value) { @@ -925,6 +960,9 @@ void Gif::setStreamed(std::unique_ptr value) { } _streamed = std::move(value); if (set) { + _streamed->instance->setWaitingCallback([=] { + history()->owner().requestViewRepaint(_parent); + }); history()->owner().registerPlayingVideoFile(_parent); } } @@ -938,7 +976,6 @@ void Gif::handleStreamingUpdate(::Media::Streaming::Update &&update) { //updatePlaybackState(); }, [&](const UpdateVideo &update) { history()->owner().requestViewRepaint(_parent); - Core::App().updateNonIdle(); //updatePlaybackState(); }, [&](const PreloadedAudio &update) { //_streamed->info.audio.state.receivedTill = update.till; @@ -955,12 +992,6 @@ void Gif::handleStreamingUpdate(::Media::Streaming::Update &&update) { } void Gif::handleStreamingError(::Media::Streaming::Error &&error) { - using namespace ::Media::Streaming; - if (error == Error::NotStreamable) { - _data->setNotSupportsStreaming(); - } else if (error == Error::OpenFailed) { - _data->setInappPlaybackFailed(); - } //if (!_data->canBePlayed()) { // redisplayContent(); //} else { diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index e1db93437..0f4b86212 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -22,7 +22,7 @@ class PlaybackProgress; namespace Media { namespace Streaming { -class Player; +class Document; struct Update; struct Information; enum class Error; @@ -93,12 +93,12 @@ private: QSize countOptimalSize() override; QSize countCurrentSize(int newWidth) override; QSize videoSize() const; - ::Media::Streaming::Player *activeRoundPlayer() const; - const ::Media::Streaming::Player *activeOwnPlayer() const; - const ::Media::Streaming::Player *activeCurrentPlayer() const; + ::Media::Streaming::Document *activeRoundStreamed() const; + const ::Media::Streaming::Document *activeOwnStreamed() const; + const ::Media::Streaming::Document *activeCurrentStreamed() const; ::Media::View::PlaybackProgress *videoPlayback() const; - void createStreamedPlayer(); + bool createStreamedPlayer(); void setStreamed(std::unique_ptr value); void handleStreamingUpdate(::Media::Streaming::Update &&update); void handleStreamingError(::Media::Streaming::Error &&error); diff --git a/Telegram/SourceFiles/media/player/media_player_float.cpp b/Telegram/SourceFiles/media/player/media_player_float.cpp index 5a60d2646..bf087a25c 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.cpp +++ b/Telegram/SourceFiles/media/player/media_player_float.cpp @@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/view/history_view_element.h" #include "media/audio/media_audio.h" -#include "media/streaming/media_streaming_player.h" +#include "media/streaming/media_streaming_document.h" #include "media/view/media_view_playback_progress.h" #include "media/player/media_player_instance.h" #include "window/window_session_controller.h" @@ -132,11 +132,11 @@ void Float::mouseDoubleClickEvent(QMouseEvent *e) { } void Float::pauseResume() { - if (const auto player = instance()->roundVideoPlayer(_item)) { - if (player->paused()) { - player->resume(); + if (const auto streamed = getStreamed()) { + if (streamed->paused()) { + streamed->resume(); } else { - player->pause(); + streamed->pause(); } } } @@ -206,8 +206,13 @@ void Float::paintEvent(QPaintEvent *e) { } } -Streaming::Player *Float::getPlayer() const { - return instance()->roundVideoPlayer(_item); +Streaming::Document *Float::getStreamed() const { + return instance()->roundVideoStreamed(_item); +} + +const Streaming::Player *Float::getPlayer() const { + const auto streamed = getStreamed(); + return streamed ? &streamed->player() : nullptr; } View::PlaybackProgress *Float::getPlayback() const { diff --git a/Telegram/SourceFiles/media/player/media_player_float.h b/Telegram/SourceFiles/media/player/media_player_float.h index d71dddfda..6a67790c2 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.h +++ b/Telegram/SourceFiles/media/player/media_player_float.h @@ -26,6 +26,7 @@ class PlaybackProgress; namespace Media { namespace Streaming { +class Document; class Player; } // namespace Streaming } // namespace Media @@ -42,7 +43,7 @@ public: Fn toggleCallback, Fn draggedCallback); - HistoryItem *item() const { + [[nodiscard]] HistoryItem *item() const { return _item; } void setOpacity(float64 opacity) { @@ -51,17 +52,17 @@ public: update(); } } - float64 countOpacityByParent() const { + [[nodiscard]] float64 countOpacityByParent() const { return outRatio(); } - bool isReady() const { + [[nodiscard]] bool isReady() const { return (getPlayer() != nullptr); } void detach(); - bool detached() const { + [[nodiscard]] bool detached() const { return !_item; } - bool dragged() const { + [[nodiscard]] bool dragged() const { return _drag; } void resetMouseState() { @@ -79,14 +80,15 @@ protected: void mouseDoubleClickEvent(QMouseEvent *e) override; private: - float64 outRatio() const; - Streaming::Player *getPlayer() const; - View::PlaybackProgress *getPlayback() const; + [[nodiscard]] float64 outRatio() const; + [[nodiscard]] Streaming::Document *getStreamed() const; + [[nodiscard]] const Streaming::Player *getPlayer() const; + [[nodiscard]] View::PlaybackProgress *getPlayback() const; void repaintItem(); void prepareShadow(); bool hasFrame() const; bool fillFrame(); - QRect getInnerRect() const; + [[nodiscard]] QRect getInnerRect() const; void finishDrag(bool closed); void pauseResume(); diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp index eee1fb065..cab28193f 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.cpp +++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "media/audio/media_audio.h" #include "media/audio/media_audio_capture.h" -#include "media/streaming/media_streaming_player.h" +#include "media/streaming/media_streaming_document.h" #include "media/streaming/media_streaming_reader.h" #include "media/view/media_view_playback_progress.h" #include "calls/calls_instance.h" @@ -60,22 +60,20 @@ void finish(not_null instance) { struct Instance::Streamed { Streamed( AudioMsgId id, - not_null<::Data::Session*> owner, - std::shared_ptr reader); + std::shared_ptr document); AudioMsgId id; - Streaming::Player player; - Streaming::Information info; + std::shared_ptr shared; View::PlaybackProgress progress; bool clearing = false; + rpl::lifetime lifetime; }; Instance::Streamed::Streamed( AudioMsgId id, - not_null<::Data::Session*> owner, - std::shared_ptr reader) + std::shared_ptr document) : id(id) -, player(owner, std::move(reader)) { +, shared(std::move(document)) { } Instance::Data::Data(AudioMsgId::Type type, SharedMediaType overview) @@ -175,7 +173,7 @@ void Instance::clearStreamed(not_null data) { return; } data->streamed->clearing = true; - data->streamed->player.stop(); + data->streamed->shared->stop(); data->isPlaying = false; requestRoundVideoResize(); emitUpdate(data->type); @@ -344,8 +342,8 @@ void Instance::play(AudioMsgId::Type type) { if (!data->streamed || IsStopped(getState(type).state)) { play(data->current); } else { - if (data->streamed->player.active()) { - data->streamed->player.resume(); + if (data->streamed->shared->active()) { + data->streamed->shared->resume(); } emitUpdate(type); } @@ -361,13 +359,13 @@ void Instance::play(const AudioMsgId &audioId) { if (document->isAudioFile() || document->isVoiceMessage() || document->isVideoMessage()) { - auto reader = document->owner().documentStreamedReader( + auto shared = document->owner().documentStreamer( document, audioId.contextId()); - if (!reader) { + if (!shared) { return; } - playStreamed(audioId, std::move(reader)); + playStreamed(audioId, std::move(shared)); } if (document->isVoiceMessage() || document->isVideoMessage()) { document->owner().markMediaRead(document); @@ -386,7 +384,7 @@ void Instance::playPause(const AudioMsgId &audioId) { void Instance::playStreamed( const AudioMsgId &audioId, - std::shared_ptr reader) { + std::shared_ptr shared) { Expects(audioId.audio() != nullptr); const auto data = getData(audioId.type()); @@ -395,23 +393,16 @@ void Instance::playStreamed( clearStreamed(data); data->streamed = std::make_unique( audioId, - &audioId.audio()->owner(), - std::move(reader)); + std::move(shared)); - data->streamed->player.updates( + data->streamed->shared->player().updates( ) | rpl::start_with_next_error([=](Streaming::Update &&update) { handleStreamingUpdate(data, std::move(update)); }, [=](Streaming::Error &&error) { handleStreamingError(data, std::move(error)); - }, data->streamed->player.lifetime()); + }, data->streamed->lifetime); - data->streamed->player.fullInCache( - ) | rpl::start_with_next([=](bool fullInCache) { - const auto document = data->streamed->id.audio(); - document->setLoadedInMediaCache(fullInCache); - }, data->streamed->player.lifetime()); - - data->streamed->player.play(streamingOptions(audioId)); + data->streamed->shared->play(streamingOptions(audioId)); emitUpdate(audioId.type()); } @@ -437,8 +428,8 @@ Streaming::PlaybackOptions Instance::streamingOptions( void Instance::pause(AudioMsgId::Type type) { if (const auto data = getData(type)) { if (data->streamed) { - if (data->streamed->player.active()) { - data->streamed->player.pause(); + if (data->streamed->shared->active()) { + data->streamed->shared->pause(); } emitUpdate(type); } @@ -459,13 +450,13 @@ void Instance::playPause(AudioMsgId::Type type) { if (!data->streamed) { play(data->current); } else { - if (!data->streamed->player.active()) { - data->streamed->player.play( - streamingOptions(data->streamed->id)); - } else if (data->streamed->player.paused()) { - data->streamed->player.resume(); + const auto shared = data->streamed->shared.get(); + if (!shared->active()) { + shared->play(streamingOptions(data->streamed->id)); + } else if (shared->paused()) { + shared->resume(); } else { - data->streamed->player.pause(); + shared->pause(); } emitUpdate(type); } @@ -542,13 +533,14 @@ void Instance::startSeeking(AudioMsgId::Type type) { void Instance::finishSeeking(AudioMsgId::Type type, float64 progress) { if (const auto data = getData(type)) { - if (data->streamed) { - const auto duration = data->streamed->info.audio.state.duration; + if (const auto streamed = data->streamed.get()) { + const auto &info = streamed->shared->info(); + const auto duration = info.audio.state.duration; if (duration != kTimeUnknown) { const auto position = crl::time(std::round( std::clamp(progress, 0., 1.) * duration)); - data->streamed->player.play(streamingOptions( - data->streamed->id, + streamed->shared->play(streamingOptions( + streamed->id, position)); emitUpdate(type); } @@ -567,7 +559,7 @@ void Instance::cancelSeeking(AudioMsgId::Type type) { void Instance::updateVoicePlaybackSpeed() { if (const auto data = getData(AudioMsgId::Type::Voice)) { if (const auto streamed = data->streamed.get()) { - streamed->player.setSpeed(Global::VoiceMsgPlaybackDoubled() + streamed->shared->setSpeed(Global::VoiceMsgPlaybackDoubled() ? kVoicePlaybackSpeedMultiplier : 1.); } @@ -590,21 +582,21 @@ void Instance::emitUpdate(AudioMsgId::Type type) { TrackState Instance::getState(AudioMsgId::Type type) const { if (const auto data = getData(type)) { if (data->streamed) { - return data->streamed->player.prepareLegacyState(); + return data->streamed->shared->player().prepareLegacyState(); } } return TrackState(); } -Streaming::Player *Instance::roundVideoPlayer(HistoryItem *item) const { +Streaming::Document *Instance::roundVideoStreamed(HistoryItem *item) const { if (!item) { return nullptr; } else if (const auto data = getData(AudioMsgId::Type::Voice)) { if (const auto streamed = data->streamed.get()) { if (streamed->id.contextId() == item->fullId()) { - const auto player = &streamed->player; + const auto player = &streamed->shared->player(); if (player->ready() && !player->videoSize().isEmpty()) { - return player; + return streamed->shared.get(); } } } @@ -614,7 +606,7 @@ Streaming::Player *Instance::roundVideoPlayer(HistoryItem *item) const { View::PlaybackProgress *Instance::roundVideoPlayback( HistoryItem *item) const { - return roundVideoPlayer(item) + return roundVideoStreamed(item) ? &getData(AudioMsgId::Type::Voice)->streamed->progress : nullptr; } @@ -627,8 +619,10 @@ void Instance::emitUpdate(AudioMsgId::Type type, CheckCallback check) { return; } setCurrent(state.id); - if (data->streamed && !data->streamed->info.video.size.isEmpty()) { - data->streamed->progress.updateState(state); + if (const auto streamed = data->streamed.get()) { + if (!streamed->shared->info().video.size.isEmpty()) { + streamed->progress.updateState(state); + } } _updatedNotifier.fire_copy({state}); if (data->isPlaying && state.state == State::StoppedAtEnd) { @@ -679,8 +673,7 @@ void Instance::handleStreamingUpdate( using namespace Streaming; update.data.match([&](Information &update) { - data->streamed->info = std::move(update); - if (!data->streamed->info.video.size.isEmpty()) { + if (!update.video.size.isEmpty()) { data->streamed->progress.setValueChangedCallback([=]( float64, float64) { @@ -692,26 +685,18 @@ void Instance::handleStreamingUpdate( } emitUpdate(data->type); }, [&](PreloadedVideo &update) { - data->streamed->info.video.state.receivedTill = update.till; //emitUpdate(data->type, [](AudioMsgId) { return true; }); }, [&](UpdateVideo &update) { - data->streamed->info.video.state.position = update.position; emitUpdate(data->type); }, [&](PreloadedAudio &update) { - data->streamed->info.audio.state.receivedTill = update.till; //emitUpdate(data->type, [](AudioMsgId) { return true; }); }, [&](UpdateAudio &update) { - data->streamed->info.audio.state.position = update.position; emitUpdate(data->type); }, [&](WaitingForData) { }, [&](MutedByOther) { }, [&](Finished) { - const auto finishTrack = [](Media::Streaming::TrackState &state) { - state.position = state.receivedTill = state.duration; - }; - finishTrack(data->streamed->info.audio.state); emitUpdate(data->type); - if (data->streamed && data->streamed->player.finished()) { + if (data->streamed && data->streamed->shared->player().finished()) { clearStreamed(data); } }); @@ -720,7 +705,7 @@ void Instance::handleStreamingUpdate( HistoryItem *Instance::roundVideoItem() const { const auto data = getData(AudioMsgId::Type::Voice); return (data->streamed - && !data->streamed->info.video.size.isEmpty()) + && !data->streamed->shared->info().video.size.isEmpty()) ? Auth().data().message(data->streamed->id.contextId()) : nullptr; } @@ -745,19 +730,17 @@ void Instance::handleStreamingError( const auto document = data->streamed->id.audio(); const auto contextId = data->streamed->id.contextId(); if (error == Streaming::Error::NotStreamable) { - document->setNotSupportsStreaming(); DocumentSaveClickHandler::Save( (contextId ? contextId : ::Data::FileOrigin()), document); } else if (error == Streaming::Error::OpenFailed) { - document->setInappPlaybackFailed(); DocumentSaveClickHandler::Save( (contextId ? contextId : ::Data::FileOrigin()), document, DocumentSaveClickHandler::Mode::ToFile); } emitUpdate(data->type); - if (data->streamed && data->streamed->player.failed()) { + if (data->streamed && data->streamed->shared->player().failed()) { clearStreamed(data); } } diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h index d55ae38be..e429ccbfa 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.h +++ b/Telegram/SourceFiles/media/player/media_player_instance.h @@ -25,7 +25,7 @@ class PlaybackProgress; namespace Media { namespace Streaming { -class Player; +class Document; class Reader; struct PlaybackOptions; struct Update; @@ -80,7 +80,7 @@ public: void playPause(const AudioMsgId &audioId); [[nodiscard]] TrackState getState(AudioMsgId::Type type) const; - [[nodiscard]] Streaming::Player *roundVideoPlayer( + [[nodiscard]] Streaming::Document *roundVideoStreamed( HistoryItem *item) const; [[nodiscard]] View::PlaybackProgress *roundVideoPlayback( HistoryItem *item) const; @@ -193,7 +193,7 @@ private: void setupShortcuts(); void playStreamed( const AudioMsgId &audioId, - std::shared_ptr reader); + std::shared_ptr shared); Streaming::PlaybackOptions streamingOptions( const AudioMsgId &audioId, crl::time position = 0); diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_document.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_document.cpp index 06f3672d9..e502fa672 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_document.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_document.cpp @@ -38,10 +38,8 @@ void Instance::callWaitingCallback() { Document::Document( not_null document, - Data::FileOrigin origin) -: _player( - &document->owner(), - document->owner().documentStreamedReader(document, origin)) + std::shared_ptr reader) +: _player(&document->owner(), reader) , _radial( [=] { waitingCallback(); }, st::defaultInfiniteRadialAnimation) @@ -83,6 +81,10 @@ void Document::resume() { _player.resume(); } +void Document::stop() { + _player.stop(); +} + void Document::saveFrameToCover() { auto request = Streaming::FrameRequest(); //request.radius = (_doc && _doc->isVideoMessage()) @@ -93,6 +95,26 @@ void Document::saveFrameToCover() { : _info.video.cover; } +bool Document::active() const { + return _player.active(); +} + +bool Document::ready() const { + return _player.ready(); +} + +bool Document::paused() const { + return _player.paused(); +} + +float64 Document::speed() const { + return _player.speed(); +} + +void Document::setSpeed(float64 speed) { + _player.setSpeed(speed); +} + not_null Document::addInstance() { return _instances.emplace(std::make_unique()).first->get(); } diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_document.h b/Telegram/SourceFiles/media/streaming/media_streaming_document.h index fa1e30e03..1810d1a0c 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_document.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_document.h @@ -36,7 +36,7 @@ class Document { public: Document( not_null document, - Data::FileOrigin origin); + std::shared_ptr reader); [[nodiscard]] const Player &player() const; [[nodiscard]] const Information &info() const; @@ -44,8 +44,17 @@ public: void play(const PlaybackOptions &options); void pause(); void resume(); + void stop(); void saveFrameToCover(); + [[nodiscard]] bool active() const; + [[nodiscard]] bool ready() const; + + [[nodiscard]] bool paused() const; + + [[nodiscard]] float64 speed() const; + void setSpeed(float64 speed); // 0.5 <= speed <= 2. + [[nodiscard]] not_null addInstance(); void removeInstance(not_null instance);