| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- 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
- */
- #pragma once
- #include "data/data_audio_msg_id.h"
- #include "data/data_shared_media.h"
- class AudioMsgId;
- class DocumentData;
- class History;
- namespace Media {
- enum class RepeatMode;
- enum class OrderMode;
- } // namespace Media
- namespace Media {
- namespace Audio {
- class Instance;
- } // namespace Audio
- } // namespace Media
- namespace Media {
- namespace View {
- class PlaybackProgress;
- } // namespace View
- } // namespace Media
- namespace Media {
- namespace Streaming {
- class Document;
- class Instance;
- struct PlaybackOptions;
- struct Update;
- enum class Error;
- } // namespace Streaming
- } // namespace Media
- namespace base {
- class PowerSaveBlocker;
- } // namespace base
- namespace Media {
- namespace Player {
- extern const char kOptionDisableAutoplayNext[];
- class Instance;
- struct TrackState;
- void start(not_null<Audio::Instance*> instance);
- void finish(not_null<Audio::Instance*> instance);
- void SaveLastPlaybackPosition(
- not_null<DocumentData*> document,
- const TrackState &state);
- not_null<Instance*> instance();
- class Instance final {
- public:
- enum class Seeking {
- Start,
- Finish,
- Cancel,
- };
- void play(AudioMsgId::Type type);
- void pause(AudioMsgId::Type type);
- void stop(AudioMsgId::Type type, bool asFinished = false);
- void playPause(AudioMsgId::Type type);
- bool next(AudioMsgId::Type type);
- bool previous(AudioMsgId::Type type);
- AudioMsgId::Type getActiveType() const;
- void play() {
- play(getActiveType());
- }
- void pause() {
- pause(getActiveType());
- }
- void stop() {
- stop(getActiveType());
- }
- void playPause() {
- playPause(getActiveType());
- }
- bool next() {
- return next(getActiveType());
- }
- bool previous() {
- return previous(getActiveType());
- }
- void playPauseCancelClicked(AudioMsgId::Type type);
- void play(const AudioMsgId &audioId);
- void playPause(const AudioMsgId &audioId);
- [[nodiscard]] TrackState getState(AudioMsgId::Type type) const;
- [[nodiscard]] Streaming::Instance *roundVideoStreamed(
- HistoryItem *item) const;
- [[nodiscard]] View::PlaybackProgress *roundVideoPlayback(
- HistoryItem *item) const;
- [[nodiscard]] Streaming::Instance *roundVideoPreview(
- not_null<DocumentData*> document) const;
- [[nodiscard]] AudioMsgId current(AudioMsgId::Type type) const {
- if (const auto data = getData(type)) {
- return data->current;
- }
- return AudioMsgId();
- }
- [[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
- if (const auto data = getData(type)) {
- return (data->seeking == data->current);
- }
- return false;
- }
- void startSeeking(AudioMsgId::Type type);
- void finishSeeking(AudioMsgId::Type type, float64 progress);
- void cancelSeeking(AudioMsgId::Type type);
- void updateVoicePlaybackSpeed();
- [[nodiscard]] bool nextAvailable(AudioMsgId::Type type) const;
- [[nodiscard]] bool previousAvailable(AudioMsgId::Type type) const;
- struct Switch {
- AudioMsgId from;
- FullMsgId to;
- };
- [[nodiscard]] rpl::producer<Switch> switchToNextEvents() const {
- return _switchToNext.events();
- }
- [[nodiscard]] rpl::producer<AudioMsgId::Type> tracksFinished() const {
- return _tracksFinished.events();
- }
- [[nodiscard]] rpl::producer<AudioMsgId::Type> trackChanged() const {
- return _trackChanged.events();
- }
- [[nodiscard]] rpl::producer<> playlistChanges(
- AudioMsgId::Type type) const;
- [[nodiscard]] rpl::producer<TrackState> updatedNotifier() const {
- return _updatedNotifier.events();
- }
- [[nodiscard]] rpl::producer<> stops(AudioMsgId::Type type) const;
- [[nodiscard]] rpl::producer<> startsPlay(AudioMsgId::Type type) const;
- [[nodiscard]] rpl::producer<Seeking> seekingChanges(
- AudioMsgId::Type type) const;
- [[nodiscard]] rpl::producer<> closePlayerRequests() const {
- return _closePlayerRequests.events();
- }
- void stopAndClose();
- private:
- using SharedMediaType = Storage::SharedMediaType;
- using SliceKey = SparseIdsMergedSlice::Key;
- struct Streamed;
- struct ShuffleData;
- struct Data {
- Data(AudioMsgId::Type type, SharedMediaType overview);
- Data(Data &&other);
- Data &operator=(Data &&other);
- ~Data();
- AudioMsgId::Type type;
- Storage::SharedMediaType overview;
- AudioMsgId current;
- AudioMsgId seeking;
- 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;
- MsgId topicRootId = 0;
- History *migrated = nullptr;
- Main::Session *session = nullptr;
- bool isPlaying = false;
- bool resumeOnCallEnd = false;
- std::unique_ptr<Streamed> streamed;
- std::unique_ptr<ShuffleData> shuffleData;
- std::unique_ptr<base::PowerSaveBlocker> powerSaveBlocker;
- std::unique_ptr<base::PowerSaveBlocker> powerSaveBlockerVideo;
- };
- struct SeekingChanges {
- Seeking seeking;
- AudioMsgId::Type type;
- };
- Instance();
- ~Instance();
- friend void start(not_null<Audio::Instance*> instance);
- friend void finish(not_null<Audio::Instance*> instance);
- void setupShortcuts();
- void playStreamed(
- const AudioMsgId &audioId,
- std::shared_ptr<Streaming::Document> shared);
- Streaming::PlaybackOptions streamingOptions(
- const AudioMsgId &audioId,
- crl::time position = -1);
- // Observed notifications.
- void handleSongUpdate(const AudioMsgId &audioId);
- void pauseOnCall(AudioMsgId::Type type);
- void resumeOnCall(AudioMsgId::Type type);
- void setCurrent(const AudioMsgId &audioId);
- void refreshPlaylist(not_null<Data*> data);
- void refreshOtherPlaylist(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);
- void updatePowerSaveBlocker(
- not_null<Data*> data,
- const TrackState &state);
- HistoryItem *itemByIndex(not_null<Data*> data, int index);
- void stopAndClear(not_null<Data*> data);
- [[nodiscard]] MsgId computeCurrentUniversalId(
- not_null<const Data*> data) const;
- void validateShuffleData(not_null<Data*> data);
- void setupShuffleData(not_null<Data*> data);
- void ensureShuffleMove(not_null<Data*> data, int delta);
- void handleStreamingUpdate(
- not_null<Data*> data,
- Streaming::Update &&update);
- void handleStreamingError(
- not_null<Data*> data,
- Streaming::Error &&error);
- void clearStreamed(not_null<Data*> data, bool savePosition = true);
- void emitUpdate(AudioMsgId::Type type);
- template <typename CheckCallback>
- void emitUpdate(AudioMsgId::Type type, CheckCallback check);
- [[nodiscard]] RepeatMode repeat(not_null<const Data*> data) const;
- [[nodiscard]] rpl::producer<RepeatMode> repeatChanges(
- not_null<const Data*> data) const;
- [[nodiscard]] OrderMode order(not_null<const Data*> data) const;
- [[nodiscard]] rpl::producer<OrderMode> orderChanges(
- not_null<const Data*> data) const;
- Data *getData(AudioMsgId::Type type) {
- if (type == AudioMsgId::Type::Song) {
- return &_songData;
- } else if (type == AudioMsgId::Type::Voice) {
- return &_voiceData;
- }
- return nullptr;
- }
- const Data *getData(AudioMsgId::Type type) const {
- if (type == AudioMsgId::Type::Song) {
- return &_songData;
- } else if (type == AudioMsgId::Type::Voice) {
- return &_voiceData;
- }
- return nullptr;
- }
- HistoryItem *roundVideoItem() const;
- void requestRoundVideoResize() const;
- void requestRoundVideoRepaint() const;
- void setHistory(
- not_null<Data*> data,
- History *history,
- Main::Session *sessionFallback = nullptr);
- void setSession(not_null<Data*> data, Main::Session *session);
- Data _songData;
- Data _voiceData;
- bool _roundPlaying = false;
- rpl::event_stream<Switch> _switchToNext;
- rpl::event_stream<AudioMsgId::Type> _tracksFinished;
- rpl::event_stream<AudioMsgId::Type> _trackChanged;
- rpl::event_stream<AudioMsgId::Type> _playerStopped;
- rpl::event_stream<AudioMsgId::Type> _playerStartedPlay;
- rpl::event_stream<TrackState> _updatedNotifier;
- rpl::event_stream<SeekingChanges> _seekingChanges;
- rpl::event_stream<> _closePlayerRequests;
- rpl::lifetime _lifetime;
- };
- } // namespace Player
- } // namespace Media
|