| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- /*
- 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/view/media_view_playback_progress.h"
- #include "media/audio/media_audio.h"
- #include "styles/style_media_view.h"
- namespace Media {
- namespace View {
- namespace {
- constexpr auto kPlaybackAnimationDurationMs = crl::time(200);
- } // namespace
- PlaybackProgress::PlaybackProgress()
- : _valueAnimation([=](crl::time now) {
- return valueAnimationCallback(now);
- })
- , _availableTillAnimation([=](crl::time now) {
- return availableTillAnimationCallback(now);
- }) {
- }
- void PlaybackProgress::updateState(
- const Player::TrackState &state,
- float64 loadedTillPercent) {
- _playing = !Player::IsStopped(state.state);
- const auto length = state.length;
- const auto position = Player::IsStoppedAtEnd(state.state)
- ? state.length
- : Player::IsStoppedOrStopping(state.state)
- ? 0
- : state.position;
- const auto receivedTill = (length && state.receivedTill > position)
- ? state.receivedTill
- : -1;
- const auto loadedTill = (loadedTillPercent != 0.)
- ? int64(std::floor(loadedTillPercent * length))
- : -1;
- const auto availableTill = (length && loadedTill > position)
- ? std::max(receivedTill, loadedTill)
- : receivedTill;
- const auto wasInLoadingState = _inLoadingState;
- if (wasInLoadingState) {
- _inLoadingState = false;
- if (_inLoadingStateChanged) {
- _inLoadingStateChanged(false);
- }
- }
- const auto progress = (position > length)
- ? 1.
- : length
- ? std::clamp(float64(position) / length, 0., 1.)
- : 0.;
- const auto availableTillProgress = (availableTill > position)
- ? std::clamp(float64(availableTill) / length, 0., 1.)
- : -1.;
- const auto animatedPosition = position + (state.frequency * kPlaybackAnimationDurationMs / 1000);
- const auto animatedProgress = length ? qMax(float64(animatedPosition) / length, 0.) : 0.;
- if (length != _length || position != _position || wasInLoadingState) {
- const auto animated = length
- && _length
- && (animatedProgress > value())
- && (position > _position)
- && (position < _position + state.frequency);
- if (animated) {
- setValue(animatedProgress, animated);
- } else {
- setValue(progress, animated);
- }
- _position = position;
- _length = length;
- }
- if (availableTill != _availableTill) {
- setAvailableTill(availableTillProgress);
- _availableTill = availableTill;
- }
- }
- void PlaybackProgress::updateLoadingState(float64 progress) {
- if (!_inLoadingState) {
- _inLoadingState = true;
- if (_inLoadingStateChanged) {
- _inLoadingStateChanged(true);
- }
- }
- auto animated = (progress > value());
- setValue(progress, animated);
- }
- float64 PlaybackProgress::value() const {
- return qMin(a_value.current(), 1.);
- }
- void PlaybackProgress::setValue(float64 value, bool animated) {
- if (animated) {
- valueAnimationCallback(crl::now());
- a_value.start(value);
- _valueAnimation.start();
- } else {
- a_value = anim::value(value, value);
- _valueAnimation.stop();
- }
- emitUpdatedValue();
- }
- void PlaybackProgress::setAvailableTill(float64 value) {
- const auto current = a_availableTill.current();
- if (value > current && current > 0.) {
- availableTillAnimationCallback(crl::now());
- a_availableTill.start(value);
- _availableTillAnimation.start();
- } else if (value > a_value.current()) {
- a_availableTill = anim::value(a_value.current(), value);
- _availableTillAnimation.start();
- } else {
- a_availableTill = anim::value(-1., -1.);
- _availableTillAnimation.stop();
- }
- emitUpdatedValue();
- }
- bool PlaybackProgress::valueAnimationCallback(float64 now) {
- const auto time = (now - _valueAnimation.started());
- const auto dt = anim::Disabled()
- ? 1.
- : (time / kPlaybackAnimationDurationMs);
- if (dt >= 1.) {
- a_value.finish();
- } else {
- a_value.update(dt, anim::linear);
- }
- emitUpdatedValue();
- return (dt < 1.);
- }
- bool PlaybackProgress::availableTillAnimationCallback(float64 now) {
- const auto time = now - _availableTillAnimation.started();
- const auto dt = anim::Disabled()
- ? 1.
- : (time / kPlaybackAnimationDurationMs);
- if (dt >= 1.) {
- a_availableTill.finish();
- } else {
- a_availableTill.update(dt, anim::linear);
- }
- emitUpdatedValue();
- return (dt < 1.);
- }
- void PlaybackProgress::emitUpdatedValue() {
- if (_valueChanged) {
- const auto value = a_value.current();
- const auto availableTill = a_availableTill.current();
- _valueChanged(value, std::max(value, availableTill));
- }
- }
- } // namespace View
- } // namespace Media
|