mirror of
https://github.com/telegramdesktop/tdesktop
synced 2024-12-15 02:44:45 +00:00
Add volume controls to the PiP window
Add volume toggle and volume level controls to the PiP window.
This commit is contained in:
parent
afc5191644
commit
d752aa3481
@ -948,6 +948,9 @@ Pip::Pip(
|
||||
})
|
||||
, _playbackProgress(std::make_unique<PlaybackProgress>())
|
||||
, _rotation(data->owner().mediaRotation().get(data))
|
||||
, _lastPositiveVolume((Core::App().settings().videoVolume() > 0.)
|
||||
? Core::App().settings().videoVolume()
|
||||
: Core::Settings::kDefaultVolume)
|
||||
, _roundRect(ImageRoundRadius::Large, st::radialBg)
|
||||
, _closeAndContinue(std::move(closeAndContinue))
|
||||
, _destroy(std::move(destroy)) {
|
||||
@ -1032,6 +1035,7 @@ void Pip::handleMouseMove(QPoint position) {
|
||||
});
|
||||
setOverState(computeState(position));
|
||||
seekUpdate(position);
|
||||
volumeControllerUpdate(position);
|
||||
}
|
||||
|
||||
void Pip::setOverState(OverState state) {
|
||||
@ -1088,6 +1092,8 @@ void Pip::updateActiveState(OverState was) {
|
||||
check(_enlarge);
|
||||
check(_play);
|
||||
check(_playback);
|
||||
check(_volumeToggle);
|
||||
check(_volumeController);
|
||||
}
|
||||
|
||||
void Pip::handleMousePress(QPoint position, Qt::MouseButton button) {
|
||||
@ -1101,10 +1107,11 @@ void Pip::handleMousePress(QPoint position, Qt::MouseButton button) {
|
||||
return;
|
||||
}
|
||||
_pressed = _over;
|
||||
if (_over == OverState::Playback) {
|
||||
if (_over == OverState::Playback || _over == OverState::VolumeController) {
|
||||
_panel.setDragDisabled(true);
|
||||
}
|
||||
seekUpdate(position);
|
||||
volumeControllerUpdate(position);
|
||||
}
|
||||
|
||||
void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
||||
@ -1118,11 +1125,18 @@ void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
||||
return;
|
||||
}
|
||||
seekUpdate(position);
|
||||
volumeControllerUpdate(position);
|
||||
const auto pressed = base::take(_pressed);
|
||||
if (pressed && *pressed == OverState::Playback) {
|
||||
_panel.setDragDisabled(false);
|
||||
seekFinish(_playbackProgress->value());
|
||||
return;
|
||||
if (pressed) {
|
||||
if (*pressed == OverState::Playback) {
|
||||
_panel.setDragDisabled(false);
|
||||
seekFinish(_playbackProgress->value());
|
||||
return;
|
||||
} else if (*pressed == OverState::VolumeController) {
|
||||
_panel.setDragDisabled(false);
|
||||
_panel.update();
|
||||
return;
|
||||
}
|
||||
} else if (_panel.dragging() || !pressed || *pressed != _over) {
|
||||
_lastHandledPress = std::nullopt;
|
||||
return;
|
||||
@ -1132,6 +1146,7 @@ void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
|
||||
switch (_over) {
|
||||
case OverState::Close: _panel.widget()->close(); break;
|
||||
case OverState::Enlarge: _closeAndContinue(); break;
|
||||
case OverState::VolumeToggle: volumeToggled(); break;
|
||||
case OverState::Other: playbackPauseResume(); break;
|
||||
}
|
||||
}
|
||||
@ -1192,10 +1207,37 @@ void Pip::seekFinish(float64 value) {
|
||||
restartAtSeekPosition(positionMs);
|
||||
}
|
||||
|
||||
void Pip::volumeChanged(float64 volume) {
|
||||
if (volume > 0.) {
|
||||
_lastPositiveVolume = volume;
|
||||
}
|
||||
Player::mixer()->setVideoVolume(volume);
|
||||
Core::App().settings().setVideoVolume(volume);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}
|
||||
|
||||
void Pip::volumeToggled() {
|
||||
const auto volume = Core::App().settings().videoVolume();
|
||||
volumeChanged(volume ? 0. : _lastPositiveVolume);
|
||||
_panel.update();
|
||||
}
|
||||
|
||||
void Pip::volumeControllerUpdate(QPoint position) {
|
||||
if (!_pressed || *_pressed != OverState::VolumeController) {
|
||||
return;
|
||||
}
|
||||
const auto unbound = (position.x() - _volumeController.icon.x())
|
||||
/ float64(_volumeController.icon.width());
|
||||
const auto value = std::clamp(unbound, 0., 1.);
|
||||
volumeChanged(value);
|
||||
}
|
||||
|
||||
void Pip::setupButtons() {
|
||||
_close.state = OverState::Close;
|
||||
_enlarge.state = OverState::Enlarge;
|
||||
_playback.state = OverState::Playback;
|
||||
_volumeToggle.state = OverState::VolumeToggle;
|
||||
_volumeController.state = OverState::VolumeController;
|
||||
_play.state = OverState::Other;
|
||||
_panel.rp()->sizeValue(
|
||||
) | rpl::map([=] {
|
||||
@ -1212,6 +1254,31 @@ void Pip::setupButtons() {
|
||||
rect.y(),
|
||||
st::pipEnlargeIcon.width() + 2 * skip,
|
||||
st::pipEnlargeIcon.height() + 2 * skip);
|
||||
|
||||
const auto volumeSkip = st::pipPlaybackSkip;
|
||||
const auto volumeHeight = 2 * volumeSkip + st::pipPlaybackWide;
|
||||
const auto volumeToggleWidth = st::mediaviewVolumeIcon0.width()
|
||||
+ 2 * skip;
|
||||
const auto volumeToggleHeight = st::mediaviewVolumeIcon0.height()
|
||||
+ 2 * skip;
|
||||
const auto volumeWidth = (((st::mediaviewVolumeWidth + 2 * skip)
|
||||
+ _close.area.width()
|
||||
+ _enlarge.area.width()
|
||||
+ volumeToggleWidth) < rect.width())
|
||||
? st::mediaviewVolumeWidth
|
||||
: 0;
|
||||
_volumeController.area = QRect(
|
||||
rect.x() + rect.width() - volumeWidth - 2 * volumeSkip,
|
||||
rect.y() + (volumeToggleHeight - volumeHeight) / 2,
|
||||
volumeWidth,
|
||||
volumeHeight);
|
||||
_volumeToggle.area = QRect(
|
||||
_volumeController.area.x()
|
||||
- st::mediaviewVolumeIcon0.width()
|
||||
- skip,
|
||||
rect.y(),
|
||||
volumeToggleWidth,
|
||||
volumeToggleHeight);
|
||||
if (!IsWindowControlsOnLeft()) {
|
||||
_close.area.moveLeft(rect.x()
|
||||
+ rect.width()
|
||||
@ -1221,15 +1288,22 @@ void Pip::setupButtons() {
|
||||
+ rect.width()
|
||||
- (_enlarge.area.x() - rect.x())
|
||||
- _enlarge.area.width());
|
||||
_volumeToggle.area.moveLeft(rect.x());
|
||||
_volumeController.area.moveLeft(_volumeToggle.area.x()
|
||||
+ _volumeToggle.area.width());
|
||||
}
|
||||
_close.icon = _close.area.marginsRemoved({ skip, skip, skip, skip });
|
||||
_enlarge.icon = _enlarge.area.marginsRemoved(
|
||||
{ skip, skip, skip, skip });
|
||||
_volumeToggle.icon = _volumeToggle.area.marginsRemoved(
|
||||
{ skip, skip, skip, skip });
|
||||
_play.icon = QRect(
|
||||
rect.x() + (rect.width() - st::pipPlayIcon.width()) / 2,
|
||||
rect.y() + (rect.height() - st::pipPlayIcon.height()) / 2,
|
||||
st::pipPlayIcon.width(),
|
||||
st::pipPlayIcon.height());
|
||||
_volumeController.icon = _volumeController.area.marginsRemoved(
|
||||
{ volumeSkip, volumeSkip, volumeSkip, volumeSkip });
|
||||
const auto playbackSkip = st::pipPlaybackSkip;
|
||||
const auto playbackHeight = 2 * playbackSkip + st::pipPlaybackWide;
|
||||
_playback.area = QRect(
|
||||
@ -1312,6 +1386,7 @@ void Pip::paintControls(QPainter &p) const {
|
||||
paintButtons(p);
|
||||
paintPlayback(p);
|
||||
paintPlaybackTexts(p);
|
||||
paintVolumeController(p);
|
||||
}
|
||||
|
||||
void Pip::paintFade(QPainter &p) const {
|
||||
@ -1355,42 +1430,73 @@ void Pip::paintButtons(QPainter &p) const {
|
||||
_showPause ? st::pipPauseIconOver : st::pipPlayIconOver);
|
||||
drawOne(_close, st::pipCloseIcon, st::pipCloseIconOver);
|
||||
drawOne(_enlarge, st::pipEnlargeIcon, st::pipEnlargeIconOver);
|
||||
const auto volume = Core::App().settings().videoVolume();
|
||||
if (volume <= 0.) {
|
||||
drawOne(
|
||||
_volumeToggle,
|
||||
st::mediaviewVolumeIcon0,
|
||||
st::mediaviewVolumeIcon0Over);
|
||||
} else if (volume < 1 / 2.) {
|
||||
drawOne(
|
||||
_volumeToggle,
|
||||
st::mediaviewVolumeIcon1,
|
||||
st::mediaviewVolumeIcon1Over);
|
||||
} else {
|
||||
drawOne(
|
||||
_volumeToggle,
|
||||
st::mediaviewVolumeIcon2,
|
||||
st::mediaviewVolumeIcon2Over);
|
||||
}
|
||||
}
|
||||
|
||||
void Pip::paintPlayback(QPainter &p) const {
|
||||
const auto radius = _playback.icon.height() / 2;
|
||||
const auto shown = activeValue(_playback);
|
||||
const auto progress = _playbackProgress->value();
|
||||
const auto width = _playback.icon.width();
|
||||
const auto height = anim::interpolate(
|
||||
st::pipPlaybackWidth,
|
||||
_playback.icon.height(),
|
||||
activeValue(_playback));
|
||||
const auto left = _playback.icon.x();
|
||||
const auto top = _playback.icon.y() + _playback.icon.height() - height;
|
||||
const auto done = int(std::round(width * progress));
|
||||
const auto rect = QRect(
|
||||
_playback.icon.x(),
|
||||
_playback.icon.y() + _playback.icon.height() - height,
|
||||
_playback.icon.width(),
|
||||
height);
|
||||
|
||||
paintProgressBar(p, rect, progress, radius);
|
||||
}
|
||||
|
||||
void Pip::paintProgressBar(
|
||||
QPainter &p,
|
||||
const QRect &rect,
|
||||
float64 progress,
|
||||
int radius) const {
|
||||
const auto done = int(std::round(rect.width() * progress));
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (done > 0) {
|
||||
p.setBrush(st::mediaviewPipPlaybackActive);
|
||||
p.setClipRect(left, top, done, height);
|
||||
p.setClipRect(rect.x(), rect.y(), done, rect.height());
|
||||
p.drawRoundedRect(
|
||||
left,
|
||||
top,
|
||||
std::min(done + radius, width),
|
||||
height,
|
||||
rect.x(),
|
||||
rect.y(),
|
||||
std::min(done + radius, rect.width()),
|
||||
rect.height(),
|
||||
radius,
|
||||
radius);
|
||||
}
|
||||
if (done < width) {
|
||||
const auto from = std::max(left + done - radius, left);
|
||||
if (done < rect.width()) {
|
||||
const auto from = std::max(rect.x() + done - radius, rect.x());
|
||||
p.setBrush(st::mediaviewPipPlaybackInactive);
|
||||
p.setClipRect(left + done, top, width - done, height);
|
||||
p.setClipRect(
|
||||
rect.x() + done,
|
||||
rect.y(),
|
||||
rect.width() - done,
|
||||
rect.height());
|
||||
p.drawRoundedRect(
|
||||
from,
|
||||
top,
|
||||
left + width - from,
|
||||
height,
|
||||
rect.y(),
|
||||
rect.x() + rect.width() - from,
|
||||
rect.height(),
|
||||
radius,
|
||||
radius);
|
||||
}
|
||||
@ -1412,6 +1518,25 @@ void Pip::paintPlaybackTexts(QPainter &p) const {
|
||||
p.drawText(right - _timeLeftWidth, top, _timeLeft);
|
||||
}
|
||||
|
||||
void Pip::paintVolumeController(QPainter &p) const {
|
||||
if (!_volumeController.icon.width()) {
|
||||
return;
|
||||
}
|
||||
const auto radius = _volumeController.icon.height() / 2;
|
||||
const auto volume = Core::App().settings().videoVolume();
|
||||
const auto height = anim::interpolate(
|
||||
st::pipPlaybackWidth,
|
||||
_volumeController.icon.height(),
|
||||
activeValue(_volumeController));
|
||||
const auto rect = QRect(
|
||||
_volumeController.icon.x(),
|
||||
_volumeController.icon.y() + radius - height / 2,
|
||||
_volumeController.icon.width(),
|
||||
height);
|
||||
|
||||
paintProgressBar(p, rect, volume, radius);
|
||||
}
|
||||
|
||||
void Pip::handleStreamingUpdate(Streaming::Update &&update) {
|
||||
using namespace Streaming;
|
||||
|
||||
@ -1703,6 +1828,10 @@ Pip::OverState Pip::computeState(QPoint position) const {
|
||||
return OverState::Enlarge;
|
||||
} else if (_playback.area.contains(position)) {
|
||||
return OverState::Playback;
|
||||
} else if (_volumeToggle.area.contains(position)) {
|
||||
return OverState::VolumeToggle;
|
||||
} else if (_volumeController.area.contains(position)) {
|
||||
return OverState::VolumeController;
|
||||
} else {
|
||||
return OverState::Other;
|
||||
}
|
||||
|
@ -144,6 +144,8 @@ private:
|
||||
Close,
|
||||
Enlarge,
|
||||
Playback,
|
||||
VolumeToggle,
|
||||
VolumeController,
|
||||
Other,
|
||||
};
|
||||
enum class ThumbState {
|
||||
@ -166,6 +168,9 @@ private:
|
||||
void setupStreaming();
|
||||
void paint(QPainter &p, FrameRequest request, bool opengl);
|
||||
void playbackPauseResume();
|
||||
void volumeChanged(float64 volume);
|
||||
void volumeToggled();
|
||||
void volumeControllerUpdate(QPoint position);
|
||||
void waitingAnimationCallback();
|
||||
void handleStreamingUpdate(Streaming::Update &&update);
|
||||
void handleStreamingError(Streaming::Error &&error);
|
||||
@ -198,7 +203,13 @@ private:
|
||||
void paintFade(QPainter &p) const;
|
||||
void paintButtons(QPainter &p) const;
|
||||
void paintPlayback(QPainter &p) const;
|
||||
void paintProgressBar(
|
||||
QPainter &p,
|
||||
const QRect &rect,
|
||||
float64 progress,
|
||||
int radius) const;
|
||||
void paintPlaybackTexts(QPainter &p) const;
|
||||
void paintVolumeController(QPainter &p) const;
|
||||
void paintRadialLoading(QPainter &p) const;
|
||||
void paintRadialLoadingContent(QPainter &p, const QRect &inner) const;
|
||||
[[nodiscard]] QRect countRadialRect() const;
|
||||
@ -222,6 +233,7 @@ private:
|
||||
QString _timeAlready, _timeLeft;
|
||||
int _timeLeftWidth = 0;
|
||||
int _rotation = 0;
|
||||
float64 _lastPositiveVolume = 1.;
|
||||
crl::time _seekPositionMs = -1;
|
||||
crl::time _lastDurationMs = 0;
|
||||
OverState _over = OverState::None;
|
||||
@ -231,6 +243,8 @@ private:
|
||||
Button _enlarge;
|
||||
Button _playback;
|
||||
Button _play;
|
||||
Button _volumeToggle;
|
||||
Button _volumeController;
|
||||
Ui::Animations::Simple _controlsShown;
|
||||
Ui::RoundRect _roundRect;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user