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