mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Support repeat all in the audio player.
This commit is contained in:
parent
68378cf8e5
commit
ecb4d1d9ba
3 changed files with 124 additions and 19 deletions
|
@ -104,6 +104,10 @@ Instance::Streamed::Streamed(
|
|||
Instance::Data::Data(AudioMsgId::Type type, SharedMediaType overview)
|
||||
: type(type)
|
||||
, overview(overview) {
|
||||
if (type == AudioMsgId::Type::Song) {
|
||||
repeat = Core::App().settings().playerRepeatModeValue();
|
||||
order = Core::App().settings().playerOrderModeValue();
|
||||
}
|
||||
}
|
||||
|
||||
Instance::Data::Data(Data &&other) = default;
|
||||
|
@ -203,6 +207,7 @@ void Instance::setSession(not_null<Data*> data, Main::Session *session) {
|
|||
return;
|
||||
}
|
||||
data->playlistLifetime.destroy();
|
||||
data->playlistOtherLifetime.destroy();
|
||||
data->sessionLifetime.destroy();
|
||||
data->session = session;
|
||||
if (session) {
|
||||
|
@ -249,6 +254,8 @@ void Instance::clearStreamed(not_null<Data*> data, bool savePosition) {
|
|||
void Instance::refreshPlaylist(not_null<Data*> data) {
|
||||
if (!validPlaylist(data)) {
|
||||
validatePlaylist(data);
|
||||
} else if (!validOtherPlaylist(data)) {
|
||||
validateOtherPlaylist(data);
|
||||
}
|
||||
playlistUpdated(data);
|
||||
}
|
||||
|
@ -263,7 +270,7 @@ void Instance::playlistUpdated(not_null<Data*> data) {
|
|||
data->playlistChanges.fire({});
|
||||
}
|
||||
|
||||
bool Instance::validPlaylist(not_null<Data*> data) {
|
||||
bool Instance::validPlaylist(not_null<const Data*> data) const {
|
||||
if (const auto key = playlistKey(data)) {
|
||||
if (!data->playlistSlice) {
|
||||
return false;
|
||||
|
@ -324,7 +331,7 @@ void Instance::validatePlaylist(not_null<Data*> data) {
|
|||
}
|
||||
}
|
||||
|
||||
auto Instance::playlistKey(not_null<Data*> data) const
|
||||
auto Instance::playlistKey(not_null<const Data*> data) const
|
||||
-> std::optional<SliceKey> {
|
||||
const auto contextId = data->current.contextId();
|
||||
const auto history = data->history;
|
||||
|
@ -346,6 +353,67 @@ auto Instance::playlistKey(not_null<Data*> data) const
|
|||
item->isScheduled());
|
||||
}
|
||||
|
||||
bool Instance::validOtherPlaylist(not_null<const Data*> data) const {
|
||||
if (const auto key = playlistOtherKey(data)) {
|
||||
return data->playlistOtherSlice
|
||||
&& (key == data->playlistOtherRequestedKey);
|
||||
}
|
||||
return !data->playlistOtherSlice;
|
||||
}
|
||||
|
||||
void Instance::validateOtherPlaylist(not_null<Data*> data) {
|
||||
data->playlistOtherLifetime.destroy();
|
||||
if (const auto key = playlistOtherKey(data)) {
|
||||
data->playlistOtherRequestedKey = key;
|
||||
|
||||
SharedMediaMergedViewer(
|
||||
&data->history->session(),
|
||||
SharedMediaMergedKey(*key, data->overview),
|
||||
kIdsLimit,
|
||||
kIdsLimit
|
||||
) | rpl::start_with_next([=](SparseIdsMergedSlice &&update) {
|
||||
data->playlistOtherSlice = std::move(update);
|
||||
playlistUpdated(data);
|
||||
}, data->playlistOtherLifetime);
|
||||
} else {
|
||||
data->playlistOtherSlice = std::nullopt;
|
||||
data->playlistOtherRequestedKey = std::nullopt;
|
||||
playlistUpdated(data);
|
||||
}
|
||||
}
|
||||
|
||||
auto Instance::playlistOtherKey(not_null<const Data*> data) const
|
||||
-> std::optional<SliceKey> {
|
||||
if (data->repeat.current() != RepeatMode::All
|
||||
|| data->order.current() == OrderMode::Shuffle
|
||||
|| !data->playlistSlice
|
||||
|| (data->playlistSlice->skippedBefore() != 0
|
||||
&& data->playlistSlice->skippedAfter() != 0)
|
||||
|| (data->playlistSlice->skippedBefore() == 0
|
||||
&& data->playlistSlice->skippedAfter() == 0)) {
|
||||
return {};
|
||||
}
|
||||
const auto contextId = data->current.contextId();
|
||||
const auto history = data->history;
|
||||
if (!contextId || !history) {
|
||||
return {};
|
||||
}
|
||||
const auto item = data->history->owner().message(contextId);
|
||||
if (!item || !item->isRegular()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return SliceKey(
|
||||
data->history->peer->id,
|
||||
data->migrated ? data->migrated->peer->id : 0,
|
||||
(data->playlistSlice->skippedBefore() == 0
|
||||
? ServerMaxMsgId - 1
|
||||
: data->migrated
|
||||
? (1 - ServerMaxMsgId)
|
||||
: 1),
|
||||
false);
|
||||
}
|
||||
|
||||
HistoryItem *Instance::itemByIndex(not_null<Data*> data, int index) {
|
||||
if (!data->playlistSlice
|
||||
|| index < 0
|
||||
|
@ -364,9 +432,7 @@ bool Instance::moveInPlaylist(
|
|||
if (!data->playlistIndex) {
|
||||
return false;
|
||||
}
|
||||
const auto newIndex = *data->playlistIndex
|
||||
+ (data->order.current() == OrderMode::Reverse ? -delta : delta);
|
||||
if (const auto item = itemByIndex(data, newIndex)) {
|
||||
const auto jumpByItem = [&](not_null<HistoryItem*> item) {
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto document = media->document()) {
|
||||
if (autonext) {
|
||||
|
@ -383,6 +449,24 @@ bool Instance::moveInPlaylist(
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const auto jumpById = [&](FullMsgId id) {
|
||||
return jumpByItem(data->history->owner().message(id));
|
||||
};
|
||||
const auto newIndex = *data->playlistIndex
|
||||
+ (data->order.current() == OrderMode::Reverse ? -delta : delta);
|
||||
if (const auto item = itemByIndex(data, newIndex)) {
|
||||
return jumpByItem(item);
|
||||
} else if (data->repeat.current() == RepeatMode::All
|
||||
&& data->playlistOtherSlice
|
||||
&& data->playlistOtherSlice->size() > 0) {
|
||||
const auto &other = *data->playlistOtherSlice;
|
||||
if (newIndex < 0 && other.skippedAfter() == 0) {
|
||||
return jumpById(other[other.size() - 1]);
|
||||
} else if (newIndex > 0 && other.skippedBefore() == 0) {
|
||||
return jumpById(other[0]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -393,6 +477,8 @@ bool Instance::previousAvailable(AudioMsgId::Type type) const {
|
|||
|
||||
if (!data->playlistIndex || !data->playlistSlice) {
|
||||
return false;
|
||||
} else if (data->repeat.current() == RepeatMode::All) {
|
||||
return true;
|
||||
}
|
||||
return (data->order.current() == OrderMode::Reverse)
|
||||
? (*data->playlistIndex + 1 < data->playlistSlice->size())
|
||||
|
@ -405,6 +491,8 @@ bool Instance::nextAvailable(AudioMsgId::Type type) const {
|
|||
|
||||
if (!data->playlistIndex || !data->playlistSlice) {
|
||||
return false;
|
||||
} else if (data->repeat.current() == RepeatMode::All) {
|
||||
return true;
|
||||
}
|
||||
return (data->order.current() == OrderMode::Reverse)
|
||||
? (*data->playlistIndex > 0)
|
||||
|
@ -418,7 +506,8 @@ rpl::producer<> Media::Player::Instance::playlistChanges(
|
|||
|
||||
return rpl::merge(
|
||||
data->playlistChanges.events(),
|
||||
data->order.changes() | rpl::to_empty);
|
||||
data->order.changes() | rpl::to_empty,
|
||||
data->repeat.changes() | rpl::to_empty);
|
||||
}
|
||||
|
||||
rpl::producer<> Media::Player::Instance::stops(AudioMsgId::Type type) const {
|
||||
|
@ -651,6 +740,23 @@ 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;
|
||||
|
|
|
@ -136,11 +136,7 @@ public:
|
|||
}
|
||||
return rpl::never<RepeatMode>();
|
||||
}
|
||||
void setRepeatMode(AudioMsgId::Type type, RepeatMode mode) {
|
||||
if (const auto data = getData(type)) {
|
||||
data->repeat = mode;
|
||||
}
|
||||
}
|
||||
void setRepeatMode(AudioMsgId::Type type, RepeatMode mode);
|
||||
|
||||
[[nodiscard]] OrderMode orderMode(AudioMsgId::Type type) const {
|
||||
if (const auto data = getData(type)) {
|
||||
|
@ -162,11 +158,7 @@ public:
|
|||
}
|
||||
return rpl::never<OrderMode>();
|
||||
}
|
||||
void setOrderMode(AudioMsgId::Type type, OrderMode mode) {
|
||||
if (const auto data = getData(type)) {
|
||||
data->order = mode;
|
||||
}
|
||||
}
|
||||
void setOrderMode(AudioMsgId::Type type, OrderMode mode);
|
||||
|
||||
[[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
|
||||
if (const auto data = getData(type)) {
|
||||
|
@ -232,8 +224,11 @@ private:
|
|||
std::optional<SparseIdsMergedSlice> playlistSlice;
|
||||
std::optional<SliceKey> playlistSliceKey;
|
||||
std::optional<SliceKey> playlistRequestedKey;
|
||||
std::optional<SparseIdsMergedSlice> playlistOtherSlice;
|
||||
std::optional<SliceKey> playlistOtherRequestedKey;
|
||||
std::optional<int> playlistIndex;
|
||||
rpl::lifetime playlistLifetime;
|
||||
rpl::lifetime playlistOtherLifetime;
|
||||
rpl::lifetime sessionLifetime;
|
||||
rpl::event_stream<> playlistChanges;
|
||||
History *history = nullptr;
|
||||
|
@ -273,9 +268,13 @@ private:
|
|||
|
||||
void setCurrent(const AudioMsgId &audioId);
|
||||
void refreshPlaylist(not_null<Data*> data);
|
||||
std::optional<SliceKey> playlistKey(not_null<Data*> data) const;
|
||||
bool validPlaylist(not_null<Data*> data);
|
||||
std::optional<SliceKey> playlistKey(not_null<const Data*> data) const;
|
||||
bool validPlaylist(not_null<const Data*> data) const;
|
||||
void validatePlaylist(not_null<Data*> data);
|
||||
std::optional<SliceKey> playlistOtherKey(
|
||||
not_null<const Data*> data) const;
|
||||
bool validOtherPlaylist(not_null<const Data*> data) const;
|
||||
void validateOtherPlaylist(not_null<Data*> data);
|
||||
void playlistUpdated(not_null<Data*> data);
|
||||
bool moveInPlaylist(not_null<Data*> data, int delta, bool autonext);
|
||||
HistoryItem *itemByIndex(not_null<Data*> data, int index);
|
||||
|
|
|
@ -593,7 +593,7 @@ void Widget::updateRepeatToggleIcon() {
|
|||
(active
|
||||
? &st::mediaPlayerReverseIcon
|
||||
: &st::mediaPlayerReverseDisabledIcon),
|
||||
active ? nullptr : &st::mediaPlayerRepeatDisabledIconOver);
|
||||
active ? nullptr : &st::mediaPlayerReverseDisabledIconOver);
|
||||
break;
|
||||
case OrderMode::Shuffle:
|
||||
_repeatToggle->setIconOverride(
|
||||
|
|
Loading…
Add table
Reference in a new issue