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:
|
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Thomas Voß (thomas-voss) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Francis Ginther (fginther) wrote : | # |
The jenkins node for the amd64 build failed, I've restarted a new ci run.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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 | 87 | ${MPRIS_HEADERS} | 87 | ${MPRIS_HEADERS} |
6 | 88 | 88 | ||
7 | 89 | client_death_observer.cpp | 89 | client_death_observer.cpp |
9 | 90 | hybris_client_death_observer.cpp | 90 | hashed_keyed_player_store.cpp |
10 | 91 | hybris_client_death_observer.cpp | ||
11 | 91 | cover_art_resolver.cpp | 92 | cover_art_resolver.cpp |
12 | 92 | engine.cpp | 93 | engine.cpp |
13 | 93 | 94 | ||
14 | 94 | 95 | ||
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 | 1 | /* | ||
20 | 2 | * Copyright © 2014 Canonical Ltd. | ||
21 | 3 | * | ||
22 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
23 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
24 | 6 | * as published by the Free Software Foundation. | ||
25 | 7 | * | ||
26 | 8 | * This program is distributed in the hope that it will be useful, | ||
27 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | 11 | * GNU Lesser General Public License for more details. | ||
30 | 12 | * | ||
31 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
32 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
33 | 15 | * | ||
34 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
35 | 17 | */ | ||
36 | 18 | |||
37 | 19 | #include <core/media/hashed_keyed_player_store.h> | ||
38 | 20 | |||
39 | 21 | namespace media = core::ubuntu::media; | ||
40 | 22 | |||
41 | 23 | media::HashedKeyedPlayerStore::HashedKeyedPlayerStore() | ||
42 | 24 | { | ||
43 | 25 | } | ||
44 | 26 | |||
45 | 27 | const core::Property<std::shared_ptr<media::Player>>& media::HashedKeyedPlayerStore::current_player() const | ||
46 | 28 | { | ||
47 | 29 | return prop_current_player; | ||
48 | 30 | } | ||
49 | 31 | |||
50 | 32 | bool media::HashedKeyedPlayerStore::has_player_for_key(const media::Player::PlayerKey& key) const | ||
51 | 33 | { | ||
52 | 34 | std::lock_guard<std::mutex> lg{guard}; | ||
53 | 35 | return map.count(key) > 0; | ||
54 | 36 | } | ||
55 | 37 | |||
56 | 38 | std::shared_ptr<media::Player> media::HashedKeyedPlayerStore::player_for_key(const media::Player::PlayerKey& key) const | ||
57 | 39 | { | ||
58 | 40 | std::lock_guard<std::mutex> lg{guard}; | ||
59 | 41 | auto it = map.find(key); | ||
60 | 42 | |||
61 | 43 | if (it == map.end()) throw std::out_of_range | ||
62 | 44 | { | ||
63 | 45 | "HashedKeyedPlayerStore::player_for_key: No player known for " + std::to_string(key) | ||
64 | 46 | }; | ||
65 | 47 | |||
66 | 48 | return it->second; | ||
67 | 49 | } | ||
68 | 50 | |||
69 | 51 | void media::HashedKeyedPlayerStore::enumerate_players(const media::KeyedPlayerStore::PlayerEnumerator& enumerator) const | ||
70 | 52 | { | ||
71 | 53 | std::lock_guard<std::mutex> lg{guard}; | ||
72 | 54 | for (const auto& pair : map) | ||
73 | 55 | enumerator(pair.first, pair.second); | ||
74 | 56 | } | ||
75 | 57 | |||
76 | 58 | void media::HashedKeyedPlayerStore::add_player_for_key(const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) | ||
77 | 59 | { | ||
78 | 60 | std::lock_guard<std::mutex> lg{guard}; | ||
79 | 61 | map[key] = player; | ||
80 | 62 | } | ||
81 | 63 | |||
82 | 64 | void media::HashedKeyedPlayerStore::remove_player_for_key(const media::Player::PlayerKey& key) | ||
83 | 65 | { | ||
84 | 66 | std::lock_guard<std::mutex> lg{guard}; | ||
85 | 67 | auto it = map.find(key); | ||
86 | 68 | if (it != map.end()) | ||
87 | 69 | { | ||
88 | 70 | if (prop_current_player == it->second) | ||
89 | 71 | prop_current_player = nullptr; | ||
90 | 72 | |||
91 | 73 | map.erase(it); | ||
92 | 74 | } | ||
93 | 75 | } | ||
94 | 76 | |||
95 | 77 | void media::HashedKeyedPlayerStore::set_current_player_for_key(const media::Player::PlayerKey& key) | ||
96 | 78 | { | ||
97 | 79 | prop_current_player = player_for_key(key); | ||
98 | 80 | } | ||
99 | 0 | 81 | ||
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 | 1 | /* | ||
105 | 2 | * Copyright © 2014 Canonical Ltd. | ||
106 | 3 | * | ||
107 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
108 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
109 | 6 | * as published by the Free Software Foundation. | ||
110 | 7 | * | ||
111 | 8 | * This program is distributed in the hope that it will be useful, | ||
112 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
113 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
114 | 11 | * GNU Lesser General Public License for more details. | ||
115 | 12 | * | ||
116 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
117 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
118 | 15 | * | ||
119 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
120 | 17 | */ | ||
121 | 18 | |||
122 | 19 | #ifndef CORE_UBUNTU_MEDIA_HASHED_KEYED_PLAYER_STORE_H_ | ||
123 | 20 | #define CORE_UBUNTU_MEDIA_HASHED_KEYED_PLAYER_STORE_H_ | ||
124 | 21 | |||
125 | 22 | #include <core/media/keyed_player_store.h> | ||
126 | 23 | |||
127 | 24 | #include <mutex> | ||
128 | 25 | #include <unordered_map> | ||
129 | 26 | |||
130 | 27 | namespace core | ||
131 | 28 | { | ||
132 | 29 | namespace ubuntu | ||
133 | 30 | { | ||
134 | 31 | namespace media | ||
135 | 32 | { | ||
136 | 33 | // Implements KeyedPlayerStore using a std::unordered_map. | ||
137 | 34 | class HashedKeyedPlayerStore : public KeyedPlayerStore | ||
138 | 35 | { | ||
139 | 36 | public: | ||
140 | 37 | HashedKeyedPlayerStore(); | ||
141 | 38 | // We keep track of the "current" player, that is, the one | ||
142 | 39 | // that has been created most recently, or has been explicitly foregrounded, or has been enabled for | ||
143 | 40 | // background playback. We provide a getable/observable access to that designated instance. | ||
144 | 41 | const core::Property<std::shared_ptr<media::Player>>& current_player() const override; | ||
145 | 42 | |||
146 | 43 | // We keep track of all known player sessions here and render them accessible via | ||
147 | 44 | // the key. All of these functions are thread-safe but not reentrant. | ||
148 | 45 | // Returns true iff a player is known for the given key. | ||
149 | 46 | bool has_player_for_key(const Player::PlayerKey& key) const override; | ||
150 | 47 | |||
151 | 48 | // Returns the player for the given key or throws std::out_of_range if no player is known | ||
152 | 49 | // for the given key. | ||
153 | 50 | // Throws std::out_of_range if no player is known for the key. | ||
154 | 51 | std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const override; | ||
155 | 52 | |||
156 | 53 | // Enumerates all known players and invokes the given enumerator for each | ||
157 | 54 | // (key, player) pair. | ||
158 | 55 | void enumerate_players(const PlayerEnumerator& enumerator) const override; | ||
159 | 56 | |||
160 | 57 | // Adds the given player with the given key. | ||
161 | 58 | void add_player_for_key(const Player::PlayerKey& key, const std::shared_ptr<Player>& player) override; | ||
162 | 59 | |||
163 | 60 | // Removes the player for the given key, and unsets it if it is the current one. | ||
164 | 61 | void remove_player_for_key(const Player::PlayerKey& key) override; | ||
165 | 62 | |||
166 | 63 | // Makes the player known under the given key current. | ||
167 | 64 | // Throws std::out_of_range if no player is known for the key. | ||
168 | 65 | void set_current_player_for_key(const Player::PlayerKey& key) override; | ||
169 | 66 | |||
170 | 67 | private: | ||
171 | 68 | core::Property<std::shared_ptr<Player>> prop_current_player; | ||
172 | 69 | mutable std::mutex guard; | ||
173 | 70 | std::unordered_map<Player::PlayerKey, std::shared_ptr<Player>> map; | ||
174 | 71 | }; | ||
175 | 72 | } | ||
176 | 73 | } | ||
177 | 74 | } | ||
178 | 75 | |||
179 | 76 | #endif // CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ | ||
180 | 0 | 77 | ||
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 | 1 | /* | ||
187 | 2 | * Copyright © 2014 Canonical Ltd. | ||
188 | 3 | * | ||
189 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
190 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
191 | 6 | * as published by the Free Software Foundation. | ||
192 | 7 | * | ||
193 | 8 | * This program is distributed in the hope that it will be useful, | ||
194 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
195 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
196 | 11 | * GNU Lesser General Public License for more details. | ||
197 | 12 | * | ||
198 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
199 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
200 | 15 | * | ||
201 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | ||
202 | 17 | */ | ||
203 | 18 | |||
204 | 19 | #ifndef CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ | ||
205 | 20 | #define CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ | ||
206 | 21 | |||
207 | 22 | #include <core/media/player.h> | ||
208 | 23 | |||
209 | 24 | #include <core/property.h> | ||
210 | 25 | |||
211 | 26 | #include <functional> | ||
212 | 27 | #include <memory> | ||
213 | 28 | |||
214 | 29 | namespace core | ||
215 | 30 | { | ||
216 | 31 | namespace ubuntu | ||
217 | 32 | { | ||
218 | 33 | namespace media | ||
219 | 34 | { | ||
220 | 35 | // An interface abstracting keyed lookups of known Player instances. | ||
221 | 36 | class KeyedPlayerStore | ||
222 | 37 | { | ||
223 | 38 | public: | ||
224 | 39 | // Save us some typing. | ||
225 | 40 | typedef std::shared_ptr<KeyedPlayerStore> Ptr; | ||
226 | 41 | // Functor for enumerating all known (key, player) pairs. | ||
227 | 42 | typedef std::function | ||
228 | 43 | < | ||
229 | 44 | void( | ||
230 | 45 | // The key of the player. | ||
231 | 46 | const Player::PlayerKey&, | ||
232 | 47 | // The actual player instance. | ||
233 | 48 | const std::shared_ptr<Player>& | ||
234 | 49 | ) | ||
235 | 50 | > PlayerEnumerator; | ||
236 | 51 | // We keep track of the "current" player, that is, the one | ||
237 | 52 | // that has been created most recently and provide a getable/observable | ||
238 | 53 | // access to that designated instance. | ||
239 | 54 | virtual const core::Property<std::shared_ptr<Player>>& current_player() const = 0; | ||
240 | 55 | |||
241 | 56 | // We keep track of all known player sessions here and render them accessible via | ||
242 | 57 | // the key. All of these functions are thread-safe but not reentrant. | ||
243 | 58 | // Returns true iff a player is known for the given key. | ||
244 | 59 | virtual bool has_player_for_key(const Player::PlayerKey& key) const = 0; | ||
245 | 60 | // Returns the player for the given key or throws std::out_of_range if no player is known | ||
246 | 61 | // for the given key. | ||
247 | 62 | virtual std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const = 0; | ||
248 | 63 | // Enumerates all known players and invokes the given enumerator for each | ||
249 | 64 | // (key, player) pair. | ||
250 | 65 | virtual void enumerate_players(const PlayerEnumerator& enumerator) const = 0; | ||
251 | 66 | // Adds the given player with the given key. | ||
252 | 67 | virtual void add_player_for_key(const Player::PlayerKey& key, const std::shared_ptr<Player>& player) = 0; | ||
253 | 68 | // Removes the player for the given key, and unsets it if it is the current one. | ||
254 | 69 | virtual void remove_player_for_key(const Player::PlayerKey& key) = 0; | ||
255 | 70 | // Makes the player known under the given key current. | ||
256 | 71 | virtual void set_current_player_for_key(const Player::PlayerKey& key) = 0; | ||
257 | 72 | |||
258 | 73 | protected: | ||
259 | 74 | KeyedPlayerStore() = default; | ||
260 | 75 | KeyedPlayerStore(const KeyedPlayerStore&) = delete; | ||
261 | 76 | virtual ~KeyedPlayerStore() = default; | ||
262 | 77 | KeyedPlayerStore& operator=(const KeyedPlayerStore&) = delete; | ||
263 | 78 | }; | ||
264 | 79 | } | ||
265 | 80 | } | ||
266 | 81 | } | ||
267 | 82 | |||
268 | 83 | #endif // CORE_UBUNTU_MEDIA_KEYED_PLAYER_STORE_H_ | ||
269 | 0 | 84 | ||
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 | 20 | #include <core/media/player.h> | 20 | #include <core/media/player.h> |
275 | 21 | #include <core/media/track_list.h> | 21 | #include <core/media/track_list.h> |
276 | 22 | 22 | ||
277 | 23 | #include "core/media/hashed_keyed_player_store.h" | ||
278 | 23 | #include "core/media/service_implementation.h" | 24 | #include "core/media/service_implementation.h" |
279 | 24 | 25 | ||
280 | 25 | #include <core/posix/signal.h> | 26 | #include <core/posix/signal.h> |
281 | @@ -103,23 +104,37 @@ | |||
282 | 103 | } | 104 | } |
283 | 104 | }; | 105 | }; |
284 | 105 | 106 | ||
285 | 107 | // Our common player store instance for tracking player instances. | ||
286 | 108 | auto player_store = std::make_shared<media::HashedKeyedPlayerStore>(); | ||
287 | 106 | // We assemble the configuration for executing the service now. | 109 | // We assemble the configuration for executing the service now. |
288 | 107 | media::ServiceImplementation::Configuration service_config | 110 | media::ServiceImplementation::Configuration service_config |
289 | 108 | { | 111 | { |
290 | 112 | std::make_shared<media::HashedKeyedPlayerStore>(), | ||
291 | 109 | external_services | 113 | external_services |
292 | 110 | }; | 114 | }; |
293 | 111 | 115 | ||
295 | 112 | auto service = std::make_shared<media::ServiceImplementation>(service_config); | 116 | auto impl = std::make_shared<media::ServiceImplementation>(media::ServiceImplementation::Configuration |
296 | 117 | { | ||
297 | 118 | player_store, | ||
298 | 119 | external_services | ||
299 | 120 | }); | ||
300 | 121 | |||
301 | 122 | auto skeleton = std::make_shared<media::ServiceSkeleton>(media::ServiceSkeleton::Configuration | ||
302 | 123 | { | ||
303 | 124 | impl, | ||
304 | 125 | player_store, | ||
305 | 126 | |||
306 | 127 | }); | ||
307 | 113 | 128 | ||
308 | 114 | std::thread service_worker | 129 | std::thread service_worker |
309 | 115 | { | 130 | { |
311 | 116 | [&shutdown_requested, service]() | 131 | [&shutdown_requested, skeleton]() |
312 | 117 | { | 132 | { |
313 | 118 | while (not shutdown_requested) | 133 | while (not shutdown_requested) |
314 | 119 | { | 134 | { |
315 | 120 | try | 135 | try |
316 | 121 | { | 136 | { |
318 | 122 | service->run(); | 137 | skeleton->run(); |
319 | 123 | } | 138 | } |
320 | 124 | catch (const std::exception& e) | 139 | catch (const std::exception& e) |
321 | 125 | { | 140 | { |
322 | @@ -142,7 +157,7 @@ | |||
323 | 142 | shutdown_requested = true; | 157 | shutdown_requested = true; |
324 | 143 | 158 | ||
325 | 144 | // And stop execution of helper and actual service. | 159 | // And stop execution of helper and actual service. |
327 | 145 | service->stop(); | 160 | skeleton->stop(); |
328 | 146 | 161 | ||
329 | 147 | if (service_worker.joinable()) | 162 | if (service_worker.joinable()) |
330 | 148 | service_worker.join(); | 163 | service_worker.join(); |
331 | 149 | 164 | ||
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 | 188 | // until all dispatches are done | 188 | // until all dispatches are done |
337 | 189 | d->configuration.external_services.io_service.post([this, key]() | 189 | d->configuration.external_services.io_service.post([this, key]() |
338 | 190 | { | 190 | { |
340 | 191 | if (!has_player_for_key(key)) | 191 | if (!d->configuration.player_store->has_player_for_key(key)) |
341 | 192 | return; | 192 | return; |
342 | 193 | 193 | ||
345 | 194 | if (player_for_key(key)->lifetime() == Player::Lifetime::normal) | 194 | if (d->configuration.player_store->player_for_key(key)->lifetime() == Player::Lifetime::normal) |
346 | 195 | remove_player_for_key(key); | 195 | d->configuration.player_store->remove_player_for_key(key); |
347 | 196 | }); | 196 | }); |
348 | 197 | }); | 197 | }); |
349 | 198 | 198 | ||
350 | @@ -213,19 +213,19 @@ | |||
351 | 213 | 213 | ||
352 | 214 | void media::ServiceImplementation::pause_other_sessions(media::Player::PlayerKey key) | 214 | void media::ServiceImplementation::pause_other_sessions(media::Player::PlayerKey key) |
353 | 215 | { | 215 | { |
355 | 216 | if (not has_player_for_key(key)) | 216 | if (not d->configuration.player_store->has_player_for_key(key)) |
356 | 217 | { | 217 | { |
357 | 218 | cerr << "Could not find Player by key: " << key << endl; | 218 | cerr << "Could not find Player by key: " << key << endl; |
358 | 219 | return; | 219 | return; |
359 | 220 | } | 220 | } |
360 | 221 | 221 | ||
362 | 222 | auto current_player = player_for_key(key); | 222 | auto current_player = d->configuration.player_store->player_for_key(key); |
363 | 223 | 223 | ||
364 | 224 | // We immediately make the player known as new current player. | 224 | // We immediately make the player known as new current player. |
365 | 225 | if (current_player->audio_stream_role() == media::Player::multimedia) | 225 | if (current_player->audio_stream_role() == media::Player::multimedia) |
367 | 226 | set_current_player_for_key(key); | 226 | d->configuration.player_store->set_current_player_for_key(key); |
368 | 227 | 227 | ||
370 | 228 | enumerate_players([current_player, key](const media::Player::PlayerKey& other_key, const std::shared_ptr<media::Player>& other_player) | 228 | d->configuration.player_store->enumerate_players([current_player, key](const media::Player::PlayerKey& other_key, const std::shared_ptr<media::Player>& other_player) |
371 | 229 | { | 229 | { |
372 | 230 | // Only pause a Player if all of the following criteria are met: | 230 | // Only pause a Player if all of the following criteria are met: |
373 | 231 | // 1) currently playing | 231 | // 1) currently playing |
374 | @@ -245,7 +245,7 @@ | |||
375 | 245 | 245 | ||
376 | 246 | void media::ServiceImplementation::pause_all_multimedia_sessions() | 246 | void media::ServiceImplementation::pause_all_multimedia_sessions() |
377 | 247 | { | 247 | { |
379 | 248 | enumerate_players([this](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) | 248 | d->configuration.player_store->enumerate_players([this](const media::Player::PlayerKey& key, const std::shared_ptr<media::Player>& player) |
380 | 249 | { | 249 | { |
381 | 250 | if (player->playback_status() == Player::playing | 250 | if (player->playback_status() == Player::playing |
382 | 251 | && player->audio_stream_role() == media::Player::multimedia) | 251 | && player->audio_stream_role() == media::Player::multimedia) |
383 | @@ -260,7 +260,7 @@ | |||
384 | 260 | void media::ServiceImplementation::resume_paused_multimedia_sessions(bool resume_video_sessions) | 260 | void media::ServiceImplementation::resume_paused_multimedia_sessions(bool resume_video_sessions) |
385 | 261 | { | 261 | { |
386 | 262 | std::for_each(d->paused_sessions.begin(), d->paused_sessions.end(), [this, resume_video_sessions](const media::Player::PlayerKey& key) { | 262 | std::for_each(d->paused_sessions.begin(), d->paused_sessions.end(), [this, resume_video_sessions](const media::Player::PlayerKey& key) { |
388 | 263 | auto player = player_for_key(key); | 263 | auto player = d->configuration.player_store->player_for_key(key); |
389 | 264 | // Only resume video playback if explicitly desired | 264 | // Only resume video playback if explicitly desired |
390 | 265 | if (resume_video_sessions || player->is_audio_source()) | 265 | if (resume_video_sessions || player->is_audio_source()) |
391 | 266 | player->play(); | 266 | player->play(); |
392 | @@ -273,10 +273,10 @@ | |||
393 | 273 | 273 | ||
394 | 274 | void media::ServiceImplementation::resume_multimedia_session() | 274 | void media::ServiceImplementation::resume_multimedia_session() |
395 | 275 | { | 275 | { |
397 | 276 | if (not has_player_for_key(d->resume_key)) | 276 | if (not d->configuration.player_store->has_player_for_key(d->resume_key)) |
398 | 277 | return; | 277 | return; |
399 | 278 | 278 | ||
401 | 279 | auto player = player_for_key(d->resume_key); | 279 | auto player = d->configuration.player_store->player_for_key(d->resume_key); |
402 | 280 | 280 | ||
403 | 281 | if (player->playback_status() == Player::paused) | 281 | if (player->playback_status() == Player::paused) |
404 | 282 | { | 282 | { |
405 | 283 | 283 | ||
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 | 30 | { | 30 | { |
411 | 31 | class Player; | 31 | class Player; |
412 | 32 | 32 | ||
414 | 33 | class ServiceImplementation : public ServiceSkeleton | 33 | class ServiceImplementation : public Service |
415 | 34 | { | 34 | { |
416 | 35 | public: | 35 | public: |
417 | 36 | // All creation time arguments go here. | 36 | // All creation time arguments go here. |
418 | 37 | struct Configuration | 37 | struct Configuration |
419 | 38 | { | 38 | { |
420 | 39 | KeyedPlayerStore::Ptr player_store; | ||
421 | 39 | helper::ExternalServices& external_services; | 40 | helper::ExternalServices& external_services; |
422 | 40 | }; | 41 | }; |
423 | 41 | 42 | ||
424 | 42 | 43 | ||
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 | 49 | 49 | ||
430 | 50 | struct media::ServiceSkeleton::Private | 50 | struct media::ServiceSkeleton::Private |
431 | 51 | { | 51 | { |
433 | 52 | Private(media::ServiceSkeleton* impl, const media::CoverArtResolver& resolver) | 52 | Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config) |
434 | 53 | : impl(impl), | 53 | : impl(impl), |
435 | 54 | object(impl->access_service()->add_object_for_path( | 54 | object(impl->access_service()->add_object_for_path( |
438 | 55 | dbus::traits::Service<media::Service>::object_path())), | 55 | dbus::traits::Service<media::Service>::object_path())), |
439 | 56 | exported(impl->access_bus(), resolver) | 56 | exported(impl->access_bus(), config.cover_art_resolver), |
440 | 57 | configuration(config) | ||
441 | 57 | { | 58 | { |
442 | 58 | object->install_method_handler<mpris::Service::CreateSession>( | 59 | object->install_method_handler<mpris::Service::CreateSession>( |
443 | 59 | std::bind( | 60 | std::bind( |
444 | @@ -105,15 +106,7 @@ | |||
445 | 105 | 106 | ||
446 | 106 | try | 107 | try |
447 | 107 | { | 108 | { |
457 | 108 | auto session = impl->create_session(config); | 109 | configuration.player_store->add_player_for_key(key, impl->create_session(config)); |
449 | 109 | |||
450 | 110 | bool inserted = false; | ||
451 | 111 | std::tie(std::ignore, inserted) | ||
452 | 112 | = session_store.insert(std::make_pair(key, session)); | ||
453 | 113 | |||
454 | 114 | if (!inserted) | ||
455 | 115 | throw std::runtime_error("Problem persisting session in session store."); | ||
456 | 116 | |||
458 | 117 | auto reply = dbus::Message::make_method_return(msg); | 110 | auto reply = dbus::Message::make_method_return(msg); |
459 | 118 | reply->writer() << op; | 111 | reply->writer() << op; |
460 | 119 | 112 | ||
461 | @@ -135,7 +128,7 @@ | |||
462 | 135 | std::string name; | 128 | std::string name; |
463 | 136 | msg->reader() >> name; | 129 | msg->reader() >> name; |
464 | 137 | 130 | ||
466 | 138 | if (fixed_session_store.count(name) == 0) { | 131 | if (named_player_map.count(name) == 0) { |
467 | 139 | // Create new session | 132 | // Create new session |
468 | 140 | auto session_info = create_session_info(); | 133 | auto session_info = create_session_info(); |
469 | 141 | 134 | ||
470 | @@ -152,14 +145,10 @@ | |||
471 | 152 | auto session = impl->create_session(config); | 145 | auto session = impl->create_session(config); |
472 | 153 | session->lifetime().set(media::Player::Lifetime::resumable); | 146 | session->lifetime().set(media::Player::Lifetime::resumable); |
473 | 154 | 147 | ||
482 | 155 | bool inserted = false; | 148 | configuration.player_store->add_player_for_key(key, session); |
483 | 156 | std::tie(std::ignore, inserted) | 149 | |
484 | 157 | = session_store.insert(std::make_pair(key, session)); | 150 | |
485 | 158 | 151 | named_player_map.insert(std::make_pair(name, key)); | |
478 | 159 | if (!inserted) | ||
479 | 160 | throw std::runtime_error("Problem persisting session in session store."); | ||
480 | 161 | |||
481 | 162 | fixed_session_store.insert(std::make_pair(name, key)); | ||
486 | 163 | 152 | ||
487 | 164 | auto reply = dbus::Message::make_method_return(msg); | 153 | auto reply = dbus::Message::make_method_return(msg); |
488 | 165 | reply->writer() << op; | 154 | reply->writer() << op; |
489 | @@ -168,8 +157,8 @@ | |||
490 | 168 | } | 157 | } |
491 | 169 | else { | 158 | else { |
492 | 170 | // Resume previous session | 159 | // Resume previous session |
495 | 171 | auto key = fixed_session_store[name]; | 160 | auto key = named_player_map.at(name); |
496 | 172 | if (session_store.count(key) == 0) { | 161 | if (not configuration.player_store->has_player_for_key(key)) { |
497 | 173 | auto reply = dbus::Message::make_error( | 162 | auto reply = dbus::Message::make_error( |
498 | 174 | msg, | 163 | msg, |
499 | 175 | mpris::Service::Errors::CreatingFixedSession::name(), | 164 | mpris::Service::Errors::CreatingFixedSession::name(), |
500 | @@ -204,7 +193,7 @@ | |||
501 | 204 | Player::PlayerKey key; | 193 | Player::PlayerKey key; |
502 | 205 | msg->reader() >> key; | 194 | msg->reader() >> key; |
503 | 206 | 195 | ||
505 | 207 | if (session_store.count(key) == 0) { | 196 | if (not configuration.player_store->has_player_for_key(key)) { |
506 | 208 | auto reply = dbus::Message::make_error( | 197 | auto reply = dbus::Message::make_error( |
507 | 209 | msg, | 198 | msg, |
508 | 210 | mpris::Service::Errors::ResumingSession::name(), | 199 | mpris::Service::Errors::ResumingSession::name(), |
509 | @@ -245,9 +234,10 @@ | |||
510 | 245 | media::ServiceSkeleton* impl; | 234 | media::ServiceSkeleton* impl; |
511 | 246 | dbus::Object::Ptr object; | 235 | dbus::Object::Ptr object; |
512 | 247 | 236 | ||
516 | 248 | // We track all running player instances. | 237 | // We remember all our creation time arguments. |
517 | 249 | std::map<media::Player::PlayerKey, std::shared_ptr<media::Player>> session_store; | 238 | ServiceSkeleton::Configuration configuration; |
518 | 250 | std::map<std::string, media::Player::PlayerKey> fixed_session_store; | 239 | // We map named/fixed player instances to their respective keys. |
519 | 240 | std::map<std::string, media::Player::PlayerKey> named_player_map; | ||
520 | 251 | // We expose the entire service as an MPRIS player. | 241 | // We expose the entire service as an MPRIS player. |
521 | 252 | struct Exported | 242 | struct Exported |
522 | 253 | { | 243 | { |
523 | @@ -481,7 +471,7 @@ | |||
524 | 481 | mpris::Player::Skeleton player; | 471 | mpris::Player::Skeleton player; |
525 | 482 | mpris::Playlists::Skeleton playlists; | 472 | mpris::Playlists::Skeleton playlists; |
526 | 483 | 473 | ||
528 | 484 | // Helper to resolve (title, artist, album) tuples to cover art. | 474 | // The CoverArtResolver used by the exported player. |
529 | 485 | media::CoverArtResolver cover_art_resolver; | 475 | media::CoverArtResolver cover_art_resolver; |
530 | 486 | // The actual player instance. | 476 | // The actual player instance. |
531 | 487 | std::weak_ptr<media::Player> current_player; | 477 | std::weak_ptr<media::Player> current_player; |
532 | @@ -516,9 +506,9 @@ | |||
533 | 516 | } exported; | 506 | } exported; |
534 | 517 | }; | 507 | }; |
535 | 518 | 508 | ||
537 | 519 | media::ServiceSkeleton::ServiceSkeleton(const media::CoverArtResolver& resolver) | 509 | media::ServiceSkeleton::ServiceSkeleton(const Configuration& configuration) |
538 | 520 | : dbus::Skeleton<media::Service>(the_session_bus()), | 510 | : dbus::Skeleton<media::Service>(the_session_bus()), |
540 | 521 | d(new Private(this, resolver)) | 511 | d(new Private(this, configuration)) |
541 | 522 | { | 512 | { |
542 | 523 | } | 513 | } |
543 | 524 | 514 | ||
544 | @@ -526,46 +516,24 @@ | |||
545 | 526 | { | 516 | { |
546 | 527 | } | 517 | } |
547 | 528 | 518 | ||
588 | 529 | bool media::ServiceSkeleton::has_player_for_key(const media::Player::PlayerKey& key) const | 519 | std::shared_ptr<media::Player> media::ServiceSkeleton::create_session(const media::Player::Configuration& config) |
589 | 530 | { | 520 | { |
590 | 531 | return d->session_store.count(key) > 0; | 521 | return d->configuration.impl->create_session(config); |
591 | 532 | } | 522 | } |
592 | 533 | 523 | ||
593 | 534 | std::shared_ptr<media::Player> media::ServiceSkeleton::player_for_key(const media::Player::PlayerKey& key) const | 524 | std::shared_ptr<media::Player> media::ServiceSkeleton::create_fixed_session(const std::string& name, const media::Player::Configuration&config) |
594 | 535 | { | 525 | { |
595 | 536 | return d->session_store.at(key); | 526 | return d->configuration.impl->create_fixed_session(name, config); |
596 | 537 | } | 527 | } |
597 | 538 | 528 | ||
598 | 539 | void media::ServiceSkeleton::enumerate_players(const media::ServiceSkeleton::PlayerEnumerator& enumerator) const | 529 | std::shared_ptr<media::Player> media::ServiceSkeleton::resume_session(media::Player::PlayerKey key) |
599 | 540 | { | 530 | { |
600 | 541 | for (const auto& pair : d->session_store) | 531 | return d->configuration.impl->resume_session(key); |
601 | 542 | enumerator(pair.first, pair.second); | 532 | } |
602 | 543 | } | 533 | |
603 | 544 | 534 | void media::ServiceSkeleton::pause_other_sessions(media::Player::PlayerKey key) | |
604 | 545 | void media::ServiceSkeleton::set_current_player_for_key(const media::Player::PlayerKey& key) | 535 | { |
605 | 546 | { | 536 | d->configuration.impl->pause_other_sessions(key); |
566 | 547 | if (not has_player_for_key(key)) | ||
567 | 548 | return; | ||
568 | 549 | |||
569 | 550 | d->exported.set_current_player(player_for_key(key)); | ||
570 | 551 | } | ||
571 | 552 | |||
572 | 553 | void media::ServiceSkeleton::remove_player_for_key(const media::Player::PlayerKey& key) | ||
573 | 554 | { | ||
574 | 555 | if (not has_player_for_key(key)) | ||
575 | 556 | return; | ||
576 | 557 | |||
577 | 558 | auto player = player_for_key(key); | ||
578 | 559 | |||
579 | 560 | d->session_store.erase(key); | ||
580 | 561 | d->exported.unset_if_current(player); | ||
581 | 562 | // All non-durable fixed sessions are also removed | ||
582 | 563 | for (auto it: d->fixed_session_store) { | ||
583 | 564 | if (it.second == key) { | ||
584 | 565 | d->fixed_session_store.erase(it.first); | ||
585 | 566 | break; | ||
586 | 567 | } | ||
587 | 568 | } | ||
606 | 569 | } | 537 | } |
607 | 570 | 538 | ||
608 | 571 | void media::ServiceSkeleton::run() | 539 | void media::ServiceSkeleton::run() |
609 | 572 | 540 | ||
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 | 22 | #include <core/media/service.h> | 22 | #include <core/media/service.h> |
615 | 23 | 23 | ||
616 | 24 | #include "cover_art_resolver.h" | 24 | #include "cover_art_resolver.h" |
617 | 25 | #include "keyed_player_store.h" | ||
618 | 25 | #include "service_traits.h" | 26 | #include "service_traits.h" |
619 | 26 | 27 | ||
620 | 27 | #include <core/dbus/skeleton.h> | 28 | #include <core/dbus/skeleton.h> |
621 | @@ -37,34 +38,22 @@ | |||
622 | 37 | class ServiceSkeleton : public core::dbus::Skeleton<core::ubuntu::media::Service> | 38 | class ServiceSkeleton : public core::dbus::Skeleton<core::ubuntu::media::Service> |
623 | 38 | { | 39 | { |
624 | 39 | public: | 40 | public: |
635 | 40 | // Functor for enumerating all known (key, player) pairs. | 41 | // Creation time arguments go here. |
636 | 41 | typedef std::function | 42 | struct Configuration |
637 | 42 | < | 43 | { |
638 | 43 | void( | 44 | std::shared_ptr<Service> impl; |
639 | 44 | // The key of the player. | 45 | KeyedPlayerStore::Ptr player_store; |
640 | 45 | const core::ubuntu::media::Player::PlayerKey&, | 46 | CoverArtResolver cover_art_resolver; |
641 | 46 | // The actual player instance. | 47 | }; |
632 | 47 | const std::shared_ptr<core::ubuntu::media::Player>& | ||
633 | 48 | ) | ||
634 | 49 | > PlayerEnumerator; | ||
642 | 50 | 48 | ||
644 | 51 | ServiceSkeleton(const CoverArtResolver& cover_art_resolver = always_missing_cover_art_resolver()); | 49 | ServiceSkeleton(const Configuration& configuration); |
645 | 52 | ~ServiceSkeleton(); | 50 | ~ServiceSkeleton(); |
646 | 53 | 51 | ||
661 | 54 | // We keep track of all known player sessions here and render them accessible via | 52 | // From media::Service |
662 | 55 | // the key. All of these functions are thread-safe but not reentrant. | 53 | std::shared_ptr<Player> create_session(const Player::Configuration&); |
663 | 56 | // Returns true iff a player is known for the given key. | 54 | std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&); |
664 | 57 | bool has_player_for_key(const Player::PlayerKey& key) const; | 55 | std::shared_ptr<Player> resume_session(Player::PlayerKey); |
665 | 58 | // Returns the player for the given key or throws std::out_of_range if no player is known | 56 | void pause_other_sessions(Player::PlayerKey key); |
652 | 59 | // for the given key. | ||
653 | 60 | std::shared_ptr<Player> player_for_key(const Player::PlayerKey& key) const; | ||
654 | 61 | // Enumerates all known players and invokes the given enumerator for each | ||
655 | 62 | // (key, player) pair. | ||
656 | 63 | void enumerate_players(const PlayerEnumerator& enumerator) const; | ||
657 | 64 | // Removes the player for the given key, and unsets it if it is the current one. | ||
658 | 65 | void remove_player_for_key(const Player::PlayerKey& key); | ||
659 | 66 | // Makes the player known under the given key current. | ||
660 | 67 | void set_current_player_for_key(const Player::PlayerKey& key); | ||
666 | 68 | 57 | ||
667 | 69 | void run(); | 58 | void run(); |
668 | 70 | void stop(); | 59 | 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://