Support round video inline playback with sound.
This commit is contained in:
		
							parent
							
								
									cbf040b4dc
								
							
						
					
					
						commit
						5480a63beb
					
				
					 12 changed files with 122 additions and 50 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								Telegram/Resources/icons/volume_mute.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Telegram/Resources/icons/volume_mute.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 147 B  | 
							
								
								
									
										
											BIN
										
									
								
								Telegram/Resources/icons/volume_mute@2x.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Telegram/Resources/icons/volume_mute@2x.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 206 B  | 
| 
						 | 
					@ -418,3 +418,7 @@ msgWaveformBar: 2px;
 | 
				
			||||||
msgWaveformSkip: 1px;
 | 
					msgWaveformSkip: 1px;
 | 
				
			||||||
msgWaveformMin: 2px;
 | 
					msgWaveformMin: 2px;
 | 
				
			||||||
msgWaveformMax: 20px;
 | 
					msgWaveformMax: 20px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					historyVideoMessageMute: icon {{ "volume_mute", historyFileThumbIconFg }};
 | 
				
			||||||
 | 
					historyVideoMessageMuteSelected: icon {{ "volume_mute", historyFileThumbIconFgSelected }};
 | 
				
			||||||
 | 
					historyVideoMessageMuteSize: 25px;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -892,17 +892,20 @@ void HistoryItem::clipCallback(Media::Clip::Notification notification) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (notification) {
 | 
						switch (notification) {
 | 
				
			||||||
	case NotificationReinit: {
 | 
						case NotificationReinit: {
 | 
				
			||||||
		bool stopped = false;
 | 
							auto stopped = false;
 | 
				
			||||||
		if (reader->autoPausedGif()) {
 | 
							if (reader->autoPausedGif()) {
 | 
				
			||||||
			if (MainWidget *m = App::main()) {
 | 
								if (auto m = App::main()) {
 | 
				
			||||||
				if (!m->isItemVisible(this)) { // stop animation if it is not visible
 | 
									if (!m->isItemVisible(this)) { // stop animation if it is not visible
 | 
				
			||||||
					media->stopInline();
 | 
										media->stopInline();
 | 
				
			||||||
					if (DocumentData *document = media->getDocument()) { // forget data from memory
 | 
										if (auto document = media->getDocument()) { // forget data from memory
 | 
				
			||||||
						document->forget();
 | 
											document->forget();
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					stopped = true;
 | 
										stopped = true;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							} else if (reader->mode() == Media::Clip::Reader::Mode::Video && reader->state() == Media::Clip::State::Finished) {
 | 
				
			||||||
 | 
								// Stop finished video message.
 | 
				
			||||||
 | 
								media->stopInline();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!stopped) {
 | 
							if (!stopped) {
 | 
				
			||||||
			setPendingInitDimensions();
 | 
								setPendingInitDimensions();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1653,7 +1653,7 @@ HistoryGif::HistoryGif(HistoryItem *parent, DocumentData *document, const QStrin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setStatusSize(FileStatusSizeReady);
 | 
						setStatusSize(FileStatusSizeReady);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!caption.isEmpty()) {
 | 
						if (!caption.isEmpty() && !_data->isRoundVideo()) {
 | 
				
			||||||
		_caption.setText(st::messageTextStyle, caption + _parent->skipBlock(), itemTextNoMonoOptions(_parent));
 | 
							_caption.setText(st::messageTextStyle, caption + _parent->skipBlock(), itemTextNoMonoOptions(_parent));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1681,8 +1681,7 @@ void HistoryGif::initDimensions() {
 | 
				
			||||||
		if (!_gif->autoplay()) {
 | 
							if (!_gif->autoplay()) {
 | 
				
			||||||
			Ui::show(Box<InformBox>(lang(lng_gif_error)));
 | 
								Ui::show(Box<InformBox>(lang(lng_gif_error)));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		App::unregGifItem(_gif.get());
 | 
							setClipReader(Media::Clip::ReaderPointer::Bad());
 | 
				
			||||||
		_gif.setBad();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_gif && _gif->ready()) {
 | 
						if (_gif && _gif->ready()) {
 | 
				
			||||||
| 
						 | 
					@ -1797,10 +1796,12 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
 | 
				
			||||||
	if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
 | 
						if (_width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_data->automaticLoad(_parent);
 | 
						_data->automaticLoad(_parent);
 | 
				
			||||||
	bool loaded = _data->loaded(), displayLoading = (_parent->id < 0) || _data->displayLoading();
 | 
						auto loaded = _data->loaded();
 | 
				
			||||||
	bool selected = (selection == FullSelection);
 | 
						auto displayLoading = (_parent->id < 0) || _data->displayLoading();
 | 
				
			||||||
 | 
						auto selected = (selection == FullSelection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (loaded && !_gif && !_gif.isBad() && cAutoPlayGif()) {
 | 
						auto videoFinished = _gif && (_gif->mode() == Media::Clip::Reader::Mode::Video) && (_gif->state() == Media::Clip::State::Finished);
 | 
				
			||||||
 | 
						if (loaded && cAutoPlayGif() && ((!_gif && !_gif.isBad()) || videoFinished)) {
 | 
				
			||||||
		Ui::autoplayMediaInlineAsync(_parent->fullId());
 | 
							Ui::autoplayMediaInlineAsync(_parent->fullId());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1811,6 +1812,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
 | 
				
			||||||
	auto captionw = width - st::msgPadding.left() - st::msgPadding.right();
 | 
						auto captionw = width - st::msgPadding.left() - st::msgPadding.right();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto isRound = _data->isRoundVideo();
 | 
						auto isRound = _data->isRoundVideo();
 | 
				
			||||||
 | 
						auto displayMute = false;
 | 
				
			||||||
	auto animating = (_gif && _gif->started());
 | 
						auto animating = (_gif && _gif->started());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!animating || _parent->id < 0) {
 | 
						if (!animating || _parent->id < 0) {
 | 
				
			||||||
| 
						 | 
					@ -1848,6 +1850,13 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
 | 
				
			||||||
		| ((isBubbleBottom() && _caption.isEmpty()) ? (ImageRoundCorner::BottomLeft | ImageRoundCorner::BottomRight) : ImageRoundCorner::None));
 | 
							| ((isBubbleBottom() && _caption.isEmpty()) ? (ImageRoundCorner::BottomLeft | ImageRoundCorner::BottomRight) : ImageRoundCorner::None));
 | 
				
			||||||
	if (animating) {
 | 
						if (animating) {
 | 
				
			||||||
		auto paused = App::wnd()->controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
 | 
							auto paused = App::wnd()->controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
 | 
				
			||||||
 | 
							if (isRound) {
 | 
				
			||||||
 | 
								if (_gif->mode() == Media::Clip::Reader::Mode::Video) {
 | 
				
			||||||
 | 
									paused = false;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									displayMute = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, roundRadius, roundCorners, paused ? 0 : ms));
 | 
							p.drawPixmap(rthumb.topLeft(), _gif->current(_thumbw, _thumbh, width, height, roundRadius, roundCorners, paused ? 0 : ms));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height, roundRadius, roundCorners));
 | 
							p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_thumbw, _thumbh, width, height, roundRadius, roundCorners));
 | 
				
			||||||
| 
						 | 
					@ -1857,8 +1866,8 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (radial || _gif.isBad() || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif()))) {
 | 
						if (radial || _gif.isBad() || (!_gif && ((!loaded && !_data->loading()) || !cAutoPlayGif()))) {
 | 
				
			||||||
		float64 radialOpacity = (radial && loaded && _parent->id > 0) ? _animation->radial.opacity() : 1;
 | 
							auto radialOpacity = (radial && loaded && _parent->id > 0) ? _animation->radial.opacity() : 1.;
 | 
				
			||||||
		QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
 | 
							auto inner = QRect(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
 | 
				
			||||||
		p.setPen(Qt::NoPen);
 | 
							p.setPen(Qt::NoPen);
 | 
				
			||||||
		if (selected) {
 | 
							if (selected) {
 | 
				
			||||||
			p.setBrush(st::msgDateImgBgSelected);
 | 
								p.setBrush(st::msgDateImgBgSelected);
 | 
				
			||||||
| 
						 | 
					@ -1908,13 +1917,21 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM
 | 
				
			||||||
			p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x());
 | 
								p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (displayMute) {
 | 
				
			||||||
 | 
							auto muteRect = rtlrect(rthumb.x() + (rthumb.width() - st::historyVideoMessageMuteSize) / 2, rthumb.y() + rthumb.height() - st::msgDateImgDelta - st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, st::historyVideoMessageMuteSize, _width);
 | 
				
			||||||
 | 
							p.setPen(Qt::NoPen);
 | 
				
			||||||
 | 
							p.setBrush(selected ? st::msgDateImgBgSelected : st::msgDateImgBg);
 | 
				
			||||||
 | 
							PainterHighQualityEnabler hq(p);
 | 
				
			||||||
 | 
							p.drawEllipse(muteRect);
 | 
				
			||||||
 | 
							(selected ? st::historyVideoMessageMuteSelected : st::historyVideoMessageMute).paintInCenter(p, muteRect);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (isRound) {
 | 
						if (isRound) {
 | 
				
			||||||
		auto mediaUnread = _parent->isMediaUnread();
 | 
							auto mediaUnread = _parent->isMediaUnread();
 | 
				
			||||||
		auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
 | 
							auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
 | 
				
			||||||
		auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
 | 
							auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
 | 
				
			||||||
		auto statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x();
 | 
							auto statusX = skipx + st::msgDateImgDelta + st::msgDateImgPadding.x();
 | 
				
			||||||
		auto statusY = skipy + height - st::msgDateImgDelta - statusH;
 | 
							auto statusY = skipy + height - st::msgDateImgDelta - statusH + st::msgDateImgPadding.y();
 | 
				
			||||||
		if (_parent->isMediaUnread()) {
 | 
							if (_parent->isMediaUnread()) {
 | 
				
			||||||
			statusW += st::mediaUnreadSkip + st::mediaUnreadSize;
 | 
								statusW += st::mediaUnreadSkip + st::mediaUnreadSize;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1970,7 +1987,7 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request)
 | 
				
			||||||
	if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
 | 
						if (x >= skipx && y >= skipy && x < skipx + width && y < skipy + height) {
 | 
				
			||||||
		if (_data->uploading()) {
 | 
							if (_data->uploading()) {
 | 
				
			||||||
			result.link = _cancell;
 | 
								result.link = _cancell;
 | 
				
			||||||
		} else if (!_gif || !cAutoPlayGif()) {
 | 
							} else if (!_gif || !cAutoPlayGif() || _data->isRoundVideo()) {
 | 
				
			||||||
			result.link = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
 | 
								result.link = _data->loaded() ? _openl : (_data->loading() ? _cancell : _savel);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (_parent->getMedia() == this) {
 | 
							if (_parent->getMedia() == this) {
 | 
				
			||||||
| 
						 | 
					@ -2047,35 +2064,56 @@ ImagePtr HistoryGif::replyPreview() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool HistoryGif::playInline(bool autoplay) {
 | 
					bool HistoryGif::playInline(bool autoplay) {
 | 
				
			||||||
 | 
						using Mode = Media::Clip::Reader::Mode;
 | 
				
			||||||
 | 
						if (_data->isRoundVideo() && _gif) {
 | 
				
			||||||
 | 
							// Stop autoplayed silent video when we start playback by click.
 | 
				
			||||||
 | 
							// Stop finished video message when autoplay starts.
 | 
				
			||||||
 | 
							if ((!autoplay && _gif->mode() == Mode::Gif)
 | 
				
			||||||
 | 
								|| (autoplay && _gif->mode() == Mode::Video && _gif->state() == Media::Clip::State::Finished)) {
 | 
				
			||||||
 | 
								stopInline();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (_gif) {
 | 
						if (_gif) {
 | 
				
			||||||
		stopInline();
 | 
							stopInline();
 | 
				
			||||||
	} else if (_data->loaded(DocumentData::FilePathResolveChecked)) {
 | 
						} else if (_data->loaded(DocumentData::FilePathResolveChecked)) {
 | 
				
			||||||
		if (!cAutoPlayGif()) {
 | 
							if (!cAutoPlayGif()) {
 | 
				
			||||||
			App::stopGifItems();
 | 
								App::stopGifItems();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		_gif = Media::Clip::MakeReader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) {
 | 
							auto mode = (!autoplay && _data->isRoundVideo()) ? Mode::Video : Mode::Gif;
 | 
				
			||||||
 | 
							setClipReader(Media::Clip::MakeReader(_data->location(), _data->data(), [this](Media::Clip::Notification notification) {
 | 
				
			||||||
			_parent->clipCallback(notification);
 | 
								_parent->clipCallback(notification);
 | 
				
			||||||
		});
 | 
							}, mode));
 | 
				
			||||||
		App::regGifItem(_gif.get(), _parent);
 | 
							if (mode == Mode::Video) {
 | 
				
			||||||
		if (_gif) _gif->setAutoplay();
 | 
								if (App::main()) {
 | 
				
			||||||
 | 
									App::main()->mediaMarkRead(_data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (_gif && autoplay) {
 | 
				
			||||||
 | 
								_gif->setAutoplay();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HistoryGif::stopInline() {
 | 
					void HistoryGif::stopInline() {
 | 
				
			||||||
	if (_gif) {
 | 
						clearClipReader();
 | 
				
			||||||
		App::unregGifItem(_gif.get());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	_gif.reset();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_parent->setPendingInitDimensions();
 | 
						_parent->setPendingInitDimensions();
 | 
				
			||||||
	Notify::historyItemLayoutChanged(_parent);
 | 
						Notify::historyItemLayoutChanged(_parent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HistoryGif::~HistoryGif() {
 | 
					void HistoryGif::setClipReader(Media::Clip::ReaderPointer gif) {
 | 
				
			||||||
	if (_gif) {
 | 
						if (_gif) {
 | 
				
			||||||
		App::unregGifItem(_gif.get());
 | 
							App::unregGifItem(_gif.get());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						_gif = std::move(gif);
 | 
				
			||||||
 | 
						if (_gif) {
 | 
				
			||||||
 | 
							App::regGifItem(_gif.get(), _parent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HistoryGif::~HistoryGif() {
 | 
				
			||||||
 | 
						clearClipReader();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float64 HistoryGif::dataProgress() const {
 | 
					float64 HistoryGif::dataProgress() const {
 | 
				
			||||||
| 
						 | 
					@ -2099,10 +2137,6 @@ HistorySticker::HistorySticker(HistoryItem *parent, DocumentData *document) : Hi
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestClickHandler : public ClickHandler {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void HistorySticker::initDimensions() {
 | 
					void HistorySticker::initDimensions() {
 | 
				
			||||||
	auto sticker = _data->sticker();
 | 
						auto sticker = _data->sticker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -515,6 +515,9 @@ public:
 | 
				
			||||||
		return _caption.originalTextWithEntities();
 | 
							return _caption.originalTextWithEntities();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	bool needsBubble() const override {
 | 
						bool needsBubble() const override {
 | 
				
			||||||
 | 
							if (_data->isRoundVideo()) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (!_caption.isEmpty()) {
 | 
							if (!_caption.isEmpty()) {
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -546,6 +549,11 @@ protected:
 | 
				
			||||||
	bool dataFinished() const override;
 | 
						bool dataFinished() const override;
 | 
				
			||||||
	bool dataLoaded() const override;
 | 
						bool dataLoaded() const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void setClipReader(Media::Clip::ReaderPointer gif);
 | 
				
			||||||
 | 
						void clearClipReader() {
 | 
				
			||||||
 | 
							setClipReader(Media::Clip::ReaderPointer());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	gsl::not_null<DocumentData*> _data;
 | 
						gsl::not_null<DocumentData*> _data;
 | 
				
			||||||
	int32 _thumbw = 1;
 | 
						int32 _thumbw = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,10 @@ MediaOverviewType messageMediaToOverviewType(HistoryMedia *media) {
 | 
				
			||||||
	case MediaTypeFile: return OverviewFiles;
 | 
						case MediaTypeFile: return OverviewFiles;
 | 
				
			||||||
	case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewCount;
 | 
						case MediaTypeMusicFile: return media->getDocument()->isMusic() ? OverviewMusicFiles : OverviewCount;
 | 
				
			||||||
	case MediaTypeVoiceFile: return OverviewVoiceFiles;
 | 
						case MediaTypeVoiceFile: return OverviewVoiceFiles;
 | 
				
			||||||
	case MediaTypeGif: return media->getDocument()->isGifv() ? OverviewCount : OverviewFiles;
 | 
						case MediaTypeGif: {
 | 
				
			||||||
 | 
							auto document = media->getDocument();
 | 
				
			||||||
 | 
							return (document->isGifv() || document->isRoundVideo()) ? OverviewCount : OverviewFiles;
 | 
				
			||||||
 | 
						} break;
 | 
				
			||||||
	default: break;
 | 
						default: break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return OverviewCount;
 | 
						return OverviewCount;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -338,8 +338,8 @@ void Gif::clipCallback(Media::Clip::Notification notification) {
 | 
				
			||||||
				_gif.setBad();
 | 
									_gif.setBad();
 | 
				
			||||||
				getShownDocument()->forget();
 | 
									getShownDocument()->forget();
 | 
				
			||||||
			} else if (_gif->ready() && !_gif->started()) {
 | 
								} else if (_gif->ready() && !_gif->started()) {
 | 
				
			||||||
				int32 height = st::inlineMediaHeight;
 | 
									auto height = st::inlineMediaHeight;
 | 
				
			||||||
				QSize frame = countFrameSize();
 | 
									auto frame = countFrameSize();
 | 
				
			||||||
				_gif->start(frame.width(), frame.height(), _width, height, ImageRoundRadius::None, ImageRoundCorner::None);
 | 
									_gif->start(frame.width(), frame.height(), _width, height, ImageRoundRadius::None, ImageRoundCorner::None);
 | 
				
			||||||
			} else if (_gif->autoPausedGif() && !context()->inlineItemVisible(this)) {
 | 
								} else if (_gif->autoPausedGif() && !context()->inlineItemVisible(this)) {
 | 
				
			||||||
				_gif.reset();
 | 
									_gif.reset();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,11 +222,12 @@ bool MediaView::fileBubbleShown() const {
 | 
				
			||||||
bool MediaView::gifShown() const {
 | 
					bool MediaView::gifShown() const {
 | 
				
			||||||
	if (_gif && _gif->ready()) {
 | 
						if (_gif && _gif->ready()) {
 | 
				
			||||||
		if (!_gif->started()) {
 | 
							if (!_gif->started()) {
 | 
				
			||||||
			if (_doc->isVideo() && _autoplayVideoDocument != _doc && !_gif->videoPaused()) {
 | 
								if ((_doc->isVideo() || _doc->isRoundVideo()) && _autoplayVideoDocument != _doc && !_gif->videoPaused()) {
 | 
				
			||||||
				_gif->pauseResumeVideo();
 | 
									_gif->pauseResumeVideo();
 | 
				
			||||||
				const_cast<MediaView*>(this)->_videoPaused = _gif->videoPaused();
 | 
									const_cast<MediaView*>(this)->_videoPaused = _gif->videoPaused();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			_gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None);
 | 
								auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None;
 | 
				
			||||||
 | 
								_gif->start(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::All);
 | 
				
			||||||
			const_cast<MediaView*>(this)->_current = QPixmap();
 | 
								const_cast<MediaView*>(this)->_current = QPixmap();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return true;// _gif->state() != Media::Clip::State::Error;
 | 
							return true;// _gif->state() != Media::Clip::State::Error;
 | 
				
			||||||
| 
						 | 
					@ -522,7 +523,7 @@ void MediaView::step_radial(TimeMs ms, bool timer) {
 | 
				
			||||||
		update(radialRect());
 | 
							update(radialRect());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (_doc && _doc->loaded() && _doc->size < App::kImageSizeLimit && (!_radial.animating() || _doc->isAnimation() || _doc->isVideo())) {
 | 
						if (_doc && _doc->loaded() && _doc->size < App::kImageSizeLimit && (!_radial.animating() || _doc->isAnimation() || _doc->isVideo())) {
 | 
				
			||||||
		if (_doc->isVideo()) {
 | 
							if (_doc->isVideo() || _doc->isRoundVideo()) {
 | 
				
			||||||
			_autoplayVideoDocument = _doc;
 | 
								_autoplayVideoDocument = _doc;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideo())) {
 | 
							if (!_doc->data().isEmpty() && (_doc->isAnimation() || _doc->isVideo())) {
 | 
				
			||||||
| 
						 | 
					@ -828,7 +829,7 @@ void MediaView::clipCallback(Media::Clip::Notification notification) {
 | 
				
			||||||
				_videoStopped = true;
 | 
									_videoStopped = true;
 | 
				
			||||||
				updateSilentVideoPlaybackState();
 | 
									updateSilentVideoPlaybackState();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				_videoIsSilent = _doc->isVideo() && !_gif->hasAudio();
 | 
									_videoIsSilent = (_doc->isVideo() || _doc->isRoundVideo()) && !_gif->hasAudio();
 | 
				
			||||||
				_videoDurationMs = _gif->getDurationMs();
 | 
									_videoDurationMs = _gif->getDurationMs();
 | 
				
			||||||
				_videoPositionMs = _gif->getPositionMs();
 | 
									_videoPositionMs = _gif->getPositionMs();
 | 
				
			||||||
				if (_videoIsSilent) {
 | 
									if (_videoIsSilent) {
 | 
				
			||||||
| 
						 | 
					@ -1140,7 +1141,7 @@ void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
 | 
				
			||||||
		_overview = doc->isVideo() ? OverviewVideos : OverviewFiles;
 | 
							_overview = doc->isVideo() ? OverviewVideos : OverviewFiles;
 | 
				
			||||||
		findCurrent();
 | 
							findCurrent();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (doc->isVideo()) {
 | 
						if (doc->isVideo() || doc->isRoundVideo()) {
 | 
				
			||||||
		_autoplayVideoDocument = doc;
 | 
							_autoplayVideoDocument = doc;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	displayDocument(doc, context);
 | 
						displayDocument(doc, context);
 | 
				
			||||||
| 
						 | 
					@ -1383,6 +1384,14 @@ void MediaView::displayFinished() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Images::Options MediaView::videoThumbOptions() const {
 | 
				
			||||||
 | 
						auto options = Images::Option::Smooth | Images::Option::Blurred;
 | 
				
			||||||
 | 
						if (_doc->isRoundVideo()) {
 | 
				
			||||||
 | 
							options |= Images::Option::Circled;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return options;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MediaView::initAnimation() {
 | 
					void MediaView::initAnimation() {
 | 
				
			||||||
	Expects(_doc != nullptr);
 | 
						Expects(_doc != nullptr);
 | 
				
			||||||
	Expects(_doc->isAnimation() || _doc->isVideo());
 | 
						Expects(_doc->isAnimation() || _doc->isVideo());
 | 
				
			||||||
| 
						 | 
					@ -1394,12 +1403,12 @@ void MediaView::initAnimation() {
 | 
				
			||||||
		createClipReader();
 | 
							createClipReader();
 | 
				
			||||||
		location.accessDisable();
 | 
							location.accessDisable();
 | 
				
			||||||
	} else if (_doc->dimensions.width() && _doc->dimensions.height()) {
 | 
						} else if (_doc->dimensions.width() && _doc->dimensions.height()) {
 | 
				
			||||||
		int w = _doc->dimensions.width();
 | 
							auto w = _doc->dimensions.width();
 | 
				
			||||||
		int h = _doc->dimensions.height();
 | 
							auto h = _doc->dimensions.height();
 | 
				
			||||||
		_current = _doc->thumb->pixNoCache(w, h, Images::Option::Smooth | Images::Option::Blurred, w / cIntRetinaFactor(), h / cIntRetinaFactor());
 | 
							_current = _doc->thumb->pixNoCache(w, h, videoThumbOptions(), w / cIntRetinaFactor(), h / cIntRetinaFactor());
 | 
				
			||||||
		if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
 | 
							if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), Images::Option::Smooth | Images::Option::Blurred, st::mediaviewFileIconSize, st::mediaviewFileIconSize);
 | 
							_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), videoThumbOptions(), st::mediaviewFileIconSize, st::mediaviewFileIconSize);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1412,12 +1421,12 @@ void MediaView::createClipReader() {
 | 
				
			||||||
	if (_doc->dimensions.width() && _doc->dimensions.height()) {
 | 
						if (_doc->dimensions.width() && _doc->dimensions.height()) {
 | 
				
			||||||
		int w = _doc->dimensions.width();
 | 
							int w = _doc->dimensions.width();
 | 
				
			||||||
		int h = _doc->dimensions.height();
 | 
							int h = _doc->dimensions.height();
 | 
				
			||||||
		_current = _doc->thumb->pixNoCache(w, h, Images::Option::Smooth | Images::Option::Blurred, w / cIntRetinaFactor(), h / cIntRetinaFactor());
 | 
							_current = _doc->thumb->pixNoCache(w, h, videoThumbOptions(), w / cIntRetinaFactor(), h / cIntRetinaFactor());
 | 
				
			||||||
		if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
 | 
							if (cRetina()) _current.setDevicePixelRatio(cRetinaFactor());
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), Images::Option::Smooth | Images::Option::Blurred, st::mediaviewFileIconSize, st::mediaviewFileIconSize);
 | 
							_current = _doc->thumb->pixNoCache(_doc->thumb->width(), _doc->thumb->height(), videoThumbOptions(), st::mediaviewFileIconSize, st::mediaviewFileIconSize);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto mode = _doc->isVideo() ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif;
 | 
						auto mode = (_doc->isVideo() || _doc->isRoundVideo()) ? Media::Clip::Reader::Mode::Video : Media::Clip::Reader::Mode::Gif;
 | 
				
			||||||
	_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
 | 
						_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
 | 
				
			||||||
		clipCallback(notification);
 | 
							clipCallback(notification);
 | 
				
			||||||
	}, mode);
 | 
						}, mode);
 | 
				
			||||||
| 
						 | 
					@ -1475,7 +1484,7 @@ void MediaView::initThemePreview() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MediaView::createClipController() {
 | 
					void MediaView::createClipController() {
 | 
				
			||||||
	if (!_doc->isVideo()) return;
 | 
						if (!_doc->isVideo() && !_doc->isRoundVideo()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_clipController.create(this);
 | 
						_clipController.create(this);
 | 
				
			||||||
	setClipControllerGeometry();
 | 
						setClipControllerGeometry();
 | 
				
			||||||
| 
						 | 
					@ -1530,7 +1539,8 @@ void MediaView::restartVideoAtSeekPosition(TimeMs positionMs) {
 | 
				
			||||||
	_autoplayVideoDocument = _doc;
 | 
						_autoplayVideoDocument = _doc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_current.isNull()) {
 | 
						if (_current.isNull()) {
 | 
				
			||||||
		_current = _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None, getms());
 | 
							auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None;
 | 
				
			||||||
 | 
							_current = _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::All, getms());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
 | 
						_gif = std::make_unique<Media::Clip::Reader>(_doc->location(), _doc->data(), [this](Media::Clip::Notification notification) {
 | 
				
			||||||
		clipCallback(notification);
 | 
							clipCallback(notification);
 | 
				
			||||||
| 
						 | 
					@ -1638,6 +1648,9 @@ void MediaView::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
		for (int i = 0, l = region.rectCount(); i < l; ++i) {
 | 
							for (int i = 0, l = region.rectCount(); i < l; ++i) {
 | 
				
			||||||
			p.fillRect(rs.at(i), st::mediaviewVideoBg);
 | 
								p.fillRect(rs.at(i), st::mediaviewVideoBg);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (_doc->isRoundVideo()) {
 | 
				
			||||||
 | 
								p.setCompositionMode(m);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		for (int i = 0, l = region.rectCount(); i < l; ++i) {
 | 
							for (int i = 0, l = region.rectCount(); i < l; ++i) {
 | 
				
			||||||
			p.fillRect(rs.at(i), st::mediaviewBg);
 | 
								p.fillRect(rs.at(i), st::mediaviewBg);
 | 
				
			||||||
| 
						 | 
					@ -1670,7 +1683,8 @@ void MediaView::paintEvent(QPaintEvent *e) {
 | 
				
			||||||
	if (_photo || fileShown()) {
 | 
						if (_photo || fileShown()) {
 | 
				
			||||||
		QRect imgRect(_x, _y, _w, _h);
 | 
							QRect imgRect(_x, _y, _w, _h);
 | 
				
			||||||
		if (imgRect.intersects(r)) {
 | 
							if (imgRect.intersects(r)) {
 | 
				
			||||||
			auto toDraw = _current.isNull() ? _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), ImageRoundRadius::None, ImageRoundCorner::None, ms) : _current;
 | 
								auto rounding = _doc->isRoundVideo() ? ImageRoundRadius::Ellipse : ImageRoundRadius::None;
 | 
				
			||||||
 | 
								auto toDraw = _current.isNull() ? _gif->current(_gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), _gif->width() / cIntRetinaFactor(), _gif->height() / cIntRetinaFactor(), rounding, ImageRoundCorner::None, ms) : _current;
 | 
				
			||||||
			if (!_gif && (!_doc || !_doc->sticker() || _doc->sticker()->img->isNull()) && toDraw.hasAlpha()) {
 | 
								if (!_gif && (!_doc || !_doc->sticker() || _doc->sticker()->img->isNull()) && toDraw.hasAlpha()) {
 | 
				
			||||||
				p.fillRect(imgRect, _transparentBrush);
 | 
									p.fillRect(imgRect, _transparentBrush);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -2011,7 +2025,7 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
 | 
				
			||||||
	} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) {
 | 
						} else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return || e->key() == Qt::Key_Space) {
 | 
				
			||||||
		if (_doc && !_doc->loading() && (fileBubbleShown() || !_doc->loaded())) {
 | 
							if (_doc && !_doc->loading() && (fileBubbleShown() || !_doc->loaded())) {
 | 
				
			||||||
			onDocClick();
 | 
								onDocClick();
 | 
				
			||||||
		} else if (_doc && _doc->isVideo()) {
 | 
							} else if (_doc && (_doc->isVideo() || _doc->isRoundVideo())) {
 | 
				
			||||||
			onVideoPauseResume();
 | 
								onVideoPauseResume();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (e->key() == Qt::Key_Left) {
 | 
						} else if (e->key() == Qt::Key_Left) {
 | 
				
			||||||
| 
						 | 
					@ -2463,7 +2477,7 @@ void MediaView::updateOver(QPoint pos) {
 | 
				
			||||||
	} else if (_closeNav.contains(pos)) {
 | 
						} else if (_closeNav.contains(pos)) {
 | 
				
			||||||
		updateOverState(OverClose);
 | 
							updateOverState(OverClose);
 | 
				
			||||||
	} else if (_doc && fileShown() && QRect(_x, _y, _w, _h).contains(pos)) {
 | 
						} else if (_doc && fileShown() && QRect(_x, _y, _w, _h).contains(pos)) {
 | 
				
			||||||
		if (_doc->isVideo() && _gif) {
 | 
							if ((_doc->isVideo() || _doc->isRoundVideo()) && _gif) {
 | 
				
			||||||
			updateOverState(OverVideo);
 | 
								updateOverState(OverVideo);
 | 
				
			||||||
		} else if (!_doc->loaded()) {
 | 
							} else if (!_doc->loaded()) {
 | 
				
			||||||
			updateOverState(OverIcon);
 | 
								updateOverState(OverIcon);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,6 +178,7 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void initAnimation();
 | 
						void initAnimation();
 | 
				
			||||||
	void createClipReader();
 | 
						void createClipReader();
 | 
				
			||||||
 | 
						Images::Options videoThumbOptions() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void initThemePreview();
 | 
						void initThemePreview();
 | 
				
			||||||
	void destroyThemePreview();
 | 
						void destroyThemePreview();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1205,14 +1205,14 @@ void DocumentOpenClickHandler::doOpen(DocumentData *data, HistoryItem *context,
 | 
				
			||||||
		} else if (data->size < App::kImageSizeLimit) {
 | 
							} else if (data->size < App::kImageSizeLimit) {
 | 
				
			||||||
			if (!data->data().isEmpty() && playAnimation) {
 | 
								if (!data->data().isEmpty() && playAnimation) {
 | 
				
			||||||
				if (action == ActionOnLoadPlayInline && context && context->getMedia()) {
 | 
									if (action == ActionOnLoadPlayInline && context && context->getMedia()) {
 | 
				
			||||||
					context->getMedia()->playInline(context);
 | 
										context->getMedia()->playInline();
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					App::wnd()->showDocument(data, context);
 | 
										App::wnd()->showDocument(data, context);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else if (location.accessEnable()) {
 | 
								} else if (location.accessEnable()) {
 | 
				
			||||||
				if (data->isAnimation() || QImageReader(location.name()).canRead()) {
 | 
									if (data->isAnimation() || QImageReader(location.name()).canRead()) {
 | 
				
			||||||
					if (action == ActionOnLoadPlayInline && context && context->getMedia()) {
 | 
										if (action == ActionOnLoadPlayInline && context && context->getMedia()) {
 | 
				
			||||||
						context->getMedia()->playInline(context);
 | 
											context->getMedia()->playInline();
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						App::wnd()->showDocument(data, context);
 | 
											App::wnd()->showDocument(data, context);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -1485,7 +1485,7 @@ void DocumentData::performActionOnLoad() {
 | 
				
			||||||
	} else if (playAnimation) {
 | 
						} else if (playAnimation) {
 | 
				
			||||||
		if (loaded()) {
 | 
							if (loaded()) {
 | 
				
			||||||
			if (_actionOnLoad == ActionOnLoadPlayInline && item->getMedia()) {
 | 
								if (_actionOnLoad == ActionOnLoadPlayInline && item->getMedia()) {
 | 
				
			||||||
				item->getMedia()->playInline(item);
 | 
									item->getMedia()->playInline();
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				App::wnd()->showDocument(this, item);
 | 
									App::wnd()->showDocument(this, item);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1504,7 +1504,7 @@ void DocumentData::performActionOnLoad() {
 | 
				
			||||||
			} else if (loc.accessEnable()) {
 | 
								} else if (loc.accessEnable()) {
 | 
				
			||||||
				if (showImage && QImageReader(loc.name()).canRead()) {
 | 
									if (showImage && QImageReader(loc.name()).canRead()) {
 | 
				
			||||||
					if (_actionOnLoad == ActionOnLoadPlayInline && item && item->getMedia()) {
 | 
										if (_actionOnLoad == ActionOnLoadPlayInline && item && item->getMedia()) {
 | 
				
			||||||
						item->getMedia()->playInline(item);
 | 
											item->getMedia()->playInline();
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						App::wnd()->showDocument(this, item);
 | 
											App::wnd()->showDocument(this, item);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,11 @@ public:
 | 
				
			||||||
	explicit operator bool() const {
 | 
						explicit operator bool() const {
 | 
				
			||||||
		return valid();
 | 
							return valid();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						static inline ReaderPointer Bad() {
 | 
				
			||||||
 | 
							ReaderPointer result;
 | 
				
			||||||
 | 
							result.setBad();
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	~ReaderPointer();
 | 
						~ReaderPointer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue