Merge lp:~thomas-voss/media-hub/decouple-service-skeleton-and-implementation into lp:media-hub
- decouple-service-skeleton-and-implementation
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~thomas-voss/media-hub/decouple-service-skeleton-and-implementation |
Merge into: | lp:media-hub |
Prerequisite: | lp:~thomas-voss/media-hub/introduce-apparmor-interfaces |
Diff against target: |
668 lines (+325/-112) 9 files modified
src/core/media/CMakeLists.txt (+2/-1) src/core/media/hashed_keyed_player_store.cpp (+80/-0) src/core/media/hashed_keyed_player_store.h (+76/-0) src/core/media/keyed_player_store.h (+83/-0) src/core/media/server/server.cpp (+19/-4) src/core/media/service_implementation.cpp (+11/-11) src/core/media/service_implementation.h (+2/-1) src/core/media/service_skeleton.cpp (+38/-70) src/core/media/service_skeleton.h (+14/-25) |
To merge this branch: | bzr merge lp:~thomas-voss/media-hub/decouple-service-skeleton-and-implementation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Jim Hodapp (community) | code | Needs Fixing | |
Review via email: mp+243283@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-03-04.
Commit message
Decouple the ServiceSkeleton from the ServiceImplemen
Provide a default implementation HashedKeyedPlay
Adjust implementation to account for ServiceImplemen
Description of the change
Decouple the ServiceSkeleton from the ServiceImplemen
Provide a default implementation HashedKeyedPlay
Adjust implementation to account for ServiceImplemen
PS Jenkins bot (ps-jenkins) wrote : | # |
Jim Hodapp (jhodapp) wrote : | # |
One simple change listed below.
- 113. By Thomas Voß
-
[ Jim Hodapp ]
* Resubmitting with prerequisite branch (LP: #1331041)
[ Justin McPherson ]
* Resubmitting with prerequisite branch (LP: #1331041)
Thomas Voß (thomas-voss) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:113
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 114. By Thomas Voß
-
[ Jim Hodapp ]
* Error reporting all the way up to the app level from the playbin
pipeline.
[ Ubuntu daily release ]
* New rebuild forced
[ Jim Hodapp ]
* Don't auto-resume playback of videos after a phone call ends. (LP:
#1411273)
[ Ubuntu daily release ]
* New rebuild forced
[ Ricardo Salveti de Araujo ]
* service_implementation: adding debug for call started/ended signals.
Make sure account and connection are available when setting up
account manager (patch from Gustavo Boiko). call_monitor: don't
check caps when hooking up on/off signals, until bug 1409125 is
fixed. Enable parallel building . (LP: #1409125)
[ Jim Hodapp ]
* Pause playback when recording begins. (LP: #1398047)
[ Ricardo Salveti de Araujo ]
* call_monitor.cpp: waiting for bridge to be up, and also protecting
the on_change call (LP: #1408137)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:114
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Francis Ginther (fginther) wrote : | # |
The jenkins node for the amd64 build failed, I've restarted a new ci run.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:114
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 115. By Thomas Voß
-
Merge prereq branch.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:115
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 116. By Thomas Voß
-
Merge prereq branch.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:116
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 117. By Thomas Voß
-
Merge prereq branch.
- 118. By Thomas Voß
-
* debian/control:
- Removing pre-depends that are not required
- Bumping standards-version to 3.9.6
[ Ricardo Salveti de Araujo ]
* Migrating tests to use ogg instead of mp3/avi removed:
tests/h264.avi tests/test.mp3 added: tests/test-audio-1. ogg
tests/test-video. ogg tests/test.mp3 renamed: tests/test.ogg =>
tests/test-audio. ogg
Unmerged revisions
Preview Diff
1 | === modified file 'src/core/media/CMakeLists.txt' |
2 | --- src/core/media/CMakeLists.txt 2015-03-04 16:37:33 +0000 |
3 | +++ src/core/media/CMakeLists.txt 2015-03-04 16:37:33 +0000 |
4 | @@ -87,7 +87,8 @@ |
5 | ${MPRIS_HEADERS} |
6 | |
7 | client_death_observer.cpp |
8 | - hybris_client_death_observer.cpp |
9 | + hashed_keyed_player_store.cpp |
10 | + hybris_client_death_observer.cpp |
11 | cover_art_resolver.cpp |
12 | engine.cpp |
13 | |
14 | |
15 | === added file 'src/core/media/hashed_keyed_player_store.cpp' |
16 | --- src/core/media/hashed_keyed_player_store.cpp 1970-01-01 00:00:00 +0000 |
17 | +++ src/core/media/hashed_keyed_player_store.cpp 2015-03-04 16:37:33 +0000 |
18 | @@ -0,0 +1,80 @@ |
19 | +/* |
20 | + * Copyright © 2014 Canonical Ltd. |
21 | + * |
22 | + * This program is free software: you can redistribute it and/or modify it |
23 | + * under the terms of the GNU Lesser General Public License version 3, |
24 | + * as published by the Free Software Foundation. |
25 | + * |
26 | + * This program is distributed in the hope that it will be useful, |
27 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | + * GNU Lesser General Public License for more details. |
30 | + * |
31 | + * You should have received a copy of the GNU Lesser General Public License |
32 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | + * |
34 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
35 | + */ |
36 | + |
37 | +#include <core/media/hashed_keyed_player_store.h> |
38 | + |
39 | +namespace media = core::ubuntu::media; |
40 | + |
41 | +media::HashedKeyedPlayerStore::HashedKeyedPlayerStore() |
42 | +{ |
43 | +} |
44 | + |
45 | +const core::Property<std::shared_ptr<media::Player>>& media::HashedKeyedPlayerStore::current_player() const |
46 | +{ |
47 | + return prop_current_player; |
48 | +} |
49 | + |
50 | +bool media::HashedKeyedPlayerStore::has_player_for_key(const media::Player::PlayerKey& key) const |
51 | +{ |
52 | + std::lock_guard<std::mutex> lg{guard}; |
53 | + return map.count(key) > 0; |
54 | +} |
55 | + |
56 | +std::shared_ptr<media::Player> media::HashedKeyedPlayerStore::player_for_key(const media::Player::PlayerKey& key) const |
57 | +{ |
58 | + std::lock_guard<std::mutex> lg{guard}; |
59 | + auto it = map.find(key); |
60 | + |
61 | + if (it == map.end()) throw std::out_of_range |
62 | + { |
63 | + "HashedKeyedPlayerStore::player_for_key: No player known for " + std::to_string(key) |
64 | + }; |
65 | + |
66 | + return it->second; |
67 | +} |
68 | + |
69 | +void media::HashedKeyedPlayerStore::enumerate_players(const media::KeyedPlayerStore::PlayerEnumerator& enumerator) const |
70 | +{ |
71 | + std::lock_guard<std::mutex> lg{guard}; |
72 | + for (const auto& pair : map) |
73 | + enumerator(pair.first, pair.second); |
74 | +} |
75 | + |
76 | +void media::HashedKeyedPlayerStore::add_player_for_key(const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) |
77 | +{ |
78 | + std::lock_guard<std::mutex> lg{guard}; |
79 | + map[key] = player; |
80 | +} |
81 | + |
82 | +void media::HashedKeyedPlayerStore::remove_player_for_key(const media::Player::PlayerKey& key) |
83 | +{ |
84 | + std::lock_guard<std::mutex> lg{guard}; |
85 | + auto it = map.find(key); |
86 | + if (it != map.end()) |
87 | + { |
88 | + if (prop_current_player == it->second) |
89 | + prop_current_player = nullptr; |
90 | + |
91 | + map.erase(it); |
92 | + } |
93 | +} |
94 | + |
95 | +void media::HashedKeyedPlayerStore::set_current_player_for_key(const media::Player::PlayerKey& key) |
96 | +{ |
97 | + prop_current_player = player_for_key(key); |
98 | +} |
99 | |
100 | === added file 'src/core/media/hashed_keyed_player_store.h' |
101 | --- src/core/media/hashed_keyed_player_store.h 1970-01-01 00:00:00 +0000 |
102 | +++ src/core/media/hashed_keyed_player_store.h 2015-03-04 16:37:33 +0000 |
103 | @@ -0,0 +1,76 @@ |
104 | +/* |
105 | + * Copyright © 2014 Canonical Ltd. |
106 | + * |
107 | + * This program is free software: you can redistribute it and/or modify it |
108 | + * under the terms of the GNU Lesser General Public License version 3, |
109 | + * as published by the Free Software Foundation. |
110 | + * |
111 | + * This program is distributed in the hope that it will be useful, |
112 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
113 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
114 | + * GNU Lesser General Public License for more details. |
115 | + * |
116 | + * You should have received a copy of the GNU Lesser General Public License |
117 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
118 | + * |
119 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
120 | + */ |
121 | + |
122 | +#ifndef CORE_UBUNTU_MEDIA_HASHED_KEYED_PLAYER_STORE_H_ |
123 | +#define CORE_UBUNTU_MEDIA_HASHED_KEYED_PLAYER_STORE_H_ |
124 | + |
125 | +#include <core/media/keyed_player_store.h> |
126 | + |
127 | +#include <mutex> |
128 | +#include <unordered_map> |
129 | + |
130 | +namespace core |
131 | +{ |
132 | +namespace ubuntu |
133 | +{ |
134 | +namespace media |
135 | +{ |
136 | +// Implements KeyedPlayerStore using a std::unordered_map. |
137 | +class HashedKeyedPlayerStore : public KeyedPlayerStore |
138 | +{ |
139 | +public: |
140 | + HashedKeyedPlayerStore(); |
141 | + // We keep track of the "current" player, that is, the one |
142 | + // that has been created most recently, or has been explicitly foregrounded, or has been enabled for |
143 | + // background playback. We provide a getable/observable access to that designated instance. |
144 | + const core::Property<std::shared_ptr<media::Player>>& current_player() const override; |
145 | + |
146 | + // We keep track of all known player sessions here and render them accessible via |
147 | + // the key. All of these functions are thread-safe but not reentrant. |
148 | + // Returns true iff a player is known for the given key. |
149 | + bool has_player_for_key(const Player::PlayerKey& key) const override; |
150 | + |
151 | + // Returns the player for the given key or throws std::out_of_range if no player is known |
152 | + // for the given key. |
153 | + // Throws std::out_of_range if no player is known for the key. |
154 | + std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const override; |
155 | + |
156 | + // Enumerates all known players and invokes the given enumerator for each |
157 | + // (key, player) pair. |
158 | + void enumerate_players(const PlayerEnumerator& enumerator) const override; |
159 | + |
160 | + // Adds the given player with the given key. |
161 | + void add_player_for_key(const Player::PlayerKey& key, const std::shared_ptr<Player>& player) override; |
162 | + |
163 | + // Removes the player for the given key, and unsets it if it is the current one. |
164 | + void remove_player_for_key(const Player::PlayerKey& key) override; |
165 | + |
166 | + // Makes the player known under the given key current. |
167 | + // Throws std::out_of_range if no player is known for the key. |
168 | + void set_current_player_for_key(const Player::PlayerKey& key) override; |
169 | + |
170 | +private: |
171 | + core::Property<std::shared_ptr<Player>> prop_current_player; |
172 | + mutable std::mutex guard; |
173 | + std::unordered_map<Player::PlayerKey, std::shared_ptr<Player>> map; |
174 | +}; |
175 | +} |
176 | +} |
177 | +} |
178 | + |
179 | +#endif // CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ |
180 | |
181 | === added file 'src/core/media/keyed_player_store.cpp' |
182 | === added file 'src/core/media/keyed_player_store.h' |
183 | --- src/core/media/keyed_player_store.h 1970-01-01 00:00:00 +0000 |
184 | +++ src/core/media/keyed_player_store.h 2015-03-04 16:37:33 +0000 |
185 | @@ -0,0 +1,83 @@ |
186 | +/* |
187 | + * Copyright © 2014 Canonical Ltd. |
188 | + * |
189 | + * This program is free software: you can redistribute it and/or modify it |
190 | + * under the terms of the GNU Lesser General Public License version 3, |
191 | + * as published by the Free Software Foundation. |
192 | + * |
193 | + * This program is distributed in the hope that it will be useful, |
194 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
195 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
196 | + * GNU Lesser General Public License for more details. |
197 | + * |
198 | + * You should have received a copy of the GNU Lesser General Public License |
199 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
200 | + * |
201 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
202 | + */ |
203 | + |
204 | +#ifndef CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ |
205 | +#define CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ |
206 | + |
207 | +#include <core/media/player.h> |
208 | + |
209 | +#include <core/property.h> |
210 | + |
211 | +#include <functional> |
212 | +#include <memory> |
213 | + |
214 | +namespace core |
215 | +{ |
216 | +namespace ubuntu |
217 | +{ |
218 | +namespace media |
219 | +{ |
220 | +// An interface abstracting keyed lookups of known Player instances. |
221 | +class KeyedPlayerStore |
222 | +{ |
223 | +public: |
224 | + // Save us some typing. |
225 | + typedef std::shared_ptr<KeyedPlayerStore> Ptr; |
226 | + // Functor for enumerating all known (key, player) pairs. |
227 | + typedef std::function |
228 | + < |
229 | + void( |
230 | + // The key of the player. |
231 | + const Player::PlayerKey&, |
232 | + // The actual player instance. |
233 | + const std::shared_ptr<Player>& |
234 | + ) |
235 | + > PlayerEnumerator; |
236 | + // We keep track of the "current" player, that is, the one |
237 | + // that has been created most recently and provide a getable/observable |
238 | + // access to that designated instance. |
239 | + virtual const core::Property<std::shared_ptr<Player>>& current_player() const = 0; |
240 | + |
241 | + // We keep track of all known player sessions here and render them accessible via |
242 | + // the key. All of these functions are thread-safe but not reentrant. |
243 | + // Returns true iff a player is known for the given key. |
244 | + virtual bool has_player_for_key(const Player::PlayerKey& key) const = 0; |
245 | + // Returns the player for the given key or throws std::out_of_range if no player is known |
246 | + // for the given key. |
247 | + virtual std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const = 0; |
248 | + // Enumerates all known players and invokes the given enumerator for each |
249 | + // (key, player) pair. |
250 | + virtual void enumerate_players(const PlayerEnumerator& enumerator) const = 0; |
251 | + // Adds the given player with the given key. |
252 | + virtual void add_player_for_key(const Player::PlayerKey& key, const std::shared_ptr<Player>& player) = 0; |
253 | + // Removes the player for the given key, and unsets it if it is the current one. |
254 | + virtual void remove_player_for_key(const Player::PlayerKey& key) = 0; |
255 | + // Makes the player known under the given key current. |
256 | + virtual void set_current_player_for_key(const Player::PlayerKey& key) = 0; |
257 | + |
258 | +protected: |
259 | + KeyedPlayerStore() = default; |
260 | + KeyedPlayerStore(const KeyedPlayerStore&) = delete; |
261 | + virtual ~KeyedPlayerStore() = default; |
262 | + KeyedPlayerStore& operator=(const KeyedPlayerStore&) = delete; |
263 | +}; |
264 | +} |
265 | +} |
266 | +} |
267 | + |
268 | +#endif // CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ |
269 | |
270 | === modified file 'src/core/media/server/server.cpp' |
271 | --- src/core/media/server/server.cpp 2015-03-04 16:37:33 +0000 |
272 | +++ src/core/media/server/server.cpp 2015-03-04 16:37:33 +0000 |
273 | @@ -20,6 +20,7 @@ |
274 | #include <core/media/player.h> |
275 | #include <core/media/track_list.h> |
276 | |
277 | +#include "core/media/hashed_keyed_player_store.h" |
278 | #include "core/media/service_implementation.h" |
279 | |
280 | #include <core/posix/signal.h> |
281 | @@ -103,23 +104,37 @@ |
282 | } |
283 | }; |
284 | |
285 | + // Our common player store instance for tracking player instances. |
286 | + auto player_store = std::make_shared<media::HashedKeyedPlayerStore>(); |
287 | // We assemble the configuration for executing the service now. |
288 | media::ServiceImplementation::Configuration service_config |
289 | { |
290 | + std::make_shared<media::HashedKeyedPlayerStore>(), |
291 | external_services |
292 | }; |
293 | |
294 | - auto service = std::make_shared<media::ServiceImplementation>(service_config); |
295 | + auto impl = std::make_shared<media::ServiceImplementation>(media::ServiceImplementation::Configuration |
296 | + { |
297 | + player_store, |
298 | + external_services |
299 | + }); |
300 | + |
301 | + auto skeleton = std::make_shared<media::ServiceSkeleton>(media::ServiceSkeleton::Configuration |
302 | + { |
303 | + impl, |
304 | + player_store, |
305 | + |
306 | + }); |
307 | |
308 | std::thread service_worker |
309 | { |
310 | - [&shutdown_requested, service]() |
311 | + [&shutdown_requested, skeleton]() |
312 | { |
313 | while (not shutdown_requested) |
314 | { |
315 | try |
316 | { |
317 | - service->run(); |
318 | + skeleton->run(); |
319 | } |
320 | catch (const std::exception& e) |
321 | { |
322 | @@ -142,7 +157,7 @@ |
323 | shutdown_requested = true; |
324 | |
325 | // And stop execution of helper and actual service. |
326 | - service->stop(); |
327 | + skeleton->stop(); |
328 | |
329 | if (service_worker.joinable()) |
330 | service_worker.join(); |
331 | |
332 | === modified file 'src/core/media/service_implementation.cpp' |
333 | --- src/core/media/service_implementation.cpp 2015-03-04 16:37:33 +0000 |
334 | +++ src/core/media/service_implementation.cpp 2015-03-04 16:37:33 +0000 |
335 | @@ -188,11 +188,11 @@ |
336 | // until all dispatches are done |
337 | d->configuration.external_services.io_service.post([this, key]() |
338 | { |
339 | - if (!has_player_for_key(key)) |
340 | + if (!d->configuration.player_store->has_player_for_key(key)) |
341 | return; |
342 | |
343 | - if (player_for_key(key)->lifetime() == Player::Lifetime::normal) |
344 | - remove_player_for_key(key); |
345 | + if (d->configuration.player_store->player_for_key(key)->lifetime() == Player::Lifetime::normal) |
346 | + d->configuration.player_store->remove_player_for_key(key); |
347 | }); |
348 | }); |
349 | |
350 | @@ -213,19 +213,19 @@ |
351 | |
352 | void media::ServiceImplementation::pause_other_sessions(media::Player::PlayerKey key) |
353 | { |
354 | - if (not has_player_for_key(key)) |
355 | + if (not d->configuration.player_store->has_player_for_key(key)) |
356 | { |
357 | cerr << "Could not find Player by key: " << key << endl; |
358 | return; |
359 | } |
360 | |
361 | - auto current_player = player_for_key(key); |
362 | + auto current_player = d->configuration.player_store->player_for_key(key); |
363 | |
364 | // We immediately make the player known as new current player. |
365 | if (current_player->audio_stream_role() == media::Player::multimedia) |
366 | - set_current_player_for_key(key); |
367 | + d->configuration.player_store->set_current_player_for_key(key); |
368 | |
369 | - enumerate_players([current_player, key](const media::Player::PlayerKey& other_key, const std::shared_ptr<media::Player>& other_player) |
370 | + d->configuration.player_store->enumerate_players([current_player, key](const media::Player::PlayerKey& other_key, const std::shared_ptr<media::Player>& other_player) |
371 | { |
372 | // Only pause a Player if all of the following criteria are met: |
373 | // 1) currently playing |
374 | @@ -245,7 +245,7 @@ |
375 | |
376 | void media::ServiceImplementation::pause_all_multimedia_sessions() |
377 | { |
378 | - enumerate_players([this](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) |
379 | + d->configuration.player_store->enumerate_players([this](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) |
380 | { |
381 | if (player->playback_status() == Player::playing |
382 | && player->audio_stream_role() == media::Player::multimedia) |
383 | @@ -260,7 +260,7 @@ |
384 | void media::ServiceImplementation::resume_paused_multimedia_sessions(bool resume_video_sessions) |
385 | { |
386 | std::for_each(d->paused_sessions.begin(), d->paused_sessions.end(), [this, resume_video_sessions](const media::Player::PlayerKey& key) { |
387 | - auto player = player_for_key(key); |
388 | + auto player = d->configuration.player_store->player_for_key(key); |
389 | // Only resume video playback if explicitly desired |
390 | if (resume_video_sessions || player->is_audio_source()) |
391 | player->play(); |
392 | @@ -273,10 +273,10 @@ |
393 | |
394 | void media::ServiceImplementation::resume_multimedia_session() |
395 | { |
396 | - if (not has_player_for_key(d->resume_key)) |
397 | + if (not d->configuration.player_store->has_player_for_key(d->resume_key)) |
398 | return; |
399 | |
400 | - auto player = player_for_key(d->resume_key); |
401 | + auto player = d->configuration.player_store->player_for_key(d->resume_key); |
402 | |
403 | if (player->playback_status() == Player::paused) |
404 | { |
405 | |
406 | === modified file 'src/core/media/service_implementation.h' |
407 | --- src/core/media/service_implementation.h 2015-03-04 16:37:33 +0000 |
408 | +++ src/core/media/service_implementation.h 2015-03-04 16:37:33 +0000 |
409 | @@ -30,12 +30,13 @@ |
410 | { |
411 | class Player; |
412 | |
413 | -class ServiceImplementation : public ServiceSkeleton |
414 | +class ServiceImplementation : public Service |
415 | { |
416 | public: |
417 | // All creation time arguments go here. |
418 | struct Configuration |
419 | { |
420 | + KeyedPlayerStore::Ptr player_store; |
421 | helper::ExternalServices& external_services; |
422 | }; |
423 | |
424 | |
425 | === modified file 'src/core/media/service_skeleton.cpp' |
426 | --- src/core/media/service_skeleton.cpp 2015-03-04 16:37:33 +0000 |
427 | +++ src/core/media/service_skeleton.cpp 2015-03-04 16:37:33 +0000 |
428 | @@ -49,11 +49,12 @@ |
429 | |
430 | struct media::ServiceSkeleton::Private |
431 | { |
432 | - Private(media::ServiceSkeleton* impl, const media::CoverArtResolver& resolver) |
433 | + Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config) |
434 | : impl(impl), |
435 | object(impl->access_service()->add_object_for_path( |
436 | - dbus::traits::Service<media::Service>::object_path())), |
437 | - exported(impl->access_bus(), resolver) |
438 | + dbus::traits::Service<media::Service>::object_path())), |
439 | + exported(impl->access_bus(), config.cover_art_resolver), |
440 | + configuration(config) |
441 | { |
442 | object->install_method_handler<mpris::Service::CreateSession>( |
443 | std::bind( |
444 | @@ -105,15 +106,7 @@ |
445 | |
446 | try |
447 | { |
448 | - auto session = impl->create_session(config); |
449 | - |
450 | - bool inserted = false; |
451 | - std::tie(std::ignore, inserted) |
452 | - = session_store.insert(std::make_pair(key, session)); |
453 | - |
454 | - if (!inserted) |
455 | - throw std::runtime_error("Problem persisting session in session store."); |
456 | - |
457 | + configuration.player_store->add_player_for_key(key, impl->create_session(config)); |
458 | auto reply = dbus::Message::make_method_return(msg); |
459 | reply->writer() << op; |
460 | |
461 | @@ -135,7 +128,7 @@ |
462 | std::string name; |
463 | msg->reader() >> name; |
464 | |
465 | - if (fixed_session_store.count(name) == 0) { |
466 | + if (named_player_map.count(name) == 0) { |
467 | // Create new session |
468 | auto session_info = create_session_info(); |
469 | |
470 | @@ -152,14 +145,10 @@ |
471 | auto session = impl->create_session(config); |
472 | session->lifetime().set(media::Player::Lifetime::resumable); |
473 | |
474 | - bool inserted = false; |
475 | - std::tie(std::ignore, inserted) |
476 | - = session_store.insert(std::make_pair(key, session)); |
477 | - |
478 | - if (!inserted) |
479 | - throw std::runtime_error("Problem persisting session in session store."); |
480 | - |
481 | - fixed_session_store.insert(std::make_pair(name, key)); |
482 | + configuration.player_store->add_player_for_key(key, session); |
483 | + |
484 | + |
485 | + named_player_map.insert(std::make_pair(name, key)); |
486 | |
487 | auto reply = dbus::Message::make_method_return(msg); |
488 | reply->writer() << op; |
489 | @@ -168,8 +157,8 @@ |
490 | } |
491 | else { |
492 | // Resume previous session |
493 | - auto key = fixed_session_store[name]; |
494 | - if (session_store.count(key) == 0) { |
495 | + auto key = named_player_map.at(name); |
496 | + if (not configuration.player_store->has_player_for_key(key)) { |
497 | auto reply = dbus::Message::make_error( |
498 | msg, |
499 | mpris::Service::Errors::CreatingFixedSession::name(), |
500 | @@ -204,7 +193,7 @@ |
501 | Player::PlayerKey key; |
502 | msg->reader() >> key; |
503 | |
504 | - if (session_store.count(key) == 0) { |
505 | + if (not configuration.player_store->has_player_for_key(key)) { |
506 | auto reply = dbus::Message::make_error( |
507 | msg, |
508 | mpris::Service::Errors::ResumingSession::name(), |
509 | @@ -245,9 +234,10 @@ |
510 | media::ServiceSkeleton* impl; |
511 | dbus::Object::Ptr object; |
512 | |
513 | - // We track all running player instances. |
514 | - std::map<media::Player::PlayerKey, std::shared_ptr<media::Player>> session_store; |
515 | - std::map<std::string, media::Player::PlayerKey> fixed_session_store; |
516 | + // We remember all our creation time arguments. |
517 | + ServiceSkeleton::Configuration configuration; |
518 | + // We map named/fixed player instances to their respective keys. |
519 | + std::map<std::string, media::Player::PlayerKey> named_player_map; |
520 | // We expose the entire service as an MPRIS player. |
521 | struct Exported |
522 | { |
523 | @@ -481,7 +471,7 @@ |
524 | mpris::Player::Skeleton player; |
525 | mpris::Playlists::Skeleton playlists; |
526 | |
527 | - // Helper to resolve (title, artist, album) tuples to cover art. |
528 | + // The CoverArtResolver used by the exported player. |
529 | media::CoverArtResolver cover_art_resolver; |
530 | // The actual player instance. |
531 | std::weak_ptr<media::Player> current_player; |
532 | @@ -516,9 +506,9 @@ |
533 | } exported; |
534 | }; |
535 | |
536 | -media::ServiceSkeleton::ServiceSkeleton(const media::CoverArtResolver& resolver) |
537 | +media::ServiceSkeleton::ServiceSkeleton(const Configuration& configuration) |
538 | : dbus::Skeleton<media::Service>(the_session_bus()), |
539 | - d(new Private(this, resolver)) |
540 | + d(new Private(this, configuration)) |
541 | { |
542 | } |
543 | |
544 | @@ -526,46 +516,24 @@ |
545 | { |
546 | } |
547 | |
548 | -bool media::ServiceSkeleton::has_player_for_key(const media::Player::PlayerKey& key) const |
549 | -{ |
550 | - return d->session_store.count(key) > 0; |
551 | -} |
552 | - |
553 | -std::shared_ptr<media::Player> media::ServiceSkeleton::player_for_key(const media::Player::PlayerKey& key) const |
554 | -{ |
555 | - return d->session_store.at(key); |
556 | -} |
557 | - |
558 | -void media::ServiceSkeleton::enumerate_players(const media::ServiceSkeleton::PlayerEnumerator& enumerator) const |
559 | -{ |
560 | - for (const auto& pair : d->session_store) |
561 | - enumerator(pair.first, pair.second); |
562 | -} |
563 | - |
564 | -void media::ServiceSkeleton::set_current_player_for_key(const media::Player::PlayerKey& key) |
565 | -{ |
566 | - if (not has_player_for_key(key)) |
567 | - return; |
568 | - |
569 | - d->exported.set_current_player(player_for_key(key)); |
570 | -} |
571 | - |
572 | -void media::ServiceSkeleton::remove_player_for_key(const media::Player::PlayerKey& key) |
573 | -{ |
574 | - if (not has_player_for_key(key)) |
575 | - return; |
576 | - |
577 | - auto player = player_for_key(key); |
578 | - |
579 | - d->session_store.erase(key); |
580 | - d->exported.unset_if_current(player); |
581 | - // All non-durable fixed sessions are also removed |
582 | - for (auto it: d->fixed_session_store) { |
583 | - if (it.second == key) { |
584 | - d->fixed_session_store.erase(it.first); |
585 | - break; |
586 | - } |
587 | - } |
588 | +std::shared_ptr<media::Player> media::ServiceSkeleton::create_session(const media::Player::Configuration& config) |
589 | +{ |
590 | + return d->configuration.impl->create_session(config); |
591 | +} |
592 | + |
593 | +std::shared_ptr<media::Player> media::ServiceSkeleton::create_fixed_session(const std::string& name, const media::Player::Configuration&config) |
594 | +{ |
595 | + return d->configuration.impl->create_fixed_session(name, config); |
596 | +} |
597 | + |
598 | +std::shared_ptr<media::Player> media::ServiceSkeleton::resume_session(media::Player::PlayerKey key) |
599 | +{ |
600 | + return d->configuration.impl->resume_session(key); |
601 | +} |
602 | + |
603 | +void media::ServiceSkeleton::pause_other_sessions(media::Player::PlayerKey key) |
604 | +{ |
605 | + d->configuration.impl->pause_other_sessions(key); |
606 | } |
607 | |
608 | void media::ServiceSkeleton::run() |
609 | |
610 | === modified file 'src/core/media/service_skeleton.h' |
611 | --- src/core/media/service_skeleton.h 2014-09-09 21:27:29 +0000 |
612 | +++ src/core/media/service_skeleton.h 2015-03-04 16:37:33 +0000 |
613 | @@ -22,6 +22,7 @@ |
614 | #include <core/media/service.h> |
615 | |
616 | #include "cover_art_resolver.h" |
617 | +#include "keyed_player_store.h" |
618 | #include "service_traits.h" |
619 | |
620 | #include <core/dbus/skeleton.h> |
621 | @@ -37,34 +38,22 @@ |
622 | class ServiceSkeleton : public core::dbus::Skeleton<core::ubuntu::media::Service> |
623 | { |
624 | public: |
625 | - // Functor for enumerating all known (key, player) pairs. |
626 | - typedef std::function |
627 | - < |
628 | - void( |
629 | - // The key of the player. |
630 | - const core::ubuntu::media::Player::PlayerKey&, |
631 | - // The actual player instance. |
632 | - const std::shared_ptr<core::ubuntu::media::Player>& |
633 | - ) |
634 | - > PlayerEnumerator; |
635 | + // Creation time arguments go here. |
636 | + struct Configuration |
637 | + { |
638 | + std::shared_ptr<Service> impl; |
639 | + KeyedPlayerStore::Ptr player_store; |
640 | + CoverArtResolver cover_art_resolver; |
641 | + }; |
642 | |
643 | - ServiceSkeleton(const CoverArtResolver& cover_art_resolver = always_missing_cover_art_resolver()); |
644 | + ServiceSkeleton(const Configuration& configuration); |
645 | ~ServiceSkeleton(); |
646 | |
647 | - // We keep track of all known player sessions here and render them accessible via |
648 | - // the key. All of these functions are thread-safe but not reentrant. |
649 | - // Returns true iff a player is known for the given key. |
650 | - bool has_player_for_key(const Player::PlayerKey& key) const; |
651 | - // Returns the player for the given key or throws std::out_of_range if no player is known |
652 | - // for the given key. |
653 | - std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const; |
654 | - // Enumerates all known players and invokes the given enumerator for each |
655 | - // (key, player) pair. |
656 | - void enumerate_players(const PlayerEnumerator& enumerator) const; |
657 | - // Removes the player for the given key, and unsets it if it is the current one. |
658 | - void remove_player_for_key(const Player::PlayerKey& key); |
659 | - // Makes the player known under the given key current. |
660 | - void set_current_player_for_key(const Player::PlayerKey& key); |
661 | + // From media::Service |
662 | + std::shared_ptr<Player> create_session(const Player::Configuration&); |
663 | + std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&); |
664 | + std::shared_ptr<Player> resume_session(Player::PlayerKey); |
665 | + void pause_other_sessions(Player::PlayerKey key); |
666 | |
667 | void run(); |
668 | void stop(); |
FAILED: Continuous integration, rev:112 jenkins. qa.ubuntu. com/job/ media-hub- ci/195/ jenkins. qa.ubuntu. com/job/ media-hub- vivid-amd64- ci/35/console jenkins. qa.ubuntu. com/job/ media-hub- vivid-armhf- ci/35/console jenkins. qa.ubuntu. com/job/ media-hub- vivid-i386- ci/35/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/media- hub-ci/ 195/rebuild
http://