174 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
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 "dialogs/ui/dialogs_video_userpic.h"
 | 
						|
 | 
						|
#include "core/file_location.h"
 | 
						|
#include "data/data_peer.h"
 | 
						|
#include "data/data_photo.h"
 | 
						|
#include "data/data_photo_media.h"
 | 
						|
#include "data/data_file_origin.h"
 | 
						|
#include "data/data_session.h"
 | 
						|
#include "dialogs/ui/dialogs_layout.h"
 | 
						|
#include "ui/painter.h"
 | 
						|
#include "styles/style_dialogs.h"
 | 
						|
 | 
						|
namespace Dialogs::Ui {
 | 
						|
 | 
						|
VideoUserpic::VideoUserpic(not_null<PeerData*> peer, Fn<void()> repaint)
 | 
						|
: _peer(peer)
 | 
						|
, _repaint(std::move(repaint)) {
 | 
						|
}
 | 
						|
 | 
						|
VideoUserpic::~VideoUserpic() = default;
 | 
						|
 | 
						|
int VideoUserpic::frameIndex() const {
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
void VideoUserpic::paintLeft(
 | 
						|
		Painter &p,
 | 
						|
		Ui::PeerUserpicView &view,
 | 
						|
		int x,
 | 
						|
		int y,
 | 
						|
		int w,
 | 
						|
		int size,
 | 
						|
		bool paused) {
 | 
						|
	_lastSize = size;
 | 
						|
 | 
						|
	const auto photoId = _peer->userpicPhotoId();
 | 
						|
	if (_videoPhotoId != photoId) {
 | 
						|
		_videoPhotoId = photoId;
 | 
						|
		_video = nullptr;
 | 
						|
		_videoPhotoMedia = nullptr;
 | 
						|
		const auto photo = _peer->owner().photo(photoId);
 | 
						|
		if (photo->isNull()) {
 | 
						|
			_peer->updateFullForced();
 | 
						|
		} else {
 | 
						|
			_videoPhotoMedia = photo->createMediaView();
 | 
						|
			_videoPhotoMedia->videoWanted(
 | 
						|
				Data::PhotoSize::Small,
 | 
						|
				_peer->userpicPhotoOrigin());
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (!_video) {
 | 
						|
		if (!_videoPhotoMedia) {
 | 
						|
			const auto photo = _peer->owner().photo(photoId);
 | 
						|
			if (!photo->isNull()) {
 | 
						|
				_videoPhotoMedia = photo->createMediaView();
 | 
						|
				_videoPhotoMedia->videoWanted(
 | 
						|
					Data::PhotoSize::Small,
 | 
						|
					_peer->userpicPhotoOrigin());
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (_videoPhotoMedia) {
 | 
						|
			auto small = _videoPhotoMedia->videoContent(
 | 
						|
				Data::PhotoSize::Small);
 | 
						|
			auto bytes = small.isEmpty()
 | 
						|
				? _videoPhotoMedia->videoContent(Data::PhotoSize::Large)
 | 
						|
				: small;
 | 
						|
			if (!bytes.isEmpty()) {
 | 
						|
				auto callback = [=](Media::Clip::Notification notification) {
 | 
						|
					clipCallback(notification);
 | 
						|
				};
 | 
						|
				_video = Media::Clip::MakeReader(
 | 
						|
					Core::FileLocation(),
 | 
						|
					std::move(bytes),
 | 
						|
					std::move(callback));
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (rtl()) {
 | 
						|
		x = w - x - size;
 | 
						|
	}
 | 
						|
	if (_video && _video->ready()) {
 | 
						|
		startReady();
 | 
						|
 | 
						|
		const auto now = paused ? crl::time(0) : crl::now();
 | 
						|
		p.drawImage(x, y, _video->current(request(size), now));
 | 
						|
	} else {
 | 
						|
		_peer->paintUserpicLeft(p, view, x, y, w, size);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
Media::Clip::FrameRequest VideoUserpic::request(int size) const {
 | 
						|
	return {
 | 
						|
		.frame = { size, size },
 | 
						|
		.outer = { size, size },
 | 
						|
		.factor = style::DevicePixelRatio(),
 | 
						|
		.radius = ImageRoundRadius::Ellipse,
 | 
						|
	};
 | 
						|
}
 | 
						|
 | 
						|
bool VideoUserpic::startReady(int size) {
 | 
						|
	if (!_video->ready() || _video->started()) {
 | 
						|
		return false;
 | 
						|
	} else if (!_lastSize) {
 | 
						|
		_lastSize = size ? size : _video->width();
 | 
						|
	}
 | 
						|
	_video->start(request(_lastSize));
 | 
						|
	_repaint();
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
void VideoUserpic::clipCallback(Media::Clip::Notification notification) {
 | 
						|
	using namespace Media::Clip;
 | 
						|
 | 
						|
	switch (notification) {
 | 
						|
	case Notification::Reinit: {
 | 
						|
		if (_video->state() == State::Error) {
 | 
						|
			_video.setBad();
 | 
						|
		} else if (startReady()) {
 | 
						|
			_repaint();
 | 
						|
		}
 | 
						|
	} break;
 | 
						|
 | 
						|
	case Notification::Repaint: _repaint(); break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void PaintUserpic(
 | 
						|
		Painter &p,
 | 
						|
		not_null<Entry*> entry,
 | 
						|
		PeerData *peer,
 | 
						|
		VideoUserpic *videoUserpic,
 | 
						|
		PeerUserpicView &view,
 | 
						|
		const Ui::PaintContext &context) {
 | 
						|
	if (peer) {
 | 
						|
		PaintUserpic(
 | 
						|
			p,
 | 
						|
			peer,
 | 
						|
			videoUserpic,
 | 
						|
			view,
 | 
						|
			context.st->padding.left(),
 | 
						|
			context.st->padding.top(),
 | 
						|
			context.width,
 | 
						|
			context.st->photoSize,
 | 
						|
			context.paused);
 | 
						|
	} else {
 | 
						|
		entry->paintUserpic(p, view, context);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void PaintUserpic(
 | 
						|
		Painter &p,
 | 
						|
		not_null<PeerData*> peer,
 | 
						|
		Ui::VideoUserpic *videoUserpic,
 | 
						|
		Ui::PeerUserpicView &view,
 | 
						|
		int x,
 | 
						|
		int y,
 | 
						|
		int outerWidth,
 | 
						|
		int size,
 | 
						|
		bool paused) {
 | 
						|
	if (videoUserpic) {
 | 
						|
		videoUserpic->paintLeft(p, view, x, y, outerWidth, size, paused);
 | 
						|
	} else {
 | 
						|
		peer->paintUserpicLeft(p, view, x, y, outerWidth, size);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
} // namespace Dialogs::Ui
 |