Merge lp:~phablet-team/media-hub/tracklist-cli into lp:media-hub
- tracklist-cli
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ricardo Mendoza |
Approved revision: | 139 |
Merged at revision: | 132 |
Proposed branch: | lp:~phablet-team/media-hub/tracklist-cli |
Merge into: | lp:media-hub |
Diff against target: |
2379 lines (+1155/-173) 32 files modified
include/core/media/player.h (+39/-2) include/core/media/track_list.h (+37/-4) src/core/media/codec.h (+2/-0) src/core/media/engine.h (+2/-1) src/core/media/gstreamer/engine.cpp (+5/-3) src/core/media/gstreamer/engine.h (+1/-1) src/core/media/gstreamer/meta_data_extractor.h (+1/-1) src/core/media/gstreamer/playbin.cpp (+6/-2) src/core/media/gstreamer/playbin.h (+3/-1) src/core/media/mpris/player.h (+8/-3) src/core/media/mpris/track_list.h (+101/-9) src/core/media/player_configuration.h (+2/-0) src/core/media/player_implementation.cpp (+81/-13) src/core/media/player_implementation.h (+1/-1) src/core/media/player_skeleton.cpp (+5/-4) src/core/media/player_skeleton.h (+4/-2) src/core/media/player_stub.cpp (+14/-8) src/core/media/player_stub.h (+3/-2) src/core/media/service_implementation.cpp (+15/-12) src/core/media/service_skeleton.cpp (+8/-2) src/core/media/service_stub.cpp (+3/-0) src/core/media/track_list_implementation.cpp (+83/-12) src/core/media/track_list_implementation.h (+10/-4) src/core/media/track_list_skeleton.cpp (+191/-58) src/core/media/track_list_skeleton.h (+23/-6) src/core/media/track_list_stub.cpp (+34/-11) src/core/media/track_list_stub.h (+11/-5) tests/CMakeLists.txt (+1/-0) tests/test-track-list/CMakeLists.txt (+17/-0) tests/test-track-list/test_track_list.cpp (+346/-0) tests/test-track-list/test_track_list.h (+86/-0) tests/unit-tests/test-gstreamer-engine.cpp (+12/-6) |
To merge this branch: | bzr merge lp:~phablet-team/media-hub/tracklist-cli |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomas Voß (community) | Needs Information | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+255900@code.launchpad.net |
Commit message
* Implements the backend portion of TrackLists required to allow clients to be able to hand off a playlist to media-hub and keep playing music in order, shuffled and/or looped without the app being in the foreground
Description of the change
* Implements the backend portion of TrackLists required to allow clients to be able to hand off a playlist to media-hub and keep playing music in order, shuffled and/or looped without the app being in the foreground
PS Jenkins bot (ps-jenkins) wrote : | # |
- 136. By Jim Hodapp
-
Initialize the TrackList property returned by Tracks().
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:136
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 137. By Jim Hodapp
-
Include codec includes for vector and string.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:137
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 138. By Jim Hodapp
-
Return the dbus Property instances instead of the local ones.
- 139. By Jim Hodapp
-
Clean up no longer necessary cout statements and one unused function add_set_
state_to_ main_context( ) in playbin.cpp
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:138
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Thomas Voß (thomas-voss) wrote : | # |
I noticed the top-approve, still wanted to leave my comments.
- 140. By Jim Hodapp
-
Make sure the skeleton uses the dbus version of the properties instead of a copy.
- 141. By Jim Hodapp
-
Fix up the tracklist dbus object name/path
- 142. By Jim Hodapp
-
Fix video playback not working because of conflicting play(), stop(), play() during setup when using open_uri().
- 143. By Jim Hodapp
-
Don't call open_uri twice and also make sure that the TrackList handle_
add_track_ with_uri_ at() checks apparmor access permissions.
Preview Diff
1 | === modified file 'include/core/media/player.h' | |||
2 | --- include/core/media/player.h 2015-03-11 16:17:23 +0000 | |||
3 | +++ include/core/media/player.h 2015-04-20 17:49:07 +0000 | |||
4 | @@ -27,6 +27,7 @@ | |||
5 | 27 | #include <core/property.h> | 27 | #include <core/property.h> |
6 | 28 | 28 | ||
7 | 29 | #include <chrono> | 29 | #include <chrono> |
8 | 30 | #include <iosfwd> | ||
9 | 30 | #include <memory> | 31 | #include <memory> |
10 | 31 | 32 | ||
11 | 32 | namespace core | 33 | namespace core |
12 | @@ -149,7 +150,7 @@ | |||
13 | 149 | virtual const core::Property<PlaybackStatus>& playback_status() const = 0; | 150 | virtual const core::Property<PlaybackStatus>& playback_status() const = 0; |
14 | 150 | virtual const core::Property<LoopStatus>& loop_status() const = 0; | 151 | virtual const core::Property<LoopStatus>& loop_status() const = 0; |
15 | 151 | virtual const core::Property<PlaybackRate>& playback_rate() const = 0; | 152 | virtual const core::Property<PlaybackRate>& playback_rate() const = 0; |
17 | 152 | virtual const core::Property<bool>& is_shuffle() const = 0; | 153 | virtual const core::Property<bool>& shuffle() const = 0; |
18 | 153 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const = 0; | 154 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const = 0; |
19 | 154 | virtual const core::Property<Volume>& volume() const = 0; | 155 | virtual const core::Property<Volume>& volume() const = 0; |
20 | 155 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const = 0; | 156 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const = 0; |
21 | @@ -162,7 +163,7 @@ | |||
22 | 162 | 163 | ||
23 | 163 | virtual core::Property<LoopStatus>& loop_status() = 0; | 164 | virtual core::Property<LoopStatus>& loop_status() = 0; |
24 | 164 | virtual core::Property<PlaybackRate>& playback_rate() = 0; | 165 | virtual core::Property<PlaybackRate>& playback_rate() = 0; |
26 | 165 | virtual core::Property<bool>& is_shuffle() = 0; | 166 | virtual core::Property<bool>& shuffle() = 0; |
27 | 166 | virtual core::Property<Volume>& volume() = 0; | 167 | virtual core::Property<Volume>& volume() = 0; |
28 | 167 | virtual core::Property<AudioStreamRole>& audio_stream_role() = 0; | 168 | virtual core::Property<AudioStreamRole>& audio_stream_role() = 0; |
29 | 168 | virtual core::Property<Lifetime>& lifetime() = 0; | 169 | virtual core::Property<Lifetime>& lifetime() = 0; |
30 | @@ -178,6 +179,42 @@ | |||
31 | 178 | Player(); | 179 | Player(); |
32 | 179 | 180 | ||
33 | 180 | }; | 181 | }; |
34 | 182 | |||
35 | 183 | // operator<< pretty prints the given playback status to the given output stream. | ||
36 | 184 | inline std::ostream& operator<<(std::ostream& out, Player::PlaybackStatus status) | ||
37 | 185 | { | ||
38 | 186 | switch (status) | ||
39 | 187 | { | ||
40 | 188 | case Player::PlaybackStatus::null: | ||
41 | 189 | return out << "PlaybackStatus::null"; | ||
42 | 190 | case Player::PlaybackStatus::ready: | ||
43 | 191 | return out << "PlaybackStatus::ready"; | ||
44 | 192 | case Player::PlaybackStatus::playing: | ||
45 | 193 | return out << "PlaybackStatus::playing"; | ||
46 | 194 | case Player::PlaybackStatus::paused: | ||
47 | 195 | return out << "PlaybackStatus::paused"; | ||
48 | 196 | case Player::PlaybackStatus::stopped: | ||
49 | 197 | return out << "PlaybackStatus::stopped"; | ||
50 | 198 | } | ||
51 | 199 | |||
52 | 200 | return out; | ||
53 | 201 | } | ||
54 | 202 | |||
55 | 203 | inline std::ostream& operator<<(std::ostream& out, Player::LoopStatus loop_status) | ||
56 | 204 | { | ||
57 | 205 | switch (loop_status) | ||
58 | 206 | { | ||
59 | 207 | case Player::LoopStatus::none: | ||
60 | 208 | return out << "LoopStatus::none"; | ||
61 | 209 | case Player::LoopStatus::track: | ||
62 | 210 | return out << "LoopStatus::track"; | ||
63 | 211 | case Player::LoopStatus::playlist: | ||
64 | 212 | return out << "LoopStatus::playlist"; | ||
65 | 213 | } | ||
66 | 214 | |||
67 | 215 | return out; | ||
68 | 216 | } | ||
69 | 217 | |||
70 | 181 | } | 218 | } |
71 | 182 | } | 219 | } |
72 | 183 | } | 220 | } |
73 | 184 | 221 | ||
74 | === modified file 'include/core/media/track_list.h' | |||
75 | --- include/core/media/track_list.h 2014-02-12 15:53:57 +0000 | |||
76 | +++ include/core/media/track_list.h 2015-04-20 17:49:07 +0000 | |||
77 | @@ -24,7 +24,8 @@ | |||
78 | 24 | #include <core/signal.h> | 24 | #include <core/signal.h> |
79 | 25 | 25 | ||
80 | 26 | #include <functional> | 26 | #include <functional> |
82 | 27 | #include <list> | 27 | #include <iosfwd> |
83 | 28 | #include <vector> | ||
84 | 28 | #include <memory> | 29 | #include <memory> |
85 | 29 | 30 | ||
86 | 30 | namespace core | 31 | namespace core |
87 | @@ -39,6 +40,7 @@ | |||
88 | 39 | { | 40 | { |
89 | 40 | public: | 41 | public: |
90 | 41 | typedef std::vector<Track::Id> Container; | 42 | typedef std::vector<Track::Id> Container; |
91 | 43 | typedef std::tuple<std::vector<Track::Id>, Track::Id> ContainerTrackIdTuple; | ||
92 | 42 | typedef Container::iterator Iterator; | 44 | typedef Container::iterator Iterator; |
93 | 43 | typedef Container::const_iterator ConstIterator; | 45 | typedef Container::const_iterator ConstIterator; |
94 | 44 | 46 | ||
95 | @@ -50,23 +52,54 @@ | |||
96 | 50 | TrackList& operator=(const TrackList&) = delete; | 52 | TrackList& operator=(const TrackList&) = delete; |
97 | 51 | bool operator==(const TrackList&) const = delete; | 53 | bool operator==(const TrackList&) const = delete; |
98 | 52 | 54 | ||
99 | 55 | /** If set to false, calling add_track_with_uri_at or remove_track will have no effect. */ | ||
100 | 53 | virtual const core::Property<bool>& can_edit_tracks() const = 0; | 56 | virtual const core::Property<bool>& can_edit_tracks() const = 0; |
101 | 57 | |||
102 | 58 | /** An array which contains the identifier of each track in the tracklist, in order. */ | ||
103 | 54 | virtual const core::Property<Container>& tracks() const = 0; | 59 | virtual const core::Property<Container>& tracks() const = 0; |
104 | 55 | 60 | ||
105 | 61 | /** Gets all the metadata available for a given Track. */ | ||
106 | 56 | virtual Track::MetaData query_meta_data_for_track(const Track::Id& id) = 0; | 62 | virtual Track::MetaData query_meta_data_for_track(const Track::Id& id) = 0; |
107 | 63 | |||
108 | 64 | /** Adds a URI in the TrackList. */ | ||
109 | 57 | virtual void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current) = 0; | 65 | virtual void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current) = 0; |
110 | 66 | |||
111 | 67 | /** Removes a Track from the TrackList. */ | ||
112 | 58 | virtual void remove_track(const Track::Id& id) = 0; | 68 | virtual void remove_track(const Track::Id& id) = 0; |
113 | 59 | 69 | ||
117 | 60 | virtual void go_to(const Track::Id& track) = 0; | 70 | /** Skip to the specified TrackId. Calls stop() and play() on the player if toggle_player_state is true. */ |
118 | 61 | 71 | virtual void go_to(const Track::Id& track, bool toggle_player_state) = 0; | |
119 | 62 | virtual const core::Signal<void>& on_track_list_replaced() const = 0; | 72 | |
120 | 73 | |||
121 | 74 | /** Reorders the tracks such that they are in a random order. */ | ||
122 | 75 | virtual void shuffle_tracks() = 0; | ||
123 | 76 | |||
124 | 77 | /** Restores the original order of tracks before shuffle mode was turned on. */ | ||
125 | 78 | virtual void unshuffle_tracks() = 0; | ||
126 | 79 | |||
127 | 80 | /** Clears and resets the TrackList to the same as a newly constructed instance. */ | ||
128 | 81 | virtual void reset() = 0; | ||
129 | 82 | |||
130 | 83 | |||
131 | 84 | /** Indicates that the entire tracklist has been replaced. */ | ||
132 | 85 | virtual const core::Signal<ContainerTrackIdTuple>& on_track_list_replaced() const = 0; | ||
133 | 86 | |||
134 | 87 | /** Indicates that a track has been added to the track list. */ | ||
135 | 63 | virtual const core::Signal<Track::Id>& on_track_added() const = 0; | 88 | virtual const core::Signal<Track::Id>& on_track_added() const = 0; |
136 | 89 | |||
137 | 90 | /** Indicates that a track has been removed from the track list. */ | ||
138 | 64 | virtual const core::Signal<Track::Id>& on_track_removed() const = 0; | 91 | virtual const core::Signal<Track::Id>& on_track_removed() const = 0; |
139 | 92 | |||
140 | 93 | /** Indicates that the track list advanced from one track to another. */ | ||
141 | 65 | virtual const core::Signal<Track::Id>& on_track_changed() const = 0; | 94 | virtual const core::Signal<Track::Id>& on_track_changed() const = 0; |
142 | 66 | 95 | ||
143 | 96 | /** Used to notify the Player of when the client requested that the Player should immediately play a new track. */ | ||
144 | 97 | virtual const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const = 0; | ||
145 | 98 | |||
146 | 67 | protected: | 99 | protected: |
147 | 68 | TrackList(); | 100 | TrackList(); |
148 | 69 | }; | 101 | }; |
149 | 102 | |||
150 | 70 | } | 103 | } |
151 | 71 | } | 104 | } |
152 | 72 | } | 105 | } |
153 | 73 | 106 | ||
154 | === modified file 'src/core/media/codec.h' | |||
155 | --- src/core/media/codec.h 2015-01-26 09:23:41 +0000 | |||
156 | +++ src/core/media/codec.h 2015-04-20 17:49:07 +0000 | |||
157 | @@ -23,6 +23,8 @@ | |||
158 | 23 | #include <core/media/player.h> | 23 | #include <core/media/player.h> |
159 | 24 | #include <core/media/track.h> | 24 | #include <core/media/track.h> |
160 | 25 | 25 | ||
161 | 26 | #include <core/dbus/types/stl/string.h> | ||
162 | 27 | #include <core/dbus/types/stl/vector.h> | ||
163 | 26 | #include <core/dbus/codec.h> | 28 | #include <core/dbus/codec.h> |
164 | 27 | 29 | ||
165 | 28 | namespace core | 30 | namespace core |
166 | 29 | 31 | ||
167 | === modified file 'src/core/media/engine.h' | |||
168 | --- src/core/media/engine.h 2015-01-26 09:23:41 +0000 | |||
169 | +++ src/core/media/engine.h 2015-04-20 17:49:07 +0000 | |||
170 | @@ -38,6 +38,7 @@ | |||
171 | 38 | 38 | ||
172 | 39 | enum class State | 39 | enum class State |
173 | 40 | { | 40 | { |
174 | 41 | no_media, | ||
175 | 41 | ready, | 42 | ready, |
176 | 42 | busy, | 43 | busy, |
177 | 43 | playing, | 44 | playing, |
178 | @@ -75,7 +76,7 @@ | |||
179 | 75 | 76 | ||
180 | 76 | virtual const core::Property<State>& state() const = 0; | 77 | virtual const core::Property<State>& state() const = 0; |
181 | 77 | 78 | ||
183 | 78 | virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri) = 0; | 79 | virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, bool do_pipeline_reset) = 0; |
184 | 79 | virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, const Player::HeadersType&) = 0; | 80 | virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, const Player::HeadersType&) = 0; |
185 | 80 | // Throws core::ubuntu::media::Player::Error::OutOfProcessBufferStreamingNotSupported if the implementation does not | 81 | // Throws core::ubuntu::media::Player::Error::OutOfProcessBufferStreamingNotSupported if the implementation does not |
186 | 81 | // support this feature. | 82 | // support this feature. |
187 | 82 | 83 | ||
188 | === modified file 'src/core/media/gstreamer/engine.cpp' | |||
189 | --- src/core/media/gstreamer/engine.cpp 2015-03-11 16:17:23 +0000 | |||
190 | +++ src/core/media/gstreamer/engine.cpp 2015-04-20 17:49:07 +0000 | |||
191 | @@ -313,12 +313,13 @@ | |||
192 | 313 | gstreamer::Engine::Engine() : d(new Private{}) | 313 | gstreamer::Engine::Engine() : d(new Private{}) |
193 | 314 | { | 314 | { |
194 | 315 | cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl; | 315 | cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl; |
196 | 316 | d->state = media::Engine::State::ready; | 316 | d->state = media::Engine::State::no_media; |
197 | 317 | } | 317 | } |
198 | 318 | 318 | ||
199 | 319 | gstreamer::Engine::~Engine() | 319 | gstreamer::Engine::~Engine() |
200 | 320 | { | 320 | { |
201 | 321 | stop(); | 321 | stop(); |
202 | 322 | d->state = media::Engine::State::no_media; | ||
203 | 322 | } | 323 | } |
204 | 323 | 324 | ||
205 | 324 | const std::shared_ptr<media::Engine::MetaDataExtractor>& gstreamer::Engine::meta_data_extractor() const | 325 | const std::shared_ptr<media::Engine::MetaDataExtractor>& gstreamer::Engine::meta_data_extractor() const |
206 | @@ -331,9 +332,9 @@ | |||
207 | 331 | return d->state; | 332 | return d->state; |
208 | 332 | } | 333 | } |
209 | 333 | 334 | ||
211 | 334 | bool gstreamer::Engine::open_resource_for_uri(const media::Track::UriType& uri) | 335 | bool gstreamer::Engine::open_resource_for_uri(const media::Track::UriType& uri, bool do_pipeline_reset) |
212 | 335 | { | 336 | { |
214 | 336 | d->playbin.set_uri(uri, core::ubuntu::media::Player::HeadersType{}); | 337 | d->playbin.set_uri(uri, core::ubuntu::media::Player::HeadersType{}, do_pipeline_reset); |
215 | 337 | return true; | 338 | return true; |
216 | 338 | } | 339 | } |
217 | 339 | 340 | ||
218 | @@ -356,6 +357,7 @@ | |||
219 | 356 | { | 357 | { |
220 | 357 | d->state = media::Engine::State::playing; | 358 | d->state = media::Engine::State::playing; |
221 | 358 | cout << __PRETTY_FUNCTION__ << endl; | 359 | cout << __PRETTY_FUNCTION__ << endl; |
222 | 360 | cout << "Engine: playing uri: " << d->playbin.uri() << endl; | ||
223 | 359 | d->playback_status_changed(media::Player::PlaybackStatus::playing); | 361 | d->playback_status_changed(media::Player::PlaybackStatus::playing); |
224 | 360 | } | 362 | } |
225 | 361 | 363 | ||
226 | 362 | 364 | ||
227 | === modified file 'src/core/media/gstreamer/engine.h' | |||
228 | --- src/core/media/gstreamer/engine.h 2015-01-26 09:23:41 +0000 | |||
229 | +++ src/core/media/gstreamer/engine.h 2015-04-20 17:49:07 +0000 | |||
230 | @@ -33,7 +33,7 @@ | |||
231 | 33 | 33 | ||
232 | 34 | const core::Property<State>& state() const; | 34 | const core::Property<State>& state() const; |
233 | 35 | 35 | ||
235 | 36 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri); | 36 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, bool do_pipeline_reset); |
236 | 37 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, const core::ubuntu::media::Player::HeadersType& headers); | 37 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, const core::ubuntu::media::Player::HeadersType& headers); |
237 | 38 | void create_video_sink(uint32_t texture_id); | 38 | void create_video_sink(uint32_t texture_id); |
238 | 39 | 39 | ||
239 | 40 | 40 | ||
240 | === modified file 'src/core/media/gstreamer/meta_data_extractor.h' | |||
241 | --- src/core/media/gstreamer/meta_data_extractor.h 2014-10-14 20:05:20 +0000 | |||
242 | +++ src/core/media/gstreamer/meta_data_extractor.h 2015-04-20 17:49:07 +0000 | |||
243 | @@ -177,7 +177,7 @@ | |||
244 | 177 | bus.on_new_message.connect( | 177 | bus.on_new_message.connect( |
245 | 178 | [&](const gstreamer::Bus::Message& msg) | 178 | [&](const gstreamer::Bus::Message& msg) |
246 | 179 | { | 179 | { |
248 | 180 | std::cout << __PRETTY_FUNCTION__ << gst_message_type_get_name(msg.type) << std::endl; | 180 | //std::cout << __PRETTY_FUNCTION__ << gst_message_type_get_name(msg.type) << std::endl; |
249 | 181 | if (msg.type == GST_MESSAGE_TAG) | 181 | if (msg.type == GST_MESSAGE_TAG) |
250 | 182 | { | 182 | { |
251 | 183 | MetaDataExtractor::on_tag_available(msg.detail.tag, meta_data); | 183 | MetaDataExtractor::on_tag_available(msg.detail.tag, meta_data); |
252 | 184 | 184 | ||
253 | === modified file 'src/core/media/gstreamer/playbin.cpp' | |||
254 | --- src/core/media/gstreamer/playbin.cpp 2015-03-11 16:17:23 +0000 | |||
255 | +++ src/core/media/gstreamer/playbin.cpp 2015-04-20 17:49:07 +0000 | |||
256 | @@ -24,6 +24,8 @@ | |||
257 | 24 | #include <hybris/media/surface_texture_client_hybris.h> | 24 | #include <hybris/media/surface_texture_client_hybris.h> |
258 | 25 | #include <hybris/media/media_codec_layer.h> | 25 | #include <hybris/media/media_codec_layer.h> |
259 | 26 | 26 | ||
260 | 27 | #include <utility> | ||
261 | 28 | |||
262 | 27 | namespace | 29 | namespace |
263 | 28 | { | 30 | { |
264 | 29 | void setup_video_sink_for_buffer_streaming(GstElement* video_sink) | 31 | void setup_video_sink_for_buffer_streaming(GstElement* video_sink) |
265 | @@ -365,9 +367,11 @@ | |||
266 | 365 | 367 | ||
267 | 366 | void gstreamer::Playbin::set_uri( | 368 | void gstreamer::Playbin::set_uri( |
268 | 367 | const std::string& uri, | 369 | const std::string& uri, |
270 | 368 | const core::ubuntu::media::Player::HeadersType& headers = core::ubuntu::media::Player::HeadersType()) | 370 | const core::ubuntu::media::Player::HeadersType& headers = core::ubuntu::media::Player::HeadersType(), |
271 | 371 | bool do_pipeline_reset) | ||
272 | 369 | { | 372 | { |
274 | 370 | reset_pipeline(); | 373 | if (do_pipeline_reset) |
275 | 374 | reset_pipeline(); | ||
276 | 371 | 375 | ||
277 | 372 | g_object_set(pipeline, "uri", uri.c_str(), NULL); | 376 | g_object_set(pipeline, "uri", uri.c_str(), NULL); |
278 | 373 | if (is_video_file(uri)) | 377 | if (is_video_file(uri)) |
279 | 374 | 378 | ||
280 | === modified file 'src/core/media/gstreamer/playbin.h' | |||
281 | --- src/core/media/gstreamer/playbin.h 2015-03-11 16:17:23 +0000 | |||
282 | +++ src/core/media/gstreamer/playbin.h 2015-04-20 17:49:07 +0000 | |||
283 | @@ -89,11 +89,13 @@ | |||
284 | 89 | uint64_t position() const; | 89 | uint64_t position() const; |
285 | 90 | uint64_t duration() const; | 90 | uint64_t duration() const; |
286 | 91 | 91 | ||
288 | 92 | void set_uri(const std::string& uri, const core::ubuntu::media::Player::HeadersType& headers); | 92 | void set_uri(const std::string& uri, const core::ubuntu::media::Player::HeadersType& headers, bool do_pipeline_reset = true); |
289 | 93 | std::string uri() const; | 93 | std::string uri() const; |
290 | 94 | 94 | ||
291 | 95 | void setup_source(GstElement *source); | 95 | void setup_source(GstElement *source); |
292 | 96 | 96 | ||
293 | 97 | // Sets the pipeline's state (stopped, playing, paused, etc). Optional parameter makes this call | ||
294 | 98 | // in the main_loop context. | ||
295 | 97 | bool set_state_and_wait(GstState new_state); | 99 | bool set_state_and_wait(GstState new_state); |
296 | 98 | bool seek(const std::chrono::microseconds& ms); | 100 | bool seek(const std::chrono::microseconds& ms); |
297 | 99 | 101 | ||
298 | 100 | 102 | ||
299 | === modified file 'src/core/media/mpris/player.h' | |||
300 | --- src/core/media/mpris/player.h 2015-03-11 16:17:23 +0000 | |||
301 | +++ src/core/media/mpris/player.h 2015-04-20 17:49:07 +0000 | |||
302 | @@ -271,7 +271,7 @@ | |||
303 | 271 | properties.orientation->set(core::ubuntu::media::Player::Orientation::rotate0); | 271 | properties.orientation->set(core::ubuntu::media::Player::Orientation::rotate0); |
304 | 272 | properties.lifetime->set(core::ubuntu::media::Player::Lifetime::normal); | 272 | properties.lifetime->set(core::ubuntu::media::Player::Lifetime::normal); |
305 | 273 | properties.playback_rate->set(configuration.defaults.playback_rate); | 273 | properties.playback_rate->set(configuration.defaults.playback_rate); |
307 | 274 | properties.is_shuffle->set(configuration.defaults.shuffle); | 274 | properties.shuffle->set(configuration.defaults.shuffle); |
308 | 275 | properties.position->set(configuration.defaults.position); | 275 | properties.position->set(configuration.defaults.position); |
309 | 276 | properties.duration->set(configuration.defaults.duration); | 276 | properties.duration->set(configuration.defaults.duration); |
310 | 277 | properties.minimum_playback_rate->set(configuration.defaults.minimum_rate); | 277 | properties.minimum_playback_rate->set(configuration.defaults.minimum_rate); |
311 | @@ -302,6 +302,11 @@ | |||
312 | 302 | { | 302 | { |
313 | 303 | on_property_value_changed<Properties::LoopStatus>(status); | 303 | on_property_value_changed<Properties::LoopStatus>(status); |
314 | 304 | }); | 304 | }); |
315 | 305 | |||
316 | 306 | properties.shuffle->changed().connect([this](bool shuffle) | ||
317 | 307 | { | ||
318 | 308 | on_property_value_changed<Properties::Shuffle>(shuffle); | ||
319 | 309 | }); | ||
320 | 305 | } | 310 | } |
321 | 306 | 311 | ||
322 | 307 | template<typename Property> | 312 | template<typename Property> |
323 | @@ -332,7 +337,7 @@ | |||
324 | 332 | dict[Properties::Orientation::name()] = dbus::types::Variant::encode(properties.orientation->get()); | 337 | dict[Properties::Orientation::name()] = dbus::types::Variant::encode(properties.orientation->get()); |
325 | 333 | dict[Properties::Lifetime::name()] = dbus::types::Variant::encode(properties.lifetime->get()); | 338 | dict[Properties::Lifetime::name()] = dbus::types::Variant::encode(properties.lifetime->get()); |
326 | 334 | dict[Properties::PlaybackRate::name()] = dbus::types::Variant::encode(properties.playback_rate->get()); | 339 | dict[Properties::PlaybackRate::name()] = dbus::types::Variant::encode(properties.playback_rate->get()); |
328 | 335 | dict[Properties::Shuffle::name()] = dbus::types::Variant::encode(properties.is_shuffle->get()); | 340 | dict[Properties::Shuffle::name()] = dbus::types::Variant::encode(properties.shuffle->get()); |
329 | 336 | dict[Properties::Duration::name()] = dbus::types::Variant::encode(properties.duration->get()); | 341 | dict[Properties::Duration::name()] = dbus::types::Variant::encode(properties.duration->get()); |
330 | 337 | dict[Properties::Position::name()] = dbus::types::Variant::encode(properties.position->get()); | 342 | dict[Properties::Position::name()] = dbus::types::Variant::encode(properties.position->get()); |
331 | 338 | dict[Properties::MinimumRate::name()] = dbus::types::Variant::encode(properties.minimum_playback_rate->get()); | 343 | dict[Properties::MinimumRate::name()] = dbus::types::Variant::encode(properties.minimum_playback_rate->get()); |
332 | @@ -363,7 +368,7 @@ | |||
333 | 363 | std::shared_ptr<core::dbus::Property<Properties::Orientation>> orientation; | 368 | std::shared_ptr<core::dbus::Property<Properties::Orientation>> orientation; |
334 | 364 | std::shared_ptr<core::dbus::Property<Properties::Lifetime>> lifetime; | 369 | std::shared_ptr<core::dbus::Property<Properties::Lifetime>> lifetime; |
335 | 365 | std::shared_ptr<core::dbus::Property<Properties::PlaybackRate>> playback_rate; | 370 | std::shared_ptr<core::dbus::Property<Properties::PlaybackRate>> playback_rate; |
337 | 366 | std::shared_ptr<core::dbus::Property<Properties::Shuffle>> is_shuffle; | 371 | std::shared_ptr<core::dbus::Property<Properties::Shuffle>> shuffle; |
338 | 367 | std::shared_ptr<core::dbus::Property<Properties::TypedMetaData>> typed_meta_data_for_current_track; | 372 | std::shared_ptr<core::dbus::Property<Properties::TypedMetaData>> typed_meta_data_for_current_track; |
339 | 368 | std::shared_ptr<core::dbus::Property<Properties::Volume>> volume; | 373 | std::shared_ptr<core::dbus::Property<Properties::Volume>> volume; |
340 | 369 | std::shared_ptr<core::dbus::Property<Properties::Position>> position; | 374 | std::shared_ptr<core::dbus::Property<Properties::Position>> position; |
341 | 370 | 375 | ||
342 | === modified file 'src/core/media/mpris/track_list.h' | |||
343 | --- src/core/media/mpris/track_list.h 2014-08-25 10:18:32 +0000 | |||
344 | +++ src/core/media/mpris/track_list.h 2015-04-20 17:49:07 +0000 | |||
345 | @@ -22,7 +22,10 @@ | |||
346 | 22 | #include <core/dbus/macros.h> | 22 | #include <core/dbus/macros.h> |
347 | 23 | 23 | ||
348 | 24 | #include <core/dbus/types/any.h> | 24 | #include <core/dbus/types/any.h> |
349 | 25 | #include <core/dbus/macros.h> | ||
350 | 25 | #include <core/dbus/types/object_path.h> | 26 | #include <core/dbus/types/object_path.h> |
351 | 27 | #include <core/dbus/object.h> | ||
352 | 28 | #include <core/dbus/property.h> | ||
353 | 26 | #include <core/dbus/types/variant.h> | 29 | #include <core/dbus/types/variant.h> |
354 | 27 | 30 | ||
355 | 28 | #include <boost/utility/identity_type.hpp> | 31 | #include <boost/utility/identity_type.hpp> |
356 | @@ -37,38 +40,42 @@ | |||
357 | 37 | { | 40 | { |
358 | 38 | struct TrackList | 41 | struct TrackList |
359 | 39 | { | 42 | { |
360 | 43 | typedef std::map<std::string, core::dbus::types::Variant> Dictionary; | ||
361 | 44 | |||
362 | 40 | static const std::string& name() | 45 | static const std::string& name() |
363 | 41 | { | 46 | { |
365 | 42 | static const std::string s{"core.ubuntu.media.Service.Player.TrackList"}; | 47 | static const std::string s{"org.mpris.MediaPlayer2.TrackList"}; |
366 | 43 | return s; | 48 | return s; |
367 | 44 | } | 49 | } |
368 | 45 | 50 | ||
373 | 46 | DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(GetTracksMetadata, TrackList, 1000) | 51 | DBUS_CPP_METHOD_DEF(GetTracksMetadata, TrackList) |
374 | 47 | DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(AddTrack, TrackList, 1000) | 52 | DBUS_CPP_METHOD_DEF(AddTrack, TrackList) |
375 | 48 | DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(RemoveTrack, TrackList, 1000) | 53 | DBUS_CPP_METHOD_DEF(RemoveTrack, TrackList) |
376 | 49 | DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(GoTo, TrackList, 1000) | 54 | DBUS_CPP_METHOD_DEF(GoTo, TrackList) |
377 | 50 | 55 | ||
378 | 51 | struct Signals | 56 | struct Signals |
379 | 52 | { | 57 | { |
380 | 58 | Signals() = delete; | ||
381 | 59 | |||
382 | 53 | DBUS_CPP_SIGNAL_DEF | 60 | DBUS_CPP_SIGNAL_DEF |
383 | 54 | ( | 61 | ( |
384 | 55 | TrackListReplaced, | 62 | TrackListReplaced, |
385 | 56 | TrackList, | 63 | TrackList, |
387 | 57 | BOOST_IDENTITY_TYPE((std::tuple<std::vector<dbus::types::ObjectPath>, dbus::types::ObjectPath>)) | 64 | BOOST_IDENTITY_TYPE((std::tuple<std::vector<core::ubuntu::media::Track::Id>, core::ubuntu::media::Track::Id>)) |
388 | 58 | ) | 65 | ) |
389 | 59 | 66 | ||
390 | 60 | DBUS_CPP_SIGNAL_DEF | 67 | DBUS_CPP_SIGNAL_DEF |
391 | 61 | ( | 68 | ( |
392 | 62 | TrackAdded, | 69 | TrackAdded, |
393 | 63 | TrackList, | 70 | TrackList, |
395 | 64 | BOOST_IDENTITY_TYPE((std::tuple<std::map<std::string, dbus::types::Variant>, dbus::types::ObjectPath>)) | 71 | core::ubuntu::media::Track::Id |
396 | 65 | ) | 72 | ) |
397 | 66 | 73 | ||
398 | 67 | DBUS_CPP_SIGNAL_DEF | 74 | DBUS_CPP_SIGNAL_DEF |
399 | 68 | ( | 75 | ( |
400 | 69 | TrackRemoved, | 76 | TrackRemoved, |
401 | 70 | TrackList, | 77 | TrackList, |
403 | 71 | dbus::types::ObjectPath | 78 | core::ubuntu::media::Track::Id |
404 | 72 | ) | 79 | ) |
405 | 73 | 80 | ||
406 | 74 | DBUS_CPP_SIGNAL_DEF | 81 | DBUS_CPP_SIGNAL_DEF |
407 | @@ -81,9 +88,94 @@ | |||
408 | 81 | 88 | ||
409 | 82 | struct Properties | 89 | struct Properties |
410 | 83 | { | 90 | { |
412 | 84 | DBUS_CPP_READABLE_PROPERTY_DEF(Tracks, TrackList, std::vector<std::string>) | 91 | Properties() = delete; |
413 | 92 | |||
414 | 93 | DBUS_CPP_READABLE_PROPERTY_DEF(Tracks, TrackList, std::vector<core::ubuntu::media::Track::Id>) | ||
415 | 85 | DBUS_CPP_READABLE_PROPERTY_DEF(CanEditTracks, TrackList, bool) | 94 | DBUS_CPP_READABLE_PROPERTY_DEF(CanEditTracks, TrackList, bool) |
416 | 86 | }; | 95 | }; |
417 | 96 | |||
418 | 97 | struct Skeleton | ||
419 | 98 | { | ||
420 | 99 | static const std::vector<std::string>& the_empty_list_of_invalidated_properties() | ||
421 | 100 | { | ||
422 | 101 | static const std::vector<std::string> instance; return instance; | ||
423 | 102 | } | ||
424 | 103 | |||
425 | 104 | // Object instance creation time properties go here. | ||
426 | 105 | struct Configuration | ||
427 | 106 | { | ||
428 | 107 | // The dbus object that should implement org.mpris.MediaPlayer2 | ||
429 | 108 | core::dbus::Object::Ptr object; | ||
430 | 109 | // Default values assigned to exported dbus interface properties on construction | ||
431 | 110 | struct Defaults | ||
432 | 111 | { | ||
433 | 112 | Properties::Tracks::ValueType tracks{std::vector<core::ubuntu::media::Track::Id>()}; | ||
434 | 113 | Properties::CanEditTracks::ValueType can_edit_tracks{true}; | ||
435 | 114 | } defaults; | ||
436 | 115 | }; | ||
437 | 116 | |||
438 | 117 | Skeleton(const Configuration& configuration) | ||
439 | 118 | : configuration(configuration), | ||
440 | 119 | properties | ||
441 | 120 | { | ||
442 | 121 | configuration.object->get_property<Properties::Tracks>(), | ||
443 | 122 | configuration.object->get_property<Properties::CanEditTracks>(), | ||
444 | 123 | }, | ||
445 | 124 | signals | ||
446 | 125 | { | ||
447 | 126 | configuration.object->get_signal<Signals::TrackListReplaced>(), | ||
448 | 127 | configuration.object->get_signal<Signals::TrackAdded>(), | ||
449 | 128 | configuration.object->get_signal<Signals::TrackRemoved>(), | ||
450 | 129 | configuration.object->get_signal<Signals::TrackMetadataChanged>(), | ||
451 | 130 | configuration.object->template get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>() | ||
452 | 131 | } | ||
453 | 132 | { | ||
454 | 133 | // Set the default value of the properties on the MPRIS TrackList dbus interface | ||
455 | 134 | properties.tracks->set(configuration.defaults.tracks); | ||
456 | 135 | properties.can_edit_tracks->set(configuration.defaults.can_edit_tracks); | ||
457 | 136 | } | ||
458 | 137 | |||
459 | 138 | template<typename Property> | ||
460 | 139 | void on_property_value_changed(const typename Property::ValueType& value) | ||
461 | 140 | { | ||
462 | 141 | Dictionary dict; | ||
463 | 142 | dict[Property::name()] = dbus::types::Variant::encode(value); | ||
464 | 143 | |||
465 | 144 | signals.properties_changed->emit(std::make_tuple( | ||
466 | 145 | dbus::traits::Service<TrackList>::interface_name(), | ||
467 | 146 | dict, | ||
468 | 147 | the_empty_list_of_invalidated_properties())); | ||
469 | 148 | } | ||
470 | 149 | |||
471 | 150 | std::map<std::string, core::dbus::types::Variant> get_all_properties() | ||
472 | 151 | { | ||
473 | 152 | std::map<std::string, core::dbus::types::Variant> dict; | ||
474 | 153 | dict[Properties::Tracks::name()] = core::dbus::types::Variant::encode(properties.tracks->get()); | ||
475 | 154 | dict[Properties::CanEditTracks::name()] = core::dbus::types::Variant::encode(properties.can_edit_tracks->get()); | ||
476 | 155 | |||
477 | 156 | return dict; | ||
478 | 157 | } | ||
479 | 158 | |||
480 | 159 | Configuration configuration; | ||
481 | 160 | |||
482 | 161 | struct | ||
483 | 162 | { | ||
484 | 163 | std::shared_ptr<core::dbus::Property<Properties::Tracks>> tracks; | ||
485 | 164 | std::shared_ptr<core::dbus::Property<Properties::CanEditTracks>> can_edit_tracks; | ||
486 | 165 | } properties; | ||
487 | 166 | |||
488 | 167 | struct | ||
489 | 168 | { | ||
490 | 169 | core::dbus::Signal<Signals::TrackListReplaced, Signals::TrackListReplaced::ArgumentType>::Ptr tracklist_replaced; | ||
491 | 170 | core::dbus::Signal<Signals::TrackAdded, Signals::TrackAdded::ArgumentType>::Ptr track_added; | ||
492 | 171 | core::dbus::Signal<Signals::TrackRemoved, Signals::TrackRemoved::ArgumentType>::Ptr track_removed; | ||
493 | 172 | core::dbus::Signal<Signals::TrackMetadataChanged, Signals::TrackMetadataChanged::ArgumentType>::Ptr track_metadata_changed; | ||
494 | 173 | |||
495 | 174 | dbus::Signal <core::dbus::interfaces::Properties::Signals::PropertiesChanged, | ||
496 | 175 | core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType | ||
497 | 176 | >::Ptr properties_changed; | ||
498 | 177 | } signals; | ||
499 | 178 | }; | ||
500 | 87 | }; | 179 | }; |
501 | 88 | } | 180 | } |
502 | 89 | 181 | ||
503 | 90 | 182 | ||
504 | === modified file 'src/core/media/player_configuration.h' | |||
505 | --- src/core/media/player_configuration.h 2014-11-26 16:23:19 +0000 | |||
506 | +++ src/core/media/player_configuration.h 2015-04-20 17:49:07 +0000 | |||
507 | @@ -31,6 +31,8 @@ | |||
508 | 31 | core::ubuntu::media::Player::PlayerKey key; | 31 | core::ubuntu::media::Player::PlayerKey key; |
509 | 32 | // The bus connection to expose objects on. | 32 | // The bus connection to expose objects on. |
510 | 33 | std::shared_ptr<core::dbus::Bus> bus; | 33 | std::shared_ptr<core::dbus::Bus> bus; |
511 | 34 | // The service instance we live under. | ||
512 | 35 | std::shared_ptr<core::dbus::Service> service; | ||
513 | 34 | // The actual session object representing a player instance. | 36 | // The actual session object representing a player instance. |
514 | 35 | std::shared_ptr<core::dbus::Object> session; | 37 | std::shared_ptr<core::dbus::Object> session; |
515 | 36 | }; | 38 | }; |
516 | 37 | 39 | ||
517 | === modified file 'src/core/media/player_implementation.cpp' | |||
518 | --- src/core/media/player_implementation.cpp 2015-03-19 19:08:47 +0000 | |||
519 | +++ src/core/media/player_implementation.cpp 2015-04-20 17:49:07 +0000 | |||
520 | @@ -1,4 +1,5 @@ | |||
521 | 1 | /* | 1 | /* |
522 | 2 | * Copyright © 2013-2015 Canonical Ltd. | ||
523 | 2 | * | 3 | * |
524 | 3 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
525 | 4 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
526 | @@ -23,7 +24,6 @@ | |||
527 | 23 | 24 | ||
528 | 24 | #include "client_death_observer.h" | 25 | #include "client_death_observer.h" |
529 | 25 | #include "engine.h" | 26 | #include "engine.h" |
530 | 26 | #include "null_track_list.h" | ||
531 | 27 | #include "track_list_implementation.h" | 27 | #include "track_list_implementation.h" |
532 | 28 | 28 | ||
533 | 29 | #include "gstreamer/engine.h" | 29 | #include "gstreamer/engine.h" |
534 | @@ -58,14 +58,20 @@ | |||
535 | 58 | display_state_lock(config.power_state_controller->display_state_lock()), | 58 | display_state_lock(config.power_state_controller->display_state_lock()), |
536 | 59 | system_state_lock(config.power_state_controller->system_state_lock()), | 59 | system_state_lock(config.power_state_controller->system_state_lock()), |
537 | 60 | engine(std::make_shared<gstreamer::Engine>()), | 60 | engine(std::make_shared<gstreamer::Engine>()), |
539 | 61 | track_list(std::make_shared<NullTrackList>()), | 61 | track_list(std::make_shared<TrackListImplementation>( |
540 | 62 | config.parent.bus, | ||
541 | 63 | config.parent.service->add_object_for_path( | ||
542 | 64 | dbus::types::ObjectPath(config.parent.session->path().as_string() + "/TrackList")), | ||
543 | 65 | engine->meta_data_extractor(), | ||
544 | 66 | config.parent.request_context_resolver, | ||
545 | 67 | config.parent.request_authenticator)), | ||
546 | 62 | system_wakelock_count(0), | 68 | system_wakelock_count(0), |
547 | 63 | display_wakelock_count(0), | 69 | display_wakelock_count(0), |
548 | 64 | previous_state(Engine::State::stopped), | 70 | previous_state(Engine::State::stopped), |
549 | 65 | engine_state_change_connection(engine->state().changed().connect(make_state_change_handler())), | 71 | engine_state_change_connection(engine->state().changed().connect(make_state_change_handler())), |
551 | 66 | engine_playback_status_change_connection(engine->playback_status_changed_signal().connect(make_playback_status_change_handler())) | 72 | engine_playback_status_change_connection(engine->playback_status_changed_signal().connect(make_playback_status_change_handler())), |
552 | 73 | doing_go_to_track(false) | ||
553 | 67 | { | 74 | { |
554 | 68 | std::cout << "Private parent instance: " << parent << std::endl; | ||
555 | 69 | // Poor man's logging of release/acquire events. | 75 | // Poor man's logging of release/acquire events. |
556 | 70 | display_state_lock->acquired().connect([](media::power::DisplayState state) | 76 | display_state_lock->acquired().connect([](media::power::DisplayState state) |
557 | 71 | { | 77 | { |
558 | @@ -99,7 +105,6 @@ | |||
559 | 99 | // by disconnecting the state change signal | 105 | // by disconnecting the state change signal |
560 | 100 | engine_state_change_connection.disconnect(); | 106 | engine_state_change_connection.disconnect(); |
561 | 101 | 107 | ||
562 | 102 | std::cout << "** Disconnecting playback_status_changed_signal connection"; | ||
563 | 103 | // The engine destructor can lead to a playback status change which will | 108 | // The engine destructor can lead to a playback status change which will |
564 | 104 | // trigger the playback status change handler. Ensure the handler is not called | 109 | // trigger the playback status change handler. Ensure the handler is not called |
565 | 105 | // by disconnecting the playback status change signal | 110 | // by disconnecting the playback status change signal |
566 | @@ -169,7 +174,7 @@ | |||
567 | 169 | { | 174 | { |
568 | 170 | return [this](const media::Player::PlaybackStatus& status) | 175 | return [this](const media::Player::PlaybackStatus& status) |
569 | 171 | { | 176 | { |
571 | 172 | std::cout << "Emiting playback_status_changed for parent: " << parent << std::endl; | 177 | std::cout << "Emiting playback_status_changed signal: " << status << std::endl; |
572 | 173 | parent->emit_playback_status_changed(status); | 178 | parent->emit_playback_status_changed(status); |
573 | 174 | }; | 179 | }; |
574 | 175 | } | 180 | } |
575 | @@ -290,13 +295,15 @@ | |||
576 | 290 | media::power::StateController::Lock<media::power::SystemState>::Ptr system_state_lock; | 295 | media::power::StateController::Lock<media::power::SystemState>::Ptr system_state_lock; |
577 | 291 | 296 | ||
578 | 292 | std::shared_ptr<Engine> engine; | 297 | std::shared_ptr<Engine> engine; |
580 | 293 | std::shared_ptr<media::NullTrackList> track_list; | 298 | std::shared_ptr<media::TrackListImplementation> track_list; |
581 | 294 | std::atomic<int> system_wakelock_count; | 299 | std::atomic<int> system_wakelock_count; |
582 | 295 | std::atomic<int> display_wakelock_count; | 300 | std::atomic<int> display_wakelock_count; |
583 | 296 | Engine::State previous_state; | 301 | Engine::State previous_state; |
584 | 297 | core::Signal<> on_client_disconnected; | 302 | core::Signal<> on_client_disconnected; |
585 | 298 | core::Connection engine_state_change_connection; | 303 | core::Connection engine_state_change_connection; |
586 | 299 | core::Connection engine_playback_status_change_connection; | 304 | core::Connection engine_playback_status_change_connection; |
587 | 305 | // Prevent the TrackList from auto advancing to the next track | ||
588 | 306 | std::atomic<bool> doing_go_to_track; | ||
589 | 300 | }; | 307 | }; |
590 | 301 | 308 | ||
591 | 302 | template<typename Parent> | 309 | template<typename Parent> |
592 | @@ -312,7 +319,7 @@ | |||
593 | 312 | Parent::can_go_next().set(true); | 319 | Parent::can_go_next().set(true); |
594 | 313 | Parent::is_video_source().set(false); | 320 | Parent::is_video_source().set(false); |
595 | 314 | Parent::is_audio_source().set(false); | 321 | Parent::is_audio_source().set(false); |
597 | 315 | Parent::is_shuffle().set(true); | 322 | Parent::shuffle().set(false); |
598 | 316 | Parent::playback_rate().set(1.f); | 323 | Parent::playback_rate().set(1.f); |
599 | 317 | Parent::playback_status().set(Player::PlaybackStatus::null); | 324 | Parent::playback_status().set(Player::PlaybackStatus::null); |
600 | 318 | Parent::loop_status().set(Player::LoopStatus::none); | 325 | Parent::loop_status().set(Player::LoopStatus::none); |
601 | @@ -352,6 +359,18 @@ | |||
602 | 352 | }; | 359 | }; |
603 | 353 | Parent::is_audio_source().install(audio_type_getter); | 360 | Parent::is_audio_source().install(audio_type_getter); |
604 | 354 | 361 | ||
605 | 362 | // When the client changes the loop status, make sure to update the TrackList | ||
606 | 363 | Parent::loop_status().changed().connect([this](media::Player::LoopStatus loop_status) | ||
607 | 364 | { | ||
608 | 365 | d->track_list->on_loop_status_changed(loop_status); | ||
609 | 366 | }); | ||
610 | 367 | |||
611 | 368 | // When the client changes the shuffle setting, make sure to update the TrackList | ||
612 | 369 | Parent::shuffle().changed().connect([this](bool shuffle) | ||
613 | 370 | { | ||
614 | 371 | d->track_list->on_shuffle_changed(shuffle); | ||
615 | 372 | }); | ||
616 | 373 | |||
617 | 355 | // Make sure that the audio_stream_role property gets updated on the Engine side | 374 | // Make sure that the audio_stream_role property gets updated on the Engine side |
618 | 356 | // whenever the client side sets the role | 375 | // whenever the client side sets the role |
619 | 357 | Parent::audio_stream_role().changed().connect([this](media::Player::AudioStreamRole new_role) | 376 | Parent::audio_stream_role().changed().connect([this](media::Player::AudioStreamRole new_role) |
620 | @@ -375,12 +394,21 @@ | |||
621 | 375 | { | 394 | { |
622 | 376 | Parent::about_to_finish()(); | 395 | Parent::about_to_finish()(); |
623 | 377 | 396 | ||
625 | 378 | if (d->track_list->has_next()) | 397 | if (!d->doing_go_to_track) |
626 | 379 | { | 398 | { |
630 | 380 | Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next()); | 399 | const media::Track::Id prev_track_id = d->track_list->current(); |
631 | 381 | if (!uri.empty()) | 400 | // Make sure that the TrackList keeps advancing. The logic for what gets played next, |
632 | 382 | d->parent->open_uri(uri); | 401 | // if anything at all, occurs in TrackListSkeleton::next() |
633 | 402 | const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next()); | ||
634 | 403 | if (prev_track_id != d->track_list->current() && !uri.empty()) | ||
635 | 404 | { | ||
636 | 405 | std::cout << "Setting next track on playbin: " << uri << std::endl; | ||
637 | 406 | static const bool do_pipeline_reset = false; | ||
638 | 407 | d->engine->open_resource_for_uri(uri, do_pipeline_reset); | ||
639 | 408 | } | ||
640 | 383 | } | 409 | } |
641 | 410 | else | ||
642 | 411 | std::cout << "Not auto-advancing the TrackList since doing_go_to_track is true" << std::endl; | ||
643 | 384 | }); | 412 | }); |
644 | 385 | 413 | ||
645 | 386 | d->engine->client_disconnected_signal().connect([this]() | 414 | d->engine->client_disconnected_signal().connect([this]() |
646 | @@ -388,6 +416,7 @@ | |||
647 | 388 | // If the client disconnects, make sure both wakelock types | 416 | // If the client disconnects, make sure both wakelock types |
648 | 389 | // are cleared | 417 | // are cleared |
649 | 390 | d->clear_wakelocks(); | 418 | d->clear_wakelocks(); |
650 | 419 | d->track_list->reset(); | ||
651 | 391 | // And tell the outside world that the client has gone away | 420 | // And tell the outside world that the client has gone away |
652 | 392 | d->on_client_disconnected(); | 421 | d->on_client_disconnected(); |
653 | 393 | }); | 422 | }); |
654 | @@ -412,6 +441,33 @@ | |||
655 | 412 | Parent::error()(e); | 441 | Parent::error()(e); |
656 | 413 | }); | 442 | }); |
657 | 414 | 443 | ||
658 | 444 | d->track_list->on_go_to_track().connect([this](std::pair<const media::Track::Id, bool> p) | ||
659 | 445 | { | ||
660 | 446 | // This prevents the TrackList from auto advancing in other areas such as the about_to_finish signal | ||
661 | 447 | // handler. | ||
662 | 448 | d->doing_go_to_track = true; | ||
663 | 449 | |||
664 | 450 | const media::Track::Id id = p.first; | ||
665 | 451 | const bool toggle_player_state = p.second; | ||
666 | 452 | |||
667 | 453 | if (toggle_player_state) | ||
668 | 454 | d->engine->stop(); | ||
669 | 455 | |||
670 | 456 | const Track::UriType uri = d->track_list->query_uri_for_track(id); | ||
671 | 457 | if (!uri.empty()) | ||
672 | 458 | { | ||
673 | 459 | std::cout << "Setting next track on playbin (on_go_to_track signal): " << uri << std::endl; | ||
674 | 460 | std::cout << "\twith a Track::Id: " << id << std::endl; | ||
675 | 461 | static const bool do_pipeline_reset = true; | ||
676 | 462 | d->engine->open_resource_for_uri(uri, do_pipeline_reset); | ||
677 | 463 | } | ||
678 | 464 | |||
679 | 465 | if (toggle_player_state) | ||
680 | 466 | d->engine->play(); | ||
681 | 467 | |||
682 | 468 | d->doing_go_to_track = false; | ||
683 | 469 | }); | ||
684 | 470 | |||
685 | 415 | // Everything is setup, we now subscribe to death notifications. | 471 | // Everything is setup, we now subscribe to death notifications. |
686 | 416 | std::weak_ptr<Private> wp{d}; | 472 | std::weak_ptr<Private> wp{d}; |
687 | 417 | 473 | ||
688 | @@ -487,7 +543,9 @@ | |||
689 | 487 | template<typename Parent> | 543 | template<typename Parent> |
690 | 488 | bool media::PlayerImplementation<Parent>::open_uri(const Track::UriType& uri) | 544 | bool media::PlayerImplementation<Parent>::open_uri(const Track::UriType& uri) |
691 | 489 | { | 545 | { |
693 | 490 | return d->engine->open_resource_for_uri(uri); | 546 | // Set new track as the current track to play |
694 | 547 | d->track_list->add_track_with_uri_at(uri, media::TrackList::after_empty_track(), true); | ||
695 | 548 | return true; | ||
696 | 491 | } | 549 | } |
697 | 492 | 550 | ||
698 | 493 | template<typename Parent> | 551 | template<typename Parent> |
699 | @@ -509,6 +567,16 @@ | |||
700 | 509 | template<typename Parent> | 567 | template<typename Parent> |
701 | 510 | void media::PlayerImplementation<Parent>::play() | 568 | void media::PlayerImplementation<Parent>::play() |
702 | 511 | { | 569 | { |
703 | 570 | if (d->track_list != nullptr && d->track_list->tracks()->size() > 0 && d->engine->state() == media::Engine::State::no_media) | ||
704 | 571 | { | ||
705 | 572 | // Using a TrackList for playback, added tracks via add_track(), but open_uri hasn't been called yet | ||
706 | 573 | // to load a media resource | ||
707 | 574 | std::cout << "No media loaded yet, calling open_uri on first track in track_list" << std::endl; | ||
708 | 575 | static const bool do_pipeline_reset = true; | ||
709 | 576 | d->engine->open_resource_for_uri(d->track_list->query_uri_for_track(d->track_list->current()), do_pipeline_reset); | ||
710 | 577 | std::cout << *d->track_list << endl; | ||
711 | 578 | } | ||
712 | 579 | |||
713 | 512 | d->engine->play(); | 580 | d->engine->play(); |
714 | 513 | } | 581 | } |
715 | 514 | 582 | ||
716 | 515 | 583 | ||
717 | === modified file 'src/core/media/player_implementation.h' | |||
718 | --- src/core/media/player_implementation.h 2015-03-19 19:08:47 +0000 | |||
719 | +++ src/core/media/player_implementation.h 2015-04-20 17:49:07 +0000 | |||
720 | @@ -78,8 +78,8 @@ | |||
721 | 78 | struct Private; | 78 | struct Private; |
722 | 79 | std::shared_ptr<Private> d; | 79 | std::shared_ptr<Private> d; |
723 | 80 | }; | 80 | }; |
724 | 81 | |||
725 | 81 | } | 82 | } |
726 | 82 | } | 83 | } |
727 | 83 | } | 84 | } |
728 | 84 | #endif // CORE_UBUNTU_MEDIA_PLAYER_IMPLEMENTATION_H_ | 85 | #endif // CORE_UBUNTU_MEDIA_PLAYER_IMPLEMENTATION_H_ |
729 | 85 | |||
730 | 86 | 86 | ||
731 | === modified file 'src/core/media/player_skeleton.cpp' | |||
732 | --- src/core/media/player_skeleton.cpp 2015-03-11 16:17:23 +0000 | |||
733 | +++ src/core/media/player_skeleton.cpp 2015-04-20 17:49:07 +0000 | |||
734 | @@ -179,6 +179,7 @@ | |||
735 | 179 | Track::UriType uri; | 179 | Track::UriType uri; |
736 | 180 | in->reader() >> uri; | 180 | in->reader() >> uri; |
737 | 181 | 181 | ||
738 | 182 | // Make sure the client has adequate apparmor permissions to open the URI | ||
739 | 182 | auto result = request_authenticator->authenticate_open_uri_request(context, uri); | 183 | auto result = request_authenticator->authenticate_open_uri_request(context, uri); |
740 | 183 | 184 | ||
741 | 184 | auto reply = dbus::Message::make_method_return(in); | 185 | auto reply = dbus::Message::make_method_return(in); |
742 | @@ -407,9 +408,9 @@ | |||
743 | 407 | return *d->skeleton.properties.playback_rate; | 408 | return *d->skeleton.properties.playback_rate; |
744 | 408 | } | 409 | } |
745 | 409 | 410 | ||
747 | 410 | const core::Property<bool>& media::PlayerSkeleton::is_shuffle() const | 411 | const core::Property<bool>& media::PlayerSkeleton::shuffle() const |
748 | 411 | { | 412 | { |
750 | 412 | return *d->skeleton.properties.is_shuffle; | 413 | return *d->skeleton.properties.shuffle; |
751 | 413 | } | 414 | } |
752 | 414 | 415 | ||
753 | 415 | const core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() const | 416 | const core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() const |
754 | @@ -467,9 +468,9 @@ | |||
755 | 467 | return *d->skeleton.properties.playback_rate; | 468 | return *d->skeleton.properties.playback_rate; |
756 | 468 | } | 469 | } |
757 | 469 | 470 | ||
759 | 470 | core::Property<bool>& media::PlayerSkeleton::is_shuffle() | 471 | core::Property<bool>& media::PlayerSkeleton::shuffle() |
760 | 471 | { | 472 | { |
762 | 472 | return *d->skeleton.properties.is_shuffle; | 473 | return *d->skeleton.properties.shuffle; |
763 | 473 | } | 474 | } |
764 | 474 | 475 | ||
765 | 475 | core::Property<media::Player::Volume>& media::PlayerSkeleton::volume() | 476 | core::Property<media::Player::Volume>& media::PlayerSkeleton::volume() |
766 | 476 | 477 | ||
767 | === modified file 'src/core/media/player_skeleton.h' | |||
768 | --- src/core/media/player_skeleton.h 2015-03-11 16:17:23 +0000 | |||
769 | +++ src/core/media/player_skeleton.h 2015-04-20 17:49:07 +0000 | |||
770 | @@ -53,6 +53,8 @@ | |||
771 | 53 | { | 53 | { |
772 | 54 | // The bus connection we are associated with. | 54 | // The bus connection we are associated with. |
773 | 55 | std::shared_ptr<core::dbus::Bus> bus; | 55 | std::shared_ptr<core::dbus::Bus> bus; |
774 | 56 | // The service instance we are exposed under. | ||
775 | 57 | std::shared_ptr<core::dbus::Service> service; | ||
776 | 56 | // The session object that we want to expose the skeleton upon. | 58 | // The session object that we want to expose the skeleton upon. |
777 | 57 | std::shared_ptr<core::dbus::Object> session; | 59 | std::shared_ptr<core::dbus::Object> session; |
778 | 58 | // Our functional dependencies. | 60 | // Our functional dependencies. |
779 | @@ -73,7 +75,7 @@ | |||
780 | 73 | virtual const core::Property<PlaybackStatus>& playback_status() const; | 75 | virtual const core::Property<PlaybackStatus>& playback_status() const; |
781 | 74 | virtual const core::Property<LoopStatus>& loop_status() const; | 76 | virtual const core::Property<LoopStatus>& loop_status() const; |
782 | 75 | virtual const core::Property<PlaybackRate>& playback_rate() const; | 77 | virtual const core::Property<PlaybackRate>& playback_rate() const; |
784 | 76 | virtual const core::Property<bool>& is_shuffle() const; | 78 | virtual const core::Property<bool>& shuffle() const; |
785 | 77 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const; | 79 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const; |
786 | 78 | virtual const core::Property<Volume>& volume() const; | 80 | virtual const core::Property<Volume>& volume() const; |
787 | 79 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const; | 81 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const; |
788 | @@ -86,7 +88,7 @@ | |||
789 | 86 | 88 | ||
790 | 87 | virtual core::Property<LoopStatus>& loop_status(); | 89 | virtual core::Property<LoopStatus>& loop_status(); |
791 | 88 | virtual core::Property<PlaybackRate>& playback_rate(); | 90 | virtual core::Property<PlaybackRate>& playback_rate(); |
793 | 89 | virtual core::Property<bool>& is_shuffle(); | 91 | virtual core::Property<bool>& shuffle(); |
794 | 90 | virtual core::Property<Volume>& volume(); | 92 | virtual core::Property<Volume>& volume(); |
795 | 91 | virtual core::Property<AudioStreamRole>& audio_stream_role(); | 93 | virtual core::Property<AudioStreamRole>& audio_stream_role(); |
796 | 92 | virtual core::Property<Lifetime>& lifetime(); | 94 | virtual core::Property<Lifetime>& lifetime(); |
797 | 93 | 95 | ||
798 | === modified file 'src/core/media/player_stub.cpp' | |||
799 | --- src/core/media/player_stub.cpp 2015-03-16 14:54:47 +0000 | |||
800 | +++ src/core/media/player_stub.cpp 2015-04-20 17:49:07 +0000 | |||
801 | @@ -43,8 +43,10 @@ | |||
802 | 43 | struct media::PlayerStub::Private | 43 | struct media::PlayerStub::Private |
803 | 44 | { | 44 | { |
804 | 45 | Private(const std::shared_ptr<Service>& parent, | 45 | Private(const std::shared_ptr<Service>& parent, |
805 | 46 | const std::shared_ptr<core::dbus::Service>& service, | ||
806 | 46 | const std::shared_ptr<core::dbus::Object>& object | 47 | const std::shared_ptr<core::dbus::Object>& object |
807 | 47 | ) : parent(parent), | 48 | ) : parent(parent), |
808 | 49 | service(service), | ||
809 | 48 | object(object), | 50 | object(object), |
810 | 49 | key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()), | 51 | key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()), |
811 | 50 | sink_factory(media::video::make_platform_default_sink_factory(key)), | 52 | sink_factory(media::video::make_platform_default_sink_factory(key)), |
812 | @@ -91,6 +93,7 @@ | |||
813 | 91 | 93 | ||
814 | 92 | std::shared_ptr<Service> parent; | 94 | std::shared_ptr<Service> parent; |
815 | 93 | std::shared_ptr<TrackList> track_list; | 95 | std::shared_ptr<TrackList> track_list; |
816 | 96 | dbus::Service::Ptr service; | ||
817 | 94 | dbus::Object::Ptr object; | 97 | dbus::Object::Ptr object; |
818 | 95 | media::Player::PlayerKey key; | 98 | media::Player::PlayerKey key; |
819 | 96 | media::video::SinkFactory sink_factory; | 99 | media::video::SinkFactory sink_factory; |
820 | @@ -108,7 +111,7 @@ | |||
821 | 108 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedPlaybackStatus>> playback_status; | 111 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedPlaybackStatus>> playback_status; |
822 | 109 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedLoopStatus>> loop_status; | 112 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedLoopStatus>> loop_status; |
823 | 110 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackRate>> playback_rate; | 113 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackRate>> playback_rate; |
825 | 111 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Shuffle>> is_shuffle; | 114 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Shuffle>> shuffle; |
826 | 112 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedMetaData>> meta_data_for_current_track; | 115 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedMetaData>> meta_data_for_current_track; |
827 | 113 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Volume>> volume; | 116 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Volume>> volume; |
828 | 114 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Position>> position; | 117 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Position>> position; |
829 | @@ -153,7 +156,7 @@ | |||
830 | 153 | { | 156 | { |
831 | 154 | dbus.seeked_to->connect([this](std::uint64_t value) | 157 | dbus.seeked_to->connect([this](std::uint64_t value) |
832 | 155 | { | 158 | { |
834 | 156 | std::cout << "seeked_to signal arrived via the bus." << std::endl; | 159 | std::cout << "SeekedTo signal arrived via the bus." << std::endl; |
835 | 157 | seeked_to(value); | 160 | seeked_to(value); |
836 | 158 | }); | 161 | }); |
837 | 159 | 162 | ||
838 | @@ -209,8 +212,9 @@ | |||
839 | 209 | 212 | ||
840 | 210 | media::PlayerStub::PlayerStub( | 213 | media::PlayerStub::PlayerStub( |
841 | 211 | const std::shared_ptr<Service>& parent, | 214 | const std::shared_ptr<Service>& parent, |
842 | 215 | const std::shared_ptr<core::dbus::Service>& service, | ||
843 | 212 | const std::shared_ptr<core::dbus::Object>& object) | 216 | const std::shared_ptr<core::dbus::Object>& object) |
845 | 213 | : d(new Private{parent, object}) | 217 | : d(new Private{parent, service, object}) |
846 | 214 | { | 218 | { |
847 | 215 | } | 219 | } |
848 | 216 | 220 | ||
849 | @@ -224,7 +228,9 @@ | |||
850 | 224 | { | 228 | { |
851 | 225 | d->track_list = std::make_shared<media::TrackListStub>( | 229 | d->track_list = std::make_shared<media::TrackListStub>( |
852 | 226 | shared_from_this(), | 230 | shared_from_this(), |
854 | 227 | dbus::types::ObjectPath(d->object->path().as_string() + "/TrackList")); | 231 | d->service->object_for_path( |
855 | 232 | dbus::types::ObjectPath( | ||
856 | 233 | d->object->path().as_string() + "/TrackList"))); | ||
857 | 228 | } | 234 | } |
858 | 229 | return d->track_list; | 235 | return d->track_list; |
859 | 230 | } | 236 | } |
860 | @@ -362,9 +368,9 @@ | |||
861 | 362 | return *d->properties.playback_rate; | 368 | return *d->properties.playback_rate; |
862 | 363 | } | 369 | } |
863 | 364 | 370 | ||
865 | 365 | const core::Property<bool>& media::PlayerStub::is_shuffle() const | 371 | const core::Property<bool>& media::PlayerStub::shuffle() const |
866 | 366 | { | 372 | { |
868 | 367 | return *d->properties.is_shuffle; | 373 | return *d->properties.shuffle; |
869 | 368 | } | 374 | } |
870 | 369 | 375 | ||
871 | 370 | const core::Property<media::Track::MetaData>& media::PlayerStub::meta_data_for_current_track() const | 376 | const core::Property<media::Track::MetaData>& media::PlayerStub::meta_data_for_current_track() const |
872 | @@ -422,9 +428,9 @@ | |||
873 | 422 | return *d->properties.playback_rate; | 428 | return *d->properties.playback_rate; |
874 | 423 | } | 429 | } |
875 | 424 | 430 | ||
877 | 425 | core::Property<bool>& media::PlayerStub::is_shuffle() | 431 | core::Property<bool>& media::PlayerStub::shuffle() |
878 | 426 | { | 432 | { |
880 | 427 | return *d->properties.is_shuffle; | 433 | return *d->properties.shuffle; |
881 | 428 | } | 434 | } |
882 | 429 | 435 | ||
883 | 430 | core::Property<media::Player::Volume>& media::PlayerStub::volume() | 436 | core::Property<media::Player::Volume>& media::PlayerStub::volume() |
884 | 431 | 437 | ||
885 | === modified file 'src/core/media/player_stub.h' | |||
886 | --- src/core/media/player_stub.h 2015-03-11 16:17:23 +0000 | |||
887 | +++ src/core/media/player_stub.h 2015-04-20 17:49:07 +0000 | |||
888 | @@ -39,6 +39,7 @@ | |||
889 | 39 | public: | 39 | public: |
890 | 40 | explicit PlayerStub( | 40 | explicit PlayerStub( |
891 | 41 | const std::shared_ptr<Service>& parent, | 41 | const std::shared_ptr<Service>& parent, |
892 | 42 | const std::shared_ptr<core::dbus::Service>& service, | ||
893 | 42 | const std::shared_ptr<core::dbus::Object>& object); | 43 | const std::shared_ptr<core::dbus::Object>& object); |
894 | 43 | 44 | ||
895 | 44 | ~PlayerStub(); | 45 | ~PlayerStub(); |
896 | @@ -67,7 +68,7 @@ | |||
897 | 67 | virtual const core::Property<PlaybackStatus>& playback_status() const; | 68 | virtual const core::Property<PlaybackStatus>& playback_status() const; |
898 | 68 | virtual const core::Property<LoopStatus>& loop_status() const; | 69 | virtual const core::Property<LoopStatus>& loop_status() const; |
899 | 69 | virtual const core::Property<PlaybackRate>& playback_rate() const; | 70 | virtual const core::Property<PlaybackRate>& playback_rate() const; |
901 | 70 | virtual const core::Property<bool>& is_shuffle() const; | 71 | virtual const core::Property<bool>& shuffle() const; |
902 | 71 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const; | 72 | virtual const core::Property<Track::MetaData>& meta_data_for_current_track() const; |
903 | 72 | virtual const core::Property<Volume>& volume() const; | 73 | virtual const core::Property<Volume>& volume() const; |
904 | 73 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const; | 74 | virtual const core::Property<PlaybackRate>& minimum_playback_rate() const; |
905 | @@ -80,7 +81,7 @@ | |||
906 | 80 | 81 | ||
907 | 81 | virtual core::Property<LoopStatus>& loop_status(); | 82 | virtual core::Property<LoopStatus>& loop_status(); |
908 | 82 | virtual core::Property<PlaybackRate>& playback_rate(); | 83 | virtual core::Property<PlaybackRate>& playback_rate(); |
910 | 83 | virtual core::Property<bool>& is_shuffle(); | 84 | virtual core::Property<bool>& shuffle(); |
911 | 84 | virtual core::Property<Volume>& volume(); | 85 | virtual core::Property<Volume>& volume(); |
912 | 85 | virtual core::Property<AudioStreamRole>& audio_stream_role(); | 86 | virtual core::Property<AudioStreamRole>& audio_stream_role(); |
913 | 86 | virtual core::Property<Lifetime>& lifetime(); | 87 | virtual core::Property<Lifetime>& lifetime(); |
914 | 87 | 88 | ||
915 | === modified file 'src/core/media/service_implementation.cpp' | |||
916 | --- src/core/media/service_implementation.cpp 2015-04-02 14:46:52 +0000 | |||
917 | +++ src/core/media/service_implementation.cpp 2015-04-20 17:49:07 +0000 | |||
918 | @@ -53,6 +53,8 @@ | |||
919 | 53 | 53 | ||
920 | 54 | struct media::ServiceImplementation::Private | 54 | struct media::ServiceImplementation::Private |
921 | 55 | { | 55 | { |
922 | 56 | // Create all of the appropriate observers and helper class instances to be | ||
923 | 57 | // passed to the PlayerImplementation | ||
924 | 56 | Private(const ServiceImplementation::Configuration& configuration) | 58 | Private(const ServiceImplementation::Configuration& configuration) |
925 | 57 | : configuration(configuration), | 59 | : configuration(configuration), |
926 | 58 | resume_key(std::numeric_limits<std::uint32_t>::max()), | 60 | resume_key(std::numeric_limits<std::uint32_t>::max()), |
927 | @@ -72,7 +74,7 @@ | |||
928 | 72 | media::ServiceImplementation::Configuration configuration; | 74 | media::ServiceImplementation::Configuration configuration; |
929 | 73 | // This holds the key of the multimedia role Player instance that was paused | 75 | // This holds the key of the multimedia role Player instance that was paused |
930 | 74 | // when the battery level reached 10% or 5% | 76 | // when the battery level reached 10% or 5% |
932 | 75 | media::Player::PlayerKey resume_key; | 77 | media::Player::PlayerKey resume_key; |
933 | 76 | media::power::BatteryObserver::Ptr battery_observer; | 78 | media::power::BatteryObserver::Ptr battery_observer; |
934 | 77 | media::power::StateController::Ptr power_state_controller; | 79 | media::power::StateController::Ptr power_state_controller; |
935 | 78 | media::power::StateController::Lock<media::power::DisplayState>::Ptr display_state_lock; | 80 | media::power::StateController::Lock<media::power::DisplayState>::Ptr display_state_lock; |
936 | @@ -185,6 +187,7 @@ | |||
937 | 185 | media::PlayerSkeleton::Configuration | 187 | media::PlayerSkeleton::Configuration |
938 | 186 | { | 188 | { |
939 | 187 | conf.bus, | 189 | conf.bus, |
940 | 190 | conf.service, | ||
941 | 188 | conf.session, | 191 | conf.session, |
942 | 189 | d->request_context_resolver, | 192 | d->request_context_resolver, |
943 | 190 | d->request_authenticator | 193 | d->request_authenticator |
944 | @@ -262,17 +265,17 @@ | |||
945 | 262 | void media::ServiceImplementation::pause_all_multimedia_sessions(bool resume_play_after_phonecall) | 265 | void media::ServiceImplementation::pause_all_multimedia_sessions(bool resume_play_after_phonecall) |
946 | 263 | { | 266 | { |
947 | 264 | d->configuration.player_store->enumerate_players([this, resume_play_after_phonecall](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) | 267 | d->configuration.player_store->enumerate_players([this, resume_play_after_phonecall](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) |
959 | 265 | { | 268 | { |
960 | 266 | if (player->playback_status() == Player::playing | 269 | if (player->playback_status() == Player::playing |
961 | 267 | && player->audio_stream_role() == media::Player::multimedia) | 270 | && player->audio_stream_role() == media::Player::multimedia) |
962 | 268 | { | 271 | { |
963 | 269 | auto paused_player_pair = std::make_pair(key, resume_play_after_phonecall); | 272 | auto paused_player_pair = std::make_pair(key, resume_play_after_phonecall); |
964 | 270 | d->paused_sessions.push_back(paused_player_pair); | 273 | d->paused_sessions.push_back(paused_player_pair); |
965 | 271 | std::cout << "Pausing Player with key: " << key << ", resuming after phone call? " | 274 | std::cout << "Pausing Player with key: " << key << ", resuming after phone call? " |
966 | 272 | << (resume_play_after_phonecall ? "yes" : "no") << std::endl; | 275 | << (resume_play_after_phonecall ? "yes" : "no") << std::endl; |
967 | 273 | player->pause(); | 276 | player->pause(); |
968 | 274 | } | 277 | } |
969 | 275 | }); | 278 | }); |
970 | 276 | } | 279 | } |
971 | 277 | 280 | ||
972 | 278 | void media::ServiceImplementation::resume_paused_multimedia_sessions(bool resume_video_sessions) | 281 | void media::ServiceImplementation::resume_paused_multimedia_sessions(bool resume_video_sessions) |
973 | 279 | 282 | ||
974 | === modified file 'src/core/media/service_skeleton.cpp' | |||
975 | --- src/core/media/service_skeleton.cpp 2014-12-15 14:43:44 +0000 | |||
976 | +++ src/core/media/service_skeleton.cpp 2015-04-20 17:49:07 +0000 | |||
977 | @@ -52,7 +52,7 @@ | |||
978 | 52 | Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config) | 52 | Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config) |
979 | 53 | : impl(impl), | 53 | : impl(impl), |
980 | 54 | object(impl->access_service()->add_object_for_path( | 54 | object(impl->access_service()->add_object_for_path( |
982 | 55 | dbus::traits::Service<media::Service>::object_path())), | 55 | dbus::traits::Service<media::Service>::object_path())), |
983 | 56 | exported(impl->access_bus(), config.cover_art_resolver), | 56 | exported(impl->access_bus(), config.cover_art_resolver), |
984 | 57 | configuration(config) | 57 | configuration(config) |
985 | 58 | { | 58 | { |
986 | @@ -101,6 +101,7 @@ | |||
987 | 101 | { | 101 | { |
988 | 102 | key, | 102 | key, |
989 | 103 | impl->access_bus(), | 103 | impl->access_bus(), |
990 | 104 | impl->access_service(), | ||
991 | 104 | impl->access_service()->add_object_for_path(op) | 105 | impl->access_service()->add_object_for_path(op) |
992 | 105 | }; | 106 | }; |
993 | 106 | 107 | ||
994 | @@ -130,7 +131,7 @@ | |||
995 | 130 | 131 | ||
996 | 131 | if (named_player_map.count(name) == 0) { | 132 | if (named_player_map.count(name) == 0) { |
997 | 132 | // Create new session | 133 | // Create new session |
999 | 133 | auto session_info = create_session_info(); | 134 | auto session_info = create_session_info(); |
1000 | 134 | 135 | ||
1001 | 135 | dbus::types::ObjectPath op{session_info.first}; | 136 | dbus::types::ObjectPath op{session_info.first}; |
1002 | 136 | media::Player::PlayerKey key{session_info.second}; | 137 | media::Player::PlayerKey key{session_info.second}; |
1003 | @@ -139,6 +140,7 @@ | |||
1004 | 139 | { | 140 | { |
1005 | 140 | key, | 141 | key, |
1006 | 141 | impl->access_bus(), | 142 | impl->access_bus(), |
1007 | 143 | impl->access_service(), | ||
1008 | 142 | impl->access_service()->add_object_for_path(op) | 144 | impl->access_service()->add_object_for_path(op) |
1009 | 143 | }; | 145 | }; |
1010 | 144 | 146 | ||
1011 | @@ -266,6 +268,7 @@ | |||
1012 | 266 | 268 | ||
1013 | 267 | static std::string service_name() | 269 | static std::string service_name() |
1014 | 268 | { | 270 | { |
1015 | 271 | #if 0 | ||
1016 | 269 | static const bool export_to_indicator_sound_via_mpris | 272 | static const bool export_to_indicator_sound_via_mpris |
1017 | 270 | { | 273 | { |
1018 | 271 | core::posix::this_process::env::get("UBUNTU_MEDIA_HUB_EXPORT_TO_INDICATOR_VIA_MPRIS", "0") == "1" | 274 | core::posix::this_process::env::get("UBUNTU_MEDIA_HUB_EXPORT_TO_INDICATOR_VIA_MPRIS", "0") == "1" |
1019 | @@ -273,6 +276,9 @@ | |||
1020 | 273 | 276 | ||
1021 | 274 | return export_to_indicator_sound_via_mpris ? "org.mpris.MediaPlayer2.MediaHub" : | 277 | return export_to_indicator_sound_via_mpris ? "org.mpris.MediaPlayer2.MediaHub" : |
1022 | 275 | "hidden.org.mpris.MediaPlayer2.MediaHub"; | 278 | "hidden.org.mpris.MediaPlayer2.MediaHub"; |
1023 | 279 | #else | ||
1024 | 280 | return "org.mpris.MediaPlayer2.MediaHub"; | ||
1025 | 281 | #endif | ||
1026 | 276 | } | 282 | } |
1027 | 277 | 283 | ||
1028 | 278 | explicit Exported(const dbus::Bus::Ptr& bus, const media::CoverArtResolver& cover_art_resolver) | 284 | explicit Exported(const dbus::Bus::Ptr& bus, const media::CoverArtResolver& cover_art_resolver) |
1029 | 279 | 285 | ||
1030 | === modified file 'src/core/media/service_stub.cpp' | |||
1031 | --- src/core/media/service_stub.cpp 2014-10-23 14:42:59 +0000 | |||
1032 | +++ src/core/media/service_stub.cpp 2015-04-20 17:49:07 +0000 | |||
1033 | @@ -66,6 +66,7 @@ | |||
1034 | 66 | return std::shared_ptr<media::Player>(new media::PlayerStub | 66 | return std::shared_ptr<media::Player>(new media::PlayerStub |
1035 | 67 | { | 67 | { |
1036 | 68 | shared_from_this(), | 68 | shared_from_this(), |
1037 | 69 | access_service(), | ||
1038 | 69 | access_service()->object_for_path(op.value()) | 70 | access_service()->object_for_path(op.value()) |
1039 | 70 | }); | 71 | }); |
1040 | 71 | } | 72 | } |
1041 | @@ -81,6 +82,7 @@ | |||
1042 | 81 | return std::shared_ptr<media::Player>(new media::PlayerStub | 82 | return std::shared_ptr<media::Player>(new media::PlayerStub |
1043 | 82 | { | 83 | { |
1044 | 83 | shared_from_this(), | 84 | shared_from_this(), |
1045 | 85 | access_service(), | ||
1046 | 84 | access_service()->object_for_path(op.value()) | 86 | access_service()->object_for_path(op.value()) |
1047 | 85 | }); | 87 | }); |
1048 | 86 | } | 88 | } |
1049 | @@ -96,6 +98,7 @@ | |||
1050 | 96 | return std::shared_ptr<media::Player>(new media::PlayerStub | 98 | return std::shared_ptr<media::Player>(new media::PlayerStub |
1051 | 97 | { | 99 | { |
1052 | 98 | shared_from_this(), | 100 | shared_from_this(), |
1053 | 101 | access_service(), | ||
1054 | 99 | access_service()->object_for_path(op.value()) | 102 | access_service()->object_for_path(op.value()) |
1055 | 100 | }); | 103 | }); |
1056 | 101 | } | 104 | } |
1057 | 102 | 105 | ||
1058 | === modified file 'src/core/media/track_list_implementation.cpp' | |||
1059 | --- src/core/media/track_list_implementation.cpp 2014-03-25 14:57:15 +0000 | |||
1060 | +++ src/core/media/track_list_implementation.cpp 2015-04-20 17:49:07 +0000 | |||
1061 | @@ -1,5 +1,5 @@ | |||
1062 | 1 | /* | 1 | /* |
1064 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2013-2015 Canonical Ltd. |
1065 | 3 | * | 3 | * |
1066 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1067 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1068 | @@ -16,8 +16,10 @@ | |||
1069 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1070 | 17 | */ | 17 | */ |
1071 | 18 | 18 | ||
1072 | 19 | #include <algorithm> | ||
1073 | 19 | #include <stdio.h> | 20 | #include <stdio.h> |
1074 | 20 | #include <stdlib.h> | 21 | #include <stdlib.h> |
1075 | 22 | #include <tuple> | ||
1076 | 21 | 23 | ||
1077 | 22 | #include "track_list_implementation.h" | 24 | #include "track_list_implementation.h" |
1078 | 23 | 25 | ||
1079 | @@ -30,16 +32,23 @@ | |||
1080 | 30 | { | 32 | { |
1081 | 31 | typedef std::map<Track::Id, std::tuple<Track::UriType, Track::MetaData>> MetaDataCache; | 33 | typedef std::map<Track::Id, std::tuple<Track::UriType, Track::MetaData>> MetaDataCache; |
1082 | 32 | 34 | ||
1084 | 33 | dbus::types::ObjectPath path; | 35 | dbus::Object::Ptr object; |
1085 | 36 | size_t track_counter; | ||
1086 | 34 | MetaDataCache meta_data_cache; | 37 | MetaDataCache meta_data_cache; |
1087 | 35 | std::shared_ptr<media::Engine::MetaDataExtractor> extractor; | 38 | std::shared_ptr<media::Engine::MetaDataExtractor> extractor; |
1088 | 39 | // Used for caching the original tracklist order to be used to restore the order | ||
1089 | 40 | // to the live TrackList after shuffle is turned off | ||
1090 | 41 | media::TrackList::Container original_tracklist; | ||
1091 | 36 | }; | 42 | }; |
1092 | 37 | 43 | ||
1093 | 38 | media::TrackListImplementation::TrackListImplementation( | 44 | media::TrackListImplementation::TrackListImplementation( |
1098 | 39 | const dbus::types::ObjectPath& op, | 45 | const dbus::Bus::Ptr& bus, |
1099 | 40 | const std::shared_ptr<media::Engine::MetaDataExtractor>& extractor) | 46 | const dbus::Object::Ptr& object, |
1100 | 41 | : media::TrackListSkeleton(op), | 47 | const std::shared_ptr<media::Engine::MetaDataExtractor>& extractor, |
1101 | 42 | d(new Private{op, Private::MetaDataCache{}, extractor}) | 48 | const media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, |
1102 | 49 | const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator) | ||
1103 | 50 | : media::TrackListSkeleton(bus, object, request_context_resolver, request_authenticator), | ||
1104 | 51 | d(new Private{object, 0, Private::MetaDataCache{}, extractor, media::TrackList::Container{}}) | ||
1105 | 43 | { | 52 | { |
1106 | 44 | can_edit_tracks().set(true); | 53 | can_edit_tracks().set(true); |
1107 | 45 | } | 54 | } |
1108 | @@ -73,15 +82,16 @@ | |||
1109 | 73 | const media::Track::Id& position, | 82 | const media::Track::Id& position, |
1110 | 74 | bool make_current) | 83 | bool make_current) |
1111 | 75 | { | 84 | { |
1113 | 76 | static size_t track_counter = 0; | 85 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
1114 | 77 | 86 | ||
1116 | 78 | std::stringstream ss; ss << d->path.as_string() << "/" << track_counter++; | 87 | std::stringstream ss; ss << d->object->path().as_string() << "/" << d->track_counter++; |
1117 | 79 | Track::Id id{ss.str()}; | 88 | Track::Id id{ss.str()}; |
1118 | 80 | 89 | ||
1119 | 81 | auto result = tracks().update([this, id, position, make_current](TrackList::Container& container) | 90 | auto result = tracks().update([this, id, position, make_current](TrackList::Container& container) |
1120 | 82 | { | 91 | { |
1121 | 83 | auto it = std::find(container.begin(), container.end(), position); | 92 | auto it = std::find(container.begin(), container.end(), position); |
1122 | 84 | container.insert(it, id); | 93 | container.insert(it, id); |
1123 | 94 | |||
1124 | 85 | return true; | 95 | return true; |
1125 | 86 | }); | 96 | }); |
1126 | 87 | 97 | ||
1127 | @@ -98,8 +108,15 @@ | |||
1128 | 98 | } | 108 | } |
1129 | 99 | 109 | ||
1130 | 100 | if (make_current) | 110 | if (make_current) |
1132 | 101 | go_to(id); | 111 | { |
1133 | 112 | // Don't automatically call stop() and play() in player_implementation.cpp on_go_to_track() | ||
1134 | 113 | // since this breaks video playback when using open_uri() (stop() and play() are unwanted in | ||
1135 | 114 | // this scenario since the qtubuntu-media will handle this automatically) | ||
1136 | 115 | const bool toggle_player_state = false; | ||
1137 | 116 | go_to(id, toggle_player_state); | ||
1138 | 117 | } | ||
1139 | 102 | 118 | ||
1140 | 119 | // Signal to the client that a track was added to the TrackList | ||
1141 | 103 | on_track_added()(id); | 120 | on_track_added()(id); |
1142 | 104 | } | 121 | } |
1143 | 105 | } | 122 | } |
1144 | @@ -121,7 +138,61 @@ | |||
1145 | 121 | 138 | ||
1146 | 122 | } | 139 | } |
1147 | 123 | 140 | ||
1151 | 124 | void media::TrackListImplementation::go_to(const media::Track::Id& track) | 141 | void media::TrackListImplementation::go_to(const media::Track::Id& track, bool toggle_player_state) |
1152 | 125 | { | 142 | { |
1153 | 126 | (void) track; | 143 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
1154 | 144 | std::pair<const media::Track::Id, bool> p = std::make_pair(track, toggle_player_state); | ||
1155 | 145 | // Signal the Player instance to go to a specific track for playback | ||
1156 | 146 | on_go_to_track()(p); | ||
1157 | 147 | on_track_changed()(track); | ||
1158 | 148 | } | ||
1159 | 149 | |||
1160 | 150 | void media::TrackListImplementation::shuffle_tracks() | ||
1161 | 151 | { | ||
1162 | 152 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
1163 | 153 | |||
1164 | 154 | auto result = tracks().update([this](TrackList::Container& container) | ||
1165 | 155 | { | ||
1166 | 156 | d->original_tracklist.assign(container.begin(), container.end()); | ||
1167 | 157 | std::random_shuffle(container.begin(), container.end()); | ||
1168 | 158 | return true; | ||
1169 | 159 | }); | ||
1170 | 160 | |||
1171 | 161 | if (result) | ||
1172 | 162 | { | ||
1173 | 163 | media::TrackList::ContainerTrackIdTuple t{std::make_tuple(tracks().get(), current())}; | ||
1174 | 164 | on_track_list_replaced()(t); | ||
1175 | 165 | } | ||
1176 | 166 | } | ||
1177 | 167 | |||
1178 | 168 | void media::TrackListImplementation::unshuffle_tracks() | ||
1179 | 169 | { | ||
1180 | 170 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
1181 | 171 | |||
1182 | 172 | auto result = tracks().update([this](TrackList::Container& container) | ||
1183 | 173 | { | ||
1184 | 174 | container.assign(d->original_tracklist.begin(), d->original_tracklist.end()); | ||
1185 | 175 | return true; | ||
1186 | 176 | }); | ||
1187 | 177 | |||
1188 | 178 | if (result) | ||
1189 | 179 | { | ||
1190 | 180 | media::TrackList::ContainerTrackIdTuple t{std::make_tuple(tracks().get(), current())}; | ||
1191 | 181 | on_track_list_replaced()(t); | ||
1192 | 182 | } | ||
1193 | 183 | } | ||
1194 | 184 | |||
1195 | 185 | void media::TrackListImplementation::reset() | ||
1196 | 186 | { | ||
1197 | 187 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
1198 | 188 | |||
1199 | 189 | auto result = tracks().update([this](TrackList::Container& container) | ||
1200 | 190 | { | ||
1201 | 191 | container.clear(); | ||
1202 | 192 | container.resize(0); | ||
1203 | 193 | d->track_counter = 0; | ||
1204 | 194 | return true; | ||
1205 | 195 | }); | ||
1206 | 196 | |||
1207 | 197 | (void) result; | ||
1208 | 127 | } | 198 | } |
1209 | 128 | 199 | ||
1210 | === modified file 'src/core/media/track_list_implementation.h' | |||
1211 | --- src/core/media/track_list_implementation.h 2014-03-25 14:57:15 +0000 | |||
1212 | +++ src/core/media/track_list_implementation.h 2015-04-20 17:49:07 +0000 | |||
1213 | @@ -1,5 +1,5 @@ | |||
1214 | 1 | /* | 1 | /* |
1216 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2013-2015 Canonical Ltd. |
1217 | 3 | * | 3 | * |
1218 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1219 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1220 | @@ -32,8 +32,11 @@ | |||
1221 | 32 | { | 32 | { |
1222 | 33 | public: | 33 | public: |
1223 | 34 | TrackListImplementation( | 34 | TrackListImplementation( |
1226 | 35 | const core::dbus::types::ObjectPath& op, | 35 | const core::dbus::Bus::Ptr& bus, |
1227 | 36 | const std::shared_ptr<Engine::MetaDataExtractor>& extractor); | 36 | const core::dbus::Object::Ptr& object, |
1228 | 37 | const std::shared_ptr<Engine::MetaDataExtractor>& extractor, | ||
1229 | 38 | const core::ubuntu::media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, | ||
1230 | 39 | const core::ubuntu::media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator); | ||
1231 | 37 | ~TrackListImplementation(); | 40 | ~TrackListImplementation(); |
1232 | 38 | 41 | ||
1233 | 39 | Track::UriType query_uri_for_track(const Track::Id& id); | 42 | Track::UriType query_uri_for_track(const Track::Id& id); |
1234 | @@ -42,7 +45,10 @@ | |||
1235 | 42 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); | 45 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); |
1236 | 43 | void remove_track(const Track::Id& id); | 46 | void remove_track(const Track::Id& id); |
1237 | 44 | 47 | ||
1239 | 45 | void go_to(const Track::Id& track); | 48 | void go_to(const Track::Id& track, bool toggle_player_state); |
1240 | 49 | void shuffle_tracks(); | ||
1241 | 50 | void unshuffle_tracks(); | ||
1242 | 51 | void reset(); | ||
1243 | 46 | 52 | ||
1244 | 47 | private: | 53 | private: |
1245 | 48 | struct Private; | 54 | struct Private; |
1246 | 49 | 55 | ||
1247 | === modified file 'src/core/media/track_list_skeleton.cpp' | |||
1248 | --- src/core/media/track_list_skeleton.cpp 2014-03-25 14:57:15 +0000 | |||
1249 | +++ src/core/media/track_list_skeleton.cpp 2015-04-20 17:49:07 +0000 | |||
1250 | @@ -1,5 +1,5 @@ | |||
1251 | 1 | /* | 1 | /* |
1253 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2015 Canonical Ltd. |
1254 | 3 | * | 3 | * |
1255 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1256 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1257 | @@ -17,6 +17,7 @@ | |||
1258 | 17 | */ | 17 | */ |
1259 | 18 | 18 | ||
1260 | 19 | #include "track_list_skeleton.h" | 19 | #include "track_list_skeleton.h" |
1261 | 20 | #include "track_list_implementation.h" | ||
1262 | 20 | 21 | ||
1263 | 21 | #include <core/media/player.h> | 22 | #include <core/media/player.h> |
1264 | 22 | #include <core/media/track_list.h> | 23 | #include <core/media/track_list.h> |
1265 | @@ -35,6 +36,7 @@ | |||
1266 | 35 | #include <core/dbus/types/stl/map.h> | 36 | #include <core/dbus/types/stl/map.h> |
1267 | 36 | #include <core/dbus/types/stl/vector.h> | 37 | #include <core/dbus/types/stl/vector.h> |
1268 | 37 | 38 | ||
1269 | 39 | #include <iostream> | ||
1270 | 38 | #include <limits> | 40 | #include <limits> |
1271 | 39 | 41 | ||
1272 | 40 | namespace dbus = core::dbus; | 42 | namespace dbus = core::dbus; |
1273 | @@ -42,14 +44,24 @@ | |||
1274 | 42 | 44 | ||
1275 | 43 | struct media::TrackListSkeleton::Private | 45 | struct media::TrackListSkeleton::Private |
1276 | 44 | { | 46 | { |
1279 | 45 | Private(media::TrackListSkeleton* impl, | 47 | Private(media::TrackListSkeleton* impl, const dbus::Bus::Ptr& bus, const dbus::Object::Ptr& object, |
1280 | 46 | dbus::Object::Ptr object) | 48 | const apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, |
1281 | 49 | const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator) | ||
1282 | 47 | : impl(impl), | 50 | : impl(impl), |
1283 | 51 | bus(bus), | ||
1284 | 48 | object(object), | 52 | object(object), |
1289 | 49 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), | 53 | request_context_resolver(request_context_resolver), |
1290 | 50 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()), | 54 | request_authenticator(request_authenticator), |
1291 | 51 | current_track(tracks->get().begin()), | 55 | skeleton(mpris::TrackList::Skeleton::Configuration{object, mpris::TrackList::Skeleton::Configuration::Defaults{}}), |
1292 | 52 | empty_iterator(tracks->get().begin()) | 56 | current_track(skeleton.properties.tracks->get().begin()), |
1293 | 57 | empty_iterator(skeleton.properties.tracks->get().begin()), | ||
1294 | 58 | loop_status(media::Player::LoopStatus::none), | ||
1295 | 59 | signals | ||
1296 | 60 | { | ||
1297 | 61 | skeleton.signals.track_added, | ||
1298 | 62 | skeleton.signals.track_removed, | ||
1299 | 63 | skeleton.signals.tracklist_replaced | ||
1300 | 64 | } | ||
1301 | 53 | { | 65 | { |
1302 | 54 | } | 66 | } |
1303 | 55 | 67 | ||
1304 | @@ -62,18 +74,29 @@ | |||
1305 | 62 | 74 | ||
1306 | 63 | auto reply = dbus::Message::make_method_return(msg); | 75 | auto reply = dbus::Message::make_method_return(msg); |
1307 | 64 | reply->writer() << *meta_data; | 76 | reply->writer() << *meta_data; |
1309 | 65 | impl->access_bus()->send(reply); | 77 | bus->send(reply); |
1310 | 66 | } | 78 | } |
1311 | 67 | 79 | ||
1312 | 68 | void handle_add_track_with_uri_at(const core::dbus::Message::Ptr& msg) | 80 | void handle_add_track_with_uri_at(const core::dbus::Message::Ptr& msg) |
1313 | 69 | { | 81 | { |
1321 | 70 | Track::UriType uri; media::Track::Id after; bool make_current; | 82 | request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, msg](const media::apparmor::ubuntu::Context& context) |
1322 | 71 | msg->reader() >> uri >> after >> make_current; | 83 | { |
1323 | 72 | 84 | Track::UriType uri; media::Track::Id after; bool make_current; | |
1324 | 73 | impl->add_track_with_uri_at(uri, after, make_current); | 85 | msg->reader() >> uri >> after >> make_current; |
1325 | 74 | 86 | ||
1326 | 75 | auto reply = dbus::Message::make_method_return(msg); | 87 | // Make sure the client has adequate apparmor permissions to open the URI |
1327 | 76 | impl->access_bus()->send(reply); | 88 | const auto result = request_authenticator->authenticate_open_uri_request(context, uri); |
1328 | 89 | |||
1329 | 90 | auto reply = dbus::Message::make_method_return(msg); | ||
1330 | 91 | // Only add the track to the TrackList if it passes the apparmor permissions check | ||
1331 | 92 | if (std::get<0>(result)) | ||
1332 | 93 | impl->add_track_with_uri_at(uri, after, make_current); | ||
1333 | 94 | else | ||
1334 | 95 | std::cerr << "Warning: Not adding track " << uri << | ||
1335 | 96 | " to TrackList because of inadequate client apparmor permissions." << std::endl; | ||
1336 | 97 | |||
1337 | 98 | bus->send(reply); | ||
1338 | 99 | }); | ||
1339 | 77 | } | 100 | } |
1340 | 78 | 101 | ||
1341 | 79 | void handle_remove_track(const core::dbus::Message::Ptr& msg) | 102 | void handle_remove_track(const core::dbus::Message::Ptr& msg) |
1342 | @@ -84,7 +107,7 @@ | |||
1343 | 84 | impl->remove_track(track); | 107 | impl->remove_track(track); |
1344 | 85 | 108 | ||
1345 | 86 | auto reply = dbus::Message::make_method_return(msg); | 109 | auto reply = dbus::Message::make_method_return(msg); |
1347 | 87 | impl->access_bus()->send(reply); | 110 | bus->send(reply); |
1348 | 88 | } | 111 | } |
1349 | 89 | 112 | ||
1350 | 90 | void handle_go_to(const core::dbus::Message::Ptr& msg) | 113 | void handle_go_to(const core::dbus::Message::Ptr& msg) |
1351 | @@ -92,30 +115,64 @@ | |||
1352 | 92 | media::Track::Id track; | 115 | media::Track::Id track; |
1353 | 93 | msg->reader() >> track; | 116 | msg->reader() >> track; |
1354 | 94 | 117 | ||
1356 | 95 | impl->go_to(track); | 118 | current_track = std::find(skeleton.properties.tracks->get().begin(), skeleton.properties.tracks->get().end(), track); |
1357 | 119 | const bool toggle_player_state = true; | ||
1358 | 120 | impl->go_to(track, toggle_player_state); | ||
1359 | 96 | 121 | ||
1360 | 97 | auto reply = dbus::Message::make_method_return(msg); | 122 | auto reply = dbus::Message::make_method_return(msg); |
1362 | 98 | impl->access_bus()->send(reply); | 123 | bus->send(reply); |
1363 | 99 | } | 124 | } |
1364 | 100 | 125 | ||
1365 | 101 | media::TrackListSkeleton* impl; | 126 | media::TrackListSkeleton* impl; |
1366 | 127 | dbus::Bus::Ptr bus; | ||
1367 | 102 | dbus::Object::Ptr object; | 128 | dbus::Object::Ptr object; |
1368 | 129 | media::apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver; | ||
1369 | 130 | media::apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator; | ||
1370 | 103 | 131 | ||
1373 | 104 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; | 132 | mpris::TrackList::Skeleton skeleton; |
1372 | 105 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; | ||
1374 | 106 | TrackList::ConstIterator current_track; | 133 | TrackList::ConstIterator current_track; |
1375 | 107 | TrackList::ConstIterator empty_iterator; | 134 | TrackList::ConstIterator empty_iterator; |
1381 | 108 | 135 | media::Player::LoopStatus loop_status; | |
1382 | 109 | core::Signal<void> on_track_list_replaced; | 136 | |
1383 | 110 | core::Signal<Track::Id> on_track_added; | 137 | struct Signals |
1384 | 111 | core::Signal<Track::Id> on_track_removed; | 138 | { |
1385 | 112 | core::Signal<Track::Id> on_track_changed; | 139 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType> DBusTrackAddedSignal; |
1386 | 140 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType> DBusTrackRemovedSignal; | ||
1387 | 141 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType> DBusTrackListReplacedSignal; | ||
1388 | 142 | |||
1389 | 143 | Signals(const std::shared_ptr<DBusTrackAddedSignal>& remote_track_added, | ||
1390 | 144 | const std::shared_ptr<DBusTrackRemovedSignal>& remote_track_removed, | ||
1391 | 145 | const std::shared_ptr<DBusTrackListReplacedSignal>& remote_track_list_replaced) | ||
1392 | 146 | { | ||
1393 | 147 | // Connect all of the MPRIS interface signals to be emitted over dbus | ||
1394 | 148 | on_track_added.connect([remote_track_added](const media::Track::Id &id) | ||
1395 | 149 | { | ||
1396 | 150 | remote_track_added->emit(id); | ||
1397 | 151 | }); | ||
1398 | 152 | |||
1399 | 153 | on_track_removed.connect([remote_track_removed](const media::Track::Id &id) | ||
1400 | 154 | { | ||
1401 | 155 | remote_track_removed->emit(id); | ||
1402 | 156 | }); | ||
1403 | 157 | |||
1404 | 158 | on_track_list_replaced.connect([remote_track_list_replaced](const media::TrackList::ContainerTrackIdTuple &tltuple) | ||
1405 | 159 | { | ||
1406 | 160 | remote_track_list_replaced->emit(tltuple); | ||
1407 | 161 | }); | ||
1408 | 162 | } | ||
1409 | 163 | |||
1410 | 164 | core::Signal<Track::Id> on_track_added; | ||
1411 | 165 | core::Signal<Track::Id> on_track_removed; | ||
1412 | 166 | core::Signal<TrackList::ContainerTrackIdTuple> on_track_list_replaced; | ||
1413 | 167 | core::Signal<Track::Id> on_track_changed; | ||
1414 | 168 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; | ||
1415 | 169 | } signals; | ||
1416 | 113 | }; | 170 | }; |
1417 | 114 | 171 | ||
1422 | 115 | media::TrackListSkeleton::TrackListSkeleton( | 172 | media::TrackListSkeleton::TrackListSkeleton(const core::dbus::Bus::Ptr& bus, const core::dbus::Object::Ptr& object, |
1423 | 116 | const dbus::types::ObjectPath& op) | 173 | const media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, |
1424 | 117 | : dbus::Skeleton<media::TrackList>(the_session_bus()), | 174 | const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator) |
1425 | 118 | d(new Private(this, access_service()->add_object_for_path(op))) | 175 | : d(new Private(this, bus, object, request_context_resolver, request_authenticator)) |
1426 | 119 | { | 176 | { |
1427 | 120 | d->object->install_method_handler<mpris::TrackList::GetTracksMetadata>( | 177 | d->object->install_method_handler<mpris::TrackList::GetTracksMetadata>( |
1428 | 121 | std::bind(&Private::handle_get_tracks_metadata, | 178 | std::bind(&Private::handle_get_tracks_metadata, |
1429 | @@ -144,80 +201,156 @@ | |||
1430 | 144 | 201 | ||
1431 | 145 | bool media::TrackListSkeleton::has_next() const | 202 | bool media::TrackListSkeleton::has_next() const |
1432 | 146 | { | 203 | { |
1434 | 147 | return d->current_track != d->tracks->get().end(); | 204 | const auto next_track = std::next(d->current_track); |
1435 | 205 | std::cout << "has_next track? " << (next_track != tracks().get().end() ? "yes" : "no") << std::endl; | ||
1436 | 206 | return next_track != tracks().get().end(); | ||
1437 | 148 | } | 207 | } |
1438 | 149 | 208 | ||
1439 | 150 | const media::Track::Id& media::TrackListSkeleton::next() | 209 | const media::Track::Id& media::TrackListSkeleton::next() |
1440 | 151 | { | 210 | { |
1451 | 152 | if (d->tracks->get().empty()) | 211 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
1452 | 153 | return *(d->current_track); | 212 | if (tracks().get().empty()) |
1453 | 154 | 213 | return *(d->current_track); | |
1454 | 155 | if (d->tracks->get().size() && (d->current_track == d->empty_iterator)) | 214 | |
1455 | 156 | { | 215 | // Loop on the current track forever |
1456 | 157 | d->current_track = d->tracks->get().begin(); | 216 | if (d->loop_status == media::Player::LoopStatus::track) |
1457 | 158 | return *(d->current_track = std::next(d->current_track)); | 217 | { |
1458 | 159 | } | 218 | std::cout << "Looping on the current track..." << std::endl; |
1459 | 160 | 219 | return *(d->current_track); | |
1460 | 161 | d->current_track = std::next(d->current_track); | 220 | } |
1461 | 221 | // Loop over the whole playlist and repeat | ||
1462 | 222 | else if (d->loop_status == media::Player::LoopStatus::playlist && !has_next()) | ||
1463 | 223 | { | ||
1464 | 224 | std::cout << "Looping on the entire TrackList..." << std::endl; | ||
1465 | 225 | d->current_track = tracks().get().begin(); | ||
1466 | 226 | return *(d->current_track); | ||
1467 | 227 | } | ||
1468 | 228 | else if (has_next()) | ||
1469 | 229 | { | ||
1470 | 230 | // Keep returning the next track until the last track is reached | ||
1471 | 231 | d->current_track = std::next(d->current_track); | ||
1472 | 232 | std::cout << *this << std::endl; | ||
1473 | 233 | } | ||
1474 | 234 | |||
1475 | 235 | return *(d->current_track); | ||
1476 | 236 | } | ||
1477 | 237 | |||
1478 | 238 | const media::Track::Id& media::TrackListSkeleton::current() | ||
1479 | 239 | { | ||
1480 | 240 | // Prevent the TrackList from sitting at the end which will cause | ||
1481 | 241 | // a segfault when calling current() | ||
1482 | 242 | if (tracks().get().size() && (d->current_track == d->empty_iterator)) | ||
1483 | 243 | d->current_track = d->skeleton.properties.tracks->get().begin(); | ||
1484 | 244 | else if (tracks().get().empty()) | ||
1485 | 245 | std::cerr << "TrackList is empty therefore there is no valid current track" << std::endl; | ||
1486 | 246 | |||
1487 | 162 | return *(d->current_track); | 247 | return *(d->current_track); |
1488 | 163 | } | 248 | } |
1489 | 164 | 249 | ||
1490 | 165 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const | 250 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const |
1491 | 166 | { | 251 | { |
1493 | 167 | return *d->can_edit_tracks; | 252 | return *d->skeleton.properties.can_edit_tracks; |
1494 | 168 | } | 253 | } |
1495 | 169 | 254 | ||
1496 | 170 | core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() | 255 | core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() |
1497 | 171 | { | 256 | { |
1499 | 172 | return *d->can_edit_tracks; | 257 | return *d->skeleton.properties.can_edit_tracks; |
1500 | 173 | } | 258 | } |
1501 | 174 | 259 | ||
1502 | 175 | core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() | 260 | core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() |
1503 | 176 | { | 261 | { |
1505 | 177 | return *d->tracks; | 262 | return *d->skeleton.properties.tracks; |
1506 | 263 | } | ||
1507 | 264 | |||
1508 | 265 | void media::TrackListSkeleton::on_loop_status_changed(const media::Player::LoopStatus& loop_status) | ||
1509 | 266 | { | ||
1510 | 267 | d->loop_status = loop_status; | ||
1511 | 268 | } | ||
1512 | 269 | |||
1513 | 270 | media::Player::LoopStatus media::TrackListSkeleton::loop_status() const | ||
1514 | 271 | { | ||
1515 | 272 | return d->loop_status; | ||
1516 | 273 | } | ||
1517 | 274 | |||
1518 | 275 | void media::TrackListSkeleton::on_shuffle_changed(bool shuffle) | ||
1519 | 276 | { | ||
1520 | 277 | if (shuffle) | ||
1521 | 278 | shuffle_tracks(); | ||
1522 | 279 | else | ||
1523 | 280 | unshuffle_tracks(); | ||
1524 | 178 | } | 281 | } |
1525 | 179 | 282 | ||
1526 | 180 | const core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() const | 283 | const core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() const |
1527 | 181 | { | 284 | { |
1529 | 182 | return *d->tracks; | 285 | return *d->skeleton.properties.tracks; |
1530 | 183 | } | 286 | } |
1531 | 184 | 287 | ||
1533 | 185 | const core::Signal<void>& media::TrackListSkeleton::on_track_list_replaced() const | 288 | const core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListSkeleton::on_track_list_replaced() const |
1534 | 186 | { | 289 | { |
1536 | 187 | return d->on_track_list_replaced; | 290 | // Print the TrackList instance |
1537 | 291 | std::cout << *this << std::endl; | ||
1538 | 292 | return d->signals.on_track_list_replaced; | ||
1539 | 188 | } | 293 | } |
1540 | 189 | 294 | ||
1541 | 190 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_added() const | 295 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_added() const |
1542 | 191 | { | 296 | { |
1544 | 192 | return d->on_track_added; | 297 | return d->signals.on_track_added; |
1545 | 193 | } | 298 | } |
1546 | 194 | 299 | ||
1547 | 195 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_removed() const | 300 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_removed() const |
1548 | 196 | { | 301 | { |
1550 | 197 | return d->on_track_removed; | 302 | return d->signals.on_track_removed; |
1551 | 198 | } | 303 | } |
1552 | 199 | 304 | ||
1553 | 200 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_changed() const | 305 | const core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_changed() const |
1554 | 201 | { | 306 | { |
1561 | 202 | return d->on_track_changed; | 307 | return d->signals.on_track_changed; |
1562 | 203 | } | 308 | } |
1563 | 204 | 309 | ||
1564 | 205 | core::Signal<void>& media::TrackListSkeleton::on_track_list_replaced() | 310 | const core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListSkeleton::on_go_to_track() const |
1565 | 206 | { | 311 | { |
1566 | 207 | return d->on_track_list_replaced; | 312 | return d->signals.on_go_to_track; |
1567 | 313 | } | ||
1568 | 314 | |||
1569 | 315 | core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListSkeleton::on_track_list_replaced() | ||
1570 | 316 | { | ||
1571 | 317 | return d->signals.on_track_list_replaced; | ||
1572 | 208 | } | 318 | } |
1573 | 209 | 319 | ||
1574 | 210 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_added() | 320 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_added() |
1575 | 211 | { | 321 | { |
1577 | 212 | return d->on_track_added; | 322 | return d->signals.on_track_added; |
1578 | 213 | } | 323 | } |
1579 | 214 | 324 | ||
1580 | 215 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_removed() | 325 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_removed() |
1581 | 216 | { | 326 | { |
1583 | 217 | return d->on_track_removed; | 327 | return d->signals.on_track_removed; |
1584 | 218 | } | 328 | } |
1585 | 219 | 329 | ||
1586 | 220 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_changed() | 330 | core::Signal<media::Track::Id>& media::TrackListSkeleton::on_track_changed() |
1587 | 221 | { | 331 | { |
1590 | 222 | return d->on_track_changed; | 332 | return d->signals.on_track_changed; |
1591 | 223 | } | 333 | } |
1592 | 334 | |||
1593 | 335 | core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListSkeleton::on_go_to_track() | ||
1594 | 336 | { | ||
1595 | 337 | return d->signals.on_go_to_track; | ||
1596 | 338 | } | ||
1597 | 339 | |||
1598 | 340 | // operator<< pretty prints the given TrackList to the given output stream. | ||
1599 | 341 | inline std::ostream& media::operator<<(std::ostream& out, const media::TrackList& tracklist) | ||
1600 | 342 | { | ||
1601 | 343 | auto non_const_tl = const_cast<media::TrackList*>(&tracklist); | ||
1602 | 344 | out << "TrackList\n---------------" << std::endl; | ||
1603 | 345 | for (const media::Track::Id &id : tracklist.tracks().get()) | ||
1604 | 346 | { | ||
1605 | 347 | // '*' denotes the current track | ||
1606 | 348 | out << "\t" << ((dynamic_cast<media::TrackListSkeleton*>(non_const_tl)->current() == id) ? "*" : ""); | ||
1607 | 349 | out << "Track Id: " << id << std::endl; | ||
1608 | 350 | out << "\t\turi: " << dynamic_cast<media::TrackListImplementation*>(non_const_tl)->query_uri_for_track(id) << std::endl; | ||
1609 | 351 | } | ||
1610 | 352 | |||
1611 | 353 | out << "---------------\nEnd TrackList" << std::endl; | ||
1612 | 354 | return out; | ||
1613 | 355 | } | ||
1614 | 356 | |||
1615 | 224 | 357 | ||
1616 | === modified file 'src/core/media/track_list_skeleton.h' | |||
1617 | --- src/core/media/track_list_skeleton.h 2014-03-25 14:57:15 +0000 | |||
1618 | +++ src/core/media/track_list_skeleton.h 2015-04-20 17:49:07 +0000 | |||
1619 | @@ -18,10 +18,13 @@ | |||
1620 | 18 | #ifndef CORE_UBUNTU_MEDIA_TRACK_LIST_SKELETON_H_ | 18 | #ifndef CORE_UBUNTU_MEDIA_TRACK_LIST_SKELETON_H_ |
1621 | 19 | #define CORE_UBUNTU_MEDIA_TRACK_LIST_SKELETON_H_ | 19 | #define CORE_UBUNTU_MEDIA_TRACK_LIST_SKELETON_H_ |
1622 | 20 | 20 | ||
1623 | 21 | #include "apparmor/ubuntu.h" | ||
1624 | 22 | |||
1625 | 21 | #include <core/media/track_list.h> | 23 | #include <core/media/track_list.h> |
1626 | 22 | 24 | ||
1627 | 23 | #include <core/media/player.h> | 25 | #include <core/media/player.h> |
1628 | 24 | 26 | ||
1629 | 27 | #include <core/dbus/object.h> | ||
1630 | 25 | #include <core/dbus/skeleton.h> | 28 | #include <core/dbus/skeleton.h> |
1631 | 26 | 29 | ||
1632 | 27 | namespace core | 30 | namespace core |
1633 | @@ -30,38 +33,52 @@ | |||
1634 | 30 | { | 33 | { |
1635 | 31 | namespace media | 34 | namespace media |
1636 | 32 | { | 35 | { |
1638 | 33 | class TrackListSkeleton : public core::dbus::Skeleton<core::ubuntu::media::TrackList> | 36 | class TrackListSkeleton : public core::ubuntu::media::TrackList |
1639 | 34 | { | 37 | { |
1640 | 35 | public: | 38 | public: |
1643 | 36 | TrackListSkeleton( | 39 | TrackListSkeleton(const core::dbus::Bus::Ptr& bus, const core::dbus::Object::Ptr& object, |
1644 | 37 | const core::dbus::types::ObjectPath& op); | 40 | const core::ubuntu::media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, |
1645 | 41 | const core::ubuntu::media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator); | ||
1646 | 38 | ~TrackListSkeleton(); | 42 | ~TrackListSkeleton(); |
1647 | 39 | 43 | ||
1648 | 40 | bool has_next() const; | 44 | bool has_next() const; |
1649 | 41 | const Track::Id& next(); | 45 | const Track::Id& next(); |
1650 | 46 | const Track::Id& current(); | ||
1651 | 42 | 47 | ||
1652 | 43 | const core::Property<bool>& can_edit_tracks() const; | 48 | const core::Property<bool>& can_edit_tracks() const; |
1653 | 44 | const core::Property<Container>& tracks() const; | 49 | const core::Property<Container>& tracks() const; |
1654 | 45 | 50 | ||
1656 | 46 | const core::Signal<void>& on_track_list_replaced() const; | 51 | const core::Signal<ContainerTrackIdTuple>& on_track_list_replaced() const; |
1657 | 47 | const core::Signal<Track::Id>& on_track_added() const; | 52 | const core::Signal<Track::Id>& on_track_added() const; |
1658 | 48 | const core::Signal<Track::Id>& on_track_removed() const; | 53 | const core::Signal<Track::Id>& on_track_removed() const; |
1659 | 49 | const core::Signal<Track::Id>& on_track_changed() const; | 54 | const core::Signal<Track::Id>& on_track_changed() const; |
1660 | 55 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; | ||
1661 | 56 | core::Signal<std::pair<Track::Id, bool>>& on_go_to_track(); | ||
1662 | 57 | core::Signal<Track::Id>& on_track_removed(); | ||
1663 | 50 | 58 | ||
1664 | 51 | core::Property<Container>& tracks(); | 59 | core::Property<Container>& tracks(); |
1665 | 60 | void on_loop_status_changed(const core::ubuntu::media::Player::LoopStatus& loop_status); | ||
1666 | 61 | core::ubuntu::media::Player::LoopStatus loop_status() const; | ||
1667 | 62 | |||
1668 | 63 | /** Gets called when the shuffle property on the Player interface is changed | ||
1669 | 64 | * by the client */ | ||
1670 | 65 | void on_shuffle_changed(bool shuffle); | ||
1671 | 52 | 66 | ||
1672 | 53 | protected: | 67 | protected: |
1673 | 54 | core::Property<bool>& can_edit_tracks(); | 68 | core::Property<bool>& can_edit_tracks(); |
1674 | 55 | 69 | ||
1676 | 56 | core::Signal<void>& on_track_list_replaced(); | 70 | core::Signal<ContainerTrackIdTuple>& on_track_list_replaced(); |
1677 | 57 | core::Signal<Track::Id>& on_track_added(); | 71 | core::Signal<Track::Id>& on_track_added(); |
1678 | 58 | core::Signal<Track::Id>& on_track_removed(); | ||
1679 | 59 | core::Signal<Track::Id>& on_track_changed(); | 72 | core::Signal<Track::Id>& on_track_changed(); |
1680 | 60 | 73 | ||
1681 | 61 | private: | 74 | private: |
1682 | 62 | struct Private; | 75 | struct Private; |
1683 | 63 | std::unique_ptr<Private> d; | 76 | std::unique_ptr<Private> d; |
1684 | 64 | }; | 77 | }; |
1685 | 78 | |||
1686 | 79 | // operator<< pretty prints the given TrackList status to the given output stream. | ||
1687 | 80 | std::ostream& operator<<(std::ostream& out, const core::ubuntu::media::TrackList& tracklist); | ||
1688 | 81 | |||
1689 | 65 | } | 82 | } |
1690 | 66 | } | 83 | } |
1691 | 67 | } | 84 | } |
1692 | 68 | 85 | ||
1693 | === modified file 'src/core/media/track_list_stub.cpp' | |||
1694 | --- src/core/media/track_list_stub.cpp 2014-02-12 15:53:57 +0000 | |||
1695 | +++ src/core/media/track_list_stub.cpp 2015-04-20 17:49:07 +0000 | |||
1696 | @@ -43,10 +43,10 @@ | |||
1697 | 43 | Private( | 43 | Private( |
1698 | 44 | TrackListStub* impl, | 44 | TrackListStub* impl, |
1699 | 45 | const std::shared_ptr<media::Player>& parent, | 45 | const std::shared_ptr<media::Player>& parent, |
1701 | 46 | const dbus::types::ObjectPath& op) | 46 | const dbus::Object::Ptr& object) |
1702 | 47 | : impl(impl), | 47 | : impl(impl), |
1703 | 48 | parent(parent), | 48 | parent(parent), |
1705 | 49 | object(impl->access_service()->object_for_path(op)), | 49 | object(object), |
1706 | 50 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), | 50 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), |
1707 | 51 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()) | 51 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()) |
1708 | 52 | { | 52 | { |
1709 | @@ -59,17 +59,17 @@ | |||
1710 | 59 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; | 59 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; |
1711 | 60 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; | 60 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; |
1712 | 61 | 61 | ||
1714 | 62 | core::Signal<void> on_track_list_replaced; | 62 | core::Signal<media::TrackList::ContainerTrackIdTuple> on_track_list_replaced; |
1715 | 63 | core::Signal<Track::Id> on_track_added; | 63 | core::Signal<Track::Id> on_track_added; |
1716 | 64 | core::Signal<Track::Id> on_track_removed; | 64 | core::Signal<Track::Id> on_track_removed; |
1717 | 65 | core::Signal<Track::Id> on_track_changed; | 65 | core::Signal<Track::Id> on_track_changed; |
1718 | 66 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; | ||
1719 | 66 | }; | 67 | }; |
1720 | 67 | 68 | ||
1721 | 68 | media::TrackListStub::TrackListStub( | 69 | media::TrackListStub::TrackListStub( |
1722 | 69 | const std::shared_ptr<media::Player>& parent, | 70 | const std::shared_ptr<media::Player>& parent, |
1726 | 70 | const core::dbus::types::ObjectPath& op) | 71 | const core::dbus::Object::Ptr& object) |
1727 | 71 | : dbus::Stub<media::TrackList>(the_session_bus()), | 72 | : d(new Private(this, parent, object)) |
1725 | 72 | d(new Private(this, parent, op)) | ||
1728 | 73 | { | 73 | { |
1729 | 74 | } | 74 | } |
1730 | 75 | 75 | ||
1731 | @@ -89,8 +89,7 @@ | |||
1732 | 89 | 89 | ||
1733 | 90 | media::Track::MetaData media::TrackListStub::query_meta_data_for_track(const media::Track::Id& id) | 90 | media::Track::MetaData media::TrackListStub::query_meta_data_for_track(const media::Track::Id& id) |
1734 | 91 | { | 91 | { |
1737 | 92 | auto op | 92 | auto op = d->object->invoke_method_synchronously< |
1736 | 93 | = d->object->invoke_method_synchronously< | ||
1738 | 94 | mpris::TrackList::GetTracksMetadata, | 93 | mpris::TrackList::GetTracksMetadata, |
1739 | 95 | std::map<std::string, std::string>>(id); | 94 | std::map<std::string, std::string>>(id); |
1740 | 96 | 95 | ||
1741 | @@ -128,8 +127,9 @@ | |||
1742 | 128 | throw std::runtime_error("Problem removing track: " + op.error()); | 127 | throw std::runtime_error("Problem removing track: " + op.error()); |
1743 | 129 | } | 128 | } |
1744 | 130 | 129 | ||
1746 | 131 | void media::TrackListStub::go_to(const media::Track::Id& track) | 130 | void media::TrackListStub::go_to(const media::Track::Id& track, bool toggle_player_state) |
1747 | 132 | { | 131 | { |
1748 | 132 | (void) toggle_player_state; | ||
1749 | 133 | auto op = d->object->invoke_method_synchronously<mpris::TrackList::GoTo, void>( | 133 | auto op = d->object->invoke_method_synchronously<mpris::TrackList::GoTo, void>( |
1750 | 134 | track); | 134 | track); |
1751 | 135 | 135 | ||
1752 | @@ -137,18 +137,36 @@ | |||
1753 | 137 | throw std::runtime_error("Problem adding track: " + op.error()); | 137 | throw std::runtime_error("Problem adding track: " + op.error()); |
1754 | 138 | } | 138 | } |
1755 | 139 | 139 | ||
1758 | 140 | const core::Signal<void>& media::TrackListStub::on_track_list_replaced() const | 140 | void media::TrackListStub::shuffle_tracks() |
1759 | 141 | { | 141 | { |
1760 | 142 | std::cerr << "shuffle_tracks() does nothing from the client side" << std::endl; | ||
1761 | 143 | } | ||
1762 | 144 | |||
1763 | 145 | void media::TrackListStub::unshuffle_tracks() | ||
1764 | 146 | { | ||
1765 | 147 | std::cerr << "unshuffle_tracks() does nothing from the client side" << std::endl; | ||
1766 | 148 | } | ||
1767 | 149 | |||
1768 | 150 | void media::TrackListStub::reset() | ||
1769 | 151 | { | ||
1770 | 152 | std::cerr << "reset() does nothing from the client side" << std::endl; | ||
1771 | 153 | } | ||
1772 | 154 | |||
1773 | 155 | const core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListStub::on_track_list_replaced() const | ||
1774 | 156 | { | ||
1775 | 157 | std::cout << "Signal on_track_list_replaced arrived via the bus" << std::endl; | ||
1776 | 142 | return d->on_track_list_replaced; | 158 | return d->on_track_list_replaced; |
1777 | 143 | } | 159 | } |
1778 | 144 | 160 | ||
1779 | 145 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_added() const | 161 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_added() const |
1780 | 146 | { | 162 | { |
1781 | 163 | std::cout << "Signal on_track_added arrived via the bus" << std::endl; | ||
1782 | 147 | return d->on_track_added; | 164 | return d->on_track_added; |
1783 | 148 | } | 165 | } |
1784 | 149 | 166 | ||
1785 | 150 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_removed() const | 167 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_removed() const |
1786 | 151 | { | 168 | { |
1787 | 169 | std::cout << "Signal on_track_removed arrived via the bus" << std::endl; | ||
1788 | 152 | return d->on_track_removed; | 170 | return d->on_track_removed; |
1789 | 153 | } | 171 | } |
1790 | 154 | 172 | ||
1791 | @@ -156,3 +174,8 @@ | |||
1792 | 156 | { | 174 | { |
1793 | 157 | return d->on_track_changed; | 175 | return d->on_track_changed; |
1794 | 158 | } | 176 | } |
1795 | 177 | |||
1796 | 178 | const core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListStub::on_go_to_track() const | ||
1797 | 179 | { | ||
1798 | 180 | return d->on_go_to_track; | ||
1799 | 181 | } | ||
1800 | 159 | 182 | ||
1801 | === modified file 'src/core/media/track_list_stub.h' | |||
1802 | --- src/core/media/track_list_stub.h 2014-02-12 15:53:57 +0000 | |||
1803 | +++ src/core/media/track_list_stub.h 2015-04-20 17:49:07 +0000 | |||
1804 | @@ -33,12 +33,12 @@ | |||
1805 | 33 | { | 33 | { |
1806 | 34 | namespace media | 34 | namespace media |
1807 | 35 | { | 35 | { |
1809 | 36 | class TrackListStub : public core::dbus::Stub<core::ubuntu::media::TrackList> | 36 | class TrackListStub : public core::ubuntu::media::TrackList |
1810 | 37 | { | 37 | { |
1811 | 38 | public: | 38 | public: |
1812 | 39 | TrackListStub( | 39 | TrackListStub( |
1813 | 40 | const std::shared_ptr<Player>& parent, | 40 | const std::shared_ptr<Player>& parent, |
1815 | 41 | const core::dbus::types::ObjectPath& op); | 41 | const core::dbus::Object::Ptr& object); |
1816 | 42 | ~TrackListStub(); | 42 | ~TrackListStub(); |
1817 | 43 | 43 | ||
1818 | 44 | const core::Property<bool>& can_edit_tracks() const; | 44 | const core::Property<bool>& can_edit_tracks() const; |
1819 | @@ -49,12 +49,18 @@ | |||
1820 | 49 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); | 49 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); |
1821 | 50 | void remove_track(const Track::Id& id); | 50 | void remove_track(const Track::Id& id); |
1822 | 51 | 51 | ||
1826 | 52 | void go_to(const Track::Id& track); | 52 | void go_to(const Track::Id& track, bool toggle_player_state); |
1827 | 53 | 53 | ||
1828 | 54 | const core::Signal<void>& on_track_list_replaced() const; | 54 | void shuffle_tracks(); |
1829 | 55 | void unshuffle_tracks(); | ||
1830 | 56 | |||
1831 | 57 | void reset(); | ||
1832 | 58 | |||
1833 | 59 | const core::Signal<ContainerTrackIdTuple>& on_track_list_replaced() const; | ||
1834 | 55 | const core::Signal<Track::Id>& on_track_added() const; | 60 | const core::Signal<Track::Id>& on_track_added() const; |
1835 | 56 | const core::Signal<Track::Id>& on_track_removed() const; | 61 | const core::Signal<Track::Id>& on_track_removed() const; |
1836 | 57 | const core::Signal<Track::Id>& on_track_changed() const; | 62 | const core::Signal<Track::Id>& on_track_changed() const; |
1837 | 63 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; | ||
1838 | 58 | 64 | ||
1839 | 59 | private: | 65 | private: |
1840 | 60 | struct Private; | 66 | struct Private; |
1841 | 61 | 67 | ||
1842 | === modified file 'tests/CMakeLists.txt' | |||
1843 | --- tests/CMakeLists.txt 2014-11-26 11:04:57 +0000 | |||
1844 | +++ tests/CMakeLists.txt 2015-04-20 17:49:07 +0000 | |||
1845 | @@ -51,4 +51,5 @@ | |||
1846 | 51 | ) | 51 | ) |
1847 | 52 | 52 | ||
1848 | 53 | # add_subdirectory(acceptance-tests) | 53 | # add_subdirectory(acceptance-tests) |
1849 | 54 | add_subdirectory(test-track-list) | ||
1850 | 54 | add_subdirectory(unit-tests) | 55 | add_subdirectory(unit-tests) |
1851 | 55 | 56 | ||
1852 | === added directory 'tests/test-track-list' | |||
1853 | === added file 'tests/test-track-list/CMakeLists.txt' | |||
1854 | --- tests/test-track-list/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
1855 | +++ tests/test-track-list/CMakeLists.txt 2015-04-20 17:49:07 +0000 | |||
1856 | @@ -0,0 +1,17 @@ | |||
1857 | 1 | include_directories( | ||
1858 | 2 | ${CMAKE_SOURCE_DIR}/src) | ||
1859 | 3 | |||
1860 | 4 | add_executable( | ||
1861 | 5 | test_track_list | ||
1862 | 6 | test_track_list.cpp | ||
1863 | 7 | ) | ||
1864 | 8 | |||
1865 | 9 | target_link_libraries( | ||
1866 | 10 | test_track_list | ||
1867 | 11 | |||
1868 | 12 | media-hub-client | ||
1869 | 13 | |||
1870 | 14 | ${CMAKE_THREAD_LIBS_INIT} | ||
1871 | 15 | ${DBUS_LIBRARIES} | ||
1872 | 16 | ${PROCESS_CPP_LDFLAGS} | ||
1873 | 17 | ) | ||
1874 | 0 | 18 | ||
1875 | === added file 'tests/test-track-list/test_track_list.cpp' | |||
1876 | --- tests/test-track-list/test_track_list.cpp 1970-01-01 00:00:00 +0000 | |||
1877 | +++ tests/test-track-list/test_track_list.cpp 2015-04-20 17:49:07 +0000 | |||
1878 | @@ -0,0 +1,346 @@ | |||
1879 | 1 | /* | ||
1880 | 2 | * Copyright © 2013-2015 Canonical Ltd. | ||
1881 | 3 | * | ||
1882 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1883 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
1884 | 6 | * as published by the Free Software Foundation. | ||
1885 | 7 | * | ||
1886 | 8 | * This program is distributed in the hope that it will be useful, | ||
1887 | 9 | * but WITHOUT ANY WARRANTY {} without even the implied warranty of | ||
1888 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1889 | 11 | * GNU Lesser General Public License for more details. | ||
1890 | 12 | * | ||
1891 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1892 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1893 | 15 | * | ||
1894 | 16 | * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | ||
1895 | 17 | */ | ||
1896 | 18 | |||
1897 | 19 | #include "test_track_list.h" | ||
1898 | 20 | #include "../../src/core/media/util/timeout.h" | ||
1899 | 21 | |||
1900 | 22 | #include <core/media/service.h> | ||
1901 | 23 | #include <core/media/track_list.h> | ||
1902 | 24 | |||
1903 | 25 | #include <cassert> | ||
1904 | 26 | #include <future> | ||
1905 | 27 | #include <iostream> | ||
1906 | 28 | #include <thread> | ||
1907 | 29 | |||
1908 | 30 | namespace media = core::ubuntu::media; | ||
1909 | 31 | using namespace std; | ||
1910 | 32 | |||
1911 | 33 | media::TestTrackList::TestTrackList() | ||
1912 | 34 | { | ||
1913 | 35 | try { | ||
1914 | 36 | m_hubService = media::Service::Client::instance(); | ||
1915 | 37 | } | ||
1916 | 38 | catch (std::runtime_error &e) { | ||
1917 | 39 | cerr << "FATAL: Failed to connect to media-hub service: " << e.what() << endl; | ||
1918 | 40 | } | ||
1919 | 41 | } | ||
1920 | 42 | |||
1921 | 43 | media::TestTrackList::~TestTrackList() | ||
1922 | 44 | { | ||
1923 | 45 | } | ||
1924 | 46 | |||
1925 | 47 | void media::TestTrackList::create_new_player_session() | ||
1926 | 48 | { | ||
1927 | 49 | try { | ||
1928 | 50 | m_hubPlayerSession = m_hubService->create_session(media::Player::Client::default_configuration()); | ||
1929 | 51 | } | ||
1930 | 52 | catch (std::runtime_error &e) { | ||
1931 | 53 | cerr << "FATAL: Failed to start a new media-hub player session: " << e.what() << endl; | ||
1932 | 54 | } | ||
1933 | 55 | |||
1934 | 56 | try { | ||
1935 | 57 | m_hubTrackList = m_hubPlayerSession->track_list(); | ||
1936 | 58 | } | ||
1937 | 59 | catch (std::runtime_error &e) { | ||
1938 | 60 | cerr << "FATAL: Failed to retrieve the current player's TrackList: " << e.what() << endl; | ||
1939 | 61 | } | ||
1940 | 62 | } | ||
1941 | 63 | |||
1942 | 64 | void media::TestTrackList::destroy_player_session() | ||
1943 | 65 | { | ||
1944 | 66 | // TODO: explicitly add a destroy session to the Service class after ricmm lands his new creation_session | ||
1945 | 67 | // that returns a session ID. This will allow me to clear the tracklist after each test. | ||
1946 | 68 | m_hubPlayerSession.reset(); | ||
1947 | 69 | } | ||
1948 | 70 | |||
1949 | 71 | void media::TestTrackList::add_track(const string &uri, bool make_current) | ||
1950 | 72 | { | ||
1951 | 73 | assert (m_hubTrackList.get() != nullptr); | ||
1952 | 74 | |||
1953 | 75 | cout << "Adding " << uri << " to the TrackList for playback." << endl; | ||
1954 | 76 | |||
1955 | 77 | try { | ||
1956 | 78 | bool can_edit_tracks = m_hubTrackList->can_edit_tracks(); | ||
1957 | 79 | cout << "can_edit_tracks: " << (can_edit_tracks ? "yes" : "no") << std::endl; | ||
1958 | 80 | if (can_edit_tracks) | ||
1959 | 81 | m_hubTrackList->add_track_with_uri_at(uri, media::TrackList::after_empty_track(), make_current); | ||
1960 | 82 | else | ||
1961 | 83 | cerr << "Can't add track to TrackList since can_edit_tracks is false" << endl; | ||
1962 | 84 | } | ||
1963 | 85 | catch (std::runtime_error &e) { | ||
1964 | 86 | cerr << "ERROR: Failed to add track " << uri << " to tracklist: " << e.what() << endl; | ||
1965 | 87 | } | ||
1966 | 88 | } | ||
1967 | 89 | |||
1968 | 90 | #include <unistd.h> | ||
1969 | 91 | void media::TestTrackList::test_basic_playback(const std::string &uri1, const std::string &uri2) | ||
1970 | 92 | { | ||
1971 | 93 | cout << "--> Running test: test_basic_playback" << std::endl; | ||
1972 | 94 | |||
1973 | 95 | core::Connection c =m_hubTrackList->on_track_added().connect([](const media::Track::Id &new_id) | ||
1974 | 96 | { | ||
1975 | 97 | cout << "Added track to TrackList with Id: " << new_id << endl; | ||
1976 | 98 | }); | ||
1977 | 99 | |||
1978 | 100 | //create_new_player_session(); | ||
1979 | 101 | |||
1980 | 102 | m_hubPlayerSession->open_uri(uri1); | ||
1981 | 103 | if (!uri2.empty()) | ||
1982 | 104 | add_track(uri2); | ||
1983 | 105 | |||
1984 | 106 | //cout << "Waiting for track to be added to TrackList" << endl; | ||
1985 | 107 | //media::Track::Id id = wait_for_on_track_added(); | ||
1986 | 108 | |||
1987 | 109 | m_hubPlayerSession->play(); | ||
1988 | 110 | m_hubPlayerSession->loop_status() = media::Player::LoopStatus::none; | ||
1989 | 111 | |||
1990 | 112 | if (m_hubPlayerSession->playback_status() == media::Player::PlaybackStatus::playing) | ||
1991 | 113 | { | ||
1992 | 114 | cout << "Waiting for first track to finish playing..." << endl; | ||
1993 | 115 | wait_for_about_to_finish(); | ||
1994 | 116 | cout << "Basic playback was successful" << endl; | ||
1995 | 117 | } | ||
1996 | 118 | |||
1997 | 119 | c.disconnect(); | ||
1998 | 120 | |||
1999 | 121 | //destroy_player_session(); | ||
2000 | 122 | } | ||
2001 | 123 | |||
2002 | 124 | void media::TestTrackList::test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2) | ||
2003 | 125 | { | ||
2004 | 126 | cout << "--> Running test: test_ensure_tracklist_is_not_empty" << std::endl; | ||
2005 | 127 | |||
2006 | 128 | add_track(uri1); | ||
2007 | 129 | if (!uri2.empty()) | ||
2008 | 130 | add_track(uri2); | ||
2009 | 131 | |||
2010 | 132 | if (m_hubTrackList->tracks()->size() == 1 or m_hubTrackList->tracks()->size() == 2) | ||
2011 | 133 | cout << "TrackList is not empty, test success" << endl; | ||
2012 | 134 | else | ||
2013 | 135 | cout << "TrackList is empty, test failure" << endl; | ||
2014 | 136 | } | ||
2015 | 137 | |||
2016 | 138 | void media::TestTrackList::test_has_next_track(const std::string &uri1, const std::string &uri2) | ||
2017 | 139 | { | ||
2018 | 140 | cout << "--> Running test: test_has_next_track" << std::endl; | ||
2019 | 141 | |||
2020 | 142 | //create_new_player_session(); | ||
2021 | 143 | |||
2022 | 144 | add_track(uri1); | ||
2023 | 145 | add_track(uri2); | ||
2024 | 146 | |||
2025 | 147 | m_hubPlayerSession->play(); | ||
2026 | 148 | m_hubPlayerSession->loop_status() = media::Player::LoopStatus::none; | ||
2027 | 149 | |||
2028 | 150 | if (m_hubPlayerSession->playback_status() == media::Player::PlaybackStatus::playing) | ||
2029 | 151 | { | ||
2030 | 152 | cout << "Waiting for first track to finish playing..." << endl; | ||
2031 | 153 | wait_for_about_to_finish(); | ||
2032 | 154 | cout << "Waiting for second track to finish playing..." << endl; | ||
2033 | 155 | wait_for_about_to_finish(); | ||
2034 | 156 | cout << "Both tracks played successfully" << endl; | ||
2035 | 157 | } | ||
2036 | 158 | else | ||
2037 | 159 | cerr << "Playback did not start successfully" << endl; | ||
2038 | 160 | |||
2039 | 161 | //destroy_player_session(); | ||
2040 | 162 | } | ||
2041 | 163 | |||
2042 | 164 | void media::TestTrackList::test_shuffle(const std::string &uri1, const std::string &uri2, const std::string &uri3) | ||
2043 | 165 | { | ||
2044 | 166 | cout << "--> Running test: test_shuffle" << std::endl; | ||
2045 | 167 | |||
2046 | 168 | add_track(uri1); | ||
2047 | 169 | add_track(uri2); | ||
2048 | 170 | add_track(uri3); | ||
2049 | 171 | add_track(uri3); | ||
2050 | 172 | add_track(uri2); | ||
2051 | 173 | add_track(uri1); | ||
2052 | 174 | add_track(uri1); | ||
2053 | 175 | add_track(uri2); | ||
2054 | 176 | |||
2055 | 177 | m_hubPlayerSession->play(); | ||
2056 | 178 | m_hubPlayerSession->loop_status() = media::Player::LoopStatus::playlist; | ||
2057 | 179 | m_hubPlayerSession->shuffle() = true; | ||
2058 | 180 | |||
2059 | 181 | if (m_hubPlayerSession->playback_status() == media::Player::PlaybackStatus::playing) | ||
2060 | 182 | { | ||
2061 | 183 | cout << "Waiting for first track to finish playing..." << endl; | ||
2062 | 184 | wait_for_about_to_finish(); | ||
2063 | 185 | |||
2064 | 186 | cout << "Turning off shuffle mode" << endl; | ||
2065 | 187 | m_hubPlayerSession->shuffle() = false; | ||
2066 | 188 | |||
2067 | 189 | cout << "Waiting for second track to finish playing..." << endl; | ||
2068 | 190 | wait_for_about_to_finish(); | ||
2069 | 191 | |||
2070 | 192 | cout << "Going straight to the Track with Id of '/core/ubuntu/media/Service/sessions/0/TrackList/4'" << std::endl; | ||
2071 | 193 | const media::Track::Id id{"/core/ubuntu/media/Service/sessions/0/TrackList/4"}; | ||
2072 | 194 | const bool toggle_player_state = true; | ||
2073 | 195 | m_hubTrackList->go_to(id, toggle_player_state); | ||
2074 | 196 | cout << "Waiting for third track to finish playing..." << endl; | ||
2075 | 197 | wait_for_about_to_finish(); | ||
2076 | 198 | } | ||
2077 | 199 | else | ||
2078 | 200 | cerr << "Playback did not start successfully" << endl; | ||
2079 | 201 | } | ||
2080 | 202 | |||
2081 | 203 | void media::TestTrackList::test_remove_track(const std::string &uri1, const std::string &uri2, const std::string &uri3) | ||
2082 | 204 | { | ||
2083 | 205 | cout << "--> Running test: test_remove_track" << std::endl; | ||
2084 | 206 | |||
2085 | 207 | core::Connection c =m_hubTrackList->on_track_removed().connect([](const media::Track::Id &new_id) | ||
2086 | 208 | { | ||
2087 | 209 | cout << "Removed track from TrackList with Id: " << new_id << endl; | ||
2088 | 210 | }); | ||
2089 | 211 | |||
2090 | 212 | add_track(uri1); | ||
2091 | 213 | add_track(uri2); | ||
2092 | 214 | add_track(uri3); | ||
2093 | 215 | |||
2094 | 216 | m_hubPlayerSession->play(); | ||
2095 | 217 | |||
2096 | 218 | if (m_hubPlayerSession->playback_status() == media::Player::PlaybackStatus::playing) | ||
2097 | 219 | { | ||
2098 | 220 | cout << "Waiting for first track to finish playing..." << endl; | ||
2099 | 221 | wait_for_about_to_finish(); | ||
2100 | 222 | |||
2101 | 223 | const media::Track::Id id{"/core/ubuntu/media/Service/sessions/0/TrackList/1"}; | ||
2102 | 224 | m_hubTrackList->remove_track(id); | ||
2103 | 225 | |||
2104 | 226 | cout << "Waiting for track after removed track to finish playing..." << endl; | ||
2105 | 227 | wait_for_about_to_finish(); | ||
2106 | 228 | } | ||
2107 | 229 | else | ||
2108 | 230 | cerr << "Playback did not start successfully" << endl; | ||
2109 | 231 | } | ||
2110 | 232 | |||
2111 | 233 | template<class T> | ||
2112 | 234 | bool media::TestTrackList::verify_signal_is_emitted(const core::Signal<T> &signal, const std::chrono::milliseconds &timeout) | ||
2113 | 235 | { | ||
2114 | 236 | bool signal_emitted = false; | ||
2115 | 237 | #if 0 | ||
2116 | 238 | static const std::chrono::milliseconds timeout{1000}; | ||
2117 | 239 | media::timeout(timeout.count(), true, [wp]() | ||
2118 | 240 | { | ||
2119 | 241 | if (auto sp = wp.lock()) | ||
2120 | 242 | sp->on_client_died(); | ||
2121 | 243 | }); | ||
2122 | 244 | signal.connect([signal_emitted]() | ||
2123 | 245 | { | ||
2124 | 246 | }); | ||
2125 | 247 | #endif | ||
2126 | 248 | |||
2127 | 249 | return false; | ||
2128 | 250 | } | ||
2129 | 251 | |||
2130 | 252 | void media::TestTrackList::wait_for_about_to_finish() | ||
2131 | 253 | { | ||
2132 | 254 | bool received_about_to_finish = false; | ||
2133 | 255 | core::Connection c = m_hubPlayerSession->about_to_finish().connect([&received_about_to_finish]() | ||
2134 | 256 | { | ||
2135 | 257 | cout << "AboutToFinish signaled" << endl; | ||
2136 | 258 | received_about_to_finish = true; | ||
2137 | 259 | }); | ||
2138 | 260 | while (!received_about_to_finish) | ||
2139 | 261 | std::this_thread::yield(); | ||
2140 | 262 | |||
2141 | 263 | c.disconnect(); | ||
2142 | 264 | } | ||
2143 | 265 | |||
2144 | 266 | void media::TestTrackList::wait_for_end_of_stream() | ||
2145 | 267 | { | ||
2146 | 268 | bool reached_end_of_first_track = false; | ||
2147 | 269 | core::Connection c = m_hubPlayerSession->end_of_stream().connect([&reached_end_of_first_track]() | ||
2148 | 270 | { | ||
2149 | 271 | cout << "EndOfStream signaled" << endl; | ||
2150 | 272 | reached_end_of_first_track = true; | ||
2151 | 273 | }); | ||
2152 | 274 | while (!reached_end_of_first_track) | ||
2153 | 275 | std::this_thread::yield(); | ||
2154 | 276 | |||
2155 | 277 | c.disconnect(); | ||
2156 | 278 | } | ||
2157 | 279 | |||
2158 | 280 | void media::TestTrackList::wait_for_playback_status_changed(core::ubuntu::media::Player::PlaybackStatus status) | ||
2159 | 281 | { | ||
2160 | 282 | bool received_playback_status_changed = false; | ||
2161 | 283 | core::Connection c = m_hubPlayerSession->playback_status().changed().connect([&received_playback_status_changed, &status](media::Player::PlaybackStatus new_status) | ||
2162 | 284 | { | ||
2163 | 285 | cout << "PlaybackStatusChanged signaled" << endl; | ||
2164 | 286 | if (new_status == status) | ||
2165 | 287 | received_playback_status_changed = true; | ||
2166 | 288 | }); | ||
2167 | 289 | while (!received_playback_status_changed) | ||
2168 | 290 | std::this_thread::yield(); | ||
2169 | 291 | |||
2170 | 292 | c.disconnect(); | ||
2171 | 293 | } | ||
2172 | 294 | |||
2173 | 295 | core::ubuntu::media::Track::Id media::TestTrackList::wait_for_on_track_added() | ||
2174 | 296 | { | ||
2175 | 297 | media::Track::Id id; | ||
2176 | 298 | bool received_on_track_added = false; | ||
2177 | 299 | core::Connection c = m_hubTrackList->on_track_added().connect([&received_on_track_added, &id](const media::Track::Id &new_id) | ||
2178 | 300 | { | ||
2179 | 301 | cout << "OnTrackAdded signaled" << endl; | ||
2180 | 302 | id = new_id; | ||
2181 | 303 | received_on_track_added = true; | ||
2182 | 304 | }); | ||
2183 | 305 | while (!received_on_track_added) | ||
2184 | 306 | std::this_thread::yield(); | ||
2185 | 307 | |||
2186 | 308 | c.disconnect(); | ||
2187 | 309 | |||
2188 | 310 | return id; | ||
2189 | 311 | } | ||
2190 | 312 | |||
2191 | 313 | int main (int argc, char **argv) | ||
2192 | 314 | { | ||
2193 | 315 | shared_ptr<media::TestTrackList> tracklist = make_shared<media::TestTrackList>(); | ||
2194 | 316 | |||
2195 | 317 | if (argc == 2) | ||
2196 | 318 | { | ||
2197 | 319 | tracklist->create_new_player_session(); | ||
2198 | 320 | tracklist->test_basic_playback(argv[1]); | ||
2199 | 321 | tracklist->test_ensure_tracklist_is_not_empty(argv[1]); | ||
2200 | 322 | } | ||
2201 | 323 | else if (argc == 3) | ||
2202 | 324 | { | ||
2203 | 325 | tracklist->create_new_player_session(); | ||
2204 | 326 | tracklist->test_basic_playback(argv[1], argv[2]); | ||
2205 | 327 | tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]); | ||
2206 | 328 | tracklist->test_has_next_track(argv[1], argv[2]); | ||
2207 | 329 | } | ||
2208 | 330 | else if (argc == 4) | ||
2209 | 331 | { | ||
2210 | 332 | tracklist->create_new_player_session(); | ||
2211 | 333 | tracklist->test_basic_playback(argv[1]); | ||
2212 | 334 | tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]); | ||
2213 | 335 | tracklist->test_has_next_track(argv[1], argv[2]); | ||
2214 | 336 | tracklist->test_shuffle(argv[1], argv[2], argv[3]); | ||
2215 | 337 | tracklist->test_remove_track(argv[1], argv[2], argv[3]); | ||
2216 | 338 | } | ||
2217 | 339 | else | ||
2218 | 340 | { | ||
2219 | 341 | cout << "Can't test TrackList, no track(s) specified." << endl; | ||
2220 | 342 | cout << argv[0] << " <track_uri_1> [<track_uri_2>] [<track_uri_3>]" << endl; | ||
2221 | 343 | } | ||
2222 | 344 | |||
2223 | 345 | return 0; | ||
2224 | 346 | } | ||
2225 | 0 | 347 | ||
2226 | === added file 'tests/test-track-list/test_track_list.h' | |||
2227 | --- tests/test-track-list/test_track_list.h 1970-01-01 00:00:00 +0000 | |||
2228 | +++ tests/test-track-list/test_track_list.h 2015-04-20 17:49:07 +0000 | |||
2229 | @@ -0,0 +1,86 @@ | |||
2230 | 1 | /* | ||
2231 | 2 | * Copyright © 2013-2015 Canonical Ltd. | ||
2232 | 3 | * | ||
2233 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2234 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
2235 | 6 | * as published by the Free Software Foundation. | ||
2236 | 7 | * | ||
2237 | 8 | * This program is distributed in the hope that it will be useful, | ||
2238 | 9 | * but WITHOUT ANY WARRANTY {} without even the implied warranty of | ||
2239 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2240 | 11 | * GNU Lesser General Public License for more details. | ||
2241 | 12 | * | ||
2242 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2243 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2244 | 15 | * | ||
2245 | 16 | * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | ||
2246 | 17 | */ | ||
2247 | 18 | |||
2248 | 19 | #ifndef TEST_TRACK_LIST_H_ | ||
2249 | 20 | #define TEST_TRACK_LIST_H_ | ||
2250 | 21 | |||
2251 | 22 | #include <core/media/player.h> | ||
2252 | 23 | #include <core/media/track.h> | ||
2253 | 24 | |||
2254 | 25 | #include <core/dbus/signal.h> | ||
2255 | 26 | |||
2256 | 27 | #include <chrono> | ||
2257 | 28 | #include <memory> | ||
2258 | 29 | #include <string> | ||
2259 | 30 | |||
2260 | 31 | namespace core | ||
2261 | 32 | { | ||
2262 | 33 | namespace ubuntu | ||
2263 | 34 | { | ||
2264 | 35 | namespace media | ||
2265 | 36 | { | ||
2266 | 37 | |||
2267 | 38 | class Player; | ||
2268 | 39 | class Service; | ||
2269 | 40 | class TrackList; | ||
2270 | 41 | |||
2271 | 42 | class TestTrackList | ||
2272 | 43 | { | ||
2273 | 44 | public: | ||
2274 | 45 | TestTrackList(); | ||
2275 | 46 | ~TestTrackList(); | ||
2276 | 47 | |||
2277 | 48 | void create_new_player_session(); | ||
2278 | 49 | void destroy_player_session(); | ||
2279 | 50 | |||
2280 | 51 | void add_track(const std::string &uri, bool make_current = false); | ||
2281 | 52 | |||
2282 | 53 | // Takes in one or two files for playback, adds it/them to the TrackList, and plays | ||
2283 | 54 | void test_basic_playback(const std::string &uri1, const std::string &uri2 = std::string{}); | ||
2284 | 55 | |||
2285 | 56 | void test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2 = std::string{}); | ||
2286 | 57 | |||
2287 | 58 | // Takes in one or two files for playback, adds it/them to the TrackList, plays and makes sure | ||
2288 | 59 | // that the Player advances the TrackList | ||
2289 | 60 | void test_has_next_track(const std::string &uri1, const std::string &uri2); | ||
2290 | 61 | |||
2291 | 62 | void test_shuffle(const std::string &uri1, const std::string &uri2, const std::string &uri3); | ||
2292 | 63 | |||
2293 | 64 | void test_remove_track(const std::string &uri1, const std::string &uri2, const std::string &uri3); | ||
2294 | 65 | |||
2295 | 66 | protected: | ||
2296 | 67 | // Synchronously verify that a signal is emitted waiting up to timeout milliseconds | ||
2297 | 68 | template<class T> | ||
2298 | 69 | bool verify_signal_is_emitted(const core::Signal<T> &signal, const std::chrono::milliseconds &timeout); | ||
2299 | 70 | |||
2300 | 71 | void wait_for_about_to_finish(); | ||
2301 | 72 | void wait_for_end_of_stream(); | ||
2302 | 73 | void wait_for_playback_status_changed(core::ubuntu::media::Player::PlaybackStatus status); | ||
2303 | 74 | core::ubuntu::media::Track::Id wait_for_on_track_added(); | ||
2304 | 75 | |||
2305 | 76 | private: | ||
2306 | 77 | std::shared_ptr<core::ubuntu::media::Service> m_hubService; | ||
2307 | 78 | std::shared_ptr<core::ubuntu::media::Player> m_hubPlayerSession; | ||
2308 | 79 | std::shared_ptr<core::ubuntu::media::TrackList> m_hubTrackList; | ||
2309 | 80 | }; | ||
2310 | 81 | |||
2311 | 82 | } // media | ||
2312 | 83 | } // ubuntu | ||
2313 | 84 | } // core | ||
2314 | 85 | |||
2315 | 86 | #endif | ||
2316 | 0 | 87 | ||
2317 | === modified file 'tests/unit-tests/test-gstreamer-engine.cpp' | |||
2318 | --- tests/unit-tests/test-gstreamer-engine.cpp 2015-03-03 22:41:22 +0000 | |||
2319 | +++ tests/unit-tests/test-gstreamer-engine.cpp 2015-04-20 17:49:07 +0000 | |||
2320 | @@ -103,7 +103,8 @@ | |||
2321 | 103 | std::ref(wst), | 103 | std::ref(wst), |
2322 | 104 | std::placeholders::_1)); | 104 | std::placeholders::_1)); |
2323 | 105 | 105 | ||
2325 | 106 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 106 | static const bool do_pipeline_reset = true; |
2326 | 107 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2327 | 107 | EXPECT_TRUE(engine.play()); | 108 | EXPECT_TRUE(engine.play()); |
2328 | 108 | EXPECT_TRUE(wst.wait_for_state_for( | 109 | EXPECT_TRUE(wst.wait_for_state_for( |
2329 | 109 | core::ubuntu::media::Engine::State::playing, | 110 | core::ubuntu::media::Engine::State::playing, |
2330 | @@ -144,7 +145,8 @@ | |||
2331 | 144 | std::ref(wst), | 145 | std::ref(wst), |
2332 | 145 | std::placeholders::_1)); | 146 | std::placeholders::_1)); |
2333 | 146 | 147 | ||
2335 | 147 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 148 | static const bool do_pipeline_reset = true; |
2336 | 149 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2337 | 148 | EXPECT_TRUE(engine.play()); | 150 | EXPECT_TRUE(engine.play()); |
2338 | 149 | EXPECT_TRUE(wst.wait_for_state_for( | 151 | EXPECT_TRUE(wst.wait_for_state_for( |
2339 | 150 | core::ubuntu::media::Engine::State::playing, | 152 | core::ubuntu::media::Engine::State::playing, |
2340 | @@ -234,7 +236,8 @@ | |||
2341 | 234 | std::ref(wst), | 236 | std::ref(wst), |
2342 | 235 | std::placeholders::_1)); | 237 | std::placeholders::_1)); |
2343 | 236 | 238 | ||
2345 | 237 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 239 | static const bool do_pipeline_reset = true; |
2346 | 240 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2347 | 238 | EXPECT_TRUE(engine.play()); | 241 | EXPECT_TRUE(engine.play()); |
2348 | 239 | EXPECT_TRUE(wst.wait_for_state_for( | 242 | EXPECT_TRUE(wst.wait_for_state_for( |
2349 | 240 | core::ubuntu::media::Engine::State::playing, | 243 | core::ubuntu::media::Engine::State::playing, |
2350 | @@ -282,7 +285,8 @@ | |||
2351 | 282 | std::ref(wst), | 285 | std::ref(wst), |
2352 | 283 | std::placeholders::_1)); | 286 | std::placeholders::_1)); |
2353 | 284 | 287 | ||
2355 | 285 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 288 | static const bool do_pipeline_reset = true; |
2356 | 289 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2357 | 286 | EXPECT_TRUE(engine.play()); | 290 | EXPECT_TRUE(engine.play()); |
2358 | 287 | EXPECT_TRUE(wst.wait_for_state_for( | 291 | EXPECT_TRUE(wst.wait_for_state_for( |
2359 | 288 | core::ubuntu::media::Engine::State::playing, | 292 | core::ubuntu::media::Engine::State::playing, |
2360 | @@ -328,7 +332,8 @@ | |||
2361 | 328 | std::ref(wst), | 332 | std::ref(wst), |
2362 | 329 | std::placeholders::_1)); | 333 | std::placeholders::_1)); |
2363 | 330 | 334 | ||
2365 | 331 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 335 | static const bool do_pipeline_reset = true; |
2366 | 336 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2367 | 332 | EXPECT_TRUE(engine.play()); | 337 | EXPECT_TRUE(engine.play()); |
2368 | 333 | EXPECT_TRUE(wst.wait_for_state_for( | 338 | EXPECT_TRUE(wst.wait_for_state_for( |
2369 | 334 | core::ubuntu::media::Engine::State::playing, | 339 | core::ubuntu::media::Engine::State::playing, |
2370 | @@ -363,7 +368,8 @@ | |||
2371 | 363 | &core::testing::WaitableStateTransition<core::ubuntu::media::Engine::State>::trigger, | 368 | &core::testing::WaitableStateTransition<core::ubuntu::media::Engine::State>::trigger, |
2372 | 364 | std::ref(wst), | 369 | std::ref(wst), |
2373 | 365 | std::placeholders::_1)); | 370 | std::placeholders::_1)); |
2375 | 366 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri)); | 371 | static const bool do_pipeline_reset = true; |
2376 | 372 | EXPECT_TRUE(engine.open_resource_for_uri(test_file_uri, do_pipeline_reset)); | ||
2377 | 367 | EXPECT_TRUE(engine.play()); | 373 | EXPECT_TRUE(engine.play()); |
2378 | 368 | EXPECT_TRUE(wst.wait_for_state_for( | 374 | EXPECT_TRUE(wst.wait_for_state_for( |
2379 | 369 | core::ubuntu::media::Engine::State::playing, | 375 | core::ubuntu::media::Engine::State::playing, |
PASSED: Continuous integration, rev:135 jenkins. qa.ubuntu. com/job/ media-hub- ci/324/ jenkins. qa.ubuntu. com/job/ media-hub- vivid-amd64- ci/164 jenkins. qa.ubuntu. com/job/ media-hub- vivid-armhf- ci/164 jenkins. qa.ubuntu. com/job/ media-hub- vivid-armhf- ci/164/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ media-hub- vivid-i386- ci/164
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/media- hub-ci/ 324/rebuild
http://