Merge lp:~phablet-team/media-hub/bg-playlists-vivid into lp:media-hub/stable
- bg-playlists-vivid
- Merge into stable
Proposed by
Jim Hodapp
Status: | Merged |
---|---|
Approved by: | Alfonso Sanchez-Beato |
Approved revision: | 168 |
Merged at revision: | 151 |
Proposed branch: | lp:~phablet-team/media-hub/bg-playlists-vivid |
Merge into: | lp:media-hub/stable |
Diff against target: |
1277 lines (+463/-218) 15 files modified
debian/changelog (+11/-5) include/core/media/track.h (+1/-0) include/core/media/track_list.h (+8/-1) src/core/media/CMakeLists.txt (+1/-1) src/core/media/gstreamer/engine.cpp (+7/-6) src/core/media/mpris/track_list.h (+17/-6) src/core/media/null_track_list.h (+0/-114) src/core/media/player_implementation.cpp (+43/-17) src/core/media/service_skeleton.cpp (+18/-15) src/core/media/track.cpp (+7/-1) src/core/media/track_list_implementation.cpp (+34/-2) src/core/media/track_list_skeleton.cpp (+204/-32) src/core/media/track_list_skeleton.h (+12/-3) src/core/media/track_list_stub.cpp (+98/-15) src/core/media/track_list_stub.h (+2/-0) |
To merge this branch: | bzr merge lp:~phablet-team/media-hub/bg-playlists-vivid |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alfonso Sanchez-Beato | Approve | ||
Ubuntu Phablet Team | Pending | ||
Review via email: mp+266765@code.launchpad.net |
Commit message
* Connected the TrackList signals on the stub side
* Make has_next() more reliable
* Make next() and previous() work better
* Fix various bugs that arose from testing the TrackList code
Description of the change
* Connected the TrackList signals on the stub side
* Make has_next() more reliable
* Make next() and previous() work better
* Fix various bugs that arose from testing the TrackList code
To post a comment you must log in.
- 165. By Jim Hodapp
-
Bump version to release on vivid+overlay
- 166. By Jim Hodapp
-
Bump version to release on vivid+overlay take 2
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : | # |
review:
Needs Fixing
- 167. By Jim Hodapp
-
Address code review comments.
- 168. By Jim Hodapp
-
Make sure media-hub debian/control version is UNRELEASED
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : | # |
LGTM
review:
Approve
- 169. By Jim Hodapp
-
Don't export MPRIS MediaPlayer2 interface on dbus until we have a client that can take advantage of it
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2015-07-10 18:12:22 +0000 | |||
3 | +++ debian/changelog 2015-08-11 16:10:30 +0000 | |||
4 | @@ -1,4 +1,10 @@ | |||
6 | 1 | media-hub (3.1.0+15.10.20150710-0ubuntu1) wily; urgency=medium | 1 | media-hub (3.1.0+15.04.20150710-0ubuntu2) UNRELEASED; urgency=medium |
7 | 2 | |||
8 | 3 | * Change version to vivid+overlay | ||
9 | 4 | |||
10 | 5 | -- Jim Hodapp <jim.hodapp@canonical.com> Fri, 07 Aug 2015 10:46:42 -0400 | ||
11 | 6 | |||
12 | 7 | media-hub (3.1.0+15.04.20150710-0ubuntu1) vivid; urgency=medium | ||
13 | 2 | 8 | ||
14 | 3 | [ CI Train Bot ] | 9 | [ CI Train Bot ] |
15 | 4 | * New rebuild forced. | 10 | * New rebuild forced. |
16 | @@ -9,7 +15,7 @@ | |||
17 | 9 | 15 | ||
18 | 10 | -- CI Train Bot <ci-train-bot@canonical.com> Fri, 10 Jul 2015 18:12:21 +0000 | 16 | -- CI Train Bot <ci-train-bot@canonical.com> Fri, 10 Jul 2015 18:12:21 +0000 |
19 | 11 | 17 | ||
21 | 12 | media-hub (3.1.0+15.10.20150604-0ubuntu1) wily; urgency=medium | 18 | media-hub (3.1.0+15.04.20150604-0ubuntu1) vivid; urgency=medium |
22 | 13 | 19 | ||
23 | 14 | [ CI Train Bot ] | 20 | [ CI Train Bot ] |
24 | 15 | * New rebuild forced. | 21 | * New rebuild forced. |
25 | @@ -20,7 +26,7 @@ | |||
26 | 20 | 26 | ||
27 | 21 | -- CI Train Bot <ci-train-bot@canonical.com> Thu, 04 Jun 2015 14:18:22 +0000 | 27 | -- CI Train Bot <ci-train-bot@canonical.com> Thu, 04 Jun 2015 14:18:22 +0000 |
28 | 22 | 28 | ||
30 | 23 | media-hub (3.1.0+15.10.20150601-0ubuntu1) wily; urgency=medium | 29 | media-hub (3.1.0+15.04.20150601-0ubuntu1) vivid; urgency=medium |
31 | 24 | 30 | ||
32 | 25 | [ CI Train Bot ] | 31 | [ CI Train Bot ] |
33 | 26 | * New rebuild forced. | 32 | * New rebuild forced. |
34 | @@ -31,7 +37,7 @@ | |||
35 | 31 | 37 | ||
36 | 32 | -- CI Train Bot <ci-train-bot@canonical.com> Mon, 01 Jun 2015 16:31:53 +0000 | 38 | -- CI Train Bot <ci-train-bot@canonical.com> Mon, 01 Jun 2015 16:31:53 +0000 |
37 | 33 | 39 | ||
39 | 34 | media-hub (3.1.0+15.10.20150527.1-0ubuntu1) wily; urgency=medium | 40 | media-hub (3.1.0+15.04.20150527.1-0ubuntu1) vivid; urgency=medium |
40 | 35 | 41 | ||
41 | 36 | [ CI Train Bot ] | 42 | [ CI Train Bot ] |
42 | 37 | * New rebuild forced. | 43 | * New rebuild forced. |
43 | @@ -42,7 +48,7 @@ | |||
44 | 42 | 48 | ||
45 | 43 | -- CI Train Bot <ci-train-bot@canonical.com> Wed, 27 May 2015 18:38:16 +0000 | 49 | -- CI Train Bot <ci-train-bot@canonical.com> Wed, 27 May 2015 18:38:16 +0000 |
46 | 44 | 50 | ||
48 | 45 | media-hub (3.1.0+15.10.20150522-0ubuntu1) wily; urgency=medium | 51 | media-hub (3.1.0+15.04.20150522-0ubuntu1) vivid; urgency=medium |
49 | 46 | 52 | ||
50 | 47 | [ Jim Hodapp ] | 53 | [ Jim Hodapp ] |
51 | 48 | * Fix issues with not reporting failed decoding error to the client. | 54 | * Fix issues with not reporting failed decoding error to the client. |
52 | 49 | 55 | ||
53 | === modified file 'include/core/media/track.h' | |||
54 | --- include/core/media/track.h 2014-02-12 16:02:48 +0000 | |||
55 | +++ include/core/media/track.h 2015-08-11 16:10:30 +0000 | |||
56 | @@ -107,6 +107,7 @@ | |||
57 | 107 | bool operator==(const Track&) const; | 107 | bool operator==(const Track&) const; |
58 | 108 | 108 | ||
59 | 109 | virtual const Id& id() const; | 109 | virtual const Id& id() const; |
60 | 110 | virtual const UriType& uri() const; | ||
61 | 110 | /* | 111 | /* |
62 | 111 | class MetaData | 112 | class MetaData |
63 | 112 | { | 113 | { |
64 | 113 | 114 | ||
65 | === modified file 'include/core/media/track_list.h' | |||
66 | --- include/core/media/track_list.h 2015-04-29 21:18:20 +0000 | |||
67 | +++ include/core/media/track_list.h 2015-08-11 16:10:30 +0000 | |||
68 | @@ -25,8 +25,9 @@ | |||
69 | 25 | 25 | ||
70 | 26 | #include <functional> | 26 | #include <functional> |
71 | 27 | #include <iosfwd> | 27 | #include <iosfwd> |
72 | 28 | #include <memory> | ||
73 | 29 | #include <string> | ||
74 | 28 | #include <vector> | 30 | #include <vector> |
75 | 29 | #include <memory> | ||
76 | 30 | 31 | ||
77 | 31 | namespace core | 32 | namespace core |
78 | 32 | { | 33 | { |
79 | @@ -61,6 +62,9 @@ | |||
80 | 61 | /** Gets all the metadata available for a given Track. */ | 62 | /** Gets all the metadata available for a given Track. */ |
81 | 62 | virtual Track::MetaData query_meta_data_for_track(const Track::Id& id) = 0; | 63 | virtual Track::MetaData query_meta_data_for_track(const Track::Id& id) = 0; |
82 | 63 | 64 | ||
83 | 65 | /** Gets the URI for a given Track. */ | ||
84 | 66 | virtual Track::UriType query_uri_for_track(const Track::Id& id) = 0; | ||
85 | 67 | |||
86 | 64 | /** Adds a URI in the TrackList. */ | 68 | /** Adds a URI in the TrackList. */ |
87 | 65 | virtual void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current) = 0; | 69 | virtual void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current) = 0; |
88 | 66 | 70 | ||
89 | @@ -108,6 +112,9 @@ | |||
90 | 108 | /** Used to notify the Player of when the client requested that the Player should immediately play a new track. */ | 112 | /** Used to notify the Player of when the client requested that the Player should immediately play a new track. */ |
91 | 109 | virtual const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const = 0; | 113 | virtual const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const = 0; |
92 | 110 | 114 | ||
93 | 115 | /** Used to notify the Player of when the end of the tracklist has been reached. */ | ||
94 | 116 | virtual const core::Signal<void>& on_end_of_tracklist() const = 0; | ||
95 | 117 | |||
96 | 111 | protected: | 118 | protected: |
97 | 112 | TrackList(); | 119 | TrackList(); |
98 | 113 | }; | 120 | }; |
99 | 114 | 121 | ||
100 | === modified file 'src/core/media/CMakeLists.txt' | |||
101 | --- src/core/media/CMakeLists.txt 2015-02-24 15:22:19 +0000 | |||
102 | +++ src/core/media/CMakeLists.txt 2015-08-11 16:10:30 +0000 | |||
103 | @@ -88,7 +88,7 @@ | |||
104 | 88 | 88 | ||
105 | 89 | client_death_observer.cpp | 89 | client_death_observer.cpp |
106 | 90 | hashed_keyed_player_store.cpp | 90 | hashed_keyed_player_store.cpp |
108 | 91 | hybris_client_death_observer.cpp | 91 | hybris_client_death_observer.cpp |
109 | 92 | cover_art_resolver.cpp | 92 | cover_art_resolver.cpp |
110 | 93 | engine.cpp | 93 | engine.cpp |
111 | 94 | 94 | ||
112 | 95 | 95 | ||
113 | === modified file 'src/core/media/gstreamer/engine.cpp' | |||
114 | --- src/core/media/gstreamer/engine.cpp 2015-06-01 16:30:59 +0000 | |||
115 | +++ src/core/media/gstreamer/engine.cpp 2015-08-11 16:10:30 +0000 | |||
116 | @@ -374,7 +374,6 @@ | |||
117 | 374 | 374 | ||
118 | 375 | gstreamer::Engine::Engine() : d(new Private{}) | 375 | gstreamer::Engine::Engine() : d(new Private{}) |
119 | 376 | { | 376 | { |
120 | 377 | cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl; | ||
121 | 378 | d->state = media::Engine::State::no_media; | 377 | d->state = media::Engine::State::no_media; |
122 | 379 | } | 378 | } |
123 | 380 | 379 | ||
124 | @@ -413,7 +412,7 @@ | |||
125 | 413 | 412 | ||
126 | 414 | bool gstreamer::Engine::play() | 413 | bool gstreamer::Engine::play() |
127 | 415 | { | 414 | { |
129 | 416 | auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING); | 415 | const auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING); |
130 | 417 | 416 | ||
131 | 418 | if (result) | 417 | if (result) |
132 | 419 | { | 418 | { |
133 | @@ -430,10 +429,12 @@ | |||
134 | 430 | { | 429 | { |
135 | 431 | // No need to wait, and we can immediately return. | 430 | // No need to wait, and we can immediately return. |
136 | 432 | if (d->state == media::Engine::State::stopped) | 431 | if (d->state == media::Engine::State::stopped) |
137 | 432 | { | ||
138 | 433 | std::cerr << "Current player state is already stopped - no need to change state to stopped" << std::endl; | ||
139 | 433 | return true; | 434 | return true; |
143 | 434 | 435 | } | |
144 | 435 | auto result = d->playbin.set_state_and_wait(GST_STATE_NULL); | 436 | |
145 | 436 | 437 | const auto result = d->playbin.set_state_and_wait(GST_STATE_NULL); | |
146 | 437 | if (result) | 438 | if (result) |
147 | 438 | { | 439 | { |
148 | 439 | d->state = media::Engine::State::stopped; | 440 | d->state = media::Engine::State::stopped; |
149 | @@ -446,7 +447,7 @@ | |||
150 | 446 | 447 | ||
151 | 447 | bool gstreamer::Engine::pause() | 448 | bool gstreamer::Engine::pause() |
152 | 448 | { | 449 | { |
154 | 449 | auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED); | 450 | const auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED); |
155 | 450 | 451 | ||
156 | 451 | if (result) | 452 | if (result) |
157 | 452 | { | 453 | { |
158 | 453 | 454 | ||
159 | === modified file 'src/core/media/mpris/track_list.h' | |||
160 | --- src/core/media/mpris/track_list.h 2015-04-14 17:02:09 +0000 | |||
161 | +++ src/core/media/mpris/track_list.h 2015-08-11 16:10:30 +0000 | |||
162 | @@ -49,9 +49,11 @@ | |||
163 | 49 | } | 49 | } |
164 | 50 | 50 | ||
165 | 51 | DBUS_CPP_METHOD_DEF(GetTracksMetadata, TrackList) | 51 | DBUS_CPP_METHOD_DEF(GetTracksMetadata, TrackList) |
166 | 52 | DBUS_CPP_METHOD_DEF(GetTracksUri, TrackList) | ||
167 | 52 | DBUS_CPP_METHOD_DEF(AddTrack, TrackList) | 53 | DBUS_CPP_METHOD_DEF(AddTrack, TrackList) |
168 | 53 | DBUS_CPP_METHOD_DEF(RemoveTrack, TrackList) | 54 | DBUS_CPP_METHOD_DEF(RemoveTrack, TrackList) |
169 | 54 | DBUS_CPP_METHOD_DEF(GoTo, TrackList) | 55 | DBUS_CPP_METHOD_DEF(GoTo, TrackList) |
170 | 56 | DBUS_CPP_METHOD_DEF(Reset, TrackList) | ||
171 | 55 | 57 | ||
172 | 56 | struct Signals | 58 | struct Signals |
173 | 57 | { | 59 | { |
174 | @@ -80,6 +82,13 @@ | |||
175 | 80 | 82 | ||
176 | 81 | DBUS_CPP_SIGNAL_DEF | 83 | DBUS_CPP_SIGNAL_DEF |
177 | 82 | ( | 84 | ( |
178 | 85 | TrackChanged, | ||
179 | 86 | TrackList, | ||
180 | 87 | core::ubuntu::media::Track::Id | ||
181 | 88 | ) | ||
182 | 89 | |||
183 | 90 | DBUS_CPP_SIGNAL_DEF | ||
184 | 91 | ( | ||
185 | 83 | TrackMetadataChanged, | 92 | TrackMetadataChanged, |
186 | 84 | TrackList, | 93 | TrackList, |
187 | 85 | BOOST_IDENTITY_TYPE((std::tuple<std::map<std::string, dbus::types::Variant>, dbus::types::ObjectPath>)) | 94 | BOOST_IDENTITY_TYPE((std::tuple<std::map<std::string, dbus::types::Variant>, dbus::types::ObjectPath>)) |
188 | @@ -118,15 +127,16 @@ | |||
189 | 118 | : configuration(configuration), | 127 | : configuration(configuration), |
190 | 119 | properties | 128 | properties |
191 | 120 | { | 129 | { |
194 | 121 | configuration.object->get_property<Properties::Tracks>(), | 130 | configuration.object->template get_property<Properties::Tracks>(), |
195 | 122 | configuration.object->get_property<Properties::CanEditTracks>(), | 131 | configuration.object->template get_property<Properties::CanEditTracks>(), |
196 | 123 | }, | 132 | }, |
197 | 124 | signals | 133 | signals |
198 | 125 | { | 134 | { |
203 | 126 | configuration.object->get_signal<Signals::TrackListReplaced>(), | 135 | configuration.object->template get_signal<Signals::TrackListReplaced>(), |
204 | 127 | configuration.object->get_signal<Signals::TrackAdded>(), | 136 | configuration.object->template get_signal<Signals::TrackAdded>(), |
205 | 128 | configuration.object->get_signal<Signals::TrackRemoved>(), | 137 | configuration.object->template get_signal<Signals::TrackRemoved>(), |
206 | 129 | configuration.object->get_signal<Signals::TrackMetadataChanged>(), | 138 | configuration.object->template get_signal<Signals::TrackChanged>(), |
207 | 139 | configuration.object->template get_signal<Signals::TrackMetadataChanged>(), | ||
208 | 130 | configuration.object->template get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>() | 140 | configuration.object->template get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>() |
209 | 131 | } | 141 | } |
210 | 132 | { | 142 | { |
211 | @@ -169,6 +179,7 @@ | |||
212 | 169 | core::dbus::Signal<Signals::TrackListReplaced, Signals::TrackListReplaced::ArgumentType>::Ptr tracklist_replaced; | 179 | core::dbus::Signal<Signals::TrackListReplaced, Signals::TrackListReplaced::ArgumentType>::Ptr tracklist_replaced; |
213 | 170 | core::dbus::Signal<Signals::TrackAdded, Signals::TrackAdded::ArgumentType>::Ptr track_added; | 180 | core::dbus::Signal<Signals::TrackAdded, Signals::TrackAdded::ArgumentType>::Ptr track_added; |
214 | 171 | core::dbus::Signal<Signals::TrackRemoved, Signals::TrackRemoved::ArgumentType>::Ptr track_removed; | 181 | core::dbus::Signal<Signals::TrackRemoved, Signals::TrackRemoved::ArgumentType>::Ptr track_removed; |
215 | 182 | core::dbus::Signal<Signals::TrackChanged, Signals::TrackChanged::ArgumentType>::Ptr track_changed; | ||
216 | 172 | core::dbus::Signal<Signals::TrackMetadataChanged, Signals::TrackMetadataChanged::ArgumentType>::Ptr track_metadata_changed; | 183 | core::dbus::Signal<Signals::TrackMetadataChanged, Signals::TrackMetadataChanged::ArgumentType>::Ptr track_metadata_changed; |
217 | 173 | 184 | ||
218 | 174 | dbus::Signal <core::dbus::interfaces::Properties::Signals::PropertiesChanged, | 185 | dbus::Signal <core::dbus::interfaces::Properties::Signals::PropertiesChanged, |
219 | 175 | 186 | ||
220 | === removed file 'src/core/media/null_track_list.h' | |||
221 | --- src/core/media/null_track_list.h 2014-12-15 21:02:14 +0000 | |||
222 | +++ src/core/media/null_track_list.h 1970-01-01 00:00:00 +0000 | |||
223 | @@ -1,114 +0,0 @@ | |||
224 | 1 | /* | ||
225 | 2 | * | ||
226 | 3 | * This program is free software: you can redistribute it and/or modify it | ||
227 | 4 | * under the terms of the GNU Lesser General Public License version 3, | ||
228 | 5 | * as published by the Free Software Foundation. | ||
229 | 6 | * | ||
230 | 7 | * This program is distributed in the hope that it will be useful, | ||
231 | 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
232 | 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
233 | 10 | * GNU Lesser General Public License for more details. | ||
234 | 11 | * | ||
235 | 12 | * You should have received a copy of the GNU Lesser General Public License | ||
236 | 13 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
237 | 14 | * | ||
238 | 15 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
239 | 16 | */ | ||
240 | 17 | |||
241 | 18 | #ifndef CORE_MEDIA_NULL_TRACK_LIST_H_ | ||
242 | 19 | #define CORE_MEDIA_NULL_TRACK_LIST_H_ | ||
243 | 20 | |||
244 | 21 | #include <core/media/track.h> | ||
245 | 22 | #include <core/media/track_list.h> | ||
246 | 23 | |||
247 | 24 | namespace core | ||
248 | 25 | { | ||
249 | 26 | namespace ubuntu | ||
250 | 27 | { | ||
251 | 28 | namespace media | ||
252 | 29 | { | ||
253 | 30 | // A helper type to replace the playlist implementation below. | ||
254 | 31 | // Please note that this type is only a temporary manner. Ideally, | ||
255 | 32 | // the actual implementation should be injected as a dependency from the | ||
256 | 33 | // outside. | ||
257 | 34 | struct NullTrackList : public media::TrackList | ||
258 | 35 | { | ||
259 | 36 | NullTrackList() = default; | ||
260 | 37 | |||
261 | 38 | bool has_next() | ||
262 | 39 | { | ||
263 | 40 | return false; | ||
264 | 41 | } | ||
265 | 42 | |||
266 | 43 | media::Track::Id next() | ||
267 | 44 | { | ||
268 | 45 | return media::Track::Id{}; | ||
269 | 46 | } | ||
270 | 47 | |||
271 | 48 | media::Track::UriType query_uri_for_track(const media::Track::Id&) | ||
272 | 49 | { | ||
273 | 50 | return media::Track::UriType{}; | ||
274 | 51 | } | ||
275 | 52 | |||
276 | 53 | const core::Property<bool>& can_edit_tracks() const override | ||
277 | 54 | { | ||
278 | 55 | return props_and_sigs.can_edit_tracks; | ||
279 | 56 | } | ||
280 | 57 | |||
281 | 58 | const core::Property<Container>& tracks() const override | ||
282 | 59 | { | ||
283 | 60 | return props_and_sigs.tracks; | ||
284 | 61 | } | ||
285 | 62 | |||
286 | 63 | virtual media::Track::MetaData query_meta_data_for_track(const media::Track::Id&) override | ||
287 | 64 | { | ||
288 | 65 | return media::Track::MetaData{}; | ||
289 | 66 | } | ||
290 | 67 | |||
291 | 68 | void add_track_with_uri_at(const media::Track::UriType&, const media::Track::Id&, bool) override | ||
292 | 69 | { | ||
293 | 70 | } | ||
294 | 71 | |||
295 | 72 | void remove_track(const media::Track::Id&) override | ||
296 | 73 | { | ||
297 | 74 | } | ||
298 | 75 | |||
299 | 76 | void go_to(const media::Track::Id&) override | ||
300 | 77 | { | ||
301 | 78 | } | ||
302 | 79 | |||
303 | 80 | const core::Signal<void>& on_track_list_replaced() const override | ||
304 | 81 | { | ||
305 | 82 | return props_and_sigs.on_track_list_replaced; | ||
306 | 83 | } | ||
307 | 84 | |||
308 | 85 | const core::Signal<media::Track::Id>& on_track_added() const override | ||
309 | 86 | { | ||
310 | 87 | return props_and_sigs.on_track_added; | ||
311 | 88 | } | ||
312 | 89 | |||
313 | 90 | const core::Signal<media::Track::Id>& on_track_removed() const override | ||
314 | 91 | { | ||
315 | 92 | return props_and_sigs.on_track_removed; | ||
316 | 93 | } | ||
317 | 94 | |||
318 | 95 | const core::Signal<media::Track::Id>& on_track_changed() const override | ||
319 | 96 | { | ||
320 | 97 | return props_and_sigs.on_track_changed; | ||
321 | 98 | } | ||
322 | 99 | |||
323 | 100 | struct | ||
324 | 101 | { | ||
325 | 102 | core::Property<bool> can_edit_tracks; | ||
326 | 103 | core::Property<TrackList::Container> tracks; | ||
327 | 104 | core::Signal<void> on_track_list_replaced; | ||
328 | 105 | core::Signal<media::Track::Id> on_track_added; | ||
329 | 106 | core::Signal<media::Track::Id> on_track_removed; | ||
330 | 107 | core::Signal<media::Track::Id> on_track_changed; | ||
331 | 108 | } props_and_sigs; | ||
332 | 109 | }; | ||
333 | 110 | } | ||
334 | 111 | } | ||
335 | 112 | } | ||
336 | 113 | |||
337 | 114 | #endif // CORE_MEDIA_NULL_TRACK_LIST_H_ | ||
338 | 115 | 0 | ||
339 | === modified file 'src/core/media/player_implementation.cpp' | |||
340 | --- src/core/media/player_implementation.cpp 2015-06-01 16:31:50 +0000 | |||
341 | +++ src/core/media/player_implementation.cpp 2015-08-11 16:10:30 +0000 | |||
342 | @@ -287,6 +287,20 @@ | |||
343 | 287 | engine->reset(); | 287 | engine->reset(); |
344 | 288 | } | 288 | } |
345 | 289 | 289 | ||
346 | 290 | void open_first_track_from_tracklist(const media::Track::Id& id) | ||
347 | 291 | { | ||
348 | 292 | const Track::UriType uri = track_list->query_uri_for_track(id); | ||
349 | 293 | if (!uri.empty()) | ||
350 | 294 | { | ||
351 | 295 | // Using a TrackList for playback, added tracks via add_track(), but open_uri hasn't been called yet | ||
352 | 296 | // to load a media resource | ||
353 | 297 | std::cout << "Calling d->engine->open_resource_for_uri() for first track added only: " << uri << std::endl; | ||
354 | 298 | std::cout << "\twith a Track::Id: " << id << std::endl; | ||
355 | 299 | static const bool do_pipeline_reset = false; | ||
356 | 300 | engine->open_resource_for_uri(uri, do_pipeline_reset); | ||
357 | 301 | } | ||
358 | 302 | } | ||
359 | 303 | |||
360 | 290 | // Our link back to our parent. | 304 | // Our link back to our parent. |
361 | 291 | media::PlayerImplementation<Parent>* parent; | 305 | media::PlayerImplementation<Parent>* parent; |
362 | 292 | // We just store the parameters passed on construction. | 306 | // We just store the parameters passed on construction. |
363 | @@ -375,6 +389,7 @@ | |||
364 | 375 | // When the client changes the loop status, make sure to update the TrackList | 389 | // When the client changes the loop status, make sure to update the TrackList |
365 | 376 | Parent::loop_status().changed().connect([this](media::Player::LoopStatus loop_status) | 390 | Parent::loop_status().changed().connect([this](media::Player::LoopStatus loop_status) |
366 | 377 | { | 391 | { |
367 | 392 | std::cout << "LoopStatus: " << loop_status << std::endl; | ||
368 | 378 | d->track_list->on_loop_status_changed(loop_status); | 393 | d->track_list->on_loop_status_changed(loop_status); |
369 | 379 | }); | 394 | }); |
370 | 380 | 395 | ||
371 | @@ -408,18 +423,20 @@ | |||
372 | 408 | if (d->doing_abandon) | 423 | if (d->doing_abandon) |
373 | 409 | return; | 424 | return; |
374 | 410 | 425 | ||
375 | 426 | // Prevent on_go_to_track from executing as it's not needed in this case. on_go_to_track | ||
376 | 427 | // (see the lambda below) is only needed when the client explicitly calls next() not during | ||
377 | 428 | // the about_to_finish condition | ||
378 | 429 | d->doing_go_to_track.lock(); | ||
379 | 430 | |||
380 | 411 | Parent::about_to_finish()(); | 431 | Parent::about_to_finish()(); |
381 | 412 | 432 | ||
382 | 413 | // This lambda needs to be mutually exclusive with the on_go_to_track lambda below | ||
383 | 414 | d->doing_go_to_track.lock(); | ||
384 | 415 | |||
385 | 416 | const media::Track::Id prev_track_id = d->track_list->current(); | 433 | const media::Track::Id prev_track_id = d->track_list->current(); |
386 | 417 | // Make sure that the TrackList keeps advancing. The logic for what gets played next, | 434 | // Make sure that the TrackList keeps advancing. The logic for what gets played next, |
387 | 418 | // if anything at all, occurs in TrackListSkeleton::next() | 435 | // if anything at all, occurs in TrackListSkeleton::next() |
388 | 419 | const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next()); | 436 | const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next()); |
389 | 420 | if (prev_track_id != d->track_list->current() && !uri.empty()) | 437 | if (prev_track_id != d->track_list->current() && !uri.empty()) |
390 | 421 | { | 438 | { |
392 | 422 | std::cout << "Setting next track on playbin: " << uri << std::endl; | 439 | std::cout << "Advancing to next track on playbin: " << uri << std::endl; |
393 | 423 | static const bool do_pipeline_reset = false; | 440 | static const bool do_pipeline_reset = false; |
394 | 424 | d->engine->open_resource_for_uri(uri, do_pipeline_reset); | 441 | d->engine->open_resource_for_uri(uri, do_pipeline_reset); |
395 | 425 | } | 442 | } |
396 | @@ -457,12 +474,25 @@ | |||
397 | 457 | Parent::error()(e); | 474 | Parent::error()(e); |
398 | 458 | }); | 475 | }); |
399 | 459 | 476 | ||
400 | 477 | d->track_list->on_end_of_tracklist().connect([this]() | ||
401 | 478 | { | ||
402 | 479 | if (d->engine->state() != gstreamer::Engine::State::ready | ||
403 | 480 | && d->engine->state() != gstreamer::Engine::State::stopped) | ||
404 | 481 | { | ||
405 | 482 | std::cout << "End of tracklist reached, stopping playback" << std::endl; | ||
406 | 483 | d->engine->stop(); | ||
407 | 484 | } | ||
408 | 485 | }); | ||
409 | 486 | |||
410 | 487 | |||
411 | 460 | d->track_list->on_go_to_track().connect([this](std::pair<const media::Track::Id, bool> p) | 488 | d->track_list->on_go_to_track().connect([this](std::pair<const media::Track::Id, bool> p) |
412 | 461 | { | 489 | { |
413 | 462 | // This prevents the TrackList from auto advancing in other areas such as the about_to_finish signal | ||
414 | 463 | // handler. | ||
415 | 464 | // This lambda needs to be mutually exclusive with the about_to_finish lambda above | 490 | // This lambda needs to be mutually exclusive with the about_to_finish lambda above |
417 | 465 | d->doing_go_to_track.lock(); | 491 | const bool locked = d->doing_go_to_track.try_lock(); |
418 | 492 | // If the try_lock fails, it means that about_to_finish lambda above has it locked and it will | ||
419 | 493 | // call d->engine->open_resource_for_uri() | ||
420 | 494 | if (!locked) | ||
421 | 495 | return; | ||
422 | 466 | 496 | ||
423 | 467 | const media::Track::Id id = p.first; | 497 | const media::Track::Id id = p.first; |
424 | 468 | const bool toggle_player_state = p.second; | 498 | const bool toggle_player_state = p.second; |
425 | @@ -483,7 +513,13 @@ | |||
426 | 483 | d->engine->play(); | 513 | d->engine->play(); |
427 | 484 | 514 | ||
428 | 485 | d->doing_go_to_track.unlock(); | 515 | d->doing_go_to_track.unlock(); |
429 | 516 | }); | ||
430 | 486 | 517 | ||
431 | 518 | d->track_list->on_track_added().connect([this](const media::Track::Id& id) | ||
432 | 519 | { | ||
433 | 520 | std::cout << "** Track was added, handling in PlayerImplementation" << std::endl; | ||
434 | 521 | if (d->track_list->tracks()->size() == 1) | ||
435 | 522 | d->open_first_track_from_tracklist(id); | ||
436 | 487 | }); | 523 | }); |
437 | 488 | 524 | ||
438 | 489 | // Everything is setup, we now subscribe to death notifications. | 525 | // Everything is setup, we now subscribe to death notifications. |
439 | @@ -614,16 +650,6 @@ | |||
440 | 614 | template<typename Parent> | 650 | template<typename Parent> |
441 | 615 | void media::PlayerImplementation<Parent>::play() | 651 | void media::PlayerImplementation<Parent>::play() |
442 | 616 | { | 652 | { |
443 | 617 | if (d->track_list != nullptr && d->track_list->tracks()->size() > 0 && d->engine->state() == media::Engine::State::no_media) | ||
444 | 618 | { | ||
445 | 619 | // Using a TrackList for playback, added tracks via add_track(), but open_uri hasn't been called yet | ||
446 | 620 | // to load a media resource | ||
447 | 621 | std::cout << "No media loaded yet, calling open_uri on first track in track_list" << std::endl; | ||
448 | 622 | static const bool do_pipeline_reset = true; | ||
449 | 623 | d->engine->open_resource_for_uri(d->track_list->query_uri_for_track(d->track_list->current()), do_pipeline_reset); | ||
450 | 624 | std::cout << *d->track_list << endl; | ||
451 | 625 | } | ||
452 | 626 | |||
453 | 627 | d->engine->play(); | 653 | d->engine->play(); |
454 | 628 | } | 654 | } |
455 | 629 | 655 | ||
456 | 630 | 656 | ||
457 | === modified file 'src/core/media/service_skeleton.cpp' | |||
458 | --- src/core/media/service_skeleton.cpp 2015-04-27 21:25:03 +0000 | |||
459 | +++ src/core/media/service_skeleton.cpp 2015-08-11 16:10:30 +0000 | |||
460 | @@ -139,7 +139,7 @@ | |||
461 | 139 | fprintf(stderr, "%s():%d -- app_name='%s', attached\n", __func__, __LINE__, context.str().c_str()); | 139 | fprintf(stderr, "%s():%d -- app_name='%s', attached\n", __func__, __LINE__, context.str().c_str()); |
462 | 140 | player_owner_map.insert(std::make_pair(key, std::make_tuple(context.str(), true, msg->sender()))); | 140 | player_owner_map.insert(std::make_pair(key, std::make_tuple(context.str(), true, msg->sender()))); |
463 | 141 | }); | 141 | }); |
465 | 142 | 142 | ||
466 | 143 | auto reply = dbus::Message::make_method_return(msg); | 143 | auto reply = dbus::Message::make_method_return(msg); |
467 | 144 | reply->writer() << std::make_tuple(op, uuid); | 144 | reply->writer() << std::make_tuple(op, uuid); |
468 | 145 | 145 | ||
469 | @@ -161,20 +161,24 @@ | |||
470 | 161 | std::string uuid; | 161 | std::string uuid; |
471 | 162 | msg->reader() >> uuid; | 162 | msg->reader() >> uuid; |
472 | 163 | 163 | ||
474 | 164 | auto key = uuid_player_map.at(uuid); | 164 | // Make sure we don't try to do a lookup if the map is empty |
475 | 165 | if (!uuid_player_map.empty()) | ||
476 | 166 | { | ||
477 | 167 | const auto key = uuid_player_map.at(uuid); | ||
478 | 165 | 168 | ||
488 | 166 | if (player_owner_map.count(key) != 0) { | 169 | if (player_owner_map.count(key) != 0) { |
489 | 167 | auto info = player_owner_map.at(key); | 170 | auto info = player_owner_map.at(key); |
490 | 168 | // Check if session is attached(1) and that the detachment | 171 | // Check if session is attached(1) and that the detachment |
491 | 169 | // request comes from the same peer(2) that created the session. | 172 | // request comes from the same peer(2) that created the session. |
492 | 170 | if (std::get<1>(info) && (std::get<2>(info) == msg->sender())) { // Player is attached | 173 | if (std::get<1>(info) && (std::get<2>(info) == msg->sender())) { // Player is attached |
493 | 171 | std::get<1>(info) = false; // Detached | 174 | std::get<1>(info) = false; // Detached |
494 | 172 | std::get<2>(info).clear(); // Clear registered sender/peer | 175 | std::get<2>(info).clear(); // Clear registered sender/peer |
495 | 173 | auto player = configuration.player_store->player_for_key(key); | 176 | auto player = configuration.player_store->player_for_key(key); |
496 | 174 | player->lifetime().set(media::Player::Lifetime::resumable); | 177 | player->lifetime().set(media::Player::Lifetime::resumable); |
497 | 178 | } | ||
498 | 175 | } | 179 | } |
499 | 176 | } | 180 | } |
501 | 177 | 181 | ||
502 | 178 | auto reply = dbus::Message::make_method_return(msg); | 182 | auto reply = dbus::Message::make_method_return(msg); |
503 | 179 | impl->access_bus()->send(reply); | 183 | impl->access_bus()->send(reply); |
504 | 180 | 184 | ||
505 | @@ -256,7 +260,6 @@ | |||
506 | 256 | 260 | ||
507 | 257 | void handle_destroy_session(const core::dbus::Message::Ptr& msg) | 261 | void handle_destroy_session(const core::dbus::Message::Ptr& msg) |
508 | 258 | { | 262 | { |
509 | 259 | |||
510 | 260 | try | 263 | try |
511 | 261 | { | 264 | { |
512 | 262 | std::string uuid; | 265 | std::string uuid; |
513 | @@ -445,9 +448,9 @@ | |||
514 | 445 | // We keep a list of keys and their respective owners and states. | 448 | // We keep a list of keys and their respective owners and states. |
515 | 446 | // value: (owner context, attached state, attached dbus name) | 449 | // value: (owner context, attached state, attached dbus name) |
516 | 447 | std::map<media::Player::PlayerKey, std::tuple<std::string, bool, std::string>> player_owner_map; | 450 | std::map<media::Player::PlayerKey, std::tuple<std::string, bool, std::string>> player_owner_map; |
518 | 448 | 451 | ||
519 | 449 | boost::uuids::random_generator gen; | 452 | boost::uuids::random_generator gen; |
521 | 450 | 453 | ||
522 | 451 | // We expose the entire service as an MPRIS player. | 454 | // We expose the entire service as an MPRIS player. |
523 | 452 | struct Exported | 455 | struct Exported |
524 | 453 | { | 456 | { |
525 | 454 | 457 | ||
526 | === modified file 'src/core/media/track.cpp' | |||
527 | --- src/core/media/track.cpp 2014-02-12 15:53:57 +0000 | |||
528 | +++ src/core/media/track.cpp 2015-08-11 16:10:30 +0000 | |||
529 | @@ -25,9 +25,10 @@ | |||
530 | 25 | struct media::Track::Private | 25 | struct media::Track::Private |
531 | 26 | { | 26 | { |
532 | 27 | media::Track::Id id; | 27 | media::Track::Id id; |
533 | 28 | media::Track::UriType uri; | ||
534 | 28 | }; | 29 | }; |
535 | 29 | 30 | ||
537 | 30 | media::Track::Track(const media::Track::Id& id) : d(new Private{id}) | 31 | media::Track::Track(const media::Track::Id& id) : d(new Private{id, std::string{}}) |
538 | 31 | { | 32 | { |
539 | 32 | } | 33 | } |
540 | 33 | 34 | ||
541 | @@ -39,3 +40,8 @@ | |||
542 | 39 | { | 40 | { |
543 | 40 | return d->id; | 41 | return d->id; |
544 | 41 | } | 42 | } |
545 | 43 | |||
546 | 44 | const media::Track::UriType& media::Track::uri() const | ||
547 | 45 | { | ||
548 | 46 | return d->uri; | ||
549 | 47 | } | ||
550 | 42 | 48 | ||
551 | === modified file 'src/core/media/track_list_implementation.cpp' | |||
552 | --- src/core/media/track_list_implementation.cpp 2015-05-22 21:19:28 +0000 | |||
553 | +++ src/core/media/track_list_implementation.cpp 2015-08-11 16:10:30 +0000 | |||
554 | @@ -59,7 +59,7 @@ | |||
555 | 59 | 59 | ||
556 | 60 | media::Track::UriType media::TrackListImplementation::query_uri_for_track(const media::Track::Id& id) | 60 | media::Track::UriType media::TrackListImplementation::query_uri_for_track(const media::Track::Id& id) |
557 | 61 | { | 61 | { |
559 | 62 | auto it = d->meta_data_cache.find(id); | 62 | const auto it = d->meta_data_cache.find(id); |
560 | 63 | 63 | ||
561 | 64 | if (it == d->meta_data_cache.end()) | 64 | if (it == d->meta_data_cache.end()) |
562 | 65 | return Track::UriType{}; | 65 | return Track::UriType{}; |
563 | @@ -69,7 +69,7 @@ | |||
564 | 69 | 69 | ||
565 | 70 | media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id) | 70 | media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id) |
566 | 71 | { | 71 | { |
568 | 72 | auto it = d->meta_data_cache.find(id); | 72 | const auto it = d->meta_data_cache.find(id); |
569 | 73 | 73 | ||
570 | 74 | if (it == d->meta_data_cache.end()) | 74 | if (it == d->meta_data_cache.end()) |
571 | 75 | return Track::MetaData{}; | 75 | return Track::MetaData{}; |
572 | @@ -87,10 +87,14 @@ | |||
573 | 87 | std::stringstream ss; ss << d->object->path().as_string() << "/" << d->track_counter++; | 87 | std::stringstream ss; ss << d->object->path().as_string() << "/" << d->track_counter++; |
574 | 88 | Track::Id id{ss.str()}; | 88 | Track::Id id{ss.str()}; |
575 | 89 | 89 | ||
576 | 90 | std::cout << "Adding Track::Id: " << id << std::endl; | ||
577 | 91 | std::cout << "\tURI: " << uri << std::endl; | ||
578 | 92 | |||
579 | 90 | auto result = tracks().update([this, id, position, make_current](TrackList::Container& container) | 93 | auto result = tracks().update([this, id, position, make_current](TrackList::Container& container) |
580 | 91 | { | 94 | { |
581 | 92 | auto it = std::find(container.begin(), container.end(), position); | 95 | auto it = std::find(container.begin(), container.end(), position); |
582 | 93 | container.insert(it, id); | 96 | container.insert(it, id); |
583 | 97 | std::cout << "container.size(): " << container.size() << std::endl; | ||
584 | 94 | 98 | ||
585 | 95 | return true; | 99 | return true; |
586 | 96 | }); | 100 | }); |
587 | @@ -99,6 +103,8 @@ | |||
588 | 99 | { | 103 | { |
589 | 100 | if (d->meta_data_cache.count(id) == 0) | 104 | if (d->meta_data_cache.count(id) == 0) |
590 | 101 | { | 105 | { |
591 | 106 | // FIXME: This code seems to conflict badly when called multiple times in a row: causes segfaults | ||
592 | 107 | #if 0 | ||
593 | 102 | try { | 108 | try { |
594 | 103 | d->meta_data_cache[id] = std::make_tuple( | 109 | d->meta_data_cache[id] = std::make_tuple( |
595 | 104 | uri, | 110 | uri, |
596 | @@ -106,6 +112,11 @@ | |||
597 | 106 | } catch (const std::runtime_error &e) { | 112 | } catch (const std::runtime_error &e) { |
598 | 107 | std::cerr << "Failed to retrieve metadata for track '" << uri << "' (" << e.what() << ")" << std::endl; | 113 | std::cerr << "Failed to retrieve metadata for track '" << uri << "' (" << e.what() << ")" << std::endl; |
599 | 108 | } | 114 | } |
600 | 115 | #else | ||
601 | 116 | d->meta_data_cache[id] = std::make_tuple( | ||
602 | 117 | uri, | ||
603 | 118 | core::ubuntu::media::Track::MetaData{}); | ||
604 | 119 | #endif | ||
605 | 109 | } else | 120 | } else |
606 | 110 | { | 121 | { |
607 | 111 | std::get<0>(d->meta_data_cache[id]) = uri; | 122 | std::get<0>(d->meta_data_cache[id]) = uri; |
608 | @@ -120,8 +131,14 @@ | |||
609 | 120 | go_to(id, toggle_player_state); | 131 | go_to(id, toggle_player_state); |
610 | 121 | } | 132 | } |
611 | 122 | 133 | ||
612 | 134 | // Signal to the client that the current track has changed for the first track added to the TrackList | ||
613 | 135 | if (tracks().get().size() == 1) | ||
614 | 136 | on_track_changed()(id); | ||
615 | 137 | |||
616 | 138 | std::cout << "Signaling that we just added track id: " << id << std::endl; | ||
617 | 123 | // Signal to the client that a track was added to the TrackList | 139 | // Signal to the client that a track was added to the TrackList |
618 | 124 | on_track_added()(id); | 140 | on_track_added()(id); |
619 | 141 | std::cout << "Signaled that we just added track id: " << id << std::endl; | ||
620 | 125 | } | 142 | } |
621 | 126 | } | 143 | } |
622 | 127 | 144 | ||
623 | @@ -133,6 +150,8 @@ | |||
624 | 133 | return true; | 150 | return true; |
625 | 134 | }); | 151 | }); |
626 | 135 | 152 | ||
627 | 153 | reset_current_iterator_if_needed(); | ||
628 | 154 | |||
629 | 136 | if (result) | 155 | if (result) |
630 | 137 | { | 156 | { |
631 | 138 | d->meta_data_cache.erase(id); | 157 | d->meta_data_cache.erase(id); |
632 | @@ -155,8 +174,12 @@ | |||
633 | 155 | { | 174 | { |
634 | 156 | std::cout << __PRETTY_FUNCTION__ << std::endl; | 175 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
635 | 157 | 176 | ||
636 | 177 | if (tracks().get().empty()) | ||
637 | 178 | return; | ||
638 | 179 | |||
639 | 158 | auto result = tracks().update([this](TrackList::Container& container) | 180 | auto result = tracks().update([this](TrackList::Container& container) |
640 | 159 | { | 181 | { |
641 | 182 | // Save off the original TrackList ordering | ||
642 | 160 | d->original_tracklist.assign(container.begin(), container.end()); | 183 | d->original_tracklist.assign(container.begin(), container.end()); |
643 | 161 | std::random_shuffle(container.begin(), container.end()); | 184 | std::random_shuffle(container.begin(), container.end()); |
644 | 162 | return true; | 185 | return true; |
645 | @@ -173,8 +196,12 @@ | |||
646 | 173 | { | 196 | { |
647 | 174 | std::cout << __PRETTY_FUNCTION__ << std::endl; | 197 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
648 | 175 | 198 | ||
649 | 199 | if (tracks().get().empty() or d->original_tracklist.empty()) | ||
650 | 200 | return; | ||
651 | 201 | |||
652 | 176 | auto result = tracks().update([this](TrackList::Container& container) | 202 | auto result = tracks().update([this](TrackList::Container& container) |
653 | 177 | { | 203 | { |
654 | 204 | // Restore the original TrackList ordering | ||
655 | 178 | container.assign(d->original_tracklist.begin(), d->original_tracklist.end()); | 205 | container.assign(d->original_tracklist.begin(), d->original_tracklist.end()); |
656 | 179 | return true; | 206 | return true; |
657 | 180 | }); | 207 | }); |
658 | @@ -190,6 +217,9 @@ | |||
659 | 190 | { | 217 | { |
660 | 191 | std::cout << __PRETTY_FUNCTION__ << std::endl; | 218 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
661 | 192 | 219 | ||
662 | 220 | // Make sure playback stops | ||
663 | 221 | on_end_of_tracklist()(); | ||
664 | 222 | |||
665 | 193 | auto result = tracks().update([this](TrackList::Container& container) | 223 | auto result = tracks().update([this](TrackList::Container& container) |
666 | 194 | { | 224 | { |
667 | 195 | container.clear(); | 225 | container.clear(); |
668 | @@ -198,5 +228,7 @@ | |||
669 | 198 | return true; | 228 | return true; |
670 | 199 | }); | 229 | }); |
671 | 200 | 230 | ||
672 | 231 | media::TrackListSkeleton::reset(); | ||
673 | 232 | |||
674 | 201 | (void) result; | 233 | (void) result; |
675 | 202 | } | 234 | } |
676 | 203 | 235 | ||
677 | === modified file 'src/core/media/track_list_skeleton.cpp' | |||
678 | --- src/core/media/track_list_skeleton.cpp 2015-04-29 21:18:20 +0000 | |||
679 | +++ src/core/media/track_list_skeleton.cpp 2015-08-11 16:10:30 +0000 | |||
680 | @@ -60,6 +60,7 @@ | |||
681 | 60 | { | 60 | { |
682 | 61 | skeleton.signals.track_added, | 61 | skeleton.signals.track_added, |
683 | 62 | skeleton.signals.track_removed, | 62 | skeleton.signals.track_removed, |
684 | 63 | skeleton.signals.track_changed, | ||
685 | 63 | skeleton.signals.tracklist_replaced | 64 | skeleton.signals.tracklist_replaced |
686 | 64 | } | 65 | } |
687 | 65 | { | 66 | { |
688 | @@ -70,15 +71,28 @@ | |||
689 | 70 | media::Track::Id track; | 71 | media::Track::Id track; |
690 | 71 | msg->reader() >> track; | 72 | msg->reader() >> track; |
691 | 72 | 73 | ||
693 | 73 | auto meta_data = impl->query_meta_data_for_track(track); | 74 | const auto meta_data = impl->query_meta_data_for_track(track); |
694 | 74 | 75 | ||
696 | 75 | auto reply = dbus::Message::make_method_return(msg); | 76 | const auto reply = dbus::Message::make_method_return(msg); |
697 | 76 | reply->writer() << *meta_data; | 77 | reply->writer() << *meta_data; |
698 | 77 | bus->send(reply); | 78 | bus->send(reply); |
699 | 78 | } | 79 | } |
700 | 79 | 80 | ||
701 | 81 | void handle_get_tracks_uri(const core::dbus::Message::Ptr& msg) | ||
702 | 82 | { | ||
703 | 83 | media::Track::Id track; | ||
704 | 84 | msg->reader() >> track; | ||
705 | 85 | |||
706 | 86 | const auto uri = impl->query_uri_for_track(track); | ||
707 | 87 | |||
708 | 88 | const auto reply = dbus::Message::make_method_return(msg); | ||
709 | 89 | reply->writer() << uri; | ||
710 | 90 | bus->send(reply); | ||
711 | 91 | } | ||
712 | 92 | |||
713 | 80 | void handle_add_track_with_uri_at(const core::dbus::Message::Ptr& msg) | 93 | void handle_add_track_with_uri_at(const core::dbus::Message::Ptr& msg) |
714 | 81 | { | 94 | { |
715 | 95 | std::cout << "*** " << __PRETTY_FUNCTION__ << std::endl; | ||
716 | 82 | request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, msg](const media::apparmor::ubuntu::Context& context) | 96 | request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, msg](const media::apparmor::ubuntu::Context& context) |
717 | 83 | { | 97 | { |
718 | 84 | Track::UriType uri; media::Track::Id after; bool make_current; | 98 | Track::UriType uri; media::Track::Id after; bool make_current; |
719 | @@ -123,6 +137,14 @@ | |||
720 | 123 | bus->send(reply); | 137 | bus->send(reply); |
721 | 124 | } | 138 | } |
722 | 125 | 139 | ||
723 | 140 | void handle_reset(const core::dbus::Message::Ptr& msg) | ||
724 | 141 | { | ||
725 | 142 | impl->reset(); | ||
726 | 143 | |||
727 | 144 | auto reply = dbus::Message::make_method_return(msg); | ||
728 | 145 | bus->send(reply); | ||
729 | 146 | } | ||
730 | 147 | |||
731 | 126 | media::TrackListSkeleton* impl; | 148 | media::TrackListSkeleton* impl; |
732 | 127 | dbus::Bus::Ptr bus; | 149 | dbus::Bus::Ptr bus; |
733 | 128 | dbus::Object::Ptr object; | 150 | dbus::Object::Ptr object; |
734 | @@ -138,10 +160,12 @@ | |||
735 | 138 | { | 160 | { |
736 | 139 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType> DBusTrackAddedSignal; | 161 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType> DBusTrackAddedSignal; |
737 | 140 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType> DBusTrackRemovedSignal; | 162 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType> DBusTrackRemovedSignal; |
738 | 163 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType> DBusTrackChangedSignal; | ||
739 | 141 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType> DBusTrackListReplacedSignal; | 164 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType> DBusTrackListReplacedSignal; |
740 | 142 | 165 | ||
741 | 143 | Signals(const std::shared_ptr<DBusTrackAddedSignal>& remote_track_added, | 166 | Signals(const std::shared_ptr<DBusTrackAddedSignal>& remote_track_added, |
742 | 144 | const std::shared_ptr<DBusTrackRemovedSignal>& remote_track_removed, | 167 | const std::shared_ptr<DBusTrackRemovedSignal>& remote_track_removed, |
743 | 168 | const std::shared_ptr<DBusTrackChangedSignal>& remote_track_changed, | ||
744 | 145 | const std::shared_ptr<DBusTrackListReplacedSignal>& remote_track_list_replaced) | 169 | const std::shared_ptr<DBusTrackListReplacedSignal>& remote_track_list_replaced) |
745 | 146 | { | 170 | { |
746 | 147 | // Connect all of the MPRIS interface signals to be emitted over dbus | 171 | // Connect all of the MPRIS interface signals to be emitted over dbus |
747 | @@ -155,6 +179,11 @@ | |||
748 | 155 | remote_track_removed->emit(id); | 179 | remote_track_removed->emit(id); |
749 | 156 | }); | 180 | }); |
750 | 157 | 181 | ||
751 | 182 | on_track_changed.connect([remote_track_changed](const media::Track::Id &id) | ||
752 | 183 | { | ||
753 | 184 | remote_track_changed->emit(id); | ||
754 | 185 | }); | ||
755 | 186 | |||
756 | 158 | on_track_list_replaced.connect([remote_track_list_replaced](const media::TrackList::ContainerTrackIdTuple &tltuple) | 187 | on_track_list_replaced.connect([remote_track_list_replaced](const media::TrackList::ContainerTrackIdTuple &tltuple) |
757 | 159 | { | 188 | { |
758 | 160 | remote_track_list_replaced->emit(tltuple); | 189 | remote_track_list_replaced->emit(tltuple); |
759 | @@ -163,9 +192,10 @@ | |||
760 | 163 | 192 | ||
761 | 164 | core::Signal<Track::Id> on_track_added; | 193 | core::Signal<Track::Id> on_track_added; |
762 | 165 | core::Signal<Track::Id> on_track_removed; | 194 | core::Signal<Track::Id> on_track_removed; |
763 | 195 | core::Signal<Track::Id> on_track_changed; | ||
764 | 166 | core::Signal<TrackList::ContainerTrackIdTuple> on_track_list_replaced; | 196 | core::Signal<TrackList::ContainerTrackIdTuple> on_track_list_replaced; |
765 | 167 | core::Signal<Track::Id> on_track_changed; | ||
766 | 168 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; | 197 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; |
767 | 198 | core::Signal<void> on_end_of_tracklist; | ||
768 | 169 | } signals; | 199 | } signals; |
769 | 170 | }; | 200 | }; |
770 | 171 | 201 | ||
771 | @@ -179,6 +209,11 @@ | |||
772 | 179 | std::ref(d), | 209 | std::ref(d), |
773 | 180 | std::placeholders::_1)); | 210 | std::placeholders::_1)); |
774 | 181 | 211 | ||
775 | 212 | d->object->install_method_handler<mpris::TrackList::GetTracksUri>( | ||
776 | 213 | std::bind(&Private::handle_get_tracks_uri, | ||
777 | 214 | std::ref(d), | ||
778 | 215 | std::placeholders::_1)); | ||
779 | 216 | |||
780 | 182 | d->object->install_method_handler<mpris::TrackList::AddTrack>( | 217 | d->object->install_method_handler<mpris::TrackList::AddTrack>( |
781 | 183 | std::bind(&Private::handle_add_track_with_uri_at, | 218 | std::bind(&Private::handle_add_track_with_uri_at, |
782 | 184 | std::ref(d), | 219 | std::ref(d), |
783 | @@ -193,74 +228,184 @@ | |||
784 | 193 | std::bind(&Private::handle_go_to, | 228 | std::bind(&Private::handle_go_to, |
785 | 194 | std::ref(d), | 229 | std::ref(d), |
786 | 195 | std::placeholders::_1)); | 230 | std::placeholders::_1)); |
787 | 231 | |||
788 | 232 | d->object->install_method_handler<mpris::TrackList::Reset>( | ||
789 | 233 | std::bind(&Private::handle_reset, | ||
790 | 234 | std::ref(d), | ||
791 | 235 | std::placeholders::_1)); | ||
792 | 196 | } | 236 | } |
793 | 197 | 237 | ||
794 | 198 | media::TrackListSkeleton::~TrackListSkeleton() | 238 | media::TrackListSkeleton::~TrackListSkeleton() |
795 | 199 | { | 239 | { |
796 | 200 | } | 240 | } |
797 | 201 | 241 | ||
799 | 202 | bool media::TrackListSkeleton::has_next() const | 242 | bool media::TrackListSkeleton::has_next() |
800 | 203 | { | 243 | { |
804 | 204 | const auto next_track = std::next(d->current_track); | 244 | if (tracks().get().empty()) |
805 | 205 | std::cout << "has_next track? " << (next_track != tracks().get().end() ? "yes" : "no") << std::endl; | 245 | return false; |
806 | 206 | return next_track != tracks().get().end(); | 246 | |
807 | 247 | const auto next_track = std::next(current_iterator()); | ||
808 | 248 | return !is_last_track(next_track); | ||
809 | 207 | } | 249 | } |
810 | 208 | 250 | ||
812 | 209 | bool media::TrackListSkeleton::has_previous() const | 251 | bool media::TrackListSkeleton::has_previous() |
813 | 210 | { | 252 | { |
814 | 253 | if (tracks().get().empty()) | ||
815 | 254 | return false; | ||
816 | 255 | |||
817 | 211 | // If we are looping over the entire list, then there is always a previous track | 256 | // If we are looping over the entire list, then there is always a previous track |
818 | 212 | if (d->loop_status == media::Player::LoopStatus::playlist) | 257 | if (d->loop_status == media::Player::LoopStatus::playlist) |
819 | 213 | return true; | 258 | return true; |
820 | 214 | 259 | ||
823 | 215 | std::cout << "has_previous track? " << (d->current_track != tracks().get().begin() ? "yes" : "no") << std::endl; | 260 | return d->current_track != std::begin(tracks().get()); |
824 | 216 | return d->current_track != tracks().get().begin(); | 261 | } |
825 | 262 | |||
826 | 263 | bool media::TrackListSkeleton::is_first_track(const ConstIterator &it) | ||
827 | 264 | { | ||
828 | 265 | return it == std::begin(tracks().get()); | ||
829 | 266 | } | ||
830 | 267 | |||
831 | 268 | bool media::TrackListSkeleton::is_last_track(const TrackList::ConstIterator &it) | ||
832 | 269 | { | ||
833 | 270 | return it == std::end(tracks().get()); | ||
834 | 217 | } | 271 | } |
835 | 218 | 272 | ||
836 | 219 | media::Track::Id media::TrackListSkeleton::next() | 273 | media::Track::Id media::TrackListSkeleton::next() |
837 | 220 | { | 274 | { |
838 | 221 | std::cout << __PRETTY_FUNCTION__ << std::endl; | 275 | std::cout << __PRETTY_FUNCTION__ << std::endl; |
839 | 222 | if (tracks().get().empty()) | 276 | if (tracks().get().empty()) |
841 | 223 | return *(d->current_track); | 277 | return *(d->empty_iterator); |
842 | 278 | |||
843 | 279 | const auto next_track = std::next(current_iterator()); | ||
844 | 280 | bool do_go_to_next_track = false; | ||
845 | 281 | |||
846 | 282 | // End of the track reached so loop around to the beginning of the track | ||
847 | 283 | if (d->loop_status == media::Player::LoopStatus::track) | ||
848 | 284 | { | ||
849 | 285 | std::cout << "Looping on the current track since LoopStatus is set to track" << std::endl; | ||
850 | 286 | do_go_to_next_track = true; | ||
851 | 287 | } | ||
852 | 288 | // End of the tracklist reached so loop around to the beginning of the tracklist | ||
853 | 289 | else if (d->loop_status == media::Player::LoopStatus::playlist && not has_next()) | ||
854 | 290 | { | ||
855 | 291 | std::cout << "Looping on the tracklist since LoopStatus is set to playlist" << std::endl; | ||
856 | 292 | d->current_track = tracks().get().begin(); | ||
857 | 293 | do_go_to_next_track = true; | ||
858 | 294 | } | ||
859 | 295 | else | ||
860 | 296 | { | ||
861 | 297 | // Next track is not the last track | ||
862 | 298 | if (not is_last_track(next_track)) | ||
863 | 299 | { | ||
864 | 300 | std::cout << "Advancing to next track: " << *(next_track) << std::endl; | ||
865 | 301 | d->current_track = next_track; | ||
866 | 302 | do_go_to_next_track = true; | ||
867 | 303 | } | ||
868 | 304 | // At the end of the tracklist and not set to loop, so we stop advancing the tracklist | ||
869 | 305 | else | ||
870 | 306 | { | ||
871 | 307 | std::cout << "End of tracklist reached, not advancing to next since LoopStatus is set to none" << std::endl; | ||
872 | 308 | on_end_of_tracklist()(); | ||
873 | 309 | } | ||
874 | 310 | } | ||
875 | 311 | |||
876 | 312 | if (do_go_to_next_track) | ||
877 | 313 | { | ||
878 | 314 | on_track_changed()(*(current_iterator())); | ||
879 | 315 | // Don't automatically call stop() and play() in player_implementation.cpp on_go_to_track() | ||
880 | 316 | // since this breaks video playback when using open_uri() (stop() and play() are unwanted in | ||
881 | 317 | // this scenario since the qtubuntu-media will handle this automatically) | ||
882 | 318 | const bool toggle_player_state = false; | ||
883 | 319 | const media::Track::Id id = *(current_iterator()); | ||
884 | 320 | const std::pair<const media::Track::Id, bool> p = std::make_pair(id, toggle_player_state); | ||
885 | 321 | // Signal the PlayerImplementation to play the next track | ||
886 | 322 | on_go_to_track()(p); | ||
887 | 323 | } | ||
888 | 324 | |||
889 | 325 | return *(current_iterator()); | ||
890 | 326 | } | ||
891 | 327 | |||
892 | 328 | media::Track::Id media::TrackListSkeleton::previous() | ||
893 | 329 | { | ||
894 | 330 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
895 | 331 | if (tracks().get().empty()) | ||
896 | 332 | return *(d->empty_iterator); | ||
897 | 333 | |||
898 | 334 | bool do_go_to_previous_track = false; | ||
899 | 224 | 335 | ||
900 | 225 | // Loop on the current track forever | 336 | // Loop on the current track forever |
901 | 226 | if (d->loop_status == media::Player::LoopStatus::track) | 337 | if (d->loop_status == media::Player::LoopStatus::track) |
902 | 227 | { | 338 | { |
903 | 228 | std::cout << "Looping on the current track..." << std::endl; | 339 | std::cout << "Looping on the current track..." << std::endl; |
905 | 229 | return *(d->current_track); | 340 | do_go_to_previous_track = true; |
906 | 230 | } | 341 | } |
907 | 231 | // Loop over the whole playlist and repeat | 342 | // Loop over the whole playlist and repeat |
909 | 232 | else if (d->loop_status == media::Player::LoopStatus::playlist && !has_next()) | 343 | else if (d->loop_status == media::Player::LoopStatus::playlist && is_first_track(current_iterator())) |
910 | 233 | { | 344 | { |
911 | 234 | std::cout << "Looping on the entire TrackList..." << std::endl; | 345 | std::cout << "Looping on the entire TrackList..." << std::endl; |
929 | 235 | d->current_track = tracks().get().begin(); | 346 | d->current_track = std::prev(tracks().get().end()); |
930 | 236 | return *(d->current_track); | 347 | do_go_to_previous_track = true; |
931 | 237 | } | 348 | } |
932 | 238 | else if (has_next()) | 349 | else |
933 | 239 | { | 350 | { |
934 | 240 | // Keep returning the next track until the last track is reached | 351 | // Current track is not the first track |
935 | 241 | d->current_track = std::next(d->current_track); | 352 | if (not is_first_track(current_iterator())) |
936 | 242 | std::cout << *this << std::endl; | 353 | { |
937 | 243 | } | 354 | // Keep returning the previous track until the first track is reached |
938 | 244 | 355 | d->current_track = std::prev(current_iterator()); | |
939 | 245 | return *(d->current_track); | 356 | do_go_to_previous_track = true; |
940 | 246 | } | 357 | } |
941 | 247 | 358 | // At the beginning of the tracklist and not set to loop, so we stop advancing the tracklist | |
942 | 248 | media::Track::Id media::TrackListSkeleton::previous() | 359 | else |
943 | 249 | { | 360 | { |
944 | 250 | // TODO: Add logic to calculate the previous track | 361 | std::cout << "Beginning of tracklist reached, not advancing to previous since LoopStatus is set to none" << std::endl; |
945 | 251 | return *(d->current_track); | 362 | on_end_of_tracklist()(); |
946 | 363 | } | ||
947 | 364 | } | ||
948 | 365 | |||
949 | 366 | if (do_go_to_previous_track) | ||
950 | 367 | { | ||
951 | 368 | on_track_changed()(*(current_iterator())); | ||
952 | 369 | // Don't automatically call stop() and play() in player_implementation.cpp on_go_to_track() | ||
953 | 370 | // since this breaks video playback when using open_uri() (stop() and play() are unwanted in | ||
954 | 371 | // this scenario since the qtubuntu-media will handle this automatically) | ||
955 | 372 | const bool toggle_player_state = false; | ||
956 | 373 | const media::Track::Id id = *(current_iterator()); | ||
957 | 374 | const std::pair<const media::Track::Id, bool> p = std::make_pair(id, toggle_player_state); | ||
958 | 375 | on_go_to_track()(p); | ||
959 | 376 | } | ||
960 | 377 | |||
961 | 378 | return *(current_iterator()); | ||
962 | 252 | } | 379 | } |
963 | 253 | 380 | ||
964 | 254 | const media::Track::Id& media::TrackListSkeleton::current() | 381 | const media::Track::Id& media::TrackListSkeleton::current() |
965 | 255 | { | 382 | { |
966 | 383 | return *(current_iterator()); | ||
967 | 384 | } | ||
968 | 385 | |||
969 | 386 | const media::TrackList::ConstIterator& media::TrackListSkeleton::current_iterator() | ||
970 | 387 | { | ||
971 | 256 | // Prevent the TrackList from sitting at the end which will cause | 388 | // Prevent the TrackList from sitting at the end which will cause |
972 | 257 | // a segfault when calling current() | 389 | // a segfault when calling current() |
973 | 258 | if (tracks().get().size() && (d->current_track == d->empty_iterator)) | 390 | if (tracks().get().size() && (d->current_track == d->empty_iterator)) |
974 | 391 | { | ||
975 | 392 | std::cout << "Wrapping d->current_track back to begin()" << std::endl; | ||
976 | 259 | d->current_track = d->skeleton.properties.tracks->get().begin(); | 393 | d->current_track = d->skeleton.properties.tracks->get().begin(); |
977 | 394 | } | ||
978 | 260 | else if (tracks().get().empty()) | 395 | else if (tracks().get().empty()) |
979 | 396 | { | ||
980 | 261 | std::cerr << "TrackList is empty therefore there is no valid current track" << std::endl; | 397 | std::cerr << "TrackList is empty therefore there is no valid current track" << std::endl; |
983 | 262 | 398 | } | |
984 | 263 | return *(d->current_track); | 399 | |
985 | 400 | return d->current_track; | ||
986 | 401 | } | ||
987 | 402 | |||
988 | 403 | void media::TrackListSkeleton::reset_current_iterator_if_needed() | ||
989 | 404 | { | ||
990 | 405 | // If all tracks got removed then we need to keep a sane current | ||
991 | 406 | // iterator for further use. | ||
992 | 407 | if (tracks().get().empty()) | ||
993 | 408 | d->current_track = d->empty_iterator; | ||
994 | 264 | } | 409 | } |
995 | 265 | 410 | ||
996 | 266 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const | 411 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const |
997 | @@ -293,7 +438,18 @@ | |||
998 | 293 | if (shuffle) | 438 | if (shuffle) |
999 | 294 | shuffle_tracks(); | 439 | shuffle_tracks(); |
1000 | 295 | else | 440 | else |
1001 | 441 | { | ||
1002 | 442 | // Save the current Track::Id of what's currently playing to restore after unshuffle | ||
1003 | 443 | const media::Track::Id current_id = *(current_iterator()); | ||
1004 | 444 | |||
1005 | 296 | unshuffle_tracks(); | 445 | unshuffle_tracks(); |
1006 | 446 | |||
1007 | 447 | // Since we use assign() in unshuffle_tracks, which invalidates existing iterators, we need | ||
1008 | 448 | // to make sure that current is pointing to the right place | ||
1009 | 449 | auto it = std::find(tracks().get().begin(), tracks().get().end(), current_id); | ||
1010 | 450 | if (it != tracks().get().end()) | ||
1011 | 451 | d->current_track = it; | ||
1012 | 452 | } | ||
1013 | 297 | } | 453 | } |
1014 | 298 | 454 | ||
1015 | 299 | const core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() const | 455 | const core::Property<media::TrackList::Container>& media::TrackListSkeleton::tracks() const |
1016 | @@ -328,6 +484,11 @@ | |||
1017 | 328 | return d->signals.on_go_to_track; | 484 | return d->signals.on_go_to_track; |
1018 | 329 | } | 485 | } |
1019 | 330 | 486 | ||
1020 | 487 | const core::Signal<void>& media::TrackListSkeleton::on_end_of_tracklist() const | ||
1021 | 488 | { | ||
1022 | 489 | return d->signals.on_end_of_tracklist; | ||
1023 | 490 | } | ||
1024 | 491 | |||
1025 | 331 | core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListSkeleton::on_track_list_replaced() | 492 | core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListSkeleton::on_track_list_replaced() |
1026 | 332 | { | 493 | { |
1027 | 333 | return d->signals.on_track_list_replaced; | 494 | return d->signals.on_track_list_replaced; |
1028 | @@ -353,6 +514,17 @@ | |||
1029 | 353 | return d->signals.on_go_to_track; | 514 | return d->signals.on_go_to_track; |
1030 | 354 | } | 515 | } |
1031 | 355 | 516 | ||
1032 | 517 | core::Signal<void>& media::TrackListSkeleton::on_end_of_tracklist() | ||
1033 | 518 | { | ||
1034 | 519 | return d->signals.on_end_of_tracklist; | ||
1035 | 520 | } | ||
1036 | 521 | |||
1037 | 522 | void media::TrackListSkeleton::reset() | ||
1038 | 523 | { | ||
1039 | 524 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
1040 | 525 | d->current_track = d->empty_iterator; | ||
1041 | 526 | } | ||
1042 | 527 | |||
1043 | 356 | // operator<< pretty prints the given TrackList to the given output stream. | 528 | // operator<< pretty prints the given TrackList to the given output stream. |
1044 | 357 | inline std::ostream& media::operator<<(std::ostream& out, const media::TrackList& tracklist) | 529 | inline std::ostream& media::operator<<(std::ostream& out, const media::TrackList& tracklist) |
1045 | 358 | { | 530 | { |
1046 | 359 | 531 | ||
1047 | === modified file 'src/core/media/track_list_skeleton.h' | |||
1048 | --- src/core/media/track_list_skeleton.h 2015-04-29 21:18:20 +0000 | |||
1049 | +++ src/core/media/track_list_skeleton.h 2015-08-11 16:10:30 +0000 | |||
1050 | @@ -41,8 +41,8 @@ | |||
1051 | 41 | const core::ubuntu::media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator); | 41 | const core::ubuntu::media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator); |
1052 | 42 | ~TrackListSkeleton(); | 42 | ~TrackListSkeleton(); |
1053 | 43 | 43 | ||
1056 | 44 | bool has_next() const; | 44 | bool has_next(); |
1057 | 45 | bool has_previous() const; | 45 | bool has_previous(); |
1058 | 46 | Track::Id next(); | 46 | Track::Id next(); |
1059 | 47 | Track::Id previous(); | 47 | Track::Id previous(); |
1060 | 48 | const Track::Id& current(); | 48 | const Track::Id& current(); |
1061 | @@ -52,10 +52,13 @@ | |||
1062 | 52 | 52 | ||
1063 | 53 | const core::Signal<ContainerTrackIdTuple>& on_track_list_replaced() const; | 53 | const core::Signal<ContainerTrackIdTuple>& on_track_list_replaced() const; |
1064 | 54 | const core::Signal<Track::Id>& on_track_added() const; | 54 | const core::Signal<Track::Id>& on_track_added() const; |
1065 | 55 | core::Signal<Track::Id>& on_track_added(); | ||
1066 | 55 | const core::Signal<Track::Id>& on_track_removed() const; | 56 | const core::Signal<Track::Id>& on_track_removed() const; |
1067 | 56 | const core::Signal<Track::Id>& on_track_changed() const; | 57 | const core::Signal<Track::Id>& on_track_changed() const; |
1068 | 57 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; | 58 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; |
1069 | 58 | core::Signal<std::pair<Track::Id, bool>>& on_go_to_track(); | 59 | core::Signal<std::pair<Track::Id, bool>>& on_go_to_track(); |
1070 | 60 | const core::Signal<void>& on_end_of_tracklist() const; | ||
1071 | 61 | core::Signal<void>& on_end_of_tracklist(); | ||
1072 | 59 | core::Signal<Track::Id>& on_track_removed(); | 62 | core::Signal<Track::Id>& on_track_removed(); |
1073 | 60 | 63 | ||
1074 | 61 | core::Property<Container>& tracks(); | 64 | core::Property<Container>& tracks(); |
1075 | @@ -67,12 +70,18 @@ | |||
1076 | 67 | void on_shuffle_changed(bool shuffle); | 70 | void on_shuffle_changed(bool shuffle); |
1077 | 68 | 71 | ||
1078 | 69 | protected: | 72 | protected: |
1079 | 73 | inline bool is_first_track(const ConstIterator &it); | ||
1080 | 74 | inline bool is_last_track(const ConstIterator &it); | ||
1081 | 75 | inline const TrackList::ConstIterator& current_iterator(); | ||
1082 | 76 | void reset_current_iterator_if_needed(); | ||
1083 | 77 | |||
1084 | 70 | core::Property<bool>& can_edit_tracks(); | 78 | core::Property<bool>& can_edit_tracks(); |
1085 | 71 | 79 | ||
1086 | 72 | core::Signal<ContainerTrackIdTuple>& on_track_list_replaced(); | 80 | core::Signal<ContainerTrackIdTuple>& on_track_list_replaced(); |
1087 | 73 | core::Signal<Track::Id>& on_track_added(); | ||
1088 | 74 | core::Signal<Track::Id>& on_track_changed(); | 81 | core::Signal<Track::Id>& on_track_changed(); |
1089 | 75 | 82 | ||
1090 | 83 | void reset(); | ||
1091 | 84 | |||
1092 | 76 | private: | 85 | private: |
1093 | 77 | struct Private; | 86 | struct Private; |
1094 | 78 | std::unique_ptr<Private> d; | 87 | std::unique_ptr<Private> d; |
1095 | 79 | 88 | ||
1096 | === modified file 'src/core/media/track_list_stub.cpp' | |||
1097 | --- src/core/media/track_list_stub.cpp 2015-04-29 21:18:20 +0000 | |||
1098 | +++ src/core/media/track_list_stub.cpp 2015-08-11 16:10:30 +0000 | |||
1099 | @@ -48,7 +48,14 @@ | |||
1100 | 48 | parent(parent), | 48 | parent(parent), |
1101 | 49 | object(object), | 49 | object(object), |
1102 | 50 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), | 50 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), |
1104 | 51 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()) | 51 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()), |
1105 | 52 | signals | ||
1106 | 53 | { | ||
1107 | 54 | object->get_signal<mpris::TrackList::Signals::TrackAdded>(), | ||
1108 | 55 | object->get_signal<mpris::TrackList::Signals::TrackRemoved>(), | ||
1109 | 56 | object->get_signal<mpris::TrackList::Signals::TrackListReplaced>(), | ||
1110 | 57 | object->get_signal<mpris::TrackList::Signals::TrackChanged>() | ||
1111 | 58 | } | ||
1112 | 52 | { | 59 | { |
1113 | 53 | } | 60 | } |
1114 | 54 | 61 | ||
1115 | @@ -59,11 +66,70 @@ | |||
1116 | 59 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; | 66 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; |
1117 | 60 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; | 67 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; |
1118 | 61 | 68 | ||
1124 | 62 | core::Signal<media::TrackList::ContainerTrackIdTuple> on_track_list_replaced; | 69 | |
1125 | 63 | core::Signal<Track::Id> on_track_added; | 70 | struct Signals |
1126 | 64 | core::Signal<Track::Id> on_track_removed; | 71 | { |
1127 | 65 | core::Signal<Track::Id> on_track_changed; | 72 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType> DBusTrackAddedSignal; |
1128 | 66 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; | 73 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType> DBusTrackRemovedSignal; |
1129 | 74 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType> DBusTrackListReplacedSignal; | ||
1130 | 75 | typedef core::dbus::Signal<mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType> DBusTrackChangedSignal; | ||
1131 | 76 | |||
1132 | 77 | Signals(const std::shared_ptr<DBusTrackAddedSignal>& track_added, | ||
1133 | 78 | const std::shared_ptr<DBusTrackRemovedSignal>& track_removed, | ||
1134 | 79 | const std::shared_ptr<DBusTrackListReplacedSignal>& track_list_replaced, | ||
1135 | 80 | const std::shared_ptr<DBusTrackChangedSignal>& track_changed) | ||
1136 | 81 | : on_track_added(), | ||
1137 | 82 | on_track_removed(), | ||
1138 | 83 | on_track_list_replaced(), | ||
1139 | 84 | on_track_changed(), | ||
1140 | 85 | dbus | ||
1141 | 86 | { | ||
1142 | 87 | track_added, | ||
1143 | 88 | track_removed, | ||
1144 | 89 | track_list_replaced, | ||
1145 | 90 | track_changed, | ||
1146 | 91 | } | ||
1147 | 92 | { | ||
1148 | 93 | dbus.on_track_added->connect([this](const Track::Id& id) | ||
1149 | 94 | { | ||
1150 | 95 | std::cout << "OnTrackAdded signal arrived via the bus." << std::endl; | ||
1151 | 96 | on_track_added(id); | ||
1152 | 97 | }); | ||
1153 | 98 | |||
1154 | 99 | dbus.on_track_removed->connect([this](const Track::Id& id) | ||
1155 | 100 | { | ||
1156 | 101 | std::cout << "OnTrackRemoved signal arrived via the bus." << std::endl; | ||
1157 | 102 | on_track_removed(id); | ||
1158 | 103 | }); | ||
1159 | 104 | |||
1160 | 105 | dbus.on_track_list_replaced->connect([this](const media::TrackList::ContainerTrackIdTuple& list) | ||
1161 | 106 | { | ||
1162 | 107 | std::cout << "OnTrackListRemoved signal arrived via the bus." << std::endl; | ||
1163 | 108 | on_track_list_replaced(list); | ||
1164 | 109 | }); | ||
1165 | 110 | |||
1166 | 111 | dbus.on_track_changed->connect([this](const Track::Id& id) | ||
1167 | 112 | { | ||
1168 | 113 | std::cout << "OnTrackChanged signal arrived via the bus." << std::endl; | ||
1169 | 114 | on_track_changed(id); | ||
1170 | 115 | }); | ||
1171 | 116 | } | ||
1172 | 117 | |||
1173 | 118 | core::Signal<Track::Id> on_track_added; | ||
1174 | 119 | core::Signal<Track::Id> on_track_removed; | ||
1175 | 120 | core::Signal<media::TrackList::ContainerTrackIdTuple> on_track_list_replaced; | ||
1176 | 121 | core::Signal<Track::Id> on_track_changed; | ||
1177 | 122 | core::Signal<std::pair<Track::Id, bool>> on_go_to_track; | ||
1178 | 123 | core::Signal<void> on_end_of_tracklist; | ||
1179 | 124 | |||
1180 | 125 | struct DBus | ||
1181 | 126 | { | ||
1182 | 127 | std::shared_ptr<DBusTrackAddedSignal> on_track_added; | ||
1183 | 128 | std::shared_ptr<DBusTrackRemovedSignal> on_track_removed; | ||
1184 | 129 | std::shared_ptr<DBusTrackListReplacedSignal> on_track_list_replaced; | ||
1185 | 130 | std::shared_ptr<DBusTrackChangedSignal> on_track_changed; | ||
1186 | 131 | } dbus; | ||
1187 | 132 | } signals; | ||
1188 | 67 | }; | 133 | }; |
1189 | 68 | 134 | ||
1190 | 69 | media::TrackListStub::TrackListStub( | 135 | media::TrackListStub::TrackListStub( |
1191 | @@ -104,6 +170,18 @@ | |||
1192 | 104 | return md; | 170 | return md; |
1193 | 105 | } | 171 | } |
1194 | 106 | 172 | ||
1195 | 173 | media::Track::UriType media::TrackListStub::query_uri_for_track(const media::Track::Id& id) | ||
1196 | 174 | { | ||
1197 | 175 | auto op = d->object->invoke_method_synchronously< | ||
1198 | 176 | mpris::TrackList::GetTracksUri, | ||
1199 | 177 | std::string>(id); | ||
1200 | 178 | |||
1201 | 179 | if (op.is_error()) | ||
1202 | 180 | throw std::runtime_error("Problem querying track for uri: " + op.error()); | ||
1203 | 181 | |||
1204 | 182 | return op.value(); | ||
1205 | 183 | } | ||
1206 | 184 | |||
1207 | 107 | void media::TrackListStub::add_track_with_uri_at( | 185 | void media::TrackListStub::add_track_with_uri_at( |
1208 | 108 | const media::Track::UriType& uri, | 186 | const media::Track::UriType& uri, |
1209 | 109 | const media::Track::Id& id, | 187 | const media::Track::Id& id, |
1210 | @@ -161,33 +239,38 @@ | |||
1211 | 161 | 239 | ||
1212 | 162 | void media::TrackListStub::reset() | 240 | void media::TrackListStub::reset() |
1213 | 163 | { | 241 | { |
1215 | 164 | std::cerr << "reset() does nothing from the client side" << std::endl; | 242 | auto op = d->object->invoke_method_synchronously<mpris::TrackList::Reset, void>(); |
1216 | 243 | |||
1217 | 244 | if (op.is_error()) | ||
1218 | 245 | throw std::runtime_error("Problem resetting tracklist: " + op.error()); | ||
1219 | 165 | } | 246 | } |
1220 | 166 | 247 | ||
1221 | 167 | const core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListStub::on_track_list_replaced() const | 248 | const core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListStub::on_track_list_replaced() const |
1222 | 168 | { | 249 | { |
1225 | 169 | std::cout << "Signal on_track_list_replaced arrived via the bus" << std::endl; | 250 | return d->signals.on_track_list_replaced; |
1224 | 170 | return d->on_track_list_replaced; | ||
1226 | 171 | } | 251 | } |
1227 | 172 | 252 | ||
1228 | 173 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_added() const | 253 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_added() const |
1229 | 174 | { | 254 | { |
1232 | 175 | std::cout << "Signal on_track_added arrived via the bus" << std::endl; | 255 | return d->signals.on_track_added; |
1231 | 176 | return d->on_track_added; | ||
1233 | 177 | } | 256 | } |
1234 | 178 | 257 | ||
1235 | 179 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_removed() const | 258 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_removed() const |
1236 | 180 | { | 259 | { |
1239 | 181 | std::cout << "Signal on_track_removed arrived via the bus" << std::endl; | 260 | return d->signals.on_track_removed; |
1238 | 182 | return d->on_track_removed; | ||
1240 | 183 | } | 261 | } |
1241 | 184 | 262 | ||
1242 | 185 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_changed() const | 263 | const core::Signal<media::Track::Id>& media::TrackListStub::on_track_changed() const |
1243 | 186 | { | 264 | { |
1245 | 187 | return d->on_track_changed; | 265 | return d->signals.on_track_changed; |
1246 | 188 | } | 266 | } |
1247 | 189 | 267 | ||
1248 | 190 | const core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListStub::on_go_to_track() const | 268 | const core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListStub::on_go_to_track() const |
1249 | 191 | { | 269 | { |
1251 | 192 | return d->on_go_to_track; | 270 | return d->signals.on_go_to_track; |
1252 | 271 | } | ||
1253 | 272 | |||
1254 | 273 | const core::Signal<void>& media::TrackListStub::on_end_of_tracklist() const | ||
1255 | 274 | { | ||
1256 | 275 | return d->signals.on_end_of_tracklist; | ||
1257 | 193 | } | 276 | } |
1258 | 194 | 277 | ||
1259 | === modified file 'src/core/media/track_list_stub.h' | |||
1260 | --- src/core/media/track_list_stub.h 2015-04-29 21:18:20 +0000 | |||
1261 | +++ src/core/media/track_list_stub.h 2015-08-11 16:10:30 +0000 | |||
1262 | @@ -45,6 +45,7 @@ | |||
1263 | 45 | const core::Property<Container>& tracks() const; | 45 | const core::Property<Container>& tracks() const; |
1264 | 46 | 46 | ||
1265 | 47 | Track::MetaData query_meta_data_for_track(const Track::Id& id); | 47 | Track::MetaData query_meta_data_for_track(const Track::Id& id); |
1266 | 48 | Track::UriType query_uri_for_track(const Track::Id& id); | ||
1267 | 48 | 49 | ||
1268 | 49 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); | 50 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); |
1269 | 50 | void remove_track(const Track::Id& id); | 51 | void remove_track(const Track::Id& id); |
1270 | @@ -64,6 +65,7 @@ | |||
1271 | 64 | const core::Signal<Track::Id>& on_track_removed() const; | 65 | const core::Signal<Track::Id>& on_track_removed() const; |
1272 | 65 | const core::Signal<Track::Id>& on_track_changed() const; | 66 | const core::Signal<Track::Id>& on_track_changed() const; |
1273 | 66 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; | 67 | const core::Signal<std::pair<Track::Id, bool>>& on_go_to_track() const; |
1274 | 68 | const core::Signal<void>& on_end_of_tracklist() const; | ||
1275 | 67 | 69 | ||
1276 | 68 | private: | 70 | private: |
1277 | 69 | struct Private; | 71 | struct Private; |
Overall looks good, although I have some comments.