Use Streaming::Player in video messages playback.

This commit is contained in:
John Preston 2019-03-26 12:54:51 +04:00
parent 8aaa70a05a
commit 3bd1bbc77a
20 changed files with 255 additions and 499 deletions

View File

@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "inline_bots/inline_bot_layout_item.h" #include "inline_bots/inline_bot_layout_item.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "storage/storage_encrypted_file.h" #include "storage/storage_encrypted_file.h"
#include "media/player/media_player_instance.h" // for instance()->play().
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "passport/passport_form_controller.h" #include "passport/passport_form_controller.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
@ -1099,6 +1100,15 @@ void Session::requestItemTextRefresh(not_null<HistoryItem*> item) {
void Session::requestAnimationPlayInline(not_null<HistoryItem*> item) { void Session::requestAnimationPlayInline(not_null<HistoryItem*> item) {
_animationPlayInlineRequest.fire_copy(item); _animationPlayInlineRequest.fire_copy(item);
if (const auto media = item->media()) {
if (const auto data = media->document()) {
if (data && data->isVideoMessage()) {
const auto msgId = item->fullId();
::Media::Player::instance()->playPause({ data, msgId });
}
}
}
} }
rpl::producer<not_null<HistoryItem*>> Session::animationPlayInlineRequest() const { rpl::producer<not_null<HistoryItem*>> Session::animationPlayInlineRequest() const {

View File

@ -12,8 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#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_round_controller.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_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"
@ -69,8 +69,6 @@ QSize HistoryGif::countOptimalSize() {
_parent->skipBlockWidth(), _parent->skipBlockWidth(),
_parent->skipBlockHeight()); _parent->skipBlockHeight());
} }
auto tw = 0;
auto th = 0;
if (_gif && _gif->state() == Media::Clip::State::Error) { if (_gif && _gif->state() == Media::Clip::State::Error) {
if (!_gif->autoplay()) { if (!_gif->autoplay()) {
Ui::show(Box<InformBox>(lang(lng_gif_error))); Ui::show(Box<InformBox>(lang(lng_gif_error)));
@ -78,20 +76,12 @@ QSize HistoryGif::countOptimalSize() {
setClipReader(Media::Clip::ReaderPointer::Bad()); setClipReader(Media::Clip::ReaderPointer::Bad());
} }
const auto reader = currentReader();
if (reader) {
tw = ConvertScale(reader->width());
th = ConvertScale(reader->height());
} else {
tw = ConvertScale(_data->dimensions.width()), th = ConvertScale(_data->dimensions.height());
if (!tw || !th) {
tw = ConvertScale(_data->thumbnail()->width());
th = ConvertScale(_data->thumbnail()->height());
}
}
const auto maxSize = _data->isVideoMessage() const auto maxSize = _data->isVideoMessage()
? st::maxVideoMessageSize ? st::maxVideoMessageSize
: st::maxGifSize; : st::maxGifSize;
const auto size = ConvertScale(videoSize());
auto tw = size.width();
auto th = size.height();
if (tw > maxSize) { if (tw > maxSize) {
th = (maxSize * th) / tw; th = (maxSize * th) / tw;
tw = maxSize; tw = maxSize;
@ -108,7 +98,7 @@ QSize HistoryGif::countOptimalSize() {
auto maxWidth = qMax(tw, st::minPhotoSize); auto maxWidth = qMax(tw, st::minPhotoSize);
auto minHeight = qMax(th, st::minPhotoSize); auto minHeight = qMax(th, st::minPhotoSize);
accumulate_max(maxWidth, _parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); accumulate_max(maxWidth, _parent->infoWidth() + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
if (!reader) { if (!currentReader() && !activeRoundPlayer()) {
accumulate_max(maxWidth, gifMaxStatusWidth(_data) + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x())); accumulate_max(maxWidth, gifMaxStatusWidth(_data) + 2 * (st::msgDateImgDelta + st::msgDateImgPadding.x()));
} }
if (_parent->hasBubble()) { if (_parent->hasBubble()) {
@ -135,21 +125,12 @@ QSize HistoryGif::countOptimalSize() {
QSize HistoryGif::countCurrentSize(int newWidth) { QSize HistoryGif::countCurrentSize(int newWidth) {
auto availableWidth = newWidth; auto availableWidth = newWidth;
int tw = 0, th = 0;
const auto reader = currentReader();
if (reader) {
tw = ConvertScale(reader->width());
th = ConvertScale(reader->height());
} else {
tw = ConvertScale(_data->dimensions.width()), th = ConvertScale(_data->dimensions.height());
if (!tw || !th) {
tw = ConvertScale(_data->thumbnail()->width());
th = ConvertScale(_data->thumbnail()->height());
}
}
const auto maxSize = _data->isVideoMessage() const auto maxSize = _data->isVideoMessage()
? st::maxVideoMessageSize ? st::maxVideoMessageSize
: st::maxGifSize; : st::maxGifSize;
const auto size = ConvertScale(videoSize());
auto tw = size.width();
auto th = size.height();
if (tw > maxSize) { if (tw > maxSize) {
th = (maxSize * th) / tw; th = (maxSize * th) / tw;
tw = maxSize; tw = maxSize;
@ -172,6 +153,7 @@ QSize HistoryGif::countCurrentSize(int newWidth) {
newWidth = qMax(tw, st::minPhotoSize); newWidth = qMax(tw, st::minPhotoSize);
auto newHeight = qMax(th, st::minPhotoSize); auto newHeight = qMax(th, st::minPhotoSize);
accumulate_max(newWidth, _parent->infoWidth() + 2 * st::msgDateImgDelta + st::msgDateImgPadding.x()); accumulate_max(newWidth, _parent->infoWidth() + 2 * st::msgDateImgDelta + st::msgDateImgPadding.x());
const auto reader = activeRoundPlayer() ? nullptr : currentReader();
if (reader) { if (reader) {
const auto own = (reader->mode() == Media::Clip::Reader::Mode::Gif); const auto own = (reader->mode() == Media::Clip::Reader::Mode::Gif);
if (own && !reader->started()) { if (own && !reader->started()) {
@ -232,6 +214,20 @@ QSize HistoryGif::countCurrentSize(int newWidth) {
return { newWidth, newHeight }; return { newWidth, newHeight };
} }
QSize HistoryGif::videoSize() const {
if (const auto player = activeRoundPlayer()) {
return player->videoSize();
} else if (const auto reader = currentReader()) {
return QSize(reader->width(), reader->height());
} else if (!_data->dimensions.isEmpty()) {
return _data->dimensions;
} else if (const auto thumbnail = _data->thumbnail()) {
return thumbnail->size();
} else {
return QSize(1, 1);
}
}
void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const { void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return; if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
@ -245,7 +241,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::
&& cAutoPlayGif() && cAutoPlayGif()
&& !_gif && !_gif
&& !_gif.isBad() && !_gif.isBad()
&& !activeRoundVideo()) { && !activeRoundPlayer()) {
_parent->delegate()->elementAnimationAutoplayAsync(_parent); _parent->delegate()->elementAnimationAutoplayAsync(_parent);
} }
@ -258,11 +254,9 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::
auto isRound = _data->isVideoMessage(); auto isRound = _data->isVideoMessage();
auto displayMute = false; auto displayMute = false;
const auto reader = currentReader(); const auto player = activeRoundPlayer();
const auto playingVideo = reader const auto reader = player ? nullptr : currentReader();
? (reader->mode() == Media::Clip::Reader::Mode::Video) const auto animating = player || (reader && reader->started());
: false;
const auto animating = reader && reader->started();
if ((!animating || item->id < 0) && displayLoading) { if ((!animating || item->id < 0) && displayLoading) {
ensureAnimation(); ensureAnimation();
@ -305,13 +299,22 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, crl::
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 (isRound) {
if (playingVideo) { if (player) {
paused = false; paused = false;
} else { } else {
displayMute = true; displayMute = true;
} }
} }
p.drawPixmap(rthumb.topLeft(), reader->current(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners, paused ? 0 : ms)); if (player) {
auto request = Media::Streaming::FrameRequest();
request.outer = QSize(usew, painth) * cIntRetinaFactor();
request.resize = QSize(_thumbw, _thumbh) * cIntRetinaFactor();
request.corners = roundCorners;
request.radius = roundRadius;
p.drawImage(rthumb, player->frame(request));
} else {
p.drawPixmap(rthumb.topLeft(), reader->current(_thumbw, _thumbh, usew, painth, roundRadius, roundCorners, paused ? 0 : ms));
}
if (const auto playback = videoPlayback()) { if (const auto playback = videoPlayback()) {
const auto value = playback->value(); const auto value = playback->value();
@ -746,18 +749,17 @@ void HistoryGif::updateStatusText() const {
} else if (_data->loaded()) { } else if (_data->loaded()) {
statusSize = FileStatusSizeLoaded; statusSize = FileStatusSizeLoaded;
if (const auto video = activeRoundPlayer()) { if (const auto video = activeRoundPlayer()) {
statusSize = -1 - _data->getDuration(); const auto state = video->prepareLegacyState();
if (state.length) {
const auto type = AudioMsgId::Type::Voice;
const auto state = Media::Player::instance()->getState(type);
if (state.id == video->audioMsgId() && state.length) {
auto position = int64(0); auto position = int64(0);
if (Media::Player::IsStoppedAtEnd(state.state)) { if (Media::Player::IsStoppedAtEnd(state.state)) {
position = state.length; position = state.length;
} else if (!Media::Player::IsStoppedOrStopping(state.state)) { } else if (!Media::Player::IsStoppedOrStopping(state.state)) {
position = state.position; position = state.position;
} }
accumulate_max(statusSize, -1 - int((state.length - position) / state.frequency + 1)); statusSize = -1 - int((state.length - position) / state.frequency + 1);
} else {
statusSize = -1 - _data->getDuration();
} }
} }
} else { } else {
@ -800,33 +802,16 @@ int HistoryGif::additionalWidth(const HistoryMessageVia *via, const HistoryMessa
return result; return result;
} }
Media::Player::RoundController *HistoryGif::activeRoundVideo() const { Media::Streaming::Player *HistoryGif::activeRoundPlayer() const {
return App::wnd()->controller()->roundVideo(_parent->data()); return Media::Player::instance()->roundVideoPlayer(_parent->data());
}
Media::Clip::Reader *HistoryGif::activeRoundPlayer() const {
if (const auto video = activeRoundVideo()) {
if (const auto result = video->reader()) {
if (result->ready()) {
return result;
}
}
}
return nullptr;
} }
Media::Clip::Reader *HistoryGif::currentReader() const { Media::Clip::Reader *HistoryGif::currentReader() const {
if (const auto result = activeRoundPlayer()) {
return result;
}
return (_gif && _gif->ready()) ? _gif.get() : nullptr; return (_gif && _gif->ready()) ? _gif.get() : nullptr;
} }
Media::View::PlaybackProgress *HistoryGif::videoPlayback() const { Media::View::PlaybackProgress *HistoryGif::videoPlayback() const {
if (const auto video = activeRoundVideo()) { return Media::Player::instance()->roundVideoPlayback(_parent->data());
return video->playback();
}
return nullptr;
} }
void HistoryGif::clipCallback(Media::Clip::Notification notification) { void HistoryGif::clipCallback(Media::Clip::Notification notification) {

View File

@ -17,10 +17,12 @@ namespace Media {
namespace View { namespace View {
class PlaybackProgress; class PlaybackProgress;
} // namespace View } // namespace View
} // namespace Media
namespace Player { namespace Media {
class RoundController; namespace Streaming {
} // namespace Player class Player;
} // namespace Streaming
} // namespace Media } // namespace Media
class HistoryGif : public HistoryFileMedia { class HistoryGif : public HistoryFileMedia {
@ -86,8 +88,8 @@ private:
void playAnimation(bool autoplay) override; void playAnimation(bool autoplay) override;
QSize countOptimalSize() override; QSize countOptimalSize() override;
QSize countCurrentSize(int newWidth) override; QSize countCurrentSize(int newWidth) override;
Media::Player::RoundController *activeRoundVideo() const; QSize videoSize() const;
Media::Clip::Reader *activeRoundPlayer() const; Media::Streaming::Player *activeRoundPlayer() const;
Media::Clip::Reader *currentReader() const; Media::Clip::Reader *currentReader() const;
Media::View::PlaybackProgress *videoPlayback() const; Media::View::PlaybackProgress *videoPlayback() const;
void clipCallback(Media::Clip::Notification notification); void clipCallback(Media::Clip::Notification notification);

View File

@ -15,10 +15,9 @@ 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/clip/media_clip_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 "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "media/player/media_player_round_controller.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "auth_session.h" #include "auth_session.h"
@ -105,9 +104,7 @@ float64 Float::outRatio() const {
void Float::mouseReleaseEvent(QMouseEvent *e) { void Float::mouseReleaseEvent(QMouseEvent *e) {
if (base::take(_down) && _item) { if (base::take(_down) && _item) {
if (const auto controller = _controller->roundVideo(_item)) { pauseResume();
controller->pauseResume();
}
} }
if (_drag) { if (_drag) {
finishDrag(outRatio() < 0.5); finishDrag(outRatio() < 0.5);
@ -124,13 +121,21 @@ void Float::finishDrag(bool closed) {
void Float::mouseDoubleClickEvent(QMouseEvent *e) { void Float::mouseDoubleClickEvent(QMouseEvent *e) {
if (_item) { if (_item) {
// Handle second click. // Handle second click.
if (const auto controller = _controller->roundVideo(_item)) { pauseResume();
controller->pauseResume();
}
Ui::showPeerHistoryAtItem(_item); Ui::showPeerHistoryAtItem(_item);
} }
} }
void Float::pauseResume() {
if (const auto player = instance()->roundVideoPlayer(_item)) {
if (player->paused()) {
player->resume();
} else {
player->pause();
}
}
}
void Float::detach() { void Float::detach() {
if (_item) { if (_item) {
_item = nullptr; _item = nullptr;
@ -196,35 +201,16 @@ void Float::paintEvent(QPaintEvent *e) {
} }
} }
Clip::Reader *Float::getReader() const { Streaming::Player *Float::getPlayer() const {
if (detached()) { return instance()->roundVideoPlayer(_item);
return nullptr;
}
if (const auto controller = _controller->roundVideo(_item)) {
if (const auto reader = controller->reader()) {
if (reader->started()) {
return reader;
}
}
}
return nullptr;
} }
View::PlaybackProgress *Float::getPlayback() const { View::PlaybackProgress *Float::getPlayback() const {
if (detached()) { return instance()->roundVideoPlayback(_item);
return nullptr;
}
if (const auto controller = _controller->roundVideo(_item)) {
return controller->playback();
}
return nullptr;
} }
bool Float::hasFrame() const { bool Float::hasFrame() const {
if (const auto reader = getReader()) { return (getPlayer() != nullptr);
return !reader->current().isNull();
}
return false;
} }
bool Float::fillFrame() { bool Float::fillFrame() {
@ -238,14 +224,17 @@ bool Float::fillFrame() {
auto frameInner = [&] { auto frameInner = [&] {
return QRect(QPoint(), _frame.size() / cIntRetinaFactor()); return QRect(QPoint(), _frame.size() / cIntRetinaFactor());
}; };
if (const auto reader = getReader()) { if (const auto player = getPlayer()) {
auto frame = reader->current(); auto request = Streaming::FrameRequest::NonStrict();
request.outer = request.resize = _frame.size();
request.radius = ImageRoundRadius::Ellipse;
auto frame = player->frame(request);
if (!frame.isNull()) { if (!frame.isNull()) {
_frame.fill(Qt::transparent); _frame.fill(Qt::transparent);
Painter p(&_frame); Painter p(&_frame);
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.drawPixmap(frameInner(), frame); p.drawImage(frameInner(), frame);
return true; return true;
} }
} }

View File

@ -19,7 +19,15 @@ namespace Media {
namespace View { namespace View {
class PlaybackProgress; class PlaybackProgress;
} // namespace View } // namespace View
} // namespace Media
namespace Media {
namespace Streaming {
class Player;
} // namespace Streaming
} // namespace Media
namespace Media {
namespace Player { namespace Player {
class Float : public Ui::RpWidget, private base::Subscriber { class Float : public Ui::RpWidget, private base::Subscriber {
@ -44,7 +52,7 @@ public:
return outRatio(); return outRatio();
} }
bool isReady() const { bool isReady() const {
return (getReader() != nullptr); return (getPlayer() != nullptr);
} }
void detach(); void detach();
bool detached() const { bool detached() const {
@ -69,7 +77,7 @@ protected:
private: private:
float64 outRatio() const; float64 outRatio() const;
Clip::Reader *getReader() const; Streaming::Player *getPlayer() const;
View::PlaybackProgress *getPlayback() const; View::PlaybackProgress *getPlayback() const;
void repaintItem(); void repaintItem();
void prepareShadow(); void prepareShadow();
@ -77,6 +85,7 @@ private:
bool fillFrame(); bool fillFrame();
QRect getInnerRect() const; QRect getInnerRect() const;
void finishDrag(bool closed); void finishDrag(bool closed);
void pauseResume();
not_null<Window::Controller*> _controller; not_null<Window::Controller*> _controller;
HistoryItem *_item = nullptr; HistoryItem *_item = nullptr;

View File

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/audio/media_audio_capture.h" #include "media/audio/media_audio_capture.h"
#include "media/streaming/media_streaming_player.h" #include "media/streaming/media_streaming_player.h"
#include "media/streaming/media_streaming_loader.h" #include "media/streaming/media_streaming_loader.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"
#include "history/history_item.h" #include "history/history_item.h"
@ -61,6 +62,7 @@ struct Instance::Streamed {
AudioMsgId id; AudioMsgId id;
Streaming::Player player; Streaming::Player player;
Streaming::Information info; Streaming::Information info;
View::PlaybackProgress progress;
}; };
Instance::Streamed::Streamed( Instance::Streamed::Streamed(
@ -112,18 +114,19 @@ Instance::Instance()
Instance::~Instance() = default; Instance::~Instance() = default;
AudioMsgId::Type Instance::getActiveType() const { AudioMsgId::Type Instance::getActiveType() const {
const auto voiceData = getData(AudioMsgId::Type::Voice); if (const auto data = getData(AudioMsgId::Type::Voice)) {
if (voiceData->current) { if (data->current) {
const auto state = getState(voiceData->type); const auto state = getState(data->type);
if (!IsStoppedOrStopping(state.state)) { if (!IsStoppedOrStopping(state.state)) {
return voiceData->type; return data->type;
}
} }
} }
return AudioMsgId::Type::Song; return AudioMsgId::Type::Song;
} }
void Instance::handleSongUpdate(const AudioMsgId &audioId) { void Instance::handleSongUpdate(const AudioMsgId &audioId) {
emitUpdate(audioId.type(), [&audioId](const AudioMsgId &playing) { emitUpdate(audioId.type(), [&](const AudioMsgId &playing) {
return (audioId == playing); return (audioId == playing);
}); });
} }
@ -166,8 +169,11 @@ void Instance::clearStreamed(not_null<Data*> data) {
} }
data->streamed->player.stop(); data->streamed->player.stop();
data->isPlaying = false; data->isPlaying = false;
requestRoundVideoResize();
emitUpdate(data->type); emitUpdate(data->type);
data->streamed = nullptr; data->streamed = nullptr;
App::wnd()->controller()->disableGifPauseReason(
Window::GifPauseReason::RoundPlaying);
} }
void Instance::refreshPlaylist(not_null<Data*> data) { void Instance::refreshPlaylist(not_null<Data*> data) {
@ -327,20 +333,13 @@ Instance *instance() {
void Instance::play(AudioMsgId::Type type) { void Instance::play(AudioMsgId::Type type) {
if (const auto data = getData(type)) { if (const auto data = getData(type)) {
const auto state = getState(type); if (!data->streamed || IsStopped(getState(type).state)) {
if (state.id) {
if (IsStopped(state.state)) {
play(state.id);
} else if (data->streamed) {
if (data->streamed->player.active()) {
data->streamed->player.resume();
}
emitUpdate(type);
} else {
mixer()->resume(state.id);
}
} else {
play(data->current); play(data->current);
} else {
if (data->streamed->player.active()) {
data->streamed->player.resume();
}
emitUpdate(type);
} }
data->resumeOnCallEnd = false; data->resumeOnCallEnd = false;
} }
@ -351,17 +350,14 @@ void Instance::play(const AudioMsgId &audioId) {
if (!document) { if (!document) {
return; return;
} }
if (document->isAudioFile() || document->isVoiceMessage()) { if (document->isAudioFile()
|| document->isVoiceMessage()
|| document->isVideoMessage()) {
auto loader = document->createStreamingLoader(audioId.contextId()); auto loader = document->createStreamingLoader(audioId.contextId());
if (!loader) { if (!loader) {
return; return;
} }
playStreamed(audioId, std::move(loader)); playStreamed(audioId, std::move(loader));
} else if (document->isVideoMessage()) {
if (const auto item = App::histItemById(audioId.contextId())) {
setCurrent(audioId);
App::wnd()->controller()->startRoundVideo(item);
}
} }
if (document->isVoiceMessage() || document->isVideoMessage()) { if (document->isVoiceMessage() || document->isVideoMessage()) {
document->owner().markMediaRead(document); document->owner().markMediaRead(document);
@ -385,9 +381,8 @@ void Instance::playStreamed(
const auto data = getData(audioId.type()); const auto data = getData(audioId.type());
Assert(data != nullptr); Assert(data != nullptr);
if (data->streamed) {
clearStreamed(data); clearStreamed(data);
}
data->streamed = std::make_unique<Streamed>( data->streamed = std::make_unique<Streamed>(
audioId, audioId,
&audioId.audio()->owner(), &audioId.audio()->owner(),
@ -408,8 +403,11 @@ void Instance::playStreamed(
Streaming::PlaybackOptions Instance::streamingOptions( Streaming::PlaybackOptions Instance::streamingOptions(
const AudioMsgId &audioId, const AudioMsgId &audioId,
crl::time position) { crl::time position) {
const auto document = audioId.audio();
auto result = Streaming::PlaybackOptions(); auto result = Streaming::PlaybackOptions();
result.mode = Streaming::Mode::Audio; result.mode = (document && document->isVideoMessage())
? Streaming::Mode::Both
: Streaming::Mode::Audio;
result.audioId = audioId; result.audioId = audioId;
result.position = position; result.position = position;
return result; return result;
@ -422,11 +420,6 @@ void Instance::pause(AudioMsgId::Type type) {
data->streamed->player.pause(); data->streamed->player.pause();
} }
emitUpdate(type); emitUpdate(type);
} else {
const auto state = getState(type);
if (state.id) {
mixer()->pause(state.id);
}
} }
} }
} }
@ -434,12 +427,7 @@ void Instance::pause(AudioMsgId::Type type) {
void Instance::stop(AudioMsgId::Type type) { void Instance::stop(AudioMsgId::Type type) {
if (const auto data = getData(type)) { if (const auto data = getData(type)) {
if (data->streamed) { if (data->streamed) {
data->streamed = nullptr; clearStreamed(data);
} else {
const auto state = getState(type);
if (state.id) {
mixer()->stop(state.id);
}
} }
data->resumeOnCallEnd = false; data->resumeOnCallEnd = false;
} }
@ -447,7 +435,9 @@ void Instance::stop(AudioMsgId::Type type) {
void Instance::playPause(AudioMsgId::Type type) { void Instance::playPause(AudioMsgId::Type type) {
if (const auto data = getData(type)) { if (const auto data = getData(type)) {
if (data->streamed) { if (!data->streamed) {
play(data->current);
} else {
if (!data->streamed->player.active()) { if (!data->streamed->player.active()) {
data->streamed->player.play( data->streamed->player.play(
streamingOptions(data->streamed->id)); streamingOptions(data->streamed->id));
@ -457,21 +447,6 @@ void Instance::playPause(AudioMsgId::Type type) {
data->streamed->player.pause(); data->streamed->player.pause();
} }
emitUpdate(type); emitUpdate(type);
} else {
const auto state = getState(type);
if (state.id
&& state.id.audio() == data->current.audio()
&& state.id.contextId() == data->current.contextId()) {
if (IsStopped(state.state)) {
play(state.id);
} else if (IsPaused(state.state) || state.state == State::Pausing) {
mixer()->resume(state.id);
} else {
mixer()->pause(state.id);
}
} else {
play(data->current);
}
} }
data->resumeOnCallEnd = false; data->resumeOnCallEnd = false;
} }
@ -556,13 +531,6 @@ void Instance::finishSeeking(AudioMsgId::Type type, float64 progress) {
position)); position));
emitUpdate(type); emitUpdate(type);
} }
//
// Right now all music is played in streaming player.
//} else {
// const auto state = getState(type);
// if (state.id && state.length && state.frequency) {
// mixer()->seek(type, qRound(progress * state.length * 1000. / state.frequency));
// }
} }
} }
cancelSeeking(type); cancelSeeking(type);
@ -594,7 +562,30 @@ TrackState Instance::getState(AudioMsgId::Type type) const {
return data->streamed->player.prepareLegacyState(); return data->streamed->player.prepareLegacyState();
} }
} }
return mixer()->currentState(type); return TrackState();
}
Streaming::Player *Instance::roundVideoPlayer(HistoryItem *item) const {
if (!item) {
return nullptr;
} else if (const auto data = getData(AudioMsgId::Type::Voice)) {
if (const auto streamed = data->streamed.get()) {
if (streamed->id.contextId() == item->fullId()) {
const auto player = &streamed->player;
if (player->ready() && !player->videoSize().isEmpty()) {
return player;
}
}
}
}
return nullptr;
}
View::PlaybackProgress *Instance::roundVideoPlayback(
HistoryItem *item) const {
return roundVideoPlayer(item)
? &getData(AudioMsgId::Type::Voice)->streamed->progress
: nullptr;
} }
template <typename CheckCallback> template <typename CheckCallback>
@ -605,6 +596,10 @@ void Instance::emitUpdate(AudioMsgId::Type type, CheckCallback check) {
return; return;
} }
setCurrent(state.id); setCurrent(state.id);
if (data->streamed && !data->streamed->info.video.size.isEmpty()) {
LOG(("ID: %1, PROGRESS: %1 / %2").arg(state.id.audio()->id).arg(state.position).arg(state.length));
data->streamed->progress.updateState(state);
}
_updatedNotifier.notify(state, true); _updatedNotifier.notify(state, true);
if (data->isPlaying && state.state == State::StoppedAtEnd) { if (data->isPlaying && state.state == State::StoppedAtEnd) {
if (data->repeatEnabled) { if (data->repeatEnabled) {
@ -662,12 +657,26 @@ void Instance::handleStreamingUpdate(
Streaming::Update &&update) { Streaming::Update &&update) {
using namespace Streaming; using namespace Streaming;
update.data.match([&](Information & update) { update.data.match([&](Information &update) {
data->streamed->info = std::move(update); data->streamed->info = std::move(update);
if (!data->streamed->info.video.size.isEmpty()) {
data->streamed->progress.setValueChangedCallback([=](
float64,
float64) {
requestRoundVideoRepaint();
});
App::wnd()->controller()->enableGifPauseReason(
Window::GifPauseReason::RoundPlaying);
requestRoundVideoResize();
}
emitUpdate(data->type); emitUpdate(data->type);
}, [&](PreloadedVideo &update) { }, [&](PreloadedVideo &update) {
data->streamed->info.video.state.receivedTill = update.till;
//emitUpdate(data->type, [](AudioMsgId) { return true; });
}, [&](UpdateVideo &update) { }, [&](UpdateVideo &update) {
}, [&](PreloadedAudio & update) { data->streamed->info.video.state.position = update.position;
emitUpdate(data->type);
}, [&](PreloadedAudio &update) {
data->streamed->info.audio.state.receivedTill = update.till; data->streamed->info.audio.state.receivedTill = update.till;
//emitUpdate(data->type, [](AudioMsgId) { return true; }); //emitUpdate(data->type, [](AudioMsgId) { return true; });
}, [&](UpdateAudio &update) { }, [&](UpdateAudio &update) {
@ -682,11 +691,32 @@ void Instance::handleStreamingUpdate(
finishTrack(data->streamed->info.audio.state); finishTrack(data->streamed->info.audio.state);
emitUpdate(data->type); emitUpdate(data->type);
if (data->streamed && data->streamed->player.finished()) { if (data->streamed && data->streamed->player.finished()) {
data->streamed = nullptr; clearStreamed(data);
} }
}); });
} }
HistoryItem *Instance::roundVideoItem() const {
const auto data = getData(AudioMsgId::Type::Voice);
return (data->streamed
&& !data->streamed->info.video.size.isEmpty())
? App::histItemById(data->streamed->id.contextId())
: nullptr;
}
void Instance::requestRoundVideoResize() const {
if (const auto item = roundVideoItem()) {
Auth().data().requestItemResize(item);
}
}
void Instance::requestRoundVideoRepaint() const {
if (const auto item = roundVideoItem()) {
Auth().data().requestItemRepaint(item);
}
}
void Instance::handleStreamingError( void Instance::handleStreamingError(
not_null<Data*> data, not_null<Data*> data,
Streaming::Error &&error) { Streaming::Error &&error) {
@ -708,7 +738,7 @@ void Instance::handleStreamingError(
} }
emitUpdate(data->type); emitUpdate(data->type);
if (data->streamed && data->streamed->player.failed()) { if (data->streamed && data->streamed->player.failed()) {
data->streamed = nullptr; clearStreamed(data);
} }
} }

View File

@ -15,7 +15,17 @@ namespace Media {
namespace Audio { namespace Audio {
class Instance; class Instance;
} // namespace Audio } // namespace Audio
} // namespace Media
namespace Media {
namespace View {
class PlaybackProgress;
} // namespace View
} // namespace Media
namespace Media {
namespace Streaming { namespace Streaming {
class Player;
class Loader; class Loader;
struct PlaybackOptions; struct PlaybackOptions;
struct Update; struct Update;
@ -68,30 +78,35 @@ public:
void play(const AudioMsgId &audioId); void play(const AudioMsgId &audioId);
void playPause(const AudioMsgId &audioId); void playPause(const AudioMsgId &audioId);
TrackState getState(AudioMsgId::Type type) const; [[nodiscard]] TrackState getState(AudioMsgId::Type type) const;
AudioMsgId current(AudioMsgId::Type type) const { [[nodiscard]] Streaming::Player *roundVideoPlayer(
if (auto data = getData(type)) { HistoryItem *item) const;
[[nodiscard]] View::PlaybackProgress *roundVideoPlayback(
HistoryItem *item) const;
[[nodiscard]] AudioMsgId current(AudioMsgId::Type type) const {
if (const auto data = getData(type)) {
return data->current; return data->current;
} }
return AudioMsgId(); return AudioMsgId();
} }
bool repeatEnabled(AudioMsgId::Type type) const { [[nodiscard]] bool repeatEnabled(AudioMsgId::Type type) const {
if (auto data = getData(type)) { if (const auto data = getData(type)) {
return data->repeatEnabled; return data->repeatEnabled;
} }
return false; return false;
} }
void toggleRepeat(AudioMsgId::Type type) { void toggleRepeat(AudioMsgId::Type type) {
if (auto data = getData(type)) { if (const auto data = getData(type)) {
data->repeatEnabled = !data->repeatEnabled; data->repeatEnabled = !data->repeatEnabled;
_repeatChangedNotifier.notify(type); _repeatChangedNotifier.notify(type);
} }
} }
bool isSeeking(AudioMsgId::Type type) const { [[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
if (auto data = getData(type)) { if (const auto data = getData(type)) {
return (data->seeking == data->current); return (data->seeking == data->current);
} }
return false; return false;
@ -100,8 +115,8 @@ public:
void finishSeeking(AudioMsgId::Type type, float64 progress); void finishSeeking(AudioMsgId::Type type, float64 progress);
void cancelSeeking(AudioMsgId::Type type); void cancelSeeking(AudioMsgId::Type type);
bool nextAvailable(AudioMsgId::Type type) const; [[nodiscard]] bool nextAvailable(AudioMsgId::Type type) const;
bool previousAvailable(AudioMsgId::Type type) const; [[nodiscard]] bool previousAvailable(AudioMsgId::Type type) const;
struct Switch { struct Switch {
AudioMsgId from; AudioMsgId from;
@ -220,6 +235,10 @@ private:
return nullptr; return nullptr;
} }
HistoryItem *roundVideoItem() const;
void requestRoundVideoResize() const;
void requestRoundVideoRepaint() const;
Data _songData; Data _songData;
Data _voiceData; Data _voiceData;

View File

@ -1,181 +0,0 @@
/*
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/player/media_player_round_controller.h"
#include "media/audio/media_audio.h"
#include "media/clip/media_clip_reader.h"
#include "media/player/media_player_instance.h"
#include "media/view/media_view_playback_progress.h"
#include "history/history_item.h"
#include "window/window_controller.h"
#include "data/data_media_types.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "auth_session.h"
namespace Media {
namespace Player {
struct RoundController::CreateTag {
};
std::unique_ptr<RoundController> RoundController::TryStart(
not_null<Window::Controller*> parent,
not_null<HistoryItem*> item) {
const auto media = item->media();
if (!media) {
return nullptr;
}
const auto document = media->document();
if (!document || !document->isVideoMessage()) {
return nullptr;
}
return std::make_unique<RoundController>(CreateTag(), parent, item);
}
RoundController::RoundController(
CreateTag&&,
not_null<Window::Controller*> parent,
not_null<HistoryItem*> item)
: _parent(parent)
, _data(item->media()->document())
, _context(item) {
Expects(_data->isVideoMessage());
subscribe(instance()->updatedNotifier(), [this](const TrackState &state) {
handleAudioUpdate(state);
});
_reader = Clip::MakeReader(
_data,
_context->fullId(),
[=](Clip::Notification notification) { callback(notification); },
Clip::Reader::Mode::Video);
_playbackProgress = std::make_unique<View::PlaybackProgress>();
_playbackProgress->setValueChangedCallback([=](float64, float64) {
Auth().data().requestItemRepaint(_context);
});
Auth().data().markMediaRead(_data);
Auth().data().itemRemoved(
) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
if (item == _context) {
stop(State::Stopped);
}
}, lifetime());
Auth().data().itemRepaintRequest(
) | rpl::start_with_next([=](not_null<const HistoryItem*> item) {
if (item == _context) {
crl::on_main(this, [=] {
checkReaderState();
});
}
}, lifetime());
}
rpl::lifetime &RoundController::lifetime() {
return _lifetime;
}
FullMsgId RoundController::contextId() const {
return _context->fullId();
}
void RoundController::pauseResume() {
if (checkReaderState()) {
_reader->pauseResumeVideo();
}
}
Clip::Reader *RoundController::reader() const {
return _reader ? _reader.get() : nullptr;
}
View::PlaybackProgress *RoundController::playback() const {
return _playbackProgress.get();
}
void RoundController::handleAudioUpdate(const TrackState &state) {
if (state.id.type() != AudioMsgId::Type::Voice) {
return;
}
const auto audio = _reader->audioMsgId();
const auto another = (state.id != _reader->audioMsgId());
const auto stopped = IsStoppedOrStopping(state.state);
if ((another && !stopped) || (!another && stopped)) {
stop(State::Stopped);
return;
} else if (another) {
return;
}
if (_playbackProgress) {
_playbackProgress->updateState(state);
}
if (IsPaused(state.state) || state.state == State::Pausing) {
if (!_reader->videoPaused()) {
_reader->pauseResumeVideo();
}
} else {
if (_reader->videoPaused()) {
_reader->pauseResumeVideo();
}
}
}
void RoundController::callback(Clip::Notification notification) {
if (!_reader) {
return;
}
switch (notification) {
case Clip::NotificationReinit: {
if (checkReaderState()) {
Auth().data().requestItemResize(_context);
}
} break;
case Clip::NotificationRepaint: {
Auth().data().requestItemRepaint(_context);
} break;
}
}
bool RoundController::checkReaderState() {
if (!_reader) {
return false;
}
const auto state = _reader->state();
if (state == Media::Clip::State::Error) {
stop(State::StoppedAtError);
return false;
} else if (state == Media::Clip::State::Finished) {
stop(State::StoppedAtEnd);
return false;
} else if (_reader->ready() && !_reader->started()) {
const auto size = QSize(_reader->width(), _reader->height())
/ cIntRetinaFactor();
_reader->start(
size.width(),
size.height(),
size.width(),
size.height(),
ImageRoundRadius::Ellipse,
RectPart::AllCorners);
}
return true;
}
void RoundController::stop(State state) {
if (const auto audioId = _reader->audioMsgId()) {
mixer()->stop(audioId, state);
}
_parent->roundVideoFinished(this);
}
RoundController::~RoundController() = default;
} // namespace Player
} // namespace Media

View File

@ -1,69 +0,0 @@
/*
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
class HistoryItem;
class AudioMsgId;
namespace Window {
class Controller;
} // namespace Window
namespace Media {
namespace View {
class PlaybackProgress;
} // namespace View
} // namespace Media
namespace Media {
namespace Player {
struct TrackState;
enum class State;
class RoundController
: public base::has_weak_ptr
, private base::Subscriber {
struct CreateTag;
public:
static std::unique_ptr<RoundController> TryStart(
not_null<Window::Controller*> parent,
not_null<HistoryItem*> item);
FullMsgId contextId() const;
void pauseResume();
Clip::Reader *reader() const;
View::PlaybackProgress *playback() const;
rpl::lifetime &lifetime();
RoundController(
CreateTag&&,
not_null<Window::Controller*> parent,
not_null<HistoryItem*> item);
~RoundController();
private:
void stop(State state);
bool checkReaderState();
void callback(Clip::Notification notification);
void handleAudioUpdate(const TrackState &audioId);
not_null<Window::Controller*> _parent;
not_null<DocumentData*> _data;
not_null<HistoryItem*> _context;
Clip::ReaderPointer _reader;
std::unique_ptr<View::PlaybackProgress> _playbackProgress;
rpl::lifetime _lifetime;
};
} // namespace Player
} // namespace Media

View File

@ -94,27 +94,27 @@ Widget::Widget(QWidget *parent) : RpWidget(parent)
_nameLabel->setAttribute(Qt::WA_TransparentForMouseEvents); _nameLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
_timeLabel->setAttribute(Qt::WA_TransparentForMouseEvents); _timeLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
_playbackProgress->setInLoadingStateChangedCallback([this](bool loading) { _playbackProgress->setInLoadingStateChangedCallback([=](bool loading) {
_playbackSlider->setDisabled(loading); _playbackSlider->setDisabled(loading);
}); });
_playbackProgress->setValueChangedCallback([this](float64 value, float64) { _playbackProgress->setValueChangedCallback([=](float64 value, float64) {
_playbackSlider->setValue(value); _playbackSlider->setValue(value);
}); });
_playbackSlider->setChangeProgressCallback([this](float64 value) { _playbackSlider->setChangeProgressCallback([=](float64 value) {
if (_type != AudioMsgId::Type::Song) { if (_type != AudioMsgId::Type::Song) {
return; // Round video seek is not supported for now :( return; // Round video seek is not supported for now :(
} }
_playbackProgress->setValue(value, false); _playbackProgress->setValue(value, false);
handleSeekProgress(value); handleSeekProgress(value);
}); });
_playbackSlider->setChangeFinishedCallback([this](float64 value) { _playbackSlider->setChangeFinishedCallback([=](float64 value) {
if (_type != AudioMsgId::Type::Song) { if (_type != AudioMsgId::Type::Song) {
return; // Round video seek is not supported for now :( return; // Round video seek is not supported for now :(
} }
_playbackProgress->setValue(value, false); _playbackProgress->setValue(value, false);
handleSeekFinished(value); handleSeekFinished(value);
}); });
_playPause->setClickedCallback([this] { _playPause->setClickedCallback([=] {
instance()->playPauseCancelClicked(_type); instance()->playPauseCancelClicked(_type);
}); });

View File

@ -114,6 +114,13 @@ struct FrameRequest {
QSize outer; QSize outer;
ImageRoundRadius radius = ImageRoundRadius(); ImageRoundRadius radius = ImageRoundRadius();
RectParts corners = RectPart::AllCorners; RectParts corners = RectPart::AllCorners;
bool strict = true;
static FrameRequest NonStrict() {
auto result = FrameRequest();
result.strict = false;
return result;
}
bool empty() const { bool empty() const {
return resize.isEmpty(); return resize.isEmpty();

View File

@ -750,13 +750,18 @@ bool Player::active() const {
} }
bool Player::ready() const { bool Player::ready() const {
return (_stage != Stage::Uninitialized) && (_stage != Stage::Initializing); return (_stage != Stage::Uninitialized)
&& (_stage != Stage::Initializing);
} }
rpl::producer<Update, Error> Player::updates() const { rpl::producer<Update, Error> Player::updates() const {
return _updates.events(); return _updates.events();
} }
QSize Player::videoSize() const {
return _information.video.size;
}
QImage Player::frame(const FrameRequest &request) const { QImage Player::frame(const FrameRequest &request) const {
Expects(_video != nullptr); Expects(_video != nullptr);
@ -775,6 +780,8 @@ Media::Player::TrackState Player::prepareLegacyState() const {
? State::StoppedAtError ? State::StoppedAtError
: finished() : finished()
? State::StoppedAtEnd ? State::StoppedAtEnd
: (_stage == Stage::Uninitialized)
? State::Stopped
: paused() : paused()
? State::Paused ? State::Paused
: State::Playing; : State::Playing;

View File

@ -58,8 +58,8 @@ public:
[[nodiscard]] rpl::producer<Update, Error> updates() const; [[nodiscard]] rpl::producer<Update, Error> updates() const;
[[nodiscard]] QSize videoSize() const;
[[nodiscard]] QImage frame(const FrameRequest &request) const; [[nodiscard]] QImage frame(const FrameRequest &request) const;
//[[nodiscard]] int videoRotation() const;
[[nodiscard]] Media::Player::TrackState prepareLegacyState() const; [[nodiscard]] Media::Player::TrackState prepareLegacyState() const;

View File

@ -506,6 +506,10 @@ QImage PrepareByRequest(
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.drawImage(QRect(QPoint(), request.outer), original); p.drawImage(QRect(QPoint(), request.outer), original);
} }
if ((request.corners & RectPart::AllCorners)
&& (request.radius != ImageRoundRadius::None)) {
Images::prepareRound(storage, request.radius, request.corners);
}
// #TODO streaming later full prepare support. // #TODO streaming later full prepare support.
return storage; return storage;
} }

View File

@ -97,7 +97,7 @@ private:
crl::time _loopingShift = 0; crl::time _loopingShift = 0;
rpl::event_stream<> _checkNextFrame; rpl::event_stream<> _checkNextFrame;
rpl::event_stream<> _waitingForData; rpl::event_stream<> _waitingForData;
FrameRequest _request; FrameRequest _request = FrameRequest::NonStrict();
bool _queued = false; bool _queued = false;
base::ConcurrentTimer _readFramesTimer; base::ConcurrentTimer _readFramesTimer;
@ -801,7 +801,8 @@ crl::time VideoTrack::markFrameDisplayed(crl::time now) {
QImage VideoTrack::frame(const FrameRequest &request) { QImage VideoTrack::frame(const FrameRequest &request) {
const auto frame = _shared->frameForPaint(); const auto frame = _shared->frameForPaint();
const auto changed = (frame->request != request); const auto changed = (frame->request != request)
&& (request.strict || !frame->request.strict);
if (changed) { if (changed) {
frame->request = request; frame->request = request;
_wrapped.with([=](Implementation &unwrapped) { _wrapped.with([=](Implementation &unwrapped) {

View File

@ -65,7 +65,7 @@ private:
crl::time displayed = kTimeUnknown; crl::time displayed = kTimeUnknown;
crl::time display = kTimeUnknown; crl::time display = kTimeUnknown;
FrameRequest request; FrameRequest request = FrameRequest::NonStrict();
QImage prepared; QImage prepared;
}; };

View File

@ -165,7 +165,6 @@ struct OverlayWidget::Streamed {
QImage frameForDirectPaint; QImage frameForDirectPaint;
bool resumeOnCallEnd = false; bool resumeOnCallEnd = false;
std::optional<Streaming::Error> lastError;
}; };
OverlayWidget::Streamed::Streamed( OverlayWidget::Streamed::Streamed(
@ -2097,7 +2096,6 @@ void OverlayWidget::handleStreamingError(Streaming::Error &&error) {
if (!_doc->canBePlayed()) { if (!_doc->canBePlayed()) {
redisplayContent(); redisplayContent();
} else { } else {
_streamed->lastError = std::move(error);
playbackWaitingChange(false); playbackWaitingChange(false);
updatePlaybackState(); updatePlaybackState();
} }
@ -2230,7 +2228,6 @@ void OverlayWidget::playbackPauseResume() {
Expects(_streamed != nullptr); Expects(_streamed != nullptr);
_streamed->resumeOnCallEnd = false; _streamed->resumeOnCallEnd = false;
_streamed->lastError = std::nullopt;
if (const auto item = App::histItemById(_msgid)) { if (const auto item = App::histItemById(_msgid)) {
if (_streamed->player.failed()) { if (_streamed->player.failed()) {
clearStreaming(); clearStreaming();

View File

@ -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 "history/feed/history_feed_section.h" #include "history/feed/history_feed_section.h"
#include "media/player/media_player_round_controller.h" #include "data/data_media_types.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_feed.h" #include "data/data_feed.h"
#include "data/data_channel.h" #include "data/data_channel.h"
@ -116,15 +116,6 @@ void Controller::showEditPeerBox(PeerData *peer) {
} }
void Controller::init() { void Controller::init() {
session().data().animationPlayInlineRequest(
) | rpl::start_with_next([=](auto item) {
if (const auto video = roundVideo(item)) {
video->pauseResume();
} else {
startRoundVideo(item);
}
}, lifetime());
if (session().supportMode()) { if (session().supportMode()) {
initSupportMode(); initSupportMode();
} }
@ -616,40 +607,6 @@ not_null<MainWidget*> Controller::chats() const {
return App::wnd()->chatsWidget(); return App::wnd()->chatsWidget();
} }
bool Controller::startRoundVideo(not_null<HistoryItem*> context) {
if (auto video = RoundController::TryStart(this, context)) {
enableGifPauseReason(Window::GifPauseReason::RoundPlaying);
_roundVideo = std::move(video);
return true;
}
return false;
}
auto Controller::currentRoundVideo() const -> RoundController* {
return _roundVideo.get();
}
auto Controller::roundVideo(not_null<const HistoryItem*> context) const
-> RoundController* {
return roundVideo(context->fullId());
}
auto Controller::roundVideo(FullMsgId contextId) const -> RoundController* {
if (const auto result = currentRoundVideo()) {
if (result->contextId() == contextId) {
return result;
}
}
return nullptr;
}
void Controller::roundVideoFinished(not_null<RoundController*> video) {
if (video == _roundVideo.get()) {
_roundVideo = nullptr;
disableGifPauseReason(Window::GifPauseReason::RoundPlaying);
}
}
void Controller::setDefaultFloatPlayerDelegate( void Controller::setDefaultFloatPlayerDelegate(
not_null<Media::Player::FloatDelegate*> delegate) { not_null<Media::Player::FloatDelegate*> delegate) {
Expects(_defaultFloatPlayerDelegate == nullptr); Expects(_defaultFloatPlayerDelegate == nullptr);

View File

@ -23,7 +23,6 @@ enum class Type;
namespace Media { namespace Media {
namespace Player { namespace Player {
class RoundController;
class FloatController; class FloatController;
class FloatDelegate; class FloatDelegate;
} // namespace Player } // namespace Player
@ -138,7 +137,7 @@ private:
}; };
class Controller class Controller
: public Navigation : public Navigation
, private base::Subscriber { , private base::Subscriber {
public: public:
@ -252,13 +251,6 @@ public:
return this; return this;
} }
using RoundController = Media::Player::RoundController;
bool startRoundVideo(not_null<HistoryItem*> context);
RoundController *currentRoundVideo() const;
RoundController *roundVideo(not_null<const HistoryItem*> context) const;
RoundController *roundVideo(FullMsgId contextId) const;
void roundVideoFinished(not_null<RoundController*> video);
void setDefaultFloatPlayerDelegate( void setDefaultFloatPlayerDelegate(
not_null<Media::Player::FloatDelegate*> delegate); not_null<Media::Player::FloatDelegate*> delegate);
void replaceFloatPlayerDelegate( void replaceFloatPlayerDelegate(
@ -307,7 +299,6 @@ private:
std::deque<Dialogs::RowDescriptor> _chatEntryHistory; std::deque<Dialogs::RowDescriptor> _chatEntryHistory;
int _chatEntryHistoryPosition = -1; int _chatEntryHistoryPosition = -1;
std::unique_ptr<RoundController> _roundVideo;
std::unique_ptr<Media::Player::FloatController> _floatPlayers; std::unique_ptr<Media::Player::FloatController> _floatPlayers;
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr; Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;

View File

@ -448,8 +448,6 @@
<(src_loc)/media/player/media_player_instance.h <(src_loc)/media/player/media_player_instance.h
<(src_loc)/media/player/media_player_panel.cpp <(src_loc)/media/player/media_player_panel.cpp
<(src_loc)/media/player/media_player_panel.h <(src_loc)/media/player/media_player_panel.h
<(src_loc)/media/player/media_player_round_controller.cpp
<(src_loc)/media/player/media_player_round_controller.h
<(src_loc)/media/player/media_player_volume_controller.cpp <(src_loc)/media/player/media_player_volume_controller.cpp
<(src_loc)/media/player/media_player_volume_controller.h <(src_loc)/media/player/media_player_volume_controller.h
<(src_loc)/media/player/media_player_widget.cpp <(src_loc)/media/player/media_player_widget.cpp