Merge lp:~thomas-voss/media-hub/decouple-service-skeleton-and-implementation into lp:media-hub

Proposed by Thomas Voß
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
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 ServiceImplementation by introducing a common interface media::KeyedPlayerStore for storing running Player sessions indexed by the Player::Key.
Provide a default implementation HashedKeyedPlayerStore relying on a hash map for keeping track of player instances.
Adjust implementation to account for ServiceImplementation no longer inheriting from ServiceSkeleton.

Description of the change

Decouple the ServiceSkeleton from the ServiceImplementation by introducing a common interface media::KeyedPlayerStore for storing running Player sessions indexed by the Player::Key.
Provide a default implementation HashedKeyedPlayerStore relying on a hash map for keeping track of player instances.
Adjust implementation to account for ServiceImplementation no longer inheriting from ServiceSkeleton.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote :

One simple change listed below.

review: Needs Fixing (code)
113. By Thomas Voß

[ Jim Hodapp ]
* Resubmitting with prerequisite branch (LP: #1331041)
[ Justin McPherson ]
* Resubmitting with prerequisite branch (LP: #1331041)

Revision history for this message
Thomas Voß (thomas-voss) :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Francis Ginther (fginther) wrote :

The jenkins node for the amd64 build failed, I've restarted a new ci run.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
115. By Thomas Voß

Merge prereq branch.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
116. By Thomas Voß

Merge prereq branch.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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();

Subscribers

People subscribed via source and target branches