mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-30 15:30:20 +00:00
Add video speed control slider.
This commit is contained in:
parent
b88219902f
commit
87cc18aff8
@ -23,6 +23,14 @@ constexpr auto kVersionTag = -1;
|
||||
constexpr auto kVersion = 1;
|
||||
constexpr auto kMaxSavedPlaybackPositions = 16;
|
||||
|
||||
[[nodiscard]] qint32 SerializePlaybackSpeed(float64 speed) {
|
||||
return int(std::round(std::clamp(speed * 4., 2., 8.))) - 2;
|
||||
}
|
||||
|
||||
float64 DeserializePlaybackSpeed(qint32 speed) {
|
||||
return (std::clamp(speed, 0, 6) + 2) / 4.;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Settings::Variables::Variables()
|
||||
@ -98,6 +106,7 @@ QByteArray Settings::serialize() const {
|
||||
for (const auto &[id, time] : _variables.mediaLastPlaybackPosition) {
|
||||
stream << quint64(id) << qint64(time);
|
||||
}
|
||||
stream << qint32(SerializePlaybackSpeed(_variables.videoPlaybackSpeed.current()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -148,6 +157,7 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||
qint32 suggestStickersByEmoji = _variables.suggestStickersByEmoji ? 1 : 0;
|
||||
qint32 spellcheckerEnabled = _variables.spellcheckerEnabled.current() ? 1 : 0;
|
||||
std::vector<std::pair<DocumentId, crl::time>> mediaLastPlaybackPosition;
|
||||
qint32 videoPlaybackSpeed = SerializePlaybackSpeed(_variables.videoPlaybackSpeed.current());
|
||||
|
||||
stream >> versionTag;
|
||||
if (versionTag == kVersionTag) {
|
||||
@ -268,6 +278,9 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> videoPlaybackSpeed;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Main::Settings::constructFromSerialized()"));
|
||||
@ -355,6 +368,7 @@ void Settings::constructFromSerialized(const QByteArray &serialized) {
|
||||
_variables.suggestStickersByEmoji = (suggestStickersByEmoji == 1);
|
||||
_variables.spellcheckerEnabled = (spellcheckerEnabled == 1);
|
||||
_variables.mediaLastPlaybackPosition = std::move(mediaLastPlaybackPosition);
|
||||
_variables.videoPlaybackSpeed = DeserializePlaybackSpeed(videoPlaybackSpeed);
|
||||
}
|
||||
|
||||
void Settings::setSupportChatsTimeSlice(int slice) {
|
||||
|
@ -241,6 +241,13 @@ public:
|
||||
return _variables.spellcheckerEnabled.changes();
|
||||
}
|
||||
|
||||
[[nodiscard]] float64 videoPlaybackSpeed() const {
|
||||
return _variables.videoPlaybackSpeed.current();
|
||||
}
|
||||
void setVideoPlaybackSpeed(float64 speed) {
|
||||
_variables.videoPlaybackSpeed = speed;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Variables {
|
||||
Variables();
|
||||
@ -281,6 +288,7 @@ private:
|
||||
bool suggestStickersByEmoji = true;
|
||||
rpl::variable<bool> spellcheckerEnabled = true;
|
||||
std::vector<std::pair<DocumentId, crl::time>> mediaLastPlaybackPosition;
|
||||
rpl::variable<float64> videoPlaybackSpeed = 1.;
|
||||
|
||||
static constexpr auto kDefaultSupportChatsLimitSlice
|
||||
= 7 * 24 * 60 * 60;
|
||||
|
@ -958,6 +958,7 @@ void Player::unlock() {
|
||||
--_locks;
|
||||
if (!_locks) {
|
||||
stopAudio();
|
||||
setSpeed(1.);
|
||||
setWaitForMarkAsShown(true);
|
||||
}
|
||||
}
|
||||
|
@ -2361,8 +2361,11 @@ void OverlayWidget::restartAtSeekPosition(crl::time position) {
|
||||
if (!_streamed->withSound) {
|
||||
options.mode = Streaming::Mode::Video;
|
||||
options.loop = true;
|
||||
} else if (_pip) {
|
||||
_pip = nullptr;
|
||||
} else {
|
||||
options.speed = _doc->session().settings().videoPlaybackSpeed();
|
||||
if (_pip) {
|
||||
_pip = nullptr;
|
||||
}
|
||||
}
|
||||
_streamed->instance.play(options);
|
||||
if (_streamingStartPaused) {
|
||||
@ -2397,13 +2400,29 @@ void OverlayWidget::playbackControlsVolumeChanged(float64 volume) {
|
||||
Global::SetVideoVolume(volume);
|
||||
updateMixerVideoVolume();
|
||||
Global::RefVideoVolumeChanged().notify();
|
||||
Auth().saveSettingsDelayed();
|
||||
if (_doc) {
|
||||
_doc->session().saveSettingsDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
float64 OverlayWidget::playbackControlsCurrentVolume() {
|
||||
return Global::VideoVolume();
|
||||
}
|
||||
|
||||
void OverlayWidget::playbackControlsSpeedChanged(float64 speed) {
|
||||
if (_doc) {
|
||||
_doc->session().settings().setVideoPlaybackSpeed(speed);
|
||||
_doc->session().saveSettingsDelayed();
|
||||
}
|
||||
if (_streamed && !videoIsGifv()) {
|
||||
_streamed->instance.setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
float64 OverlayWidget::playbackControlsCurrentSpeed() {
|
||||
return _doc ? _doc->session().settings().videoPlaybackSpeed() : 1.;
|
||||
}
|
||||
|
||||
void OverlayWidget::switchToPip() {
|
||||
const auto document = _doc;
|
||||
const auto msgId = _msgid;
|
||||
|
@ -172,6 +172,8 @@ private:
|
||||
void playbackControlsSeekFinished(crl::time position) override;
|
||||
void playbackControlsVolumeChanged(float64 volume) override;
|
||||
float64 playbackControlsCurrentVolume() override;
|
||||
void playbackControlsSpeedChanged(float64 speed);
|
||||
float64 playbackControlsCurrentSpeed() override;
|
||||
void playbackControlsToFullScreen() override;
|
||||
void playbackControlsFromFullScreen() override;
|
||||
void playbackControlsToPictureInPicture() override;
|
||||
|
@ -11,6 +11,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "media/streaming/media_streaming_document.h"
|
||||
#include "media/streaming/media_streaming_utility.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_settings.h"
|
||||
#include "data/data_document.h"
|
||||
#include "core/application.h"
|
||||
#include "ui/platform/ui_platform_utility.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
@ -721,6 +724,9 @@ void Pip::restartAtSeekPosition(crl::time position) {
|
||||
auto options = Streaming::PlaybackOptions();
|
||||
options.position = position;
|
||||
options.audioId = _instance.player().prepareLegacyState().id;
|
||||
options.speed = options.audioId.audio()
|
||||
? options.audioId.audio()->session().settings().videoPlaybackSpeed()
|
||||
: 1.;
|
||||
_instance.play(options);
|
||||
updatePlaybackState();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ PlaybackControls::PlaybackControls(
|
||||
, _playbackSlider(this, st::mediaviewPlayback)
|
||||
, _playbackProgress(std::make_unique<PlaybackProgress>())
|
||||
, _volumeController(this, st::mediaviewPlayback)
|
||||
, _speedController(this, st::mediaviewPlayback)
|
||||
, _fullScreenToggle(this, st::mediaviewFullScreenButton)
|
||||
, _pictureInPicture(this, st::mediaviewFullScreenButton)
|
||||
, _playedAlready(this, st::mediaviewPlayProgressLabel)
|
||||
@ -54,6 +55,12 @@ PlaybackControls::PlaybackControls(
|
||||
_volumeController->setChangeProgressCallback([=](float64 value) {
|
||||
_delegate->playbackControlsVolumeChanged(value);
|
||||
});
|
||||
_speedController->setPseudoDiscrete(
|
||||
7,
|
||||
[=](int index) { return (index + 2) / 4.; },
|
||||
_delegate->playbackControlsCurrentSpeed(),
|
||||
[=](float64 speed) { _delegate->playbackControlsSpeedChanged(speed); });
|
||||
_speedController->setAlwaysDisplayMarker(false);
|
||||
|
||||
_playPauseResume->addClickHandler([=] {
|
||||
if (_showPause) {
|
||||
@ -121,6 +128,7 @@ void PlaybackControls::startFading(Callback start) {
|
||||
showChildren();
|
||||
_playbackSlider->disablePaint(true);
|
||||
_volumeController->disablePaint(true);
|
||||
_speedController->disablePaint(true);
|
||||
_childrenHidden = false;
|
||||
}
|
||||
start();
|
||||
@ -128,7 +136,8 @@ void PlaybackControls::startFading(Callback start) {
|
||||
for (const auto child : children()) {
|
||||
if (child->isWidgetType()
|
||||
&& child != _playbackSlider
|
||||
&& child != _volumeController) {
|
||||
&& child != _volumeController
|
||||
&& child != _speedController) {
|
||||
static_cast<QWidget*>(child)->hide();
|
||||
}
|
||||
}
|
||||
@ -138,6 +147,7 @@ void PlaybackControls::startFading(Callback start) {
|
||||
}
|
||||
_playbackSlider->disablePaint(false);
|
||||
_volumeController->disablePaint(false);
|
||||
_speedController->disablePaint(false);
|
||||
}
|
||||
|
||||
void PlaybackControls::showAnimated() {
|
||||
@ -159,6 +169,7 @@ void PlaybackControls::fadeFinished() {
|
||||
void PlaybackControls::fadeUpdated(float64 opacity) {
|
||||
_playbackSlider->setFadeOpacity(opacity);
|
||||
_volumeController->setFadeOpacity(opacity);
|
||||
_speedController->setFadeOpacity(opacity);
|
||||
}
|
||||
|
||||
void PlaybackControls::updatePlayback(const Player::TrackState &state) {
|
||||
@ -306,8 +317,12 @@ void PlaybackControls::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
_pictureInPicture->moveToLeft(left, playTop);
|
||||
|
||||
const auto volumeTop = playTop + (_fullScreenToggle->height() - _volumeController->height()) / 2;
|
||||
_volumeController->resize(st::mediaviewVolumeWidth, st::mediaviewPlayback.seekSize.height());
|
||||
_volumeController->moveToRight(skip, playTop + (_fullScreenToggle->height() - _volumeController->height()) / 2);
|
||||
_volumeController->moveToRight(skip, volumeTop);
|
||||
|
||||
_speedController->resize(st::mediaviewVolumeWidth, st::mediaviewPlayback.seekSize.height());
|
||||
_speedController->moveToRight(skip + _volumeController->width() + skip, volumeTop);
|
||||
}
|
||||
|
||||
void PlaybackControls::paintEvent(QPaintEvent *e) {
|
||||
@ -320,6 +335,7 @@ void PlaybackControls::paintEvent(QPaintEvent *e) {
|
||||
showChildren();
|
||||
_playbackSlider->setFadeOpacity(1.);
|
||||
_volumeController->setFadeOpacity(1.);
|
||||
_speedController->setFadeOpacity(1.);
|
||||
_childrenHidden = false;
|
||||
}
|
||||
App::roundRect(p, rect(), st::mediaviewSaveMsgBg, MediaviewSaveCorners);
|
||||
|
@ -36,6 +36,8 @@ public:
|
||||
virtual void playbackControlsSeekFinished(crl::time position) = 0;
|
||||
virtual void playbackControlsVolumeChanged(float64 volume) = 0;
|
||||
[[nodiscard]] virtual float64 playbackControlsCurrentVolume() = 0;
|
||||
virtual void playbackControlsSpeedChanged(float64 speed) = 0;
|
||||
[[nodiscard]] virtual float64 playbackControlsCurrentSpeed() = 0;
|
||||
virtual void playbackControlsToFullScreen() = 0;
|
||||
virtual void playbackControlsFromFullScreen() = 0;
|
||||
virtual void playbackControlsToPictureInPicture() = 0;
|
||||
@ -90,6 +92,7 @@ private:
|
||||
std::unique_ptr<PlaybackProgress> _playbackProgress;
|
||||
std::unique_ptr<PlaybackProgress> _receivedTillProgress;
|
||||
object_ptr<Ui::MediaSlider> _volumeController;
|
||||
object_ptr<Ui::MediaSlider> _speedController;
|
||||
object_ptr<Ui::IconButton> _fullScreenToggle;
|
||||
object_ptr<Ui::IconButton> _pictureInPicture;
|
||||
object_ptr<Ui::LabelSimple> _playedAlready;
|
||||
|
Loading…
Reference in New Issue
Block a user