mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-21 15:47:38 +00:00
Allow switching video quality.
This commit is contained in:
parent
7ba78540ac
commit
3f2f3ebd51
@ -29,6 +29,7 @@ MediaPlayerButton {
|
||||
|
||||
MediaSpeedMenu {
|
||||
dropdown: DropdownMenu;
|
||||
qualityMenu: Menu;
|
||||
activeCheck: icon;
|
||||
activeCheckSkip: pixels;
|
||||
sliderStyle: TextStyle;
|
||||
@ -165,16 +166,20 @@ mediaPlayerMenu: DropdownMenu(defaultDropdownMenu) {
|
||||
}
|
||||
mediaPlayerMenuCheck: icon {{ "player/player_check", mediaPlayerActiveFg }};
|
||||
|
||||
mediaPlayerSpeedMenuInner: Menu(menuWithIcons) {
|
||||
separator: MenuSeparator(defaultMenuSeparator) {
|
||||
padding: margins(0px, 4px, 0px, 4px);
|
||||
width: 6px;
|
||||
}
|
||||
itemPadding: margins(54px, 7px, 54px, 9px);
|
||||
itemFgDisabled: mediaPlayerActiveFg;
|
||||
}
|
||||
mediaPlayerSpeedMenu: MediaSpeedMenu {
|
||||
dropdown: DropdownMenu(mediaPlayerMenu) {
|
||||
menu: Menu(menuWithIcons) {
|
||||
separator: MenuSeparator(defaultMenuSeparator) {
|
||||
padding: margins(0px, 4px, 0px, 4px);
|
||||
width: 6px;
|
||||
}
|
||||
itemPadding: margins(54px, 7px, 54px, 9px);
|
||||
itemFgDisabled: mediaPlayerActiveFg;
|
||||
}
|
||||
menu: mediaPlayerSpeedMenuInner;
|
||||
}
|
||||
qualityMenu: Menu(mediaPlayerSpeedMenuInner) {
|
||||
itemPadding: margins(17px, 7px, 54px, 9px);
|
||||
}
|
||||
activeCheck: mediaPlayerMenuCheck;
|
||||
activeCheckSkip: 8px;
|
||||
|
@ -177,7 +177,8 @@ void FillSpeedMenu(
|
||||
not_null<Ui::Menu::Menu*> menu,
|
||||
const style::MediaSpeedMenu &st,
|
||||
rpl::producer<float64> value,
|
||||
Fn<void(float64)> callback) {
|
||||
Fn<void(float64)> callback,
|
||||
bool onlySlider) {
|
||||
auto slider = base::make_unique_q<SpeedSliderItem>(
|
||||
menu,
|
||||
st,
|
||||
@ -198,6 +199,11 @@ void FillSpeedMenu(
|
||||
));
|
||||
|
||||
menu->addAction(std::move(slider));
|
||||
|
||||
if (onlySlider) {
|
||||
return;
|
||||
}
|
||||
|
||||
menu->addSeparator(&st.dropdown.menu.separator);
|
||||
|
||||
struct SpeedPoint {
|
||||
@ -693,7 +699,10 @@ SpeedController::SpeedController(
|
||||
not_null<QWidget*> menuParent,
|
||||
Fn<void(bool)> menuOverCallback,
|
||||
Fn<float64(bool lastNonDefault)> value,
|
||||
Fn<void(float64)> change)
|
||||
Fn<void(float64)> change,
|
||||
std::vector<int> qualities,
|
||||
Fn<int()> quality,
|
||||
Fn<void(int)> changeQuality)
|
||||
: WithDropdownController(
|
||||
button,
|
||||
menuParent,
|
||||
@ -702,7 +711,12 @@ SpeedController::SpeedController(
|
||||
std::move(menuOverCallback))
|
||||
, _st(button->st())
|
||||
, _lookup(std::move(value))
|
||||
, _change(std::move(change)) {
|
||||
, _change(std::move(change))
|
||||
, _qualities(std::move(qualities))
|
||||
, _lookupQuality(std::move(quality))
|
||||
, _changeQuality(std::move(changeQuality)) {
|
||||
Expects(_qualities.empty() || (_lookupQuality && _changeQuality));
|
||||
|
||||
button->setClickedCallback([=] {
|
||||
toggleDefault();
|
||||
save();
|
||||
@ -756,12 +770,63 @@ void SpeedController::save() {
|
||||
_saved.fire({});
|
||||
}
|
||||
|
||||
void SpeedController::setQuality(int quality) {
|
||||
_quality = quality;
|
||||
_changeQuality(quality);
|
||||
}
|
||||
|
||||
void SpeedController::fillMenu(not_null<Ui::DropdownMenu*> menu) {
|
||||
FillSpeedMenu(
|
||||
menu->menu(),
|
||||
_st.menu,
|
||||
_speedChanged.events_starting_with(speed()),
|
||||
[=](float64 speed) { setSpeed(speed); save(); });
|
||||
[=](float64 speed) { setSpeed(speed); save(); },
|
||||
!_qualities.empty());
|
||||
if (_qualities.empty()) {
|
||||
return;
|
||||
}
|
||||
_quality = _lookupQuality();
|
||||
const auto raw = menu->menu();
|
||||
const auto &st = _st.menu;
|
||||
raw->addSeparator(&st.dropdown.menu.separator);
|
||||
|
||||
const auto add = [&](int quality) {
|
||||
const auto text = quality ? u"%1p"_q.arg(quality) : u"Original"_q;
|
||||
auto action = base::make_unique_q<Ui::Menu::Action>(
|
||||
raw,
|
||||
st.qualityMenu,
|
||||
Ui::Menu::CreateAction(raw, text, [=] { _changeQuality(quality); }),
|
||||
nullptr,
|
||||
nullptr);
|
||||
const auto raw = action.get();
|
||||
const auto check = Ui::CreateChild<Ui::RpWidget>(raw);
|
||||
check->resize(st.activeCheck.size());
|
||||
check->paintRequest(
|
||||
) | rpl::start_with_next([check, icon = &st.activeCheck] {
|
||||
auto p = QPainter(check);
|
||||
icon->paint(p, 0, 0, check->width());
|
||||
}, check->lifetime());
|
||||
raw->sizeValue(
|
||||
) | rpl::start_with_next([=, skip = st.activeCheckSkip](QSize size) {
|
||||
check->moveToRight(
|
||||
skip,
|
||||
(size.height() - check->height()) / 2,
|
||||
size.width());
|
||||
}, check->lifetime());
|
||||
check->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
_quality.value(
|
||||
) | rpl::start_with_next([=](int now) {
|
||||
const auto chosen = (now == quality);
|
||||
raw->action()->setEnabled(!chosen);
|
||||
check->setVisible(chosen);
|
||||
}, raw->lifetime());
|
||||
menu->addAction(std::move(action));
|
||||
};
|
||||
|
||||
add(0);
|
||||
for (const auto quality : _qualities) {
|
||||
add(quality);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Media::Player
|
||||
|
@ -129,7 +129,10 @@ public:
|
||||
not_null<QWidget*> menuParent,
|
||||
Fn<void(bool)> menuOverCallback,
|
||||
Fn<float64(bool lastNonDefault)> value,
|
||||
Fn<void(float64)> change);
|
||||
Fn<void(float64)> change,
|
||||
std::vector<int> qualities = {},
|
||||
Fn<int()> quality = nullptr,
|
||||
Fn<void(int)> changeQuality = nullptr);
|
||||
|
||||
[[nodiscard]] rpl::producer<> saved() const;
|
||||
|
||||
@ -141,6 +144,7 @@ private:
|
||||
[[nodiscard]] float64 lastNonDefaultSpeed() const;
|
||||
void toggleDefault();
|
||||
void setSpeed(float64 newSpeed);
|
||||
void setQuality(int quality);
|
||||
void save();
|
||||
|
||||
const style::MediaSpeedButton &_st;
|
||||
@ -151,6 +155,11 @@ private:
|
||||
rpl::event_stream<float64> _speedChanged;
|
||||
rpl::event_stream<> _saved;
|
||||
|
||||
std::vector<int> _qualities;
|
||||
Fn<int()> _lookupQuality;
|
||||
Fn<void(int)> _changeQuality;
|
||||
rpl::variable<int> _quality;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Media::Player
|
||||
|
@ -17,6 +17,9 @@ inline constexpr auto kTimeUnknown = std::numeric_limits<crl::time>::min();
|
||||
inline constexpr auto kDurationMax = crl::time(std::numeric_limits<int>::max());
|
||||
inline constexpr auto kDurationUnavailable = std::numeric_limits<crl::time>::max();
|
||||
|
||||
inline constexpr auto kOriginalQuality = 0;
|
||||
inline constexpr auto kAutoQuality = -1;
|
||||
|
||||
namespace Audio {
|
||||
bool SupportsSpeedControl();
|
||||
} // namespace Audio
|
||||
|
@ -307,17 +307,21 @@ mediaviewTitleMaximizeMacPadding: margins(0px, 4px, 8px, 4px);
|
||||
mediaviewShadowTop: icon{{ "mediaview/shadow_top", windowShadowFg }};
|
||||
mediaviewShadowBottom: icon{{ "mediaview/shadow_bottom", windowShadowFg }};
|
||||
|
||||
mediaviewSpeedMenuInner: Menu(mediaviewMenu) {
|
||||
separator: MenuSeparator(mediaviewMenuSeparator) {
|
||||
fg: groupCallMenuBgOver;
|
||||
padding: margins(0px, 4px, 0px, 4px);
|
||||
width: 6px;
|
||||
}
|
||||
itemPadding: margins(54px, 7px, 54px, 9px);
|
||||
itemFgDisabled: mediaviewTextLinkFg;
|
||||
}
|
||||
mediaviewSpeedMenu: MediaSpeedMenu(mediaPlayerSpeedMenu) {
|
||||
dropdown: DropdownMenu(mediaviewDropdownMenu) {
|
||||
menu: Menu(mediaviewMenu) {
|
||||
separator: MenuSeparator(mediaviewMenuSeparator) {
|
||||
fg: groupCallMenuBgOver;
|
||||
padding: margins(0px, 4px, 0px, 4px);
|
||||
width: 6px;
|
||||
}
|
||||
itemPadding: margins(54px, 7px, 54px, 9px);
|
||||
itemFgDisabled: mediaviewTextLinkFg;
|
||||
}
|
||||
menu: mediaviewSpeedMenuInner;
|
||||
}
|
||||
qualityMenu: Menu(mediaviewSpeedMenuInner) {
|
||||
itemPadding: margins(17px, 7px, 54px, 9px);
|
||||
}
|
||||
activeCheck: icon {{ "player/player_check", mediaviewTextLinkFg }};
|
||||
slider: MediaSlider(defaultContinuousSlider) {
|
||||
|
@ -1112,7 +1112,10 @@ bool OverlayWidget::videoShown() const {
|
||||
QSize OverlayWidget::videoSize() const {
|
||||
Expects(videoShown());
|
||||
|
||||
return flipSizeByRotation(_streamed->instance.info().video.size);
|
||||
const auto use = (_document && _chosenQuality != _document)
|
||||
? _document->dimensions
|
||||
: _streamed->instance.info().video.size;
|
||||
return flipSizeByRotation(use);
|
||||
}
|
||||
|
||||
bool OverlayWidget::streamingRequiresControls() const {
|
||||
@ -2257,16 +2260,37 @@ OverlayWidget::~OverlayWidget() {
|
||||
_dropdown.destroy();
|
||||
}
|
||||
|
||||
not_null<DocumentData*> OverlayWidget::chooseQuality() const {
|
||||
Expects(_document != nullptr);
|
||||
|
||||
const auto video = _document->video();
|
||||
if (!video || video->qualities.empty() || _quality == kOriginalQuality) {
|
||||
return _document;
|
||||
}
|
||||
auto closest = _document;
|
||||
auto closestAbs = std::abs(_quality - _document->resolveVideoQuality());
|
||||
for (const auto &quality : video->qualities) {
|
||||
const auto abs = std::abs(_quality - quality->resolveVideoQuality());
|
||||
if (abs < closestAbs) {
|
||||
closestAbs = abs;
|
||||
closest = quality;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
void OverlayWidget::assignMediaPointer(DocumentData *document) {
|
||||
_savePhotoVideoWhenLoaded = SavePhotoVideo::None;
|
||||
_photo = nullptr;
|
||||
_photoMedia = nullptr;
|
||||
if (_document != document) {
|
||||
if ((_document = document)) {
|
||||
_chosenQuality = chooseQuality();
|
||||
_documentMedia = _document->createMediaView();
|
||||
_documentMedia->goodThumbnailWanted();
|
||||
_documentMedia->thumbnailWanted(fileOrigin());
|
||||
} else {
|
||||
_chosenQuality = nullptr;
|
||||
_documentMedia = nullptr;
|
||||
}
|
||||
_documentLoadingTo = QString();
|
||||
@ -2275,6 +2299,7 @@ void OverlayWidget::assignMediaPointer(DocumentData *document) {
|
||||
|
||||
void OverlayWidget::assignMediaPointer(not_null<PhotoData*> photo) {
|
||||
_savePhotoVideoWhenLoaded = SavePhotoVideo::None;
|
||||
_chosenQuality = nullptr;
|
||||
_document = nullptr;
|
||||
_documentMedia = nullptr;
|
||||
_documentLoadingTo = QString();
|
||||
@ -3848,12 +3873,12 @@ void OverlayWidget::startStreamingPlayer(
|
||||
return;
|
||||
}
|
||||
|
||||
const auto position = _document
|
||||
_streamedPosition = _document
|
||||
? startStreaming.startTime
|
||||
: _photo
|
||||
? _photo->videoStartPosition()
|
||||
: 0;
|
||||
restartAtSeekPosition(position);
|
||||
restartAtSeekPosition(_streamedPosition);
|
||||
}
|
||||
|
||||
void OverlayWidget::initStreamingThumbnail() {
|
||||
@ -3892,9 +3917,15 @@ void OverlayWidget::initStreamingThumbnail() {
|
||||
: good
|
||||
? good->size()
|
||||
: _document->dimensions;
|
||||
if (!good && !thumbnail && !blurred) {
|
||||
if (size.isEmpty()) {
|
||||
return;
|
||||
} else if (size.isEmpty()) {
|
||||
} else if (!_streamedQualityChangeFrame.isNull()) {
|
||||
setStaticContent(_streamedQualityChangeFrame.scaled(
|
||||
size,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
return;
|
||||
} else if (!good && !thumbnail && !blurred) {
|
||||
return;
|
||||
}
|
||||
const auto options = VideoThumbOptions(_document);
|
||||
@ -3917,6 +3948,7 @@ void OverlayWidget::initStreamingThumbnail() {
|
||||
void OverlayWidget::streamingReady(Streaming::Information &&info) {
|
||||
if (videoShown()) {
|
||||
applyVideoSize();
|
||||
_streamedQualityChangeFrame = QImage();
|
||||
} else {
|
||||
updateContentRect();
|
||||
}
|
||||
@ -3938,8 +3970,9 @@ bool OverlayWidget::createStreamingObjects() {
|
||||
|
||||
const auto origin = fileOrigin();
|
||||
const auto callback = [=] { waitingAnimationCallback(); };
|
||||
if (_document) {
|
||||
_streamed = std::make_unique<Streamed>(_document, origin, callback);
|
||||
const auto video = _chosenQuality ? _chosenQuality : _document;
|
||||
if (video) {
|
||||
_streamed = std::make_unique<Streamed>(video, origin, callback);
|
||||
} else {
|
||||
_streamed = std::make_unique<Streamed>(_photo, origin, callback);
|
||||
}
|
||||
@ -3950,8 +3983,8 @@ bool OverlayWidget::createStreamingObjects() {
|
||||
++_streamedCreated;
|
||||
_streamed->instance.setPriority(kOverlayLoaderPriority);
|
||||
_streamed->instance.lockPlayer();
|
||||
_streamed->withSound = _document
|
||||
&& !_document->isSilentVideo()
|
||||
_streamed->withSound = video
|
||||
&& !video->isSilentVideo()
|
||||
&& (_document->isAudioFile()
|
||||
|| _document->isVideoFile()
|
||||
|| _document->isVoiceMessage()
|
||||
@ -4018,6 +4051,7 @@ void OverlayWidget::handleStreamingUpdate(Streaming::Update &&update) {
|
||||
updateContentRect();
|
||||
Core::App().updateNonIdle();
|
||||
updatePlaybackState();
|
||||
_streamedPosition = update.position;
|
||||
}, [&](const PreloadedAudio &update) {
|
||||
updatePlaybackState();
|
||||
}, [&](const UpdateAudio &update) {
|
||||
@ -4381,6 +4415,45 @@ float64 OverlayWidget::playbackControlsCurrentSpeed(bool lastNonDefault) {
|
||||
return Core::App().settings().videoPlaybackSpeed(lastNonDefault);
|
||||
}
|
||||
|
||||
std::vector<int> OverlayWidget::playbackControlsQualities() {
|
||||
const auto video = _document ? _document->video() : nullptr;
|
||||
if (!video || video->qualities.empty()) {
|
||||
return {};
|
||||
}
|
||||
auto result = std::vector<int>();
|
||||
result.reserve(video->qualities.size());
|
||||
for (const auto &quality : video->qualities) {
|
||||
result.push_back(quality->resolveVideoQuality());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int OverlayWidget::playbackControlsCurrentQuality() {
|
||||
return _quality;
|
||||
}
|
||||
|
||||
void OverlayWidget::playbackControlsQualityChanged(int quality) {
|
||||
const auto now = _chosenQuality;
|
||||
if (_quality != quality) {
|
||||
_quality = quality;
|
||||
if (_document) {
|
||||
_chosenQuality = chooseQuality();
|
||||
if (_chosenQuality != now) {
|
||||
if (_streamed && _streamed->instance.ready()) {
|
||||
_streamedQualityChangeFrame = currentVideoFrameImage();
|
||||
}
|
||||
clearStreaming();
|
||||
_streamingStartPaused = false;
|
||||
const auto time = _streamedPosition;
|
||||
const auto startStreaming = StartStreaming(false, time);
|
||||
if (!canInitStreaming() || !initStreaming(startStreaming)) {
|
||||
redisplayContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayWidget::switchToPip() {
|
||||
Expects(_streamed != nullptr);
|
||||
Expects(_document != nullptr);
|
||||
@ -4628,6 +4701,7 @@ void OverlayWidget::updatePlaybackState() {
|
||||
}
|
||||
const auto state = _streamed->instance.player().prepareLegacyState();
|
||||
if (state.position != kTimeUnknown && state.length != kTimeUnknown) {
|
||||
_streamedPosition = state.position;
|
||||
if (_streamed->controls) {
|
||||
_streamed->controls->updatePlayback(state);
|
||||
_touchbarTrackState.fire_copy(state);
|
||||
|
@ -236,6 +236,9 @@ private:
|
||||
void playbackControlsVolumeChangeFinished() override;
|
||||
void playbackControlsSpeedChanged(float64 speed) override;
|
||||
float64 playbackControlsCurrentSpeed(bool lastNonDefault) override;
|
||||
std::vector<int> playbackControlsQualities() override;
|
||||
int playbackControlsCurrentQuality() override;
|
||||
void playbackControlsQualityChanged(int quality) override;
|
||||
void playbackControlsToFullScreen() override;
|
||||
void playbackControlsFromFullScreen() override;
|
||||
void playbackControlsToPictureInPicture() override;
|
||||
@ -315,11 +318,11 @@ private:
|
||||
void checkForSaveLoaded();
|
||||
void showPremiumDownloadPromo();
|
||||
|
||||
Entity entityForUserPhotos(int index) const;
|
||||
Entity entityForSharedMedia(int index) const;
|
||||
Entity entityForCollage(int index) const;
|
||||
Entity entityByIndex(int index) const;
|
||||
Entity entityForItemId(const FullMsgId &itemId) const;
|
||||
[[nodiscard]] Entity entityForUserPhotos(int index) const;
|
||||
[[nodiscard]] Entity entityForSharedMedia(int index) const;
|
||||
[[nodiscard]] Entity entityForCollage(int index) const;
|
||||
[[nodiscard]] Entity entityByIndex(int index) const;
|
||||
[[nodiscard]] Entity entityForItemId(const FullMsgId &itemId) const;
|
||||
bool moveToEntity(const Entity &entity, int preloadDelta = 0);
|
||||
|
||||
void setContext(std::variant<
|
||||
@ -335,23 +338,23 @@ private:
|
||||
struct SharedMedia;
|
||||
using SharedMediaType = SharedMediaWithLastSlice::Type;
|
||||
using SharedMediaKey = SharedMediaWithLastSlice::Key;
|
||||
std::optional<SharedMediaType> sharedMediaType() const;
|
||||
std::optional<SharedMediaKey> sharedMediaKey() const;
|
||||
std::optional<SharedMediaType> computeOverviewType() const;
|
||||
[[nodiscard]] std::optional<SharedMediaType> sharedMediaType() const;
|
||||
[[nodiscard]] std::optional<SharedMediaKey> sharedMediaKey() const;
|
||||
[[nodiscard]] std::optional<SharedMediaType> computeOverviewType() const;
|
||||
bool validSharedMedia() const;
|
||||
void validateSharedMedia();
|
||||
void handleSharedMediaUpdate(SharedMediaWithLastSlice &&update);
|
||||
|
||||
struct UserPhotos;
|
||||
using UserPhotosKey = UserPhotosSlice::Key;
|
||||
std::optional<UserPhotosKey> userPhotosKey() const;
|
||||
[[nodiscard]] std::optional<UserPhotosKey> userPhotosKey() const;
|
||||
bool validUserPhotos() const;
|
||||
void validateUserPhotos();
|
||||
void handleUserPhotosUpdate(UserPhotosSlice &&update);
|
||||
|
||||
struct Collage;
|
||||
using CollageKey = WebPageCollage::Item;
|
||||
std::optional<CollageKey> collageKey() const;
|
||||
[[nodiscard]] std::optional<CollageKey> collageKey() const;
|
||||
bool validCollage() const;
|
||||
void validateCollage();
|
||||
|
||||
@ -430,11 +433,11 @@ private:
|
||||
void contentSizeChanged();
|
||||
|
||||
// Radial animation interface.
|
||||
float64 radialProgress() const;
|
||||
bool radialLoading() const;
|
||||
QRect radialRect() const;
|
||||
[[nodiscard]] float64 radialProgress() const;
|
||||
[[nodiscard]] bool radialLoading() const;
|
||||
[[nodiscard]] QRect radialRect() const;
|
||||
void radialStart();
|
||||
crl::time radialTimeShift() const;
|
||||
[[nodiscard]] crl::time radialTimeShift() const;
|
||||
|
||||
void updateHeader();
|
||||
void snapXY();
|
||||
@ -524,6 +527,7 @@ private:
|
||||
void clearStreaming(bool savePosition = true);
|
||||
[[nodiscard]] bool canInitStreaming() const;
|
||||
[[nodiscard]] bool saveControlLocked() const;
|
||||
[[nodiscard]] not_null<DocumentData*> chooseQuality() const;
|
||||
|
||||
[[nodiscard]] bool topShadowOnTheRight() const;
|
||||
void applyHideWindowWorkaround();
|
||||
@ -551,6 +555,8 @@ private:
|
||||
rpl::lifetime _sessionLifetime;
|
||||
PhotoData *_photo = nullptr;
|
||||
DocumentData *_document = nullptr;
|
||||
DocumentData *_chosenQuality = nullptr;
|
||||
int _quality = {};
|
||||
QString _documentLoadingTo;
|
||||
std::shared_ptr<Data::PhotoMedia> _photoMedia;
|
||||
std::shared_ptr<Data::DocumentMedia> _documentMedia;
|
||||
@ -625,6 +631,8 @@ private:
|
||||
|
||||
std::unique_ptr<Streamed> _streamed;
|
||||
std::unique_ptr<PipWrap> _pip;
|
||||
QImage _streamedQualityChangeFrame;
|
||||
crl::time _streamedPosition = 0;
|
||||
int _streamedCreated = 0;
|
||||
bool _showAsPip = false;
|
||||
|
||||
|
@ -47,7 +47,10 @@ PlaybackControls::PlaybackControls(
|
||||
parent,
|
||||
[=](bool) {},
|
||||
[=](bool lastNonDefault) { return speedLookup(lastNonDefault); },
|
||||
[=](float64 speed) { saveSpeed(speed); })
|
||||
[=](float64 speed) { saveSpeed(speed); },
|
||||
_delegate->playbackControlsQualities(),
|
||||
[=] { return _delegate->playbackControlsCurrentQuality(); },
|
||||
[=](int quality) { saveQuality(quality); })
|
||||
: nullptr)
|
||||
, _fadeAnimation(std::make_unique<Ui::FadeAnimation>(this)) {
|
||||
_fadeAnimation->show();
|
||||
@ -192,6 +195,10 @@ void PlaybackControls::saveSpeed(float64 speed) {
|
||||
_delegate->playbackControlsSpeedChanged(speed);
|
||||
}
|
||||
|
||||
void PlaybackControls::saveQuality(int quality) {
|
||||
_delegate->playbackControlsQualityChanged(quality);
|
||||
}
|
||||
|
||||
void PlaybackControls::updatePlaybackSpeed(float64 speed) {
|
||||
DEBUG_LOG(("Media playback speed: update to %1.").arg(speed));
|
||||
_delegate->playbackControlsSpeedChanged(speed);
|
||||
|
@ -44,6 +44,10 @@ public:
|
||||
virtual void playbackControlsSpeedChanged(float64 speed) = 0;
|
||||
[[nodiscard]] virtual float64 playbackControlsCurrentSpeed(
|
||||
bool lastNonDefault) = 0;
|
||||
[[nodiscard]] virtual auto playbackControlsQualities()
|
||||
-> std::vector<int> = 0;
|
||||
[[nodiscard]] virtual int playbackControlsCurrentQuality() = 0;
|
||||
virtual void playbackControlsQualityChanged(int quality) = 0;
|
||||
virtual void playbackControlsToFullScreen() = 0;
|
||||
virtual void playbackControlsFromFullScreen() = 0;
|
||||
virtual void playbackControlsToPictureInPicture() = 0;
|
||||
@ -90,6 +94,8 @@ private:
|
||||
[[nodiscard]] float64 speedLookup(bool lastNonDefault) const;
|
||||
void saveSpeed(float64 speed);
|
||||
|
||||
void saveQuality(int quality);
|
||||
|
||||
const not_null<Delegate*> _delegate;
|
||||
|
||||
bool _inFullScreen = false;
|
||||
|
Loading…
Reference in New Issue
Block a user