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 <cursespp/Window.h>
38 #include <cursespp/IKeyHandler.h>
39 #include <musikcore/library/track/Track.h>
40 #include <musikcore/runtime/IMessage.h>
41 #include <musikcore/audio/PlaybackService.h>
42 #include <musikcore/support/PreferenceKeys.h>
43 #include <sigslot/sigslot.h>
44 
45 namespace musik {
46     namespace cube {
47         struct TransportDisplayCache;
48 
49         class TransportWindow:
50             public cursespp::Window,
51             public cursespp::IKeyHandler,
52             public sigslot::has_slots<>
53         {
54             public:
55                 enum FocusTarget {
56                     FocusNone = 0,
57                     FocusVolume = 1,
58                     FocusTime = 2
59                 };
60 
61                 TransportWindow(
62                     musik::core::ILibraryPtr library,
63                     musik::core::audio::PlaybackService& playback);
64 
65                 virtual ~TransportWindow();
66 
67                 virtual void ProcessMessage(musik::core::runtime::IMessage &message);
68                 virtual void OnFocusChanged(bool focused);
69                 virtual void OnRedraw();
70                 virtual bool KeyPress(const std::string& key);
71                 virtual bool MouseEvent(const IMouseHandler::Event& mouseEvent);
72 
73                 void SetFocus(FocusTarget target);
74                 FocusTarget GetFocus() const;
75                 bool FocusNext();
76                 bool FocusPrev();
77                 void FocusFirst();
78                 void FocusLast();
79                 void RestoreFocus();
80 
81             private:
82                 enum TimeMode {
83                     TimeLast = 0,
84                     TimeSmooth = 1,
85                     TimeSync = 2
86                 };
87 
88                 /* a little structure used to make mouse event handling a bit
89                 less verbose. */
90                 struct Position {
PositionPosition91                     Position() {
92                         this->x = this->y = this->width = 0;
93                     }
PositionPosition94                     Position(int x, int y, int width) {
95                         this->x = x;
96                         this->y = y;
97                         this->width = width;
98                     }
SetPosition99                     void Set(int x, int width) {
100                         this->x = x;
101                         this->width = width;
102                     }
PercentPosition103                     double Percent(int x) {
104                         return std::max(0.0, std::min(1.0,
105                             double(x - this->x) / double(this->width - 1)));
106                     }
ContainsPosition107                     bool Contains(const IMouseHandler::Event& event) {
108                         return event.y == this->y &&
109                             event.x >= this->x &&
110                             event.x < this->x + this->width;
111                     }
112                     int x, y, width;
113                 };
114 
115                 void Update(TimeMode mode = TimeSmooth);
116 
117                 void OnPlaybackServiceTrackChanged(size_t index, musik::core::TrackPtr track);
118                 void OnPlaybackModeChanged();
119                 void OnPlaybackStreamStateChanged(musik::core::sdk::StreamState);
120                 void OnTransportVolumeChanged();
121                 void OnTransportTimeChanged(double time);
122                 void OnPlaybackShuffled(bool shuffled);
123                 void UpdateReplayGainState();
124 
125                 bool paused;
126                 bool hasReplayGain;
127                 Position shufflePos, repeatPos, volumePos, timePos;
128                 musik::core::sdk::ReplayGainMode replayGainMode;
129                 musik::core::ILibraryPtr library;
130                 musik::core::audio::ITransport& transport;
131                 musik::core::audio::PlaybackService& playback;
132                 musik::core::TrackPtr currentTrack;
133                 FocusTarget focus, lastFocus;
134                 std::unique_ptr<TransportDisplayCache> displayCache;
135                 bool buffering{ false };
136                 double lastTime;
137         };
138     }
139 }
140