mirror of https://github.com/procxx/kepka.git
All players create own Media::Streaming::Instance.
This commit is contained in:
parent
bfa5accc29
commit
2d7adbc68a
|
@ -622,6 +622,8 @@ PRIVATE
|
|||
media/streaming/media_streaming_file.cpp
|
||||
media/streaming/media_streaming_file.h
|
||||
media/streaming/media_streaming_file_delegate.h
|
||||
media/streaming/media_streaming_instance.cpp
|
||||
media/streaming/media_streaming_instance.h
|
||||
media/streaming/media_streaming_loader.cpp
|
||||
media/streaming/media_streaming_loader.h
|
||||
media/streaming/media_streaming_loader_local.cpp
|
||||
|
|
|
@ -14,7 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/audio/media_audio.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "media/view/media_view_playback_progress.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "history/history_item_components.h"
|
||||
|
@ -44,26 +45,6 @@ int gifMaxStatusWidth(DocumentData *document) {
|
|||
|
||||
} // namespace
|
||||
|
||||
struct Gif::Streamed {
|
||||
explicit Streamed(
|
||||
std::shared_ptr<::Media::Streaming::Document> document);
|
||||
~Streamed();
|
||||
|
||||
std::shared_ptr<::Media::Streaming::Document> shared;
|
||||
not_null<::Media::Streaming::Instance*> instance;
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
Gif::Streamed::Streamed(
|
||||
std::shared_ptr<::Media::Streaming::Document> document)
|
||||
: shared(std::move(document))
|
||||
, instance(shared->addInstance()) {
|
||||
}
|
||||
|
||||
Gif::Streamed::~Streamed() {
|
||||
shared->removeInstance(instance);
|
||||
}
|
||||
|
||||
Gif::Gif(
|
||||
not_null<Element*> parent,
|
||||
not_null<DocumentData*> document)
|
||||
|
@ -388,7 +369,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
|
|||
if (radial
|
||||
|| (!player
|
||||
&& !startPlayAsync
|
||||
&& ((_streamed && _streamed->shared->player().failed())
|
||||
&& ((_streamed && _streamed->player().failed())
|
||||
|| (!_data->loaded() && !_data->loading())
|
||||
|| !autoplayEnabled()))) {
|
||||
auto radialOpacity = (radial && _data->loaded() && item->id > 0)
|
||||
|
@ -844,21 +825,21 @@ int Gif::additionalWidth(const HistoryMessageVia *via, const HistoryMessageReply
|
|||
return result;
|
||||
}
|
||||
|
||||
::Media::Streaming::Document *Gif::activeRoundStreamed() const {
|
||||
::Media::Streaming::Instance *Gif::activeRoundStreamed() const {
|
||||
return ::Media::Player::instance()->roundVideoStreamed(_parent->data());
|
||||
}
|
||||
|
||||
const ::Media::Streaming::Document *Gif::activeOwnStreamed() const {
|
||||
const ::Media::Streaming::Instance *Gif::activeOwnStreamed() const {
|
||||
return (_streamed
|
||||
&& _streamed->shared->player().ready()
|
||||
&& !_streamed->shared->player().videoSize().isEmpty())
|
||||
? _streamed->shared.get()
|
||||
&& _streamed->player().ready()
|
||||
&& !_streamed->player().videoSize().isEmpty())
|
||||
? _streamed.get()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
const ::Media::Streaming::Document *Gif::activeCurrentStreamed() const {
|
||||
if (const auto player = activeRoundStreamed()) {
|
||||
return player;
|
||||
const ::Media::Streaming::Instance *Gif::activeCurrentStreamed() const {
|
||||
if (const auto streamed = activeRoundStreamed()) {
|
||||
return streamed;
|
||||
}
|
||||
return activeOwnStreamed();
|
||||
}
|
||||
|
@ -926,7 +907,7 @@ void Gif::playAnimation(bool autoplay) {
|
|||
options.mode = ::Media::Streaming::Mode::Video;
|
||||
options.loop = true;
|
||||
//}
|
||||
_streamed->shared->play(options);
|
||||
_streamed->play(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,22 +918,24 @@ bool Gif::createStreamedPlayer() {
|
|||
if (!shared) {
|
||||
return false;
|
||||
}
|
||||
setStreamed(std::make_unique<Streamed>(std::move(shared)));
|
||||
setStreamed(std::make_unique<::Media::Streaming::Instance>(
|
||||
std::move(shared),
|
||||
[=] { history()->owner().requestViewRepaint(_parent); }));
|
||||
|
||||
_streamed->shared->player().updates(
|
||||
_streamed->player().updates(
|
||||
) | rpl::start_with_next_error([=](::Media::Streaming::Update &&update) {
|
||||
handleStreamingUpdate(std::move(update));
|
||||
}, [=](::Media::Streaming::Error &&error) {
|
||||
handleStreamingError(std::move(error));
|
||||
}, _streamed->lifetime);
|
||||
}, _streamed->lifetime());
|
||||
|
||||
if (_streamed->shared->player().ready()) {
|
||||
streamingReady(base::duplicate(_streamed->shared->info()));
|
||||
if (_streamed->ready()) {
|
||||
streamingReady(base::duplicate(_streamed->info()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Gif::setStreamed(std::unique_ptr<Streamed> value) {
|
||||
void Gif::setStreamed(std::unique_ptr<::Media::Streaming::Instance> value) {
|
||||
const auto removed = (_streamed && !value);
|
||||
const auto set = (!_streamed && value);
|
||||
if (removed) {
|
||||
|
@ -960,9 +943,6 @@ void Gif::setStreamed(std::unique_ptr<Streamed> value) {
|
|||
}
|
||||
_streamed = std::move(value);
|
||||
if (set) {
|
||||
_streamed->instance->setWaitingCallback([=] {
|
||||
history()->owner().requestViewRepaint(_parent);
|
||||
});
|
||||
history()->owner().registerPlayingVideoFile(_parent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class PlaybackProgress;
|
|||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
class Document;
|
||||
class Instance;
|
||||
struct Update;
|
||||
struct Information;
|
||||
enum class Error;
|
||||
|
@ -81,8 +81,6 @@ public:
|
|||
void parentTextUpdated() override;
|
||||
|
||||
private:
|
||||
struct Streamed;
|
||||
|
||||
float64 dataProgress() const override;
|
||||
bool dataFinished() const override;
|
||||
bool dataLoaded() const override;
|
||||
|
@ -93,13 +91,13 @@ private:
|
|||
QSize countOptimalSize() override;
|
||||
QSize countCurrentSize(int newWidth) override;
|
||||
QSize videoSize() const;
|
||||
::Media::Streaming::Document *activeRoundStreamed() const;
|
||||
const ::Media::Streaming::Document *activeOwnStreamed() const;
|
||||
const ::Media::Streaming::Document *activeCurrentStreamed() const;
|
||||
::Media::Streaming::Instance *activeRoundStreamed() const;
|
||||
const ::Media::Streaming::Instance *activeOwnStreamed() const;
|
||||
const ::Media::Streaming::Instance *activeCurrentStreamed() const;
|
||||
::Media::View::PlaybackProgress *videoPlayback() const;
|
||||
|
||||
bool createStreamedPlayer();
|
||||
void setStreamed(std::unique_ptr<Streamed> value);
|
||||
void setStreamed(std::unique_ptr<::Media::Streaming::Instance> value);
|
||||
void handleStreamingUpdate(::Media::Streaming::Update &&update);
|
||||
void handleStreamingError(::Media::Streaming::Error &&error);
|
||||
void streamingReady(::Media::Streaming::Information &&info);
|
||||
|
@ -117,7 +115,7 @@ private:
|
|||
int _thumbw = 1;
|
||||
int _thumbh = 1;
|
||||
Ui::Text::String _caption;
|
||||
std::unique_ptr<Streamed> _streamed;
|
||||
std::unique_ptr<::Media::Streaming::Instance> _streamed;
|
||||
|
||||
void setStatusSize(int newSize) const;
|
||||
void updateStatusText() const;
|
||||
|
|
|
@ -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_document.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/view/media_view_playback_progress.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
@ -206,21 +206,16 @@ void Float::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
}
|
||||
|
||||
Streaming::Document *Float::getStreamed() const {
|
||||
Streaming::Instance *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 {
|
||||
return instance()->roundVideoPlayback(_item);
|
||||
}
|
||||
|
||||
bool Float::hasFrame() const {
|
||||
return (getPlayer() != nullptr);
|
||||
return (getStreamed() != nullptr);
|
||||
}
|
||||
|
||||
bool Float::fillFrame() {
|
||||
|
@ -234,11 +229,11 @@ bool Float::fillFrame() {
|
|||
auto frameInner = [&] {
|
||||
return QRect(QPoint(), _frame.size() / cIntRetinaFactor());
|
||||
};
|
||||
if (const auto player = getPlayer()) {
|
||||
if (const auto streamed = getStreamed()) {
|
||||
auto request = Streaming::FrameRequest::NonStrict();
|
||||
request.outer = request.resize = _frame.size();
|
||||
request.radius = ImageRoundRadius::Ellipse;
|
||||
auto frame = player->frame(request);
|
||||
auto frame = streamed->frame(request);
|
||||
if (!frame.isNull()) {
|
||||
_frame.fill(Qt::transparent);
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ class PlaybackProgress;
|
|||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
class Document;
|
||||
class Player;
|
||||
class Instance;
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
||||
|
||||
|
@ -56,7 +55,7 @@ public:
|
|||
return outRatio();
|
||||
}
|
||||
[[nodiscard]] bool isReady() const {
|
||||
return (getPlayer() != nullptr);
|
||||
return (getStreamed() != nullptr);
|
||||
}
|
||||
void detach();
|
||||
[[nodiscard]] bool detached() const {
|
||||
|
@ -81,8 +80,7 @@ protected:
|
|||
|
||||
private:
|
||||
[[nodiscard]] float64 outRatio() const;
|
||||
[[nodiscard]] Streaming::Document *getStreamed() const;
|
||||
[[nodiscard]] const Streaming::Player *getPlayer() const;
|
||||
[[nodiscard]] Streaming::Instance *getStreamed() const;
|
||||
[[nodiscard]] View::PlaybackProgress *getPlayback() const;
|
||||
void repaintItem();
|
||||
void prepareShadow();
|
||||
|
|
|
@ -11,8 +11,8 @@ 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_document.h"
|
||||
#include "media/streaming/media_streaming_reader.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "media/view/media_view_playback_progress.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "history/history.h"
|
||||
|
@ -63,7 +63,7 @@ struct Instance::Streamed {
|
|||
std::shared_ptr<Streaming::Document> document);
|
||||
|
||||
AudioMsgId id;
|
||||
std::shared_ptr<Streaming::Document> shared;
|
||||
Streaming::Instance instance;
|
||||
View::PlaybackProgress progress;
|
||||
bool clearing = false;
|
||||
rpl::lifetime lifetime;
|
||||
|
@ -73,7 +73,7 @@ Instance::Streamed::Streamed(
|
|||
AudioMsgId id,
|
||||
std::shared_ptr<Streaming::Document> document)
|
||||
: id(id)
|
||||
, shared(std::move(document)) {
|
||||
, instance(std::move(document), nullptr) {
|
||||
}
|
||||
|
||||
Instance::Data::Data(AudioMsgId::Type type, SharedMediaType overview)
|
||||
|
@ -173,7 +173,7 @@ void Instance::clearStreamed(not_null<Data*> data) {
|
|||
return;
|
||||
}
|
||||
data->streamed->clearing = true;
|
||||
data->streamed->shared->stop();
|
||||
data->streamed->instance.stop();
|
||||
data->isPlaying = false;
|
||||
requestRoundVideoResize();
|
||||
emitUpdate(data->type);
|
||||
|
@ -342,8 +342,8 @@ void Instance::play(AudioMsgId::Type type) {
|
|||
if (!data->streamed || IsStopped(getState(type).state)) {
|
||||
play(data->current);
|
||||
} else {
|
||||
if (data->streamed->shared->active()) {
|
||||
data->streamed->shared->resume();
|
||||
if (data->streamed->instance.active()) {
|
||||
data->streamed->instance.resume();
|
||||
}
|
||||
emitUpdate(type);
|
||||
}
|
||||
|
@ -395,14 +395,14 @@ void Instance::playStreamed(
|
|||
audioId,
|
||||
std::move(shared));
|
||||
|
||||
data->streamed->shared->player().updates(
|
||||
data->streamed->instance.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->lifetime);
|
||||
|
||||
data->streamed->shared->play(streamingOptions(audioId));
|
||||
data->streamed->instance.play(streamingOptions(audioId));
|
||||
|
||||
emitUpdate(audioId.type());
|
||||
}
|
||||
|
@ -428,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->shared->active()) {
|
||||
data->streamed->shared->pause();
|
||||
if (data->streamed->instance.active()) {
|
||||
data->streamed->instance.pause();
|
||||
}
|
||||
emitUpdate(type);
|
||||
}
|
||||
|
@ -450,13 +450,13 @@ void Instance::playPause(AudioMsgId::Type type) {
|
|||
if (!data->streamed) {
|
||||
play(data->current);
|
||||
} else {
|
||||
const auto shared = data->streamed->shared.get();
|
||||
if (!shared->active()) {
|
||||
shared->play(streamingOptions(data->streamed->id));
|
||||
} else if (shared->paused()) {
|
||||
shared->resume();
|
||||
auto &streamed = data->streamed->instance;
|
||||
if (!streamed.active()) {
|
||||
streamed.play(streamingOptions(data->streamed->id));
|
||||
} else if (streamed.paused()) {
|
||||
streamed.resume();
|
||||
} else {
|
||||
shared->pause();
|
||||
streamed.pause();
|
||||
}
|
||||
emitUpdate(type);
|
||||
}
|
||||
|
@ -534,12 +534,12 @@ void Instance::startSeeking(AudioMsgId::Type type) {
|
|||
void Instance::finishSeeking(AudioMsgId::Type type, float64 progress) {
|
||||
if (const auto data = getData(type)) {
|
||||
if (const auto streamed = data->streamed.get()) {
|
||||
const auto &info = streamed->shared->info();
|
||||
const auto &info = streamed->instance.info();
|
||||
const auto duration = info.audio.state.duration;
|
||||
if (duration != kTimeUnknown) {
|
||||
const auto position = crl::time(std::round(
|
||||
std::clamp(progress, 0., 1.) * duration));
|
||||
streamed->shared->play(streamingOptions(
|
||||
streamed->instance.play(streamingOptions(
|
||||
streamed->id,
|
||||
position));
|
||||
emitUpdate(type);
|
||||
|
@ -559,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->shared->setSpeed(Global::VoiceMsgPlaybackDoubled()
|
||||
streamed->instance.setSpeed(Global::VoiceMsgPlaybackDoubled()
|
||||
? kVoicePlaybackSpeedMultiplier
|
||||
: 1.);
|
||||
}
|
||||
|
@ -582,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->shared->player().prepareLegacyState();
|
||||
return data->streamed->instance.player().prepareLegacyState();
|
||||
}
|
||||
}
|
||||
return TrackState();
|
||||
}
|
||||
|
||||
Streaming::Document *Instance::roundVideoStreamed(HistoryItem *item) const {
|
||||
Streaming::Instance *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->shared->player();
|
||||
const auto player = &streamed->instance.player();
|
||||
if (player->ready() && !player->videoSize().isEmpty()) {
|
||||
return streamed->shared.get();
|
||||
return &streamed->instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -620,7 +620,7 @@ void Instance::emitUpdate(AudioMsgId::Type type, CheckCallback check) {
|
|||
}
|
||||
setCurrent(state.id);
|
||||
if (const auto streamed = data->streamed.get()) {
|
||||
if (!streamed->shared->info().video.size.isEmpty()) {
|
||||
if (!streamed->instance.info().video.size.isEmpty()) {
|
||||
streamed->progress.updateState(state);
|
||||
}
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ void Instance::handleStreamingUpdate(
|
|||
}, [&](MutedByOther) {
|
||||
}, [&](Finished) {
|
||||
emitUpdate(data->type);
|
||||
if (data->streamed && data->streamed->shared->player().finished()) {
|
||||
if (data->streamed && data->streamed->instance.player().finished()) {
|
||||
clearStreamed(data);
|
||||
}
|
||||
});
|
||||
|
@ -705,7 +705,7 @@ void Instance::handleStreamingUpdate(
|
|||
HistoryItem *Instance::roundVideoItem() const {
|
||||
const auto data = getData(AudioMsgId::Type::Voice);
|
||||
return (data->streamed
|
||||
&& !data->streamed->shared->info().video.size.isEmpty())
|
||||
&& !data->streamed->instance.info().video.size.isEmpty())
|
||||
? Auth().data().message(data->streamed->id.contextId())
|
||||
: nullptr;
|
||||
}
|
||||
|
@ -740,7 +740,7 @@ void Instance::handleStreamingError(
|
|||
DocumentSaveClickHandler::Mode::ToFile);
|
||||
}
|
||||
emitUpdate(data->type);
|
||||
if (data->streamed && data->streamed->shared->player().failed()) {
|
||||
if (data->streamed && data->streamed->instance.player().failed()) {
|
||||
clearStreamed(data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class PlaybackProgress;
|
|||
namespace Media {
|
||||
namespace Streaming {
|
||||
class Document;
|
||||
class Reader;
|
||||
class Instance;
|
||||
struct PlaybackOptions;
|
||||
struct Update;
|
||||
enum class Error;
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
void playPause(const AudioMsgId &audioId);
|
||||
[[nodiscard]] TrackState getState(AudioMsgId::Type type) const;
|
||||
|
||||
[[nodiscard]] Streaming::Document *roundVideoStreamed(
|
||||
[[nodiscard]] Streaming::Instance *roundVideoStreamed(
|
||||
HistoryItem *item) const;
|
||||
[[nodiscard]] View::PlaybackProgress *roundVideoPlayback(
|
||||
HistoryItem *item) const;
|
||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_file_origin.h"
|
||||
|
@ -26,16 +27,6 @@ constexpr auto kGoodThumbnailQuality = 87;
|
|||
|
||||
} // namespace
|
||||
|
||||
void Instance::setWaitingCallback(Fn<void()> callback) {
|
||||
_waitingCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void Instance::callWaitingCallback() {
|
||||
if (_waitingCallback) {
|
||||
_waitingCallback();
|
||||
}
|
||||
}
|
||||
|
||||
Document::Document(
|
||||
not_null<DocumentData*> document,
|
||||
std::shared_ptr<Reader> reader)
|
||||
|
@ -57,6 +48,10 @@ Document::Document(
|
|||
}, _player.lifetime());
|
||||
}
|
||||
|
||||
Player &Document::player() {
|
||||
return _player;
|
||||
}
|
||||
|
||||
const Player &Document::player() const {
|
||||
return _player;
|
||||
}
|
||||
|
@ -73,18 +68,6 @@ void Document::play(const PlaybackOptions &options) {
|
|||
waitingChange(true);
|
||||
}
|
||||
|
||||
void Document::pause() {
|
||||
_player.pause();
|
||||
}
|
||||
|
||||
void Document::resume() {
|
||||
_player.resume();
|
||||
}
|
||||
|
||||
void Document::stop() {
|
||||
_player.stop();
|
||||
}
|
||||
|
||||
void Document::saveFrameToCover() {
|
||||
auto request = Streaming::FrameRequest();
|
||||
//request.radius = (_doc && _doc->isVideoMessage())
|
||||
|
@ -95,39 +78,12 @@ void Document::saveFrameToCover() {
|
|||
: _info.video.cover;
|
||||
}
|
||||
|
||||
bool Document::active() const {
|
||||
return _player.active();
|
||||
void Document::registerInstance(not_null<Instance*> instance) {
|
||||
_instances.emplace(instance);
|
||||
}
|
||||
|
||||
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<Instance*> Document::addInstance() {
|
||||
return _instances.emplace(std::make_unique<Instance>()).first->get();
|
||||
}
|
||||
|
||||
void Document::removeInstance(not_null<Instance*> instance) {
|
||||
const auto i = ranges::lower_bound(
|
||||
_instances,
|
||||
instance.get(),
|
||||
ranges::less(),
|
||||
&std::unique_ptr<Instance>::get);
|
||||
if (i != _instances.end() && i->get() == instance) {
|
||||
_instances.erase(i);
|
||||
}
|
||||
void Document::unregisterInstance(not_null<Instance*> instance) {
|
||||
_instances.remove(instance);
|
||||
}
|
||||
|
||||
bool Document::waitingShown() const {
|
||||
|
|
|
@ -14,23 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class DocumentData;
|
||||
|
||||
namespace Data {
|
||||
struct FileOrigin;
|
||||
} // namespace Data
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
|
||||
class Instance {
|
||||
public:
|
||||
void setWaitingCallback(Fn<void()> callback);
|
||||
|
||||
void callWaitingCallback();
|
||||
|
||||
private:
|
||||
Fn<void()> _waitingCallback;
|
||||
|
||||
};
|
||||
class Instance;
|
||||
|
||||
class Document {
|
||||
public:
|
||||
|
@ -38,31 +25,23 @@ public:
|
|||
not_null<DocumentData*> document,
|
||||
std::shared_ptr<Reader> reader);
|
||||
|
||||
[[nodiscard]] const Player &player() const;
|
||||
[[nodiscard]] const Information &info() const;
|
||||
|
||||
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<Instance*> addInstance();
|
||||
void removeInstance(not_null<Instance*> instance);
|
||||
[[nodiscard]] Player &player();
|
||||
[[nodiscard]] const Player &player() const;
|
||||
[[nodiscard]] const Information &info() const;
|
||||
|
||||
[[nodiscard]] bool waitingShown() const;
|
||||
[[nodiscard]] float64 waitingOpacity() const;
|
||||
[[nodiscard]] Ui::RadialState waitingState() const;
|
||||
|
||||
private:
|
||||
friend class Instance;
|
||||
|
||||
void registerInstance(not_null<Instance*> instance);
|
||||
void unregisterInstance(not_null<Instance*> instance);
|
||||
|
||||
void waitingCallback();
|
||||
|
||||
void handleUpdate(Update &&update);
|
||||
|
@ -80,7 +59,7 @@ private:
|
|||
mutable Ui::InfiniteRadialAnimation _radial;
|
||||
Ui::Animations::Simple _fading;
|
||||
base::Timer _timer;
|
||||
base::flat_set<std::unique_ptr<Instance>> _instances;
|
||||
base::flat_set<not_null<Instance*>> _instances;
|
||||
|
||||
not_null<DocumentData*> _document;
|
||||
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
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_instance.h"
|
||||
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_session.h"
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
|
||||
Instance::Instance(
|
||||
std::shared_ptr<Document> shared,
|
||||
Fn<void()> waitingCallback)
|
||||
: _shared(std::move(shared))
|
||||
, _waitingCallback(std::move(waitingCallback)) {
|
||||
if (_shared) {
|
||||
_shared->registerInstance(this);
|
||||
}
|
||||
}
|
||||
|
||||
Instance::Instance(
|
||||
not_null<DocumentData*> document,
|
||||
Data::FileOrigin origin,
|
||||
Fn<void()> waitingCallback)
|
||||
: Instance(
|
||||
document->owner().documentStreamer(document, origin),
|
||||
std::move(waitingCallback)) {
|
||||
}
|
||||
|
||||
Instance::~Instance() {
|
||||
if (_shared) {
|
||||
_shared->unregisterInstance(this);
|
||||
}
|
||||
}
|
||||
|
||||
const Player &Instance::player() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->player();
|
||||
}
|
||||
|
||||
const Information &Instance::info() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->info();
|
||||
}
|
||||
|
||||
void Instance::play(const PlaybackOptions &options) {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->play(options);
|
||||
}
|
||||
|
||||
void Instance::pause() {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->player().pause();
|
||||
}
|
||||
|
||||
void Instance::resume() {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->player().resume();
|
||||
}
|
||||
|
||||
void Instance::stop() {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->player().stop();
|
||||
}
|
||||
|
||||
void Instance::saveFrameToCover() {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->saveFrameToCover();
|
||||
}
|
||||
|
||||
bool Instance::active() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->player().active();
|
||||
}
|
||||
|
||||
bool Instance::ready() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->player().ready();
|
||||
}
|
||||
|
||||
bool Instance::paused() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->player().paused();
|
||||
}
|
||||
|
||||
float64 Instance::speed() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->player().speed();
|
||||
}
|
||||
|
||||
void Instance::setSpeed(float64 speed) {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
_shared->player().setSpeed(speed);
|
||||
}
|
||||
|
||||
bool Instance::waitingShown() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->waitingShown();
|
||||
}
|
||||
|
||||
float64 Instance::waitingOpacity() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->waitingOpacity();
|
||||
}
|
||||
|
||||
Ui::RadialState Instance::waitingState() const {
|
||||
Expects(_shared != nullptr);
|
||||
|
||||
return _shared->waitingState();
|
||||
}
|
||||
|
||||
void Instance::callWaitingCallback() {
|
||||
if (_waitingCallback) {
|
||||
_waitingCallback();
|
||||
}
|
||||
}
|
||||
|
||||
QImage Instance::frame(const FrameRequest &request) const {
|
||||
return player().frame(request);
|
||||
}
|
||||
|
||||
rpl::lifetime &Instance::lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
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_common.h"
|
||||
|
||||
class DocumentData;
|
||||
|
||||
namespace Ui {
|
||||
struct RadialState;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
struct FileOrigin;
|
||||
} // namespace Data
|
||||
|
||||
namespace Media {
|
||||
namespace Streaming {
|
||||
|
||||
class Document;
|
||||
class Player;
|
||||
|
||||
class Instance {
|
||||
public:
|
||||
Instance(
|
||||
std::shared_ptr<Document> shared,
|
||||
Fn<void()> waitingCallback);
|
||||
Instance(
|
||||
not_null<DocumentData*> document,
|
||||
Data::FileOrigin origin,
|
||||
Fn<void()> waitingCallback);
|
||||
~Instance();
|
||||
|
||||
[[nodiscard]] const Player &player() const;
|
||||
[[nodiscard]] const Information &info() const;
|
||||
|
||||
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]] bool waitingShown() const;
|
||||
[[nodiscard]] float64 waitingOpacity() const;
|
||||
[[nodiscard]] Ui::RadialState waitingState() const;
|
||||
|
||||
void callWaitingCallback();
|
||||
|
||||
[[nodiscard]] QImage frame(const FrameRequest &request) const;
|
||||
|
||||
rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
const std::shared_ptr<Document> _shared;
|
||||
Fn<void()> _waitingCallback;
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Streaming
|
||||
} // namespace Media
|
|
@ -26,9 +26,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/audio/media_audio.h"
|
||||
#include "media/view/media_view_playback_controls.h"
|
||||
#include "media/view/media_view_group_thumbs.h"
|
||||
#include "media/streaming/media_streaming_instance.h"
|
||||
#include "media/streaming/media_streaming_player.h"
|
||||
#include "media/streaming/media_streaming_reader.h"
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_message.h"
|
||||
|
@ -190,10 +189,8 @@ struct OverlayWidget::Streamed {
|
|||
QWidget *controlsParent,
|
||||
not_null<PlaybackControls::Delegate*> controlsDelegate,
|
||||
Callback &&loadingCallback);
|
||||
~Streamed();
|
||||
|
||||
std::shared_ptr<Streaming::Document> shared;
|
||||
not_null<Streaming::Instance*> instance;
|
||||
Streaming::Instance instance;
|
||||
PlaybackControls controls;
|
||||
|
||||
QImage frameForDirectPaint;
|
||||
|
@ -201,8 +198,6 @@ struct OverlayWidget::Streamed {
|
|||
bool withSound = false;
|
||||
bool pausedBySeek = false;
|
||||
bool resumeOnCallEnd = false;
|
||||
|
||||
rpl::lifetime lifetime;
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
|
@ -212,14 +207,8 @@ OverlayWidget::Streamed::Streamed(
|
|||
QWidget *controlsParent,
|
||||
not_null<PlaybackControls::Delegate*> controlsDelegate,
|
||||
Callback &&loadingCallback)
|
||||
: shared(document->owner().documentStreamer(document, origin))
|
||||
, instance(shared->addInstance())
|
||||
: instance(document, origin, std::forward<Callback>(loadingCallback))
|
||||
, controls(controlsParent, controlsDelegate) {
|
||||
instance->setWaitingCallback(std::forward<Callback>(loadingCallback));
|
||||
}
|
||||
|
||||
OverlayWidget::Streamed::~Streamed() {
|
||||
shared->removeInstance(instance);
|
||||
}
|
||||
|
||||
OverlayWidget::OverlayWidget()
|
||||
|
@ -367,13 +356,13 @@ void OverlayWidget::moveToScreen(bool force) {
|
|||
}
|
||||
|
||||
bool OverlayWidget::videoShown() const {
|
||||
return _streamed && !_streamed->shared->info().video.cover.isNull();
|
||||
return _streamed && !_streamed->instance.info().video.cover.isNull();
|
||||
}
|
||||
|
||||
QSize OverlayWidget::videoSize() const {
|
||||
Expects(videoShown());
|
||||
|
||||
return _streamed->shared->info().video.size;
|
||||
return _streamed->instance.info().video.size;
|
||||
}
|
||||
|
||||
bool OverlayWidget::videoIsGifv() const {
|
||||
|
@ -387,9 +376,9 @@ QImage OverlayWidget::videoFrame() const {
|
|||
//request.radius = (_doc && _doc->isVideoMessage())
|
||||
// ? ImageRoundRadius::Ellipse
|
||||
// : ImageRoundRadius::None;
|
||||
return _streamed->shared->player().ready()
|
||||
? _streamed->shared->player().frame(request)
|
||||
: _streamed->shared->info().video.cover;
|
||||
return _streamed->instance.player().ready()
|
||||
? _streamed->instance.player().frame(request)
|
||||
: _streamed->instance.info().video.cover;
|
||||
}
|
||||
|
||||
QImage OverlayWidget::videoFrameForDirectPaint() const {
|
||||
|
@ -2007,12 +1996,12 @@ void OverlayWidget::initStreaming() {
|
|||
|
||||
Core::App().updateNonIdle();
|
||||
|
||||
_streamed->shared->player().updates(
|
||||
_streamed->instance.player().updates(
|
||||
) | rpl::start_with_next_error([=](Streaming::Update &&update) {
|
||||
handleStreamingUpdate(std::move(update));
|
||||
}, [=](Streaming::Error &&error) {
|
||||
handleStreamingError(std::move(error));
|
||||
}, _streamed->lifetime);
|
||||
}, _streamed->instance.lifetime());
|
||||
|
||||
restartAtSeekPosition(0);
|
||||
}
|
||||
|
@ -2092,14 +2081,14 @@ void OverlayWidget::createStreamingObjects() {
|
|||
QImage OverlayWidget::transformVideoFrame(QImage frame) const {
|
||||
Expects(videoShown());
|
||||
|
||||
if (_streamed->shared->info().video.rotation != 0) {
|
||||
if (_streamed->instance.info().video.rotation != 0) {
|
||||
auto transform = QTransform();
|
||||
transform.rotate(_streamed->shared->info().video.rotation);
|
||||
transform.rotate(_streamed->instance.info().video.rotation);
|
||||
frame = frame.transformed(transform);
|
||||
}
|
||||
if (frame.size() != _streamed->shared->info().video.size) {
|
||||
if (frame.size() != _streamed->instance.info().video.size) {
|
||||
frame = frame.scaled(
|
||||
_streamed->shared->info().video.size,
|
||||
_streamed->instance.info().video.size,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
|
@ -2276,18 +2265,18 @@ void OverlayWidget::playbackPauseResume() {
|
|||
Expects(_streamed != nullptr);
|
||||
|
||||
_streamed->resumeOnCallEnd = false;
|
||||
if (_streamed->shared->player().failed()) {
|
||||
if (_streamed->instance.player().failed()) {
|
||||
clearStreaming();
|
||||
initStreaming();
|
||||
} else if (_streamed->shared->player().finished()) {
|
||||
} else if (_streamed->instance.player().finished()) {
|
||||
_streamingStartPaused = false;
|
||||
restartAtSeekPosition(0);
|
||||
} else if (_streamed->shared->player().paused()) {
|
||||
_streamed->shared->resume();
|
||||
} else if (_streamed->instance.player().paused()) {
|
||||
_streamed->instance.resume();
|
||||
updatePlaybackState();
|
||||
playbackPauseMusic();
|
||||
} else {
|
||||
_streamed->shared->pause();
|
||||
_streamed->instance.pause();
|
||||
updatePlaybackState();
|
||||
}
|
||||
}
|
||||
|
@ -2297,7 +2286,7 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
|||
Expects(_doc != nullptr);
|
||||
|
||||
if (videoShown()) {
|
||||
_streamed->shared->saveFrameToCover();
|
||||
_streamed->instance.saveFrameToCover();
|
||||
_current = Images::PixmapFast(transformVideoFrame(videoFrame()));
|
||||
update(contentRect());
|
||||
}
|
||||
|
@ -2308,9 +2297,9 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
|||
options.mode = Streaming::Mode::Video;
|
||||
options.loop = true;
|
||||
}
|
||||
_streamed->shared->play(options);
|
||||
_streamed->instance.play(options);
|
||||
if (_streamingStartPaused) {
|
||||
_streamed->shared->pause();
|
||||
_streamed->instance.pause();
|
||||
} else {
|
||||
playbackPauseMusic();
|
||||
}
|
||||
|
@ -2322,8 +2311,8 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
|||
void OverlayWidget::playbackControlsSeekProgress(crl::time position) {
|
||||
Expects(_streamed != nullptr);
|
||||
|
||||
if (!_streamed->shared->player().paused()
|
||||
&& !_streamed->shared->player().finished()) {
|
||||
if (!_streamed->instance.player().paused()
|
||||
&& !_streamed->instance.player().finished()) {
|
||||
_streamed->pausedBySeek = true;
|
||||
playbackControlsPause();
|
||||
}
|
||||
|
@ -2333,7 +2322,7 @@ void OverlayWidget::playbackControlsSeekFinished(crl::time position) {
|
|||
Expects(_streamed != nullptr);
|
||||
|
||||
_streamingStartPaused = !_streamed->pausedBySeek
|
||||
&& !_streamed->shared->player().finished();
|
||||
&& !_streamed->instance.player().finished();
|
||||
restartAtSeekPosition(position);
|
||||
}
|
||||
|
||||
|
@ -2371,12 +2360,12 @@ void OverlayWidget::playbackToggleFullScreen() {
|
|||
void OverlayWidget::playbackPauseOnCall() {
|
||||
Expects(_streamed != nullptr);
|
||||
|
||||
if (_streamed->shared->player().finished()
|
||||
|| _streamed->shared->player().paused()) {
|
||||
if (_streamed->instance.player().finished()
|
||||
|| _streamed->instance.player().paused()) {
|
||||
return;
|
||||
}
|
||||
_streamed->resumeOnCallEnd = true;
|
||||
_streamed->shared->pause();
|
||||
_streamed->instance.pause();
|
||||
updatePlaybackState();
|
||||
}
|
||||
|
||||
|
@ -2385,7 +2374,7 @@ void OverlayWidget::playbackResumeOnCall() {
|
|||
|
||||
if (_streamed->resumeOnCallEnd) {
|
||||
_streamed->resumeOnCallEnd = false;
|
||||
_streamed->shared->resume();
|
||||
_streamed->instance.resume();
|
||||
updatePlaybackState();
|
||||
playbackPauseMusic();
|
||||
}
|
||||
|
@ -2407,7 +2396,7 @@ void OverlayWidget::updatePlaybackState() {
|
|||
if (videoIsGifv()) {
|
||||
return;
|
||||
}
|
||||
const auto state = _streamed->shared->player().prepareLegacyState();
|
||||
const auto state = _streamed->instance.player().prepareLegacyState();
|
||||
if (state.position != kTimeUnknown && state.length != kTimeUnknown) {
|
||||
_streamed->controls.updatePlayback(state);
|
||||
}
|
||||
|
@ -2711,7 +2700,7 @@ void OverlayWidget::paintEvent(QPaintEvent *e) {
|
|||
|
||||
void OverlayWidget::checkGroupThumbsAnimation() {
|
||||
if (_groupThumbs
|
||||
&& (!_streamed || _streamed->shared->player().ready())) {
|
||||
&& (!_streamed || _streamed->instance.player().ready())) {
|
||||
_groupThumbs->checkForAnimationStart();
|
||||
}
|
||||
}
|
||||
|
@ -2723,7 +2712,7 @@ void OverlayWidget::paintTransformedVideoFrame(Painter &p) {
|
|||
// const auto fill = rect.intersected(this->rect());
|
||||
// PaintImageProfile(p, image, rect, fill);
|
||||
//} else {
|
||||
const auto rotation = _streamed->shared->info().video.rotation;
|
||||
const auto rotation = _streamed->instance.info().video.rotation;
|
||||
const auto rotated = [](QRect rect, int rotation) {
|
||||
switch (rotation) {
|
||||
case 0: return rect;
|
||||
|
@ -2763,7 +2752,7 @@ void OverlayWidget::paintRadialLoading(
|
|||
bool radial,
|
||||
float64 radialOpacity) {
|
||||
if (_streamed) {
|
||||
if (!_streamed->shared->waitingShown()) {
|
||||
if (!_streamed->instance.waitingShown()) {
|
||||
return;
|
||||
}
|
||||
} else if (!radial && (!_doc || _doc->loaded())) {
|
||||
|
@ -2816,11 +2805,11 @@ void OverlayWidget::paintRadialLoadingContent(
|
|||
|
||||
if (_streamed) {
|
||||
paintBg(
|
||||
_streamed->shared->waitingOpacity(),
|
||||
_streamed->instance.waitingOpacity(),
|
||||
st::radialBg);
|
||||
Ui::InfiniteRadialAnimation::Draw(
|
||||
p,
|
||||
_streamed->shared->waitingState(),
|
||||
_streamed->instance.waitingState(),
|
||||
arc.topLeft(),
|
||||
arc.size(),
|
||||
width(),
|
||||
|
|
Loading…
Reference in New Issue