Added ability to change playback speed for long audio files.

This commit is contained in:
23rd 2021-08-31 19:11:37 +03:00
parent b635a9d4a5
commit bcbab7ad8e
5 changed files with 45 additions and 14 deletions

View file

@ -9,6 +9,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h" #include "data/data_document.h"
namespace {
constexpr auto kMinLengthForChangeablePlaybackSpeed = 20 * TimeId(60); // 20 minutes.
} // namespace
AudioMsgId::AudioMsgId() { AudioMsgId::AudioMsgId() {
} }
@ -18,7 +24,10 @@ AudioMsgId::AudioMsgId(
uint32 externalPlayId) uint32 externalPlayId)
: _audio(audio) : _audio(audio)
, _contextId(msgId) , _contextId(msgId)
, _externalPlayId(externalPlayId) { , _externalPlayId(externalPlayId)
, _changeablePlaybackSpeed(_audio->isVoiceMessage()
|| _audio->isVideoMessage()
|| (_audio->getDuration() >= kMinLengthForChangeablePlaybackSpeed)) {
setTypeFromAudio(); setTypeFromAudio();
} }
@ -62,6 +71,10 @@ uint32 AudioMsgId::externalPlayId() const {
return _externalPlayId; return _externalPlayId;
} }
bool AudioMsgId::changeablePlaybackSpeed() const {
return _changeablePlaybackSpeed;
}
AudioMsgId::operator bool() const { AudioMsgId::operator bool() const {
return (_audio != nullptr) || (_externalPlayId != 0); return (_audio != nullptr) || (_externalPlayId != 0);
} }

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class DocumentData; class DocumentData;
class AudioMsgId { class AudioMsgId final {
public: public:
enum class Type { enum class Type {
Unknown, Unknown,
@ -31,6 +31,7 @@ public:
[[nodiscard]] DocumentData *audio() const; [[nodiscard]] DocumentData *audio() const;
[[nodiscard]] FullMsgId contextId() const; [[nodiscard]] FullMsgId contextId() const;
[[nodiscard]] uint32 externalPlayId() const; [[nodiscard]] uint32 externalPlayId() const;
[[nodiscard]] bool changeablePlaybackSpeed() const;
[[nodiscard]] explicit operator bool() const; [[nodiscard]] explicit operator bool() const;
bool operator<(const AudioMsgId &other) const; bool operator<(const AudioMsgId &other) const;
@ -44,5 +45,6 @@ private:
Type _type = Type::Unknown; Type _type = Type::Unknown;
FullMsgId _contextId; FullMsgId _contextId;
uint32 _externalPlayId = 0; uint32 _externalPlayId = 0;
bool _changeablePlaybackSpeed = false;
}; };

View file

@ -519,8 +519,7 @@ Streaming::PlaybackOptions Instance::streamingOptions(
result.mode = (document && document->isVideoMessage()) result.mode = (document && document->isVideoMessage())
? Streaming::Mode::Both ? Streaming::Mode::Both
: Streaming::Mode::Audio; : Streaming::Mode::Audio;
result.speed = (document result.speed = audioId.changeablePlaybackSpeed()
&& (document->isVoiceMessage() || document->isVideoMessage()))
? VoicePlaybackSpeed() ? VoicePlaybackSpeed()
: 1.; : 1.;
result.audioId = audioId; result.audioId = audioId;
@ -677,7 +676,10 @@ void Instance::cancelSeeking(AudioMsgId::Type type) {
} }
void Instance::updateVoicePlaybackSpeed() { void Instance::updateVoicePlaybackSpeed() {
if (const auto data = getData(AudioMsgId::Type::Voice)) { if (const auto data = getData(getActiveType())) {
if (!data->current.changeablePlaybackSpeed()) {
return;
}
if (const auto streamed = data->streamed.get()) { if (const auto streamed = data->streamed.get()) {
streamed->instance.setSpeed(VoicePlaybackSpeed()); streamed->instance.setSpeed(VoicePlaybackSpeed());
} }

View file

@ -164,6 +164,8 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
subscribe(instance()->trackChangedNotifier(), [this](AudioMsgId::Type type) { subscribe(instance()->trackChangedNotifier(), [this](AudioMsgId::Type type) {
if (type == _type) { if (type == _type) {
handleSongChange(); handleSongChange();
updateControlsVisibility();
updateLabelsGeometry();
} }
}); });
subscribe(instance()->tracksFinishedNotifier(), [this](AudioMsgId::Type type) { subscribe(instance()->tracksFinishedNotifier(), [this](AudioMsgId::Type type) {
@ -278,6 +280,10 @@ void Widget::handleSeekFinished(float64 progress) {
} }
void Widget::resizeEvent(QResizeEvent *e) { void Widget::resizeEvent(QResizeEvent *e) {
updateControlsGeometry();
}
void Widget::updateControlsGeometry() {
auto right = st::mediaPlayerCloseRight; auto right = st::mediaPlayerCloseRight;
_close->moveToRight(right, st::mediaPlayerPlayTop); right += _close->width(); _close->moveToRight(right, st::mediaPlayerPlayTop); right += _close->width();
if (hasPlaybackSpeedControl()) { if (hasPlaybackSpeedControl()) {
@ -371,7 +377,8 @@ int Widget::getLabelsRight() const {
auto result = st::mediaPlayerCloseRight + _close->width(); auto result = st::mediaPlayerCloseRight + _close->width();
if (_type == AudioMsgId::Type::Song) { if (_type == AudioMsgId::Type::Song) {
result += _repeatTrack->width() + _volumeToggle->width(); result += _repeatTrack->width() + _volumeToggle->width();
} else if (hasPlaybackSpeedControl()) { }
if (hasPlaybackSpeedControl()) {
result += _playbackSpeed->width(); result += _playbackSpeed->width();
} }
result += st::mediaPlayerPadding; result += st::mediaPlayerPadding;
@ -421,21 +428,26 @@ void Widget::checkForTypeChange() {
} }
bool Widget::hasPlaybackSpeedControl() const { bool Widget::hasPlaybackSpeedControl() const {
return (_type == AudioMsgId::Type::Voice) return _lastSongId.changeablePlaybackSpeed()
&& Media::Audio::SupportsSpeedControl(); && Media::Audio::SupportsSpeedControl();
} }
void Widget::updateControlsVisibility() {
_repeatTrack->setVisible(_type == AudioMsgId::Type::Song);
_volumeToggle->setVisible(_type == AudioMsgId::Type::Song);
_playbackSpeed->setVisible(hasPlaybackSpeedControl());
if (!_shadow->isHidden()) {
_playbackSlider->setVisible(_type == AudioMsgId::Type::Song);
}
updateControlsGeometry();
}
void Widget::setType(AudioMsgId::Type type) { void Widget::setType(AudioMsgId::Type type) {
if (_type != type) { if (_type != type) {
_type = type; _type = type;
_repeatTrack->setVisible(_type == AudioMsgId::Type::Song);
_volumeToggle->setVisible(_type == AudioMsgId::Type::Song);
_playbackSpeed->setVisible(hasPlaybackSpeedControl());
if (!_shadow->isHidden()) {
_playbackSlider->setVisible(_type == AudioMsgId::Type::Song);
}
updateLabelsGeometry();
handleSongChange(); handleSongChange();
updateControlsVisibility();
updateLabelsGeometry();
handleSongUpdate(instance()->getState(_type)); handleSongUpdate(instance()->getState(_type));
updateOverLabelsState(_labelsOver); updateOverLabelsState(_labelsOver);
_playlistChangesLifetime = instance()->playlistChanges( _playlistChangesLifetime = instance()->playlistChanges(

View file

@ -75,6 +75,8 @@ private:
void updatePlayPrevNextPositions(); void updatePlayPrevNextPositions();
void updateLabelsGeometry(); void updateLabelsGeometry();
void updateRepeatTrackIcon(); void updateRepeatTrackIcon();
void updateControlsVisibility();
void updateControlsGeometry();
void updatePlaybackSpeedIcon(); void updatePlaybackSpeedIcon();
void createPrevNextButtons(); void createPrevNextButtons();
void destroyPrevNextButtons(); void destroyPrevNextButtons();