mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add repeat / order controls to the audio player.
This commit is contained in:
parent
395100584f
commit
92e2b91f81
10 changed files with 294 additions and 44 deletions
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/section_widget.h"
|
#include "window/section_widget.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "webrtc/webrtc_create_adm.h"
|
#include "webrtc/webrtc_create_adm.h"
|
||||||
|
#include "media/player/media_player_instance.h"
|
||||||
#include "ui/gl/gl_detection.h"
|
#include "ui/gl/gl_detection.h"
|
||||||
#include "calls/group/calls_group_common.h"
|
#include "calls/group/calls_group_common.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
|
@ -125,7 +126,8 @@ QByteArray Settings::serialize() const {
|
||||||
+ sizeof(qint32) * 2
|
+ sizeof(qint32) * 2
|
||||||
+ Serialize::bytearraySize(_photoEditorBrush)
|
+ Serialize::bytearraySize(_photoEditorBrush)
|
||||||
+ sizeof(qint32) * 3
|
+ sizeof(qint32) * 3
|
||||||
+ Serialize::stringSize(_customDeviceModel.current());
|
+ Serialize::stringSize(_customDeviceModel.current())
|
||||||
|
+ sizeof(qint32) * 2;
|
||||||
|
|
||||||
auto result = QByteArray();
|
auto result = QByteArray();
|
||||||
result.reserve(size);
|
result.reserve(size);
|
||||||
|
@ -223,7 +225,9 @@ QByteArray Settings::serialize() const {
|
||||||
<< qint32(_groupCallNoiseSuppression ? 1 : 0)
|
<< qint32(_groupCallNoiseSuppression ? 1 : 0)
|
||||||
<< qint32(_voicePlaybackSpeed * 100)
|
<< qint32(_voicePlaybackSpeed * 100)
|
||||||
<< qint32(_closeToTaskbar.current() ? 1 : 0)
|
<< qint32(_closeToTaskbar.current() ? 1 : 0)
|
||||||
<< _customDeviceModel.current();
|
<< _customDeviceModel.current()
|
||||||
|
<< qint32(_playerRepeatMode.current())
|
||||||
|
<< qint32(_playerOrderMode.current());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -308,6 +312,8 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
QByteArray photoEditorBrush = _photoEditorBrush;
|
QByteArray photoEditorBrush = _photoEditorBrush;
|
||||||
qint32 closeToTaskbar = _closeToTaskbar.current() ? 1 : 0;
|
qint32 closeToTaskbar = _closeToTaskbar.current() ? 1 : 0;
|
||||||
QString customDeviceModel = _customDeviceModel.current();
|
QString customDeviceModel = _customDeviceModel.current();
|
||||||
|
qint32 playerRepeatMode = static_cast<qint32>(_playerRepeatMode.current());
|
||||||
|
qint32 playerOrderMode = static_cast<qint32>(_playerOrderMode.current());
|
||||||
|
|
||||||
stream >> themesAccentColors;
|
stream >> themesAccentColors;
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
|
@ -471,6 +477,11 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
stream >> customDeviceModel;
|
stream >> customDeviceModel;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream
|
||||||
|
>> playerRepeatMode
|
||||||
|
>> playerOrderMode;
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||||
|
@ -613,6 +624,18 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||||
_photoEditorBrush = photoEditorBrush;
|
_photoEditorBrush = photoEditorBrush;
|
||||||
_closeToTaskbar = (closeToTaskbar == 1);
|
_closeToTaskbar = (closeToTaskbar == 1);
|
||||||
_customDeviceModel = customDeviceModel;
|
_customDeviceModel = customDeviceModel;
|
||||||
|
const auto uncheckedPlayerRepeatMode = static_cast<Media::Player::RepeatMode>(playerRepeatMode);
|
||||||
|
switch (uncheckedPlayerRepeatMode) {
|
||||||
|
case Media::Player::RepeatMode::None:
|
||||||
|
case Media::Player::RepeatMode::One:
|
||||||
|
case Media::Player::RepeatMode::All: _playerRepeatMode = uncheckedPlayerRepeatMode; break;
|
||||||
|
}
|
||||||
|
const auto uncheckedPlayerOrderMode = static_cast<Media::Player::OrderMode>(playerOrderMode);
|
||||||
|
switch (uncheckedPlayerOrderMode) {
|
||||||
|
case Media::Player::OrderMode::Default:
|
||||||
|
case Media::Player::OrderMode::Reverse:
|
||||||
|
case Media::Player::OrderMode::Shuffle: _playerOrderMode = uncheckedPlayerOrderMode; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::getSoundPath(const QString &key) const {
|
QString Settings::getSoundPath(const QString &key) const {
|
||||||
|
|
|
@ -32,6 +32,11 @@ namespace Calls::Group {
|
||||||
enum class StickedTooltip;
|
enum class StickedTooltip;
|
||||||
} // namespace Calls::Group
|
} // namespace Calls::Group
|
||||||
|
|
||||||
|
namespace Media::Player {
|
||||||
|
enum class RepeatMode;
|
||||||
|
enum class OrderMode;
|
||||||
|
} // namespace Media::Player
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
struct WindowPosition {
|
struct WindowPosition {
|
||||||
|
@ -630,6 +635,31 @@ public:
|
||||||
[[nodiscard]] rpl::producer<QString> deviceModelChanges() const;
|
[[nodiscard]] rpl::producer<QString> deviceModelChanges() const;
|
||||||
[[nodiscard]] rpl::producer<QString> deviceModelValue() const;
|
[[nodiscard]] rpl::producer<QString> deviceModelValue() const;
|
||||||
|
|
||||||
|
void setPlayerRepeatMode(Media::Player::RepeatMode mode) {
|
||||||
|
_playerRepeatMode = mode;
|
||||||
|
}
|
||||||
|
[[nodiscard]] Media::Player::RepeatMode playerRepeatMode() const {
|
||||||
|
return _playerRepeatMode.current();
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<Media::Player::RepeatMode> playerRepeatModeValue() const {
|
||||||
|
return _playerRepeatMode.value();
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<Media::Player::RepeatMode> playerRepeatModeChanges() const {
|
||||||
|
return _playerRepeatMode.changes();
|
||||||
|
}
|
||||||
|
void setPlayerOrderMode(Media::Player::OrderMode mode) {
|
||||||
|
_playerOrderMode = mode;
|
||||||
|
}
|
||||||
|
[[nodiscard]] Media::Player::OrderMode playerOrderMode() const {
|
||||||
|
return _playerOrderMode.current();
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<Media::Player::OrderMode> playerOrderModeValue() const {
|
||||||
|
return _playerOrderMode.value();
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<Media::Player::OrderMode> playerOrderModeChanges() const {
|
||||||
|
return _playerOrderMode.changes();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] static bool ThirdColumnByDefault();
|
[[nodiscard]] static bool ThirdColumnByDefault();
|
||||||
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
||||||
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
|
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
|
||||||
|
@ -731,6 +761,8 @@ private:
|
||||||
base::flags<Calls::Group::StickedTooltip> _hiddenGroupCallTooltips;
|
base::flags<Calls::Group::StickedTooltip> _hiddenGroupCallTooltips;
|
||||||
rpl::variable<bool> _closeToTaskbar = false;
|
rpl::variable<bool> _closeToTaskbar = false;
|
||||||
rpl::variable<QString> _customDeviceModel;
|
rpl::variable<QString> _customDeviceModel;
|
||||||
|
rpl::variable<Media::Player::RepeatMode> _playerRepeatMode;
|
||||||
|
rpl::variable<Media::Player::OrderMode> _playerOrderMode;
|
||||||
|
|
||||||
bool _tabbedReplacedWithInfo = false; // per-window
|
bool _tabbedReplacedWithInfo = false; // per-window
|
||||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||||
|
|
|
@ -852,9 +852,7 @@ void MainWidget::createPlayer() {
|
||||||
_controller);
|
_controller);
|
||||||
_player->entity()->volumeWidgetCreated(_playerVolume);
|
_player->entity()->volumeWidgetCreated(_playerVolume);
|
||||||
_playerRepeat.create(this);
|
_playerRepeat.create(this);
|
||||||
Media::Player::PrepareRepeatDropdown(
|
Media::Player::PrepareRepeatDropdown(_playerRepeat.data());
|
||||||
_playerRepeat.data(),
|
|
||||||
_controller);
|
|
||||||
_player->entity()->repeatWidgetCreated(_playerRepeat);
|
_player->entity()->repeatWidgetCreated(_playerRepeat);
|
||||||
orderWidgets();
|
orderWidgets();
|
||||||
if (_a_show.animating()) {
|
if (_a_show.animating()) {
|
||||||
|
|
|
@ -97,9 +97,21 @@ mediaPlayerShuffleDisabledIconOver: icon {
|
||||||
mediaPlayerRepeatReverseIcon: icon {
|
mediaPlayerRepeatReverseIcon: icon {
|
||||||
{ "player/player_repeat_reverse", mediaPlayerActiveFg, point(9px, 11px)}
|
{ "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 {
|
mediaPlayerRepeatShuffleIcon: icon {
|
||||||
{ "player/player_repeat_shuffle", mediaPlayerActiveFg, point(9px, 11px)}
|
{ "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;
|
mediaPlayerRepeatDisabledRippleBg: windowBgOver;
|
||||||
|
|
||||||
mediaPlayerSpeedButton: IconButton {
|
mediaPlayerSpeedButton: IconButton {
|
||||||
|
|
|
@ -746,7 +746,7 @@ void Instance::emitUpdate(AudioMsgId::Type type, CheckCallback check) {
|
||||||
}
|
}
|
||||||
_updatedNotifier.fire_copy({state});
|
_updatedNotifier.fire_copy({state});
|
||||||
if (data->isPlaying && state.state == State::StoppedAtEnd) {
|
if (data->isPlaying && state.state == State::StoppedAtEnd) {
|
||||||
if (data->repeatEnabled) {
|
if (data->repeat.current() == RepeatMode::One) {
|
||||||
play(data->current);
|
play(data->current);
|
||||||
} else if (!moveInPlaylist(data, 1, true)) {
|
} else if (!moveInPlaylist(data, 1, true)) {
|
||||||
_tracksFinishedNotifier.notify(type);
|
_tracksFinishedNotifier.notify(type);
|
||||||
|
|
|
@ -38,6 +38,18 @@ enum class Error;
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
|
||||||
|
enum class RepeatMode {
|
||||||
|
None,
|
||||||
|
One,
|
||||||
|
All,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class OrderMode {
|
||||||
|
Default,
|
||||||
|
Reverse,
|
||||||
|
Shuffle,
|
||||||
|
};
|
||||||
|
|
||||||
class Instance;
|
class Instance;
|
||||||
struct TrackState;
|
struct TrackState;
|
||||||
|
|
||||||
|
@ -104,16 +116,55 @@ public:
|
||||||
return AudioMsgId();
|
return AudioMsgId();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool repeatEnabled(AudioMsgId::Type type) const {
|
[[nodiscard]] RepeatMode repeatMode(AudioMsgId::Type type) const {
|
||||||
if (const auto data = getData(type)) {
|
if (const auto data = getData(type)) {
|
||||||
return data->repeatEnabled;
|
return data->repeat.current();
|
||||||
}
|
}
|
||||||
return false;
|
return RepeatMode::None;
|
||||||
}
|
}
|
||||||
void toggleRepeat(AudioMsgId::Type type) {
|
[[nodiscard]] rpl::producer<RepeatMode> repeatModeValue(
|
||||||
|
AudioMsgId::Type type) const {
|
||||||
if (const auto data = getData(type)) {
|
if (const auto data = getData(type)) {
|
||||||
data->repeatEnabled = !data->repeatEnabled;
|
return data->repeat.value();
|
||||||
_repeatChangedNotifier.notify(type);
|
}
|
||||||
|
return rpl::single(RepeatMode::None);
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<RepeatMode> repeatModeChanges(
|
||||||
|
AudioMsgId::Type type) const {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
return data->repeat.changes();
|
||||||
|
}
|
||||||
|
return rpl::never<RepeatMode>();
|
||||||
|
}
|
||||||
|
void setRepeatMode(AudioMsgId::Type type, RepeatMode mode) {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
data->repeat = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] OrderMode orderMode(AudioMsgId::Type type) const {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
return data->order.current();
|
||||||
|
}
|
||||||
|
return OrderMode::Default;
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<OrderMode> orderModeValue(
|
||||||
|
AudioMsgId::Type type) const {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
return data->order.value();
|
||||||
|
}
|
||||||
|
return rpl::single(OrderMode::Default);
|
||||||
|
}
|
||||||
|
[[nodiscard]] rpl::producer<OrderMode> orderModeChanges(
|
||||||
|
AudioMsgId::Type type) const {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
return data->order.changes();
|
||||||
|
}
|
||||||
|
return rpl::never<OrderMode>();
|
||||||
|
}
|
||||||
|
void setOrderMode(AudioMsgId::Type type, OrderMode mode) {
|
||||||
|
if (const auto data = getData(type)) {
|
||||||
|
data->order = mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,9 +200,6 @@ public:
|
||||||
base::Observable<AudioMsgId::Type> &trackChangedNotifier() {
|
base::Observable<AudioMsgId::Type> &trackChangedNotifier() {
|
||||||
return _trackChangedNotifier;
|
return _trackChangedNotifier;
|
||||||
}
|
}
|
||||||
base::Observable<AudioMsgId::Type> &repeatChangedNotifier() {
|
|
||||||
return _repeatChangedNotifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<> playlistChanges(AudioMsgId::Type type) const;
|
rpl::producer<> playlistChanges(AudioMsgId::Type type) const;
|
||||||
|
|
||||||
|
@ -192,7 +240,8 @@ private:
|
||||||
History *history = nullptr;
|
History *history = nullptr;
|
||||||
History *migrated = nullptr;
|
History *migrated = nullptr;
|
||||||
Main::Session *session = nullptr;
|
Main::Session *session = nullptr;
|
||||||
bool repeatEnabled = false;
|
rpl::variable<RepeatMode> repeat = RepeatMode::None;
|
||||||
|
rpl::variable<OrderMode> order = OrderMode::Default;
|
||||||
bool isPlaying = false;
|
bool isPlaying = false;
|
||||||
bool resumeOnCallEnd = false;
|
bool resumeOnCallEnd = false;
|
||||||
std::unique_ptr<Streamed> streamed;
|
std::unique_ptr<Streamed> streamed;
|
||||||
|
@ -278,7 +327,6 @@ private:
|
||||||
base::Observable<bool> _playerWidgetOver;
|
base::Observable<bool> _playerWidgetOver;
|
||||||
base::Observable<AudioMsgId::Type> _tracksFinishedNotifier;
|
base::Observable<AudioMsgId::Type> _tracksFinishedNotifier;
|
||||||
base::Observable<AudioMsgId::Type> _trackChangedNotifier;
|
base::Observable<AudioMsgId::Type> _trackChangedNotifier;
|
||||||
base::Observable<AudioMsgId::Type> _repeatChangedNotifier;
|
|
||||||
|
|
||||||
rpl::event_stream<AudioMsgId::Type> _playerStopped;
|
rpl::event_stream<AudioMsgId::Type> _playerStopped;
|
||||||
rpl::event_stream<AudioMsgId::Type> _playerStartedPlay;
|
rpl::event_stream<AudioMsgId::Type> _playerStartedPlay;
|
||||||
|
|
|
@ -8,14 +8,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "media/player/media_player_repeat_controls.h"
|
#include "media/player/media_player_repeat_controls.h"
|
||||||
|
|
||||||
#include "media/player/media_player_dropdown.h"
|
#include "media/player/media_player_dropdown.h"
|
||||||
|
#include "media/player/media_player_instance.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "core/core_settings.h"
|
||||||
|
#include "core/application.h"
|
||||||
#include "styles/style_media_player.h"
|
#include "styles/style_media_player.h"
|
||||||
|
|
||||||
namespace Media::Player {
|
namespace Media::Player {
|
||||||
|
|
||||||
void PrepareRepeatDropdown(
|
void PrepareRepeatDropdown(not_null<Dropdown*> dropdown) {
|
||||||
not_null<Dropdown*> dropdown,
|
|
||||||
not_null<Window::SessionController*> controller) {
|
|
||||||
const auto makeButton = [&] {
|
const auto makeButton = [&] {
|
||||||
const auto result = Ui::CreateChild<Ui::IconButton>(
|
const auto result = Ui::CreateChild<Ui::IconButton>(
|
||||||
dropdown.get(),
|
dropdown.get(),
|
||||||
|
@ -25,13 +26,72 @@ void PrepareRepeatDropdown(
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto repeatOne = makeButton();
|
const auto repeatOne = makeButton();
|
||||||
const auto repeat = makeButton();
|
const auto repeatAll = makeButton();
|
||||||
const auto shuffle = makeButton();
|
const auto shuffle = makeButton();
|
||||||
const auto reverse = makeButton();
|
const auto reverse = makeButton();
|
||||||
|
|
||||||
repeatOne->setIconOverride(&st::mediaPlayerRepeatOneIcon);
|
Core::App().settings().playerRepeatModeValue(
|
||||||
shuffle->setIconOverride(&st::mediaPlayerShuffleIcon);
|
) | rpl::start_with_next([=](RepeatMode mode) {
|
||||||
reverse->setIconOverride(&st::mediaPlayerReverseIcon);
|
const auto one = (mode == RepeatMode::One);
|
||||||
|
repeatOne->setIconOverride(one
|
||||||
|
? &st::mediaPlayerRepeatOneIcon
|
||||||
|
: &st::mediaPlayerRepeatOneDisabledIcon,
|
||||||
|
one ? nullptr : &st::mediaPlayerRepeatOneDisabledIconOver);
|
||||||
|
repeatOne->setRippleColorOverride(
|
||||||
|
one ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
|
const auto all = (mode == RepeatMode::All);
|
||||||
|
repeatAll->setIconOverride(all
|
||||||
|
? nullptr
|
||||||
|
: &st::mediaPlayerRepeatDisabledIcon,
|
||||||
|
all ? nullptr : &st::mediaPlayerRepeatDisabledIconOver);
|
||||||
|
repeatAll->setRippleColorOverride(
|
||||||
|
all ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
|
}, dropdown->lifetime());
|
||||||
|
|
||||||
|
Core::App().settings().playerOrderModeValue(
|
||||||
|
) | rpl::start_with_next([=](OrderMode mode) {
|
||||||
|
const auto shuffled = (mode == OrderMode::Shuffle);
|
||||||
|
shuffle->setIconOverride(shuffled
|
||||||
|
? &st::mediaPlayerShuffleIcon
|
||||||
|
: &st::mediaPlayerShuffleDisabledIcon,
|
||||||
|
shuffled ? nullptr : &st::mediaPlayerShuffleDisabledIconOver);
|
||||||
|
shuffle->setRippleColorOverride(
|
||||||
|
shuffled ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
|
const auto reversed = (mode == OrderMode::Reverse);
|
||||||
|
reverse->setIconOverride(reversed
|
||||||
|
? &st::mediaPlayerReverseIcon
|
||||||
|
: &st::mediaPlayerReverseDisabledIcon,
|
||||||
|
reversed ? nullptr : &st::mediaPlayerReverseDisabledIconOver);
|
||||||
|
reverse->setRippleColorOverride(
|
||||||
|
reversed ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
|
}, dropdown->lifetime());
|
||||||
|
|
||||||
|
const auto toggleRepeat = [](RepeatMode mode) {
|
||||||
|
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); });
|
||||||
|
repeatAll->setClickedCallback([=] { toggleRepeat(RepeatMode::All); });
|
||||||
|
shuffle->setClickedCallback([=] { toggleOrder(OrderMode::Shuffle); });
|
||||||
|
reverse->setClickedCallback([=] { toggleOrder(OrderMode::Reverse); });
|
||||||
|
|
||||||
dropdown->sizeValue(
|
dropdown->sizeValue(
|
||||||
) | rpl::start_with_next([=](QSize size) {
|
) | rpl::start_with_next([=](QSize size) {
|
||||||
|
@ -44,7 +104,7 @@ void PrepareRepeatDropdown(
|
||||||
top += widget->height() + skip;
|
top += widget->height() + skip;
|
||||||
};
|
};
|
||||||
move(repeatOne);
|
move(repeatOne);
|
||||||
move(repeat);
|
move(repeatAll);
|
||||||
move(shuffle);
|
move(shuffle);
|
||||||
move(reverse);
|
move(reverse);
|
||||||
}, dropdown->lifetime());
|
}, dropdown->lifetime());
|
||||||
|
|
|
@ -7,16 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Window {
|
|
||||||
class SessionController;
|
|
||||||
} // namespace Window
|
|
||||||
|
|
||||||
namespace Media::Player {
|
namespace Media::Player {
|
||||||
|
|
||||||
class Dropdown;
|
class Dropdown;
|
||||||
|
|
||||||
void PrepareRepeatDropdown(
|
void PrepareRepeatDropdown(not_null<Dropdown*> dropdown);
|
||||||
not_null<Dropdown*> dropdown,
|
|
||||||
not_null<Window::SessionController*> controller);
|
|
||||||
|
|
||||||
} // namespace Media::Player
|
} // namespace Media::Player
|
||||||
|
|
|
@ -290,9 +290,33 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
|
||||||
updateVolumeToggleIcon();
|
updateVolumeToggleIcon();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
updateRepeatTrackIcon();
|
rpl::combine(
|
||||||
|
Core::App().settings().playerRepeatModeValue(),
|
||||||
|
Core::App().settings().playerOrderModeValue(),
|
||||||
|
instance()->repeatModeValue(AudioMsgId::Type::Song),
|
||||||
|
instance()->orderModeValue(AudioMsgId::Type::Song)
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
updateRepeatToggleIcon();
|
||||||
|
}, lifetime());
|
||||||
_repeatToggle->setClickedCallback([=] {
|
_repeatToggle->setClickedCallback([=] {
|
||||||
instance()->toggleRepeat(AudioMsgId::Type::Song);
|
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
_playbackSpeed->saved(
|
_playbackSpeed->saved(
|
||||||
|
@ -300,11 +324,6 @@ Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
|
||||||
instance()->updateVoicePlaybackSpeed();
|
instance()->updateVoicePlaybackSpeed();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
subscribe(instance()->repeatChangedNotifier(), [this](AudioMsgId::Type type) {
|
|
||||||
if (type == _type) {
|
|
||||||
updateRepeatTrackIcon();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
subscribe(instance()->trackChangedNotifier(), [this](AudioMsgId::Type type) {
|
subscribe(instance()->trackChangedNotifier(), [this](AudioMsgId::Type type) {
|
||||||
if (type == _type) {
|
if (type == _type) {
|
||||||
handleSongChange();
|
handleSongChange();
|
||||||
|
@ -552,10 +571,74 @@ void Widget::updateLabelsGeometry() {
|
||||||
_timeLabel->moveToRight(right, st::mediaPlayerNameTop - st::mediaPlayerTime.font->ascent);
|
_timeLabel->moveToRight(right, st::mediaPlayerNameTop - st::mediaPlayerTime.font->ascent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::updateRepeatTrackIcon() {
|
void Widget::updateRepeatToggleIcon() {
|
||||||
auto repeating = instance()->repeatEnabled(AudioMsgId::Type::Song);
|
const auto type = AudioMsgId::Type::Song;
|
||||||
_repeatToggle->setIconOverride(repeating ? nullptr : &st::mediaPlayerRepeatDisabledIcon, repeating ? nullptr : &st::mediaPlayerRepeatDisabledIconOver);
|
const auto repeat = Core::App().settings().playerRepeatMode();
|
||||||
_repeatToggle->setRippleColorOverride(repeating ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
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::mediaPlayerRepeatDisabledIconOver);
|
||||||
|
break;
|
||||||
|
case OrderMode::Shuffle:
|
||||||
|
_repeatToggle->setIconOverride(
|
||||||
|
(active
|
||||||
|
? &st::mediaPlayerShuffleIcon
|
||||||
|
: &st::mediaPlayerShuffleDisabledIcon),
|
||||||
|
active ? nullptr : &st::mediaPlayerShuffleDisabledIconOver);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RepeatMode::One:
|
||||||
|
_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));
|
||||||
|
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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_repeatToggle->setRippleColorOverride(
|
||||||
|
active ? nullptr : &st::mediaPlayerRepeatDisabledRippleBg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::checkForTypeChange() {
|
void Widget::checkForTypeChange() {
|
||||||
|
|
|
@ -78,7 +78,7 @@ private:
|
||||||
|
|
||||||
void updatePlayPrevNextPositions();
|
void updatePlayPrevNextPositions();
|
||||||
void updateLabelsGeometry();
|
void updateLabelsGeometry();
|
||||||
void updateRepeatTrackIcon();
|
void updateRepeatToggleIcon();
|
||||||
void updateControlsVisibility();
|
void updateControlsVisibility();
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
void createPrevNextButtons();
|
void createPrevNextButtons();
|
||||||
|
|
Loading…
Add table
Reference in a new issue