Play video userpics in profiles and settings.
This commit is contained in:
		
							parent
							
								
									8c45b5e0f8
								
							
						
					
					
						commit
						060fe6a928
					
				
					 3 changed files with 154 additions and 4 deletions
				
			
		| 
						 | 
					@ -816,8 +816,7 @@ int EditCaptionBox::errorTopSkip() const {
 | 
				
			||||||
void EditCaptionBox::checkStreamedIsStarted() {
 | 
					void EditCaptionBox::checkStreamedIsStarted() {
 | 
				
			||||||
	if (!_streamed) {
 | 
						if (!_streamed) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						} else if (_streamed->paused()) {
 | 
				
			||||||
	if (_streamed->paused()) {
 | 
					 | 
				
			||||||
		_streamed->resume();
 | 
							_streamed->resume();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!_streamed->active() && !_streamed->failed()) {
 | 
						if (!_streamed->active() && !_streamed->failed()) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,11 +21,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "data/data_channel.h"
 | 
					#include "data/data_channel.h"
 | 
				
			||||||
#include "data/data_cloud_file.h"
 | 
					#include "data/data_cloud_file.h"
 | 
				
			||||||
#include "data/data_changes.h"
 | 
					#include "data/data_changes.h"
 | 
				
			||||||
 | 
					#include "data/data_user.h"
 | 
				
			||||||
 | 
					#include "data/data_streaming.h"
 | 
				
			||||||
 | 
					#include "data/data_file_origin.h"
 | 
				
			||||||
#include "history/history.h"
 | 
					#include "history/history.h"
 | 
				
			||||||
#include "core/file_utilities.h"
 | 
					#include "core/file_utilities.h"
 | 
				
			||||||
#include "core/application.h"
 | 
					#include "core/application.h"
 | 
				
			||||||
#include "boxes/photo_crop_box.h"
 | 
					#include "boxes/photo_crop_box.h"
 | 
				
			||||||
#include "boxes/confirm_box.h"
 | 
					#include "boxes/confirm_box.h"
 | 
				
			||||||
 | 
					#include "media/streaming/media_streaming_instance.h"
 | 
				
			||||||
 | 
					#include "media/streaming/media_streaming_player.h"
 | 
				
			||||||
 | 
					#include "media/streaming/media_streaming_document.h"
 | 
				
			||||||
#include "window/window_session_controller.h"
 | 
					#include "window/window_session_controller.h"
 | 
				
			||||||
#include "lang/lang_keys.h"
 | 
					#include "lang/lang_keys.h"
 | 
				
			||||||
#include "main/main_session.h"
 | 
					#include "main/main_session.h"
 | 
				
			||||||
| 
						 | 
					@ -582,7 +588,7 @@ void UserpicButton::setClickHandlerByRole() {
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case Role::OpenPhoto:
 | 
						case Role::OpenPhoto:
 | 
				
			||||||
		addClickHandler([this] {
 | 
							addClickHandler([=] {
 | 
				
			||||||
			openPeerPhoto();
 | 
								openPeerPhoto();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -674,7 +680,7 @@ void UserpicButton::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
			p.drawPixmapLeft(photoPosition, width(), _oldUserpic);
 | 
								p.drawPixmapLeft(photoPosition, width(), _oldUserpic);
 | 
				
			||||||
			p.setOpacity(_a_appearance.value(1.));
 | 
								p.setOpacity(_a_appearance.value(1.));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		p.drawPixmapLeft(photoPosition, width(), _userpic);
 | 
							paintUserpicFrame(p, photoPosition);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_role == Role::ChangePhoto) {
 | 
						if (_role == Role::ChangePhoto) {
 | 
				
			||||||
| 
						 | 
					@ -754,6 +760,27 @@ void UserpicButton::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::paintUserpicFrame(Painter &p, QPoint photoPosition) {
 | 
				
			||||||
 | 
						checkStreamedIsStarted();
 | 
				
			||||||
 | 
						if (_streamed
 | 
				
			||||||
 | 
							&& _streamed->player().ready()
 | 
				
			||||||
 | 
							&& !_streamed->player().videoSize().isEmpty()) {
 | 
				
			||||||
 | 
							const auto paused = _controller->isGifPausedAtLeastFor(
 | 
				
			||||||
 | 
								Window::GifPauseReason::RoundPlaying);
 | 
				
			||||||
 | 
							auto request = Media::Streaming::FrameRequest();
 | 
				
			||||||
 | 
							auto size = QSize{ _st.photoSize, _st.photoSize };
 | 
				
			||||||
 | 
							request.outer = size * cIntRetinaFactor();
 | 
				
			||||||
 | 
							request.resize = size * cIntRetinaFactor();
 | 
				
			||||||
 | 
							request.radius = ImageRoundRadius::Ellipse;
 | 
				
			||||||
 | 
							p.drawImage(QRect(photoPosition, size), _streamed->frame(request));
 | 
				
			||||||
 | 
							if (!paused) {
 | 
				
			||||||
 | 
								_streamed->markFrameShown();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.drawPixmapLeft(photoPosition, width(), _userpic);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QPoint UserpicButton::countPhotoPosition() const {
 | 
					QPoint UserpicButton::countPhotoPosition() const {
 | 
				
			||||||
	auto photoLeft = (_st.photoPosition.x() < 0)
 | 
						auto photoLeft = (_st.photoPosition.x() < 0)
 | 
				
			||||||
		? (width() - _st.photoSize) / 2
 | 
							? (width() - _st.photoSize) / 2
 | 
				
			||||||
| 
						 | 
					@ -790,6 +817,7 @@ void UserpicButton::processPeerPhoto() {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		_canOpenPhoto = (_peer->userpicPhotoId() != 0);
 | 
							_canOpenPhoto = (_peer->userpicPhotoId() != 0);
 | 
				
			||||||
		updateCursor();
 | 
							updateCursor();
 | 
				
			||||||
 | 
							updateVideo();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -801,6 +829,109 @@ void UserpicButton::updateCursor() {
 | 
				
			||||||
	setPointerCursor(pointer);
 | 
						setPointerCursor(pointer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool UserpicButton::createStreamingObjects(not_null<PhotoData*> photo) {
 | 
				
			||||||
 | 
						Expects(_peer != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using namespace Media::Streaming;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto origin = _peer->isUser()
 | 
				
			||||||
 | 
							? Data::FileOriginUserPhoto(_peer->asUser()->bareId(), photo->id)
 | 
				
			||||||
 | 
							: Data::FileOrigin(Data::FileOriginPeerPhoto(_peer->id));
 | 
				
			||||||
 | 
						_streamed = std::make_unique<Instance>(
 | 
				
			||||||
 | 
							photo->owner().streaming().sharedDocument(photo, origin),
 | 
				
			||||||
 | 
							[=] { update(); });
 | 
				
			||||||
 | 
						_streamed->player().updates(
 | 
				
			||||||
 | 
						) | rpl::start_with_next_error([=](Update &&update) {
 | 
				
			||||||
 | 
							handleStreamingUpdate(std::move(update));
 | 
				
			||||||
 | 
						}, [=](Error &&error) {
 | 
				
			||||||
 | 
							handleStreamingError(std::move(error));
 | 
				
			||||||
 | 
						}, _streamed->lifetime());
 | 
				
			||||||
 | 
						if (_streamed->ready()) {
 | 
				
			||||||
 | 
							streamingReady(base::duplicate(_streamed->info()));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!_streamed->valid()) {
 | 
				
			||||||
 | 
							clearStreaming();
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::clearStreaming() {
 | 
				
			||||||
 | 
						_streamed = nullptr;
 | 
				
			||||||
 | 
						_streamedPhoto = nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::handleStreamingUpdate(Media::Streaming::Update &&update) {
 | 
				
			||||||
 | 
						using namespace Media::Streaming;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						update.data.match([&](Information &update) {
 | 
				
			||||||
 | 
							streamingReady(std::move(update));
 | 
				
			||||||
 | 
						}, [&](const PreloadedVideo &update) {
 | 
				
			||||||
 | 
						}, [&](const UpdateVideo &update) {
 | 
				
			||||||
 | 
							this->update();
 | 
				
			||||||
 | 
						}, [&](const PreloadedAudio &update) {
 | 
				
			||||||
 | 
						}, [&](const UpdateAudio &update) {
 | 
				
			||||||
 | 
						}, [&](const WaitingForData &update) {
 | 
				
			||||||
 | 
						}, [&](MutedByOther) {
 | 
				
			||||||
 | 
						}, [&](Finished) {
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::handleStreamingError(Media::Streaming::Error &&error) {
 | 
				
			||||||
 | 
						Expects(_peer != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_streamedPhoto->setVideoPlaybackFailed();
 | 
				
			||||||
 | 
						_streamedPhoto = nullptr;
 | 
				
			||||||
 | 
						_streamed = nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::streamingReady(Media::Streaming::Information &&info) {
 | 
				
			||||||
 | 
						update();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::updateVideo() {
 | 
				
			||||||
 | 
						Expects(_role == Role::OpenPhoto);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using namespace Media::Streaming;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const auto id = _peer->userpicPhotoId();
 | 
				
			||||||
 | 
						if (!id) {
 | 
				
			||||||
 | 
							clearStreaming();
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const auto photo = _peer->owner().photo(id);
 | 
				
			||||||
 | 
						if (!photo->date || !photo->videoCanBePlayed()) {
 | 
				
			||||||
 | 
							clearStreaming();
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (_streamed && _streamedPhoto == photo) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!createStreamingObjects(photo)) {
 | 
				
			||||||
 | 
							photo->setVideoPlaybackFailed();
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_streamedPhoto = photo;
 | 
				
			||||||
 | 
						checkStreamedIsStarted();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UserpicButton::checkStreamedIsStarted() {
 | 
				
			||||||
 | 
						Expects(!_streamed || _streamedPhoto);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!_streamed) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (_streamed->paused()) {
 | 
				
			||||||
 | 
							_streamed->resume();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (_streamed && !_streamed->active() && !_streamed->failed()) {
 | 
				
			||||||
 | 
							const auto position = _streamedPhoto->videoStartPosition();
 | 
				
			||||||
 | 
							auto options = Media::Streaming::PlaybackOptions();
 | 
				
			||||||
 | 
							options.position = position;
 | 
				
			||||||
 | 
							options.mode = Media::Streaming::Mode::Video;
 | 
				
			||||||
 | 
							options.loop = true;
 | 
				
			||||||
 | 
							_streamed->play(options);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void UserpicButton::mouseMoveEvent(QMouseEvent *e) {
 | 
					void UserpicButton::mouseMoveEvent(QMouseEvent *e) {
 | 
				
			||||||
	RippleButton::mouseMoveEvent(e);
 | 
						RippleButton::mouseMoveEvent(e);
 | 
				
			||||||
	if (_role == Role::OpenPhoto) {
 | 
						if (_role == Role::OpenPhoto) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,16 @@ namespace Window {
 | 
				
			||||||
class SessionController;
 | 
					class SessionController;
 | 
				
			||||||
} // namespace Window
 | 
					} // namespace Window
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Media {
 | 
				
			||||||
 | 
					namespace Streaming {
 | 
				
			||||||
 | 
					class Instance;
 | 
				
			||||||
 | 
					class Document;
 | 
				
			||||||
 | 
					struct Update;
 | 
				
			||||||
 | 
					enum class Error;
 | 
				
			||||||
 | 
					struct Information;
 | 
				
			||||||
 | 
					} // namespace Streaming
 | 
				
			||||||
 | 
					} // namespace Media
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Ui {
 | 
					namespace Ui {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InfiniteRadialAnimation;
 | 
					class InfiniteRadialAnimation;
 | 
				
			||||||
| 
						 | 
					@ -211,7 +221,15 @@ private:
 | 
				
			||||||
	void updateCursorInChangeOverlay(QPoint localPos);
 | 
						void updateCursorInChangeOverlay(QPoint localPos);
 | 
				
			||||||
	void setCursorInChangeOverlay(bool inOverlay);
 | 
						void setCursorInChangeOverlay(bool inOverlay);
 | 
				
			||||||
	void updateCursor();
 | 
						void updateCursor();
 | 
				
			||||||
 | 
						void updateVideo();
 | 
				
			||||||
 | 
						void checkStreamedIsStarted();
 | 
				
			||||||
 | 
						bool createStreamingObjects(not_null<PhotoData*> photo);
 | 
				
			||||||
 | 
						void clearStreaming();
 | 
				
			||||||
 | 
						void handleStreamingUpdate(Media::Streaming::Update &&update);
 | 
				
			||||||
 | 
						void handleStreamingError(Media::Streaming::Error &&error);
 | 
				
			||||||
 | 
						void streamingReady(Media::Streaming::Information &&info);
 | 
				
			||||||
	bool showSavedMessages() const;
 | 
						bool showSavedMessages() const;
 | 
				
			||||||
 | 
						void paintUserpicFrame(Painter &p, QPoint photoPosition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void grabOldUserpic();
 | 
						void grabOldUserpic();
 | 
				
			||||||
	void setClickHandlerByRole();
 | 
						void setClickHandlerByRole();
 | 
				
			||||||
| 
						 | 
					@ -233,6 +251,8 @@ private:
 | 
				
			||||||
	InMemoryKey _userpicUniqueKey;
 | 
						InMemoryKey _userpicUniqueKey;
 | 
				
			||||||
	Ui::Animations::Simple _a_appearance;
 | 
						Ui::Animations::Simple _a_appearance;
 | 
				
			||||||
	QImage _result;
 | 
						QImage _result;
 | 
				
			||||||
 | 
						std::unique_ptr<Media::Streaming::Instance> _streamed;
 | 
				
			||||||
 | 
						PhotoData *_streamedPhoto = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool _showSavedMessagesOnSelf = false;
 | 
						bool _showSavedMessagesOnSelf = false;
 | 
				
			||||||
	bool _canOpenPhoto = false;
 | 
						bool _canOpenPhoto = false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue