From 0309eb023ecd6aa814c71b14de6d2ec31bb2137a Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 19 Nov 2021 19:27:10 +0400 Subject: [PATCH] Cycle through repeat modes by repeat toggle button. --- .../media/player/media_player.style | 12 -- .../media/player/media_player_instance.cpp | 45 +++---- .../media/player/media_player_instance.h | 45 +------ .../player/media_player_repeat_controls.cpp | 10 -- .../media/player/media_player_widget.cpp | 117 ++++++------------ 5 files changed, 61 insertions(+), 168 deletions(-) diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index 3a3392c55..22a726790 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -97,21 +97,9 @@ mediaPlayerShuffleDisabledIconOver: icon { mediaPlayerRepeatReverseIcon: icon { { "player/player_repeat_reverse", mediaPlayerActiveFg, point(9px, 11px)} }; -mediaPlayerRepeatReverseDisabledIcon: icon { - { "player/player_repeat_reverse", menuIconFg, point(9px, 11px)} -}; -mediaPlayerRepeatReverseDisabledIconOver: icon { - { "player/player_repeat_reverse", menuIconFgOver, point(9px, 11px)} -}; mediaPlayerRepeatShuffleIcon: icon { { "player/player_repeat_shuffle", mediaPlayerActiveFg, point(9px, 11px)} }; -mediaPlayerRepeatShuffleDisabledIcon: icon { - { "player/player_repeat_shuffle", menuIconFg, point(9px, 11px)} -}; -mediaPlayerRepeatShuffleDisabledIconOver: icon { - { "player/player_repeat_shuffle", menuIconFgOver, point(9px, 11px)} -}; mediaPlayerRepeatDisabledRippleBg: windowBgOver; mediaPlayerSpeedButton: IconButton { diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp index f32825002..4fe8f80a9 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.cpp +++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp @@ -121,6 +121,13 @@ Instance::Instance() handleSongUpdate(audioId); }); + _songData.repeat.changes( + ) | rpl::start_with_next([=](RepeatMode mode) { + if (mode == RepeatMode::All) { + refreshPlaylist(&_songData); + } + }, _lifetime); + using namespace rpl::mappers; rpl::combine( Core::App().calls().currentCallValue(), @@ -254,7 +261,13 @@ void Instance::clearStreamed(not_null data, bool savePosition) { void Instance::refreshPlaylist(not_null data) { if (!validPlaylist(data)) { validatePlaylist(data); - } else if (!validOtherPlaylist(data)) { + } else { + refreshOtherPlaylist(data); + } +} + +void Instance::refreshOtherPlaylist(not_null data) { + if (!validOtherPlaylist(data)) { validateOtherPlaylist(data); } playlistUpdated(data); @@ -322,12 +335,12 @@ void Instance::validatePlaylist(not_null data) { ) | rpl::start_with_next([=](SparseIdsMergedSlice &&update) { data->playlistSlice = std::move(update); data->playlistSliceKey = key; - playlistUpdated(data); + refreshOtherPlaylist(data); }, data->playlistLifetime); } else { data->playlistSlice = std::nullopt; data->playlistSliceKey = data->playlistRequestedKey = std::nullopt; - playlistUpdated(data); + refreshOtherPlaylist(data); } } @@ -456,7 +469,14 @@ bool Instance::moveInPlaylist( }; const auto newIndex = *data->playlistIndex + (data->order.current() == OrderMode::Reverse ? -delta : delta); - if (const auto item = itemByIndex(data, newIndex)) { + const auto useIndex = (!data->playlistSlice + || data->playlistSlice->skippedAfter() != 0 + || data->playlistSlice->skippedBefore() != 0 + || !data->playlistSlice->size()) + ? newIndex + : ((newIndex + int(data->playlistSlice->size())) + % int(data->playlistSlice->size())); + if (const auto item = itemByIndex(data, useIndex)) { return jumpByItem(item); } else if (data->repeat.current() == RepeatMode::All && data->playlistOtherSlice @@ -740,23 +760,6 @@ void Instance::playPauseCancelClicked(AudioMsgId::Type type) { } } -void Instance::setRepeatMode(AudioMsgId::Type type, RepeatMode mode) { - if (const auto data = getData(type)) { - const auto otherNeeded = (mode == RepeatMode::All) - && (data->repeat.current() != RepeatMode::All); - data->repeat = mode; - if (otherNeeded) { - refreshPlaylist(data); - } - } -} - -void Instance::setOrderMode(AudioMsgId::Type type, OrderMode mode) { - if (const auto data = getData(type)) { - data->order = mode; - } -} - void Instance::startSeeking(AudioMsgId::Type type) { if (auto data = getData(type)) { data->seeking = data->current; diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h index d5f129bbd..bb39322a6 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.h +++ b/Telegram/SourceFiles/media/player/media_player_instance.h @@ -116,50 +116,6 @@ public: return AudioMsgId(); } - [[nodiscard]] RepeatMode repeatMode(AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->repeat.current(); - } - return RepeatMode::None; - } - [[nodiscard]] rpl::producer repeatModeValue( - AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->repeat.value(); - } - return rpl::single(RepeatMode::None); - } - [[nodiscard]] rpl::producer repeatModeChanges( - AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->repeat.changes(); - } - return rpl::never(); - } - void setRepeatMode(AudioMsgId::Type type, RepeatMode mode); - - [[nodiscard]] OrderMode orderMode(AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->order.current(); - } - return OrderMode::Default; - } - [[nodiscard]] rpl::producer orderModeValue( - AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->order.value(); - } - return rpl::single(OrderMode::Default); - } - [[nodiscard]] rpl::producer orderModeChanges( - AudioMsgId::Type type) const { - if (const auto data = getData(type)) { - return data->order.changes(); - } - return rpl::never(); - } - void setOrderMode(AudioMsgId::Type type, OrderMode mode); - [[nodiscard]] bool isSeeking(AudioMsgId::Type type) const { if (const auto data = getData(type)) { return (data->seeking == data->current); @@ -268,6 +224,7 @@ private: void setCurrent(const AudioMsgId &audioId); void refreshPlaylist(not_null data); + void refreshOtherPlaylist(not_null data); std::optional playlistKey(not_null data) const; bool validPlaylist(not_null data) const; void validatePlaylist(not_null data); diff --git a/Telegram/SourceFiles/media/player/media_player_repeat_controls.cpp b/Telegram/SourceFiles/media/player/media_player_repeat_controls.cpp index 302852dd0..3eb372d8e 100644 --- a/Telegram/SourceFiles/media/player/media_player_repeat_controls.cpp +++ b/Telegram/SourceFiles/media/player/media_player_repeat_controls.cpp @@ -70,22 +70,12 @@ void PrepareRepeatDropdown(not_null dropdown) { auto &settings = Core::App().settings(); const auto active = (settings.playerRepeatMode() == mode); settings.setPlayerRepeatMode(active ? RepeatMode::None : mode); - const auto type = AudioMsgId::Type::Song; - instance()->setRepeatMode(type, settings.playerRepeatMode()); - if (!active) { - instance()->setOrderMode(type, settings.playerOrderMode()); - } Core::App().saveSettingsDelayed(); }; const auto toggleOrder = [](OrderMode mode) { auto &settings = Core::App().settings(); const auto active = (settings.playerOrderMode() == mode); settings.setPlayerOrderMode(active ? OrderMode::Default : mode); - const auto type = AudioMsgId::Type::Song; - instance()->setOrderMode(type, settings.playerOrderMode()); - if (!active) { - instance()->setRepeatMode(type, settings.playerRepeatMode()); - } Core::App().saveSettingsDelayed(); }; repeatOne->setClickedCallback([=] { toggleRepeat(RepeatMode::One); }); diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp index 0b149b973..2d016c0c0 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.cpp +++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp @@ -292,31 +292,22 @@ Widget::Widget(QWidget *parent, not_null session) rpl::combine( Core::App().settings().playerRepeatModeValue(), - Core::App().settings().playerOrderModeValue(), - instance()->repeatModeValue(AudioMsgId::Type::Song), - instance()->orderModeValue(AudioMsgId::Type::Song) + Core::App().settings().playerOrderModeValue() ) | rpl::start_with_next([=] { updateRepeatToggleIcon(); }, lifetime()); + _repeatToggle->setClickedCallback([=] { - const auto type = AudioMsgId::Type::Song; - const auto repeat = Core::App().settings().playerRepeatMode(); - const auto order = Core::App().settings().playerOrderMode(); - const auto mayBeActive = (repeat != RepeatMode::None) - || (order != OrderMode::Default); - const auto active = mayBeActive - && (repeat == instance()->repeatMode(type)) - && (order == instance()->orderMode(type)); - if (!active && !mayBeActive) { - Core::App().settings().setPlayerRepeatMode(RepeatMode::All); - Core::App().saveSettingsDelayed(); - } - instance()->setRepeatMode(type, active - ? RepeatMode::None - : mayBeActive - ? repeat - : RepeatMode::All); - instance()->setOrderMode(type, active ? OrderMode::Default : order); + auto &settings = Core::App().settings(); + settings.setPlayerRepeatMode([&] { + switch (settings.playerRepeatMode()) { + case RepeatMode::None: return RepeatMode::One; + case RepeatMode::One: return RepeatMode::All; + case RepeatMode::All: return RepeatMode::None; + } + Unexpected("Repeat mode in Settings."); + }()); + Core::App().saveSettingsDelayed(); }); _playbackSpeed->saved( @@ -577,70 +568,34 @@ void Widget::updateRepeatToggleIcon() { const auto type = AudioMsgId::Type::Song; const auto repeat = Core::App().settings().playerRepeatMode(); const auto order = Core::App().settings().playerOrderMode(); - const auto active = (repeat == instance()->repeatMode(type)) - && (order == instance()->orderMode(type)) - && (repeat != RepeatMode::None || order != OrderMode::Default); - switch (repeat) { - case RepeatMode::None: - switch (order) { - case OrderMode::Default: - _repeatToggle->setIconOverride( - &st::mediaPlayerRepeatDisabledIcon, - &st::mediaPlayerRepeatDisabledIconOver); - break; - case OrderMode::Reverse: - _repeatToggle->setIconOverride( - (active - ? &st::mediaPlayerReverseIcon - : &st::mediaPlayerReverseDisabledIcon), - active ? nullptr : &st::mediaPlayerReverseDisabledIconOver); - break; - case OrderMode::Shuffle: - _repeatToggle->setIconOverride( - (active - ? &st::mediaPlayerShuffleIcon - : &st::mediaPlayerShuffleDisabledIcon), - active ? nullptr : &st::mediaPlayerShuffleDisabledIconOver); - break; - } - break; - case RepeatMode::One: + if (repeat == RepeatMode::None && order == OrderMode::Default) { _repeatToggle->setIconOverride( - (active - ? &st::mediaPlayerRepeatOneIcon - : &st::mediaPlayerRepeatOneDisabledIcon), - active ? nullptr : &st::mediaPlayerRepeatOneDisabledIconOver); - break; - case RepeatMode::All: - switch (order) { - case OrderMode::Default: - _repeatToggle->setIconOverride( - (active ? nullptr : &st::mediaPlayerRepeatDisabledIcon), - (active ? nullptr : &st::mediaPlayerRepeatDisabledIconOver)); + &st::mediaPlayerRepeatDisabledIcon, + &st::mediaPlayerRepeatDisabledIconOver); + _repeatToggle->setRippleColorOverride( + &st::mediaPlayerRepeatDisabledRippleBg); + return; + } + const auto &icon = [&]() -> const style::icon& { + switch (repeat) { + case RepeatMode::None: + switch (order) { + case OrderMode::Reverse: return st::mediaPlayerReverseIcon; + case OrderMode::Shuffle: return st::mediaPlayerShuffleIcon; + } break; - case OrderMode::Reverse: - _repeatToggle->setIconOverride( - (active - ? &st::mediaPlayerRepeatReverseIcon - : &st::mediaPlayerRepeatReverseDisabledIcon), - (active - ? nullptr - : &st::mediaPlayerRepeatReverseDisabledIconOver)); - break; - case OrderMode::Shuffle: - _repeatToggle->setIconOverride( - (active - ? &st::mediaPlayerRepeatShuffleIcon - : &st::mediaPlayerRepeatShuffleDisabledIcon), - (active - ? nullptr - : &st::mediaPlayerRepeatShuffleDisabledIconOver)); + case RepeatMode::One: return st::mediaPlayerRepeatOneIcon; + case RepeatMode::All: + switch (order) { + case OrderMode::Default: return st::mediaPlayerRepeatButton.icon; + case OrderMode::Reverse: return st::mediaPlayerRepeatReverseIcon; + case OrderMode::Shuffle: return st::mediaPlayerRepeatShuffleIcon; + } break; } - break; - } - _repeatToggle->setRippleColorOverride( - active ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg); + Unexpected("Repeat / order values in Settings."); + }(); + _repeatToggle->setIconOverride(&icon); } void Widget::checkForTypeChange() {