1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (c) 2004-2021 musikcube team 4 // 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright notice, 11 // this list of conditions and the following disclaimer. 12 // 13 // * Redistributions in binary form must reproduce the above copyright 14 // notice, this list of conditions and the following disclaimer in the 15 // documentation and/or other materials provided with the distribution. 16 // 17 // * Neither the name of the author nor the names of other contributors may 18 // be used to endorse or promote products derived from this software 19 // without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 // POSSIBILITY OF SUCH DAMAGE. 32 // 33 ////////////////////////////////////////////////////////////////////////////// 34 35 #pragma once 36 37 #include <sigslot/sigslot.h> 38 39 #include <musikcore/sdk/IPlaybackService.h> 40 #include <musikcore/sdk/IPlaybackRemote.h> 41 #include <musikcore/library/track/Track.h> 42 #include <musikcore/library/track/TrackList.h> 43 #include <musikcore/library/ILibrary.h> 44 #include <musikcore/audio/MasterTransport.h> 45 #include <musikcore/support/Preferences.h> 46 #include <musikcore/runtime/IMessageQueue.h> 47 48 #include <mutex> 49 50 namespace musik { namespace core { namespace audio { 51 52 class PlaybackService : 53 public musik::core::sdk::IPlaybackService, 54 public musik::core::runtime::IMessageTarget, 55 public sigslot::has_slots<> 56 { 57 public: 58 /* our unique events */ 59 sigslot::signal2<size_t, musik::core::TrackPtr> TrackChanged; 60 sigslot::signal0<> ModeChanged; 61 sigslot::signal1<bool> Shuffled; 62 sigslot::signal0<> QueueEdited; 63 64 /* copied from Transport, but will be automatically called on the 65 specified MessageQueue's thread! */ 66 sigslot::signal1<musik::core::sdk::PlaybackState> PlaybackStateChanged; 67 sigslot::signal1<musik::core::sdk::StreamState> StreamStateChanged; 68 sigslot::signal0<> VolumeChanged; 69 sigslot::signal1<double> TimeChanged; 70 71 PlaybackService( 72 musik::core::runtime::IMessageQueue& messageQueue, 73 musik::core::ILibraryPtr library, 74 std::shared_ptr<musik::core::audio::ITransport> transport); 75 76 PlaybackService( 77 musik::core::runtime::IMessageQueue& messageQueue, 78 musik::core::ILibraryPtr library); 79 80 virtual ~PlaybackService(); 81 82 /* IMessageTarget */ 83 void ProcessMessage(musik::core::runtime::IMessage &message) override; 84 85 /* IPlaybackService */ 86 void Play(size_t index) override; 87 bool Next() override; 88 bool Previous() override; Stop()89 void Stop() override { transport->Stop(); } GetRepeatMode()90 musik::core::sdk::RepeatMode GetRepeatMode() override { return this->repeatMode; } 91 void SetRepeatMode(musik::core::sdk::RepeatMode mode) override; 92 void ToggleRepeatMode() override; 93 musik::core::sdk::PlaybackState GetPlaybackState() override; 94 bool IsShuffled() override; 95 void ToggleShuffle() override; 96 size_t GetIndex() noexcept override; 97 size_t Count() override; 98 double GetVolume() override; 99 void SetVolume(double vol) override; 100 void PauseOrResume() override; 101 bool IsMuted() override; 102 void ToggleMute() override; 103 double GetPosition() override; 104 void SetPosition(double seconds) override; 105 double GetDuration() override; 106 musik::core::sdk::ITrack* GetTrack(size_t index) override; 107 musik::core::sdk::ITrack* GetPlayingTrack() override; 108 void CopyFrom(const musik::core::sdk::ITrackList* source) override; 109 void Play(const musik::core::sdk::ITrackList* source, size_t index) override; 110 musik::core::sdk::ITrackListEditor* EditPlaylist() override; 111 musik::core::sdk::TimeChangeMode GetTimeChangeMode() noexcept override; 112 void SetTimeChangeMode(musik::core::sdk::TimeChangeMode) noexcept override; 113 void ReloadOutput() override; 114 musik::core::sdk::ITrackList* Clone() override; 115 116 /* TODO: include in SDK? */ 117 virtual bool HotSwap(const TrackList& source, size_t index = 0); 118 119 /* app-specific implementation. similar to some SDK methods, but use 120 concrete data types with known optimizations */ 121 void Play(const musik::core::TrackList& tracks, size_t index); 122 void Prepare(size_t index, double position = 0.0f); 123 void CopyTo(musik::core::TrackList& target); 124 void CopyFrom(const musik::core::TrackList& source); 125 musik::core::TrackPtr GetPlaying(); 126 GetTransport()127 musik::core::audio::ITransport& GetTransport() noexcept { 128 return *this->transport.get(); 129 } 130 GetTrackList()131 std::shared_ptr<const musik::core::TrackList> GetTrackList() noexcept { 132 return std::shared_ptr<const musik::core::TrackList>( 133 &this->playlist, [](const musik::core::TrackList*) {}); 134 } 135 136 /* required to make changes to the playlist. this little data structure 137 privately owns a lock to the internal data structure and will release 138 that lock when it's destructed. */ 139 class Editor : public musik::core::sdk::ITrackListEditor { 140 public: 141 using IEditor = std::shared_ptr<musik::core::sdk::ITrackListEditor>; 142 143 Editor(Editor&& other); 144 virtual ~Editor(); 145 146 /* ITrackListEditor */ 147 bool Insert(int64_t id, size_t index) override; 148 bool Swap(size_t index1, size_t index2) override; 149 bool Move(size_t from, size_t to) override; 150 bool Delete(size_t index) override; 151 void Add(const int64_t id) override; 152 void Clear() override; 153 void Shuffle() override; 154 void Release() noexcept override; 155 156 private: 157 friend class PlaybackService; 158 using Mutex = std::recursive_mutex; 159 using Lock = std::unique_lock<Mutex>; 160 using Queue = musik::core::runtime::IMessageQueue; 161 162 Editor( 163 PlaybackService& playback, 164 TrackList& tracks, 165 Queue& queue, 166 Mutex& mutex); 167 168 PlaybackService& playback; 169 IEditor tracks; 170 Queue& queue; 171 Lock lock; 172 size_t playIndex; 173 bool nextTrackInvalidated; 174 bool edited; 175 }; 176 177 Editor Edit(); 178 179 private: 180 void OnStreamEvent(musik::core::sdk::StreamState eventType, std::string uri); 181 void OnPlaybackEvent(musik::core::sdk::PlaybackState eventType); 182 void OnTrackChanged(size_t pos, musik::core::TrackPtr track); 183 void OnVolumeChanged(); 184 void OnTimeChanged(double time); 185 void OnIndexerFinished(int trackCount); 186 187 void NotifyRemotesModeChanged(); 188 void PrepareNextTrack(); 189 void InitRemotes(); 190 void ResetRemotes(); 191 void MarkTrackAsPlayed(int64_t trackId); 192 193 void PlayAt(size_t index, ITransport::StartMode mode); 194 195 musik::core::TrackPtr TrackAtIndexWithTimeout(size_t index); 196 197 std::string UriAtIndex(size_t index); 198 musik::core::audio::ITransport::Gain GainAtIndex(size_t index); 199 200 musik::core::TrackList playlist; 201 musik::core::TrackList unshuffled; 202 std::recursive_mutex playlistMutex; 203 204 std::vector<std::shared_ptr<musik::core::sdk::IPlaybackRemote>> remotes; 205 std::shared_ptr<musik::core::Preferences> playbackPrefs; 206 std::shared_ptr<musik::core::Preferences> appPrefs; 207 musik::core::TrackPtr playingTrack; 208 209 musik::core::ILibraryPtr library; 210 std::shared_ptr<musik::core::audio::ITransport> transport; 211 size_t index, nextIndex; 212 213 musik::core::sdk::RepeatMode repeatMode; 214 musik::core::sdk::TimeChangeMode timeChangeMode; 215 216 double seekPosition; 217 218 musik::core::runtime::IMessageQueue& messageQueue; 219 }; 220 221 } } } 222