media_player_instance.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "data/data_audio_msg_id.h"
  9. #include "data/data_shared_media.h"
  10. class AudioMsgId;
  11. class DocumentData;
  12. class History;
  13. namespace Media {
  14. enum class RepeatMode;
  15. enum class OrderMode;
  16. } // namespace Media
  17. namespace Media {
  18. namespace Audio {
  19. class Instance;
  20. } // namespace Audio
  21. } // namespace Media
  22. namespace Media {
  23. namespace View {
  24. class PlaybackProgress;
  25. } // namespace View
  26. } // namespace Media
  27. namespace Media {
  28. namespace Streaming {
  29. class Document;
  30. class Instance;
  31. struct PlaybackOptions;
  32. struct Update;
  33. enum class Error;
  34. } // namespace Streaming
  35. } // namespace Media
  36. namespace base {
  37. class PowerSaveBlocker;
  38. } // namespace base
  39. namespace Media {
  40. namespace Player {
  41. extern const char kOptionDisableAutoplayNext[];
  42. class Instance;
  43. struct TrackState;
  44. void start(not_null<Audio::Instance*> instance);
  45. void finish(not_null<Audio::Instance*> instance);
  46. void SaveLastPlaybackPosition(
  47. not_null<DocumentData*> document,
  48. const TrackState &state);
  49. not_null<Instance*> instance();
  50. class Instance final {
  51. public:
  52. enum class Seeking {
  53. Start,
  54. Finish,
  55. Cancel,
  56. };
  57. void play(AudioMsgId::Type type);
  58. void pause(AudioMsgId::Type type);
  59. void stop(AudioMsgId::Type type, bool asFinished = false);
  60. void playPause(AudioMsgId::Type type);
  61. bool next(AudioMsgId::Type type);
  62. bool previous(AudioMsgId::Type type);
  63. AudioMsgId::Type getActiveType() const;
  64. void play() {
  65. play(getActiveType());
  66. }
  67. void pause() {
  68. pause(getActiveType());
  69. }
  70. void stop() {
  71. stop(getActiveType());
  72. }
  73. void playPause() {
  74. playPause(getActiveType());
  75. }
  76. bool next() {
  77. return next(getActiveType());
  78. }
  79. bool previous() {
  80. return previous(getActiveType());
  81. }
  82. void playPauseCancelClicked(AudioMsgId::Type type);
  83. void play(const AudioMsgId &audioId);
  84. void playPause(const AudioMsgId &audioId);
  85. [[nodiscard]] TrackState getState(AudioMsgId::Type type) const;
  86. [[nodiscard]] Streaming::Instance *roundVideoStreamed(
  87. HistoryItem *item) const;
  88. [[nodiscard]] View::PlaybackProgress *roundVideoPlayback(
  89. HistoryItem *item) const;
  90. [[nodiscard]] Streaming::Instance *roundVideoPreview(
  91. not_null<DocumentData*> document) const;
  92. [[nodiscard]] AudioMsgId current(AudioMsgId::Type type) const {
  93. if (const auto data = getData(type)) {
  94. return data->current;
  95. }
  96. return AudioMsgId();
  97. }
  98. [[nodiscard]] bool isSeeking(AudioMsgId::Type type) const {
  99. if (const auto data = getData(type)) {
  100. return (data->seeking == data->current);
  101. }
  102. return false;
  103. }
  104. void startSeeking(AudioMsgId::Type type);
  105. void finishSeeking(AudioMsgId::Type type, float64 progress);
  106. void cancelSeeking(AudioMsgId::Type type);
  107. void updateVoicePlaybackSpeed();
  108. [[nodiscard]] bool nextAvailable(AudioMsgId::Type type) const;
  109. [[nodiscard]] bool previousAvailable(AudioMsgId::Type type) const;
  110. struct Switch {
  111. AudioMsgId from;
  112. FullMsgId to;
  113. };
  114. [[nodiscard]] rpl::producer<Switch> switchToNextEvents() const {
  115. return _switchToNext.events();
  116. }
  117. [[nodiscard]] rpl::producer<AudioMsgId::Type> tracksFinished() const {
  118. return _tracksFinished.events();
  119. }
  120. [[nodiscard]] rpl::producer<AudioMsgId::Type> trackChanged() const {
  121. return _trackChanged.events();
  122. }
  123. [[nodiscard]] rpl::producer<> playlistChanges(
  124. AudioMsgId::Type type) const;
  125. [[nodiscard]] rpl::producer<TrackState> updatedNotifier() const {
  126. return _updatedNotifier.events();
  127. }
  128. [[nodiscard]] rpl::producer<> stops(AudioMsgId::Type type) const;
  129. [[nodiscard]] rpl::producer<> startsPlay(AudioMsgId::Type type) const;
  130. [[nodiscard]] rpl::producer<Seeking> seekingChanges(
  131. AudioMsgId::Type type) const;
  132. [[nodiscard]] rpl::producer<> closePlayerRequests() const {
  133. return _closePlayerRequests.events();
  134. }
  135. void stopAndClose();
  136. private:
  137. using SharedMediaType = Storage::SharedMediaType;
  138. using SliceKey = SparseIdsMergedSlice::Key;
  139. struct Streamed;
  140. struct ShuffleData;
  141. struct Data {
  142. Data(AudioMsgId::Type type, SharedMediaType overview);
  143. Data(Data &&other);
  144. Data &operator=(Data &&other);
  145. ~Data();
  146. AudioMsgId::Type type;
  147. Storage::SharedMediaType overview;
  148. AudioMsgId current;
  149. AudioMsgId seeking;
  150. std::optional<SparseIdsMergedSlice> playlistSlice;
  151. std::optional<SliceKey> playlistSliceKey;
  152. std::optional<SliceKey> playlistRequestedKey;
  153. std::optional<SparseIdsMergedSlice> playlistOtherSlice;
  154. std::optional<SliceKey> playlistOtherRequestedKey;
  155. std::optional<int> playlistIndex;
  156. rpl::lifetime playlistLifetime;
  157. rpl::lifetime playlistOtherLifetime;
  158. rpl::lifetime sessionLifetime;
  159. rpl::event_stream<> playlistChanges;
  160. History *history = nullptr;
  161. MsgId topicRootId = 0;
  162. History *migrated = nullptr;
  163. Main::Session *session = nullptr;
  164. bool isPlaying = false;
  165. bool resumeOnCallEnd = false;
  166. std::unique_ptr<Streamed> streamed;
  167. std::unique_ptr<ShuffleData> shuffleData;
  168. std::unique_ptr<base::PowerSaveBlocker> powerSaveBlocker;
  169. std::unique_ptr<base::PowerSaveBlocker> powerSaveBlockerVideo;
  170. };
  171. struct SeekingChanges {
  172. Seeking seeking;
  173. AudioMsgId::Type type;
  174. };
  175. Instance();
  176. ~Instance();
  177. friend void start(not_null<Audio::Instance*> instance);
  178. friend void finish(not_null<Audio::Instance*> instance);
  179. void setupShortcuts();
  180. void playStreamed(
  181. const AudioMsgId &audioId,
  182. std::shared_ptr<Streaming::Document> shared);
  183. Streaming::PlaybackOptions streamingOptions(
  184. const AudioMsgId &audioId,
  185. crl::time position = -1);
  186. // Observed notifications.
  187. void handleSongUpdate(const AudioMsgId &audioId);
  188. void pauseOnCall(AudioMsgId::Type type);
  189. void resumeOnCall(AudioMsgId::Type type);
  190. void setCurrent(const AudioMsgId &audioId);
  191. void refreshPlaylist(not_null<Data*> data);
  192. void refreshOtherPlaylist(not_null<Data*> data);
  193. std::optional<SliceKey> playlistKey(not_null<const Data*> data) const;
  194. bool validPlaylist(not_null<const Data*> data) const;
  195. void validatePlaylist(not_null<Data*> data);
  196. std::optional<SliceKey> playlistOtherKey(
  197. not_null<const Data*> data) const;
  198. bool validOtherPlaylist(not_null<const Data*> data) const;
  199. void validateOtherPlaylist(not_null<Data*> data);
  200. void playlistUpdated(not_null<Data*> data);
  201. bool moveInPlaylist(not_null<Data*> data, int delta, bool autonext);
  202. void updatePowerSaveBlocker(
  203. not_null<Data*> data,
  204. const TrackState &state);
  205. HistoryItem *itemByIndex(not_null<Data*> data, int index);
  206. void stopAndClear(not_null<Data*> data);
  207. [[nodiscard]] MsgId computeCurrentUniversalId(
  208. not_null<const Data*> data) const;
  209. void validateShuffleData(not_null<Data*> data);
  210. void setupShuffleData(not_null<Data*> data);
  211. void ensureShuffleMove(not_null<Data*> data, int delta);
  212. void handleStreamingUpdate(
  213. not_null<Data*> data,
  214. Streaming::Update &&update);
  215. void handleStreamingError(
  216. not_null<Data*> data,
  217. Streaming::Error &&error);
  218. void clearStreamed(not_null<Data*> data, bool savePosition = true);
  219. void emitUpdate(AudioMsgId::Type type);
  220. template <typename CheckCallback>
  221. void emitUpdate(AudioMsgId::Type type, CheckCallback check);
  222. [[nodiscard]] RepeatMode repeat(not_null<const Data*> data) const;
  223. [[nodiscard]] rpl::producer<RepeatMode> repeatChanges(
  224. not_null<const Data*> data) const;
  225. [[nodiscard]] OrderMode order(not_null<const Data*> data) const;
  226. [[nodiscard]] rpl::producer<OrderMode> orderChanges(
  227. not_null<const Data*> data) const;
  228. Data *getData(AudioMsgId::Type type) {
  229. if (type == AudioMsgId::Type::Song) {
  230. return &_songData;
  231. } else if (type == AudioMsgId::Type::Voice) {
  232. return &_voiceData;
  233. }
  234. return nullptr;
  235. }
  236. const Data *getData(AudioMsgId::Type type) const {
  237. if (type == AudioMsgId::Type::Song) {
  238. return &_songData;
  239. } else if (type == AudioMsgId::Type::Voice) {
  240. return &_voiceData;
  241. }
  242. return nullptr;
  243. }
  244. HistoryItem *roundVideoItem() const;
  245. void requestRoundVideoResize() const;
  246. void requestRoundVideoRepaint() const;
  247. void setHistory(
  248. not_null<Data*> data,
  249. History *history,
  250. Main::Session *sessionFallback = nullptr);
  251. void setSession(not_null<Data*> data, Main::Session *session);
  252. Data _songData;
  253. Data _voiceData;
  254. bool _roundPlaying = false;
  255. rpl::event_stream<Switch> _switchToNext;
  256. rpl::event_stream<AudioMsgId::Type> _tracksFinished;
  257. rpl::event_stream<AudioMsgId::Type> _trackChanged;
  258. rpl::event_stream<AudioMsgId::Type> _playerStopped;
  259. rpl::event_stream<AudioMsgId::Type> _playerStartedPlay;
  260. rpl::event_stream<TrackState> _updatedNotifier;
  261. rpl::event_stream<SeekingChanges> _seekingChanges;
  262. rpl::event_stream<> _closePlayerRequests;
  263. rpl::lifetime _lifetime;
  264. };
  265. } // namespace Player
  266. } // namespace Media