Merge lp:~ricmm/media-hub/session-reattach-nonfixed into lp:media-hub

Proposed by Ricardo Mendoza
Status: Merged
Approved by: Jim Hodapp
Approved revision: 155
Merged at revision: 133
Proposed branch: lp:~ricmm/media-hub/session-reattach-nonfixed
Merge into: lp:media-hub
Prerequisite: lp:~phablet-team/media-hub/tracklist-cli
Diff against target: 1135 lines (+555/-61)
19 files modified
CMakeLists.txt (+1/-1)
debian/changelog (+6/-0)
include/core/media/player.h (+4/-0)
include/core/media/service.h (+16/-0)
src/core/media/mpris/service.h (+39/-0)
src/core/media/player_configuration.h (+1/-1)
src/core/media/player_implementation.cpp (+47/-17)
src/core/media/player_implementation.h (+4/-0)
src/core/media/player_stub.cpp (+22/-3)
src/core/media/player_stub.h (+6/-1)
src/core/media/server/server.cpp (+1/-1)
src/core/media/service_implementation.cpp (+16/-0)
src/core/media/service_implementation.h (+3/-0)
src/core/media/service_skeleton.cpp (+235/-12)
src/core/media/service_skeleton.h (+6/-0)
src/core/media/service_stub.cpp (+39/-3)
src/core/media/service_stub.h (+3/-0)
tests/test-track-list/test_track_list.cpp (+99/-20)
tests/test-track-list/test_track_list.h (+7/-2)
To merge this branch: bzr merge lp:~ricmm/media-hub/session-reattach-nonfixed
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Thomas Voß (community) Approve
Jim Hodapp (community) code Approve
Review via email: mp+256101@code.launchpad.net

This proposal supersedes a proposal from 2015-04-10.

Commit message

Player session attaching/detaching with UUID

Description of the change

Player session attaching/detaching with UUID

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:139
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~ricmm/media-hub/session-reattach-nonfixed/+merge/256101/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/media-hub-ci/325/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-vivid-amd64-ci/165/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-vivid-armhf-ci/165/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-vivid-i386-ci/165/console

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/media-hub-ci/325/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote :

Looks good, a few things to fix.

review: Needs Fixing (code)
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 :

Looks good, thanks.

review: Approve (code)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
141. By Ricardo Mendoza

Merge parent

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

A few comments inline, one bigger question:

What is the difference between reattach/detach and the existing resume_session functionality?

review: Needs Fixing
Revision history for this message
Jim Hodapp (jhodapp) wrote :

Some added comments to my review and tvoss' review.

Revision history for this message
Thomas Voß (thomas-voss) wrote :

Replied inline.

Revision history for this message
Jim Hodapp (jhodapp) :
142. By Ricardo Mendoza

Address review comments and plug through no-impl methods of the Service parts

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
143. By Ricardo Mendoza

Not a reference

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
144. By Ricardo Mendoza

Correctly propagate track list changes from bus to local and viceversa

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Thomas Voß (thomas-voss) wrote :
Download full text (33.8 KiB)

On Thu, Apr 16, 2015 at 5:14 PM, Jim Hodapp <email address hidden> wrote:
>
>
> Diff comments:
>
>> === modified file 'CMakeLists.txt'
>> --- CMakeLists.txt 2015-01-23 13:00:36 +0000
>> +++ CMakeLists.txt 2015-04-15 18:29:47 +0000
>> @@ -3,7 +3,7 @@
>> project(ubuntu-media-hub)
>>
>> set(UBUNTU_MEDIA_HUB_VERSION_MAJOR 3)
>> -set(UBUNTU_MEDIA_HUB_VERSION_MINOR 0)
>> +set(UBUNTU_MEDIA_HUB_VERSION_MINOR 1)
>> set(UBUNTU_MEDIA_HUB_VERSION_PATCH 0)
>>
>> set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fPIC -pthread")
>>
>> === modified file 'debian/changelog'
>> --- debian/changelog 2015-04-02 16:43:42 +0000
>> +++ debian/changelog 2015-04-15 18:29:47 +0000
>> @@ -1,3 +1,9 @@
>> +media-hub (3.1.0) UNRELEASED; urgency=medium
>> +
>> + * Support for signalling player reconnection up the stack.
>> +
>> + -- Ricardo Mendoza <email address hidden> Fri, 10 Apr 2015 18:20:32 +0200
>> +
>> media-hub (3.0.0+15.04.20150402-0ubuntu1) vivid; urgency=medium
>>
>> [ Jim Hodapp ]
>>
>> === modified file 'include/core/media/player.h'
>> --- include/core/media/player.h 2015-04-15 18:29:47 +0000
>> +++ include/core/media/player.h 2015-04-15 18:29:47 +0000
>> @@ -126,6 +126,9 @@
>> Player& operator=(const Player&) = delete;
>> bool operator==(const Player&) const = delete;
>>
>> + virtual std::string uuid() const = 0;
>
> Yeah I would say this isn't hugely important though as the likely-hood of this happening is very slim. Also, we could just change it if that unlikely event occurred.
>

That's somewhat difficult as this is public facing API. Your call.

>> + virtual void reconnect() = 0;
>> +
>> virtual std::shared_ptr<TrackList> track_list() = 0;
>> virtual PlayerKey key() const = 0;
>>
>>
>> === modified file 'include/core/media/service.h'
>> --- include/core/media/service.h 2014-09-30 06:51:15 +0000
>> +++ include/core/media/service.h 2015-04-15 18:29:47 +0000
>> @@ -42,9 +42,25 @@
>> Service& operator=(const Service&) = delete;
>> bool operator==(const Service&) const = delete;
>>
>> + /** @brief Creates a session with the media-hub service. */
>> virtual std::shared_ptr<Player> create_session(const Player::Configuration&) = 0;
>> +
>> + /** @brief Detaches a UUID-identified session for later resuming. */
>> + virtual void detach_session(const std::string& uuid, const Player::Configuration&) = 0;
>> +
>> + /** @brief Reattaches to a UUID-identified session that is in detached state. */
>> + virtual std::shared_ptr<Player> reattach_session(const std::string& uuid, const Player::Configuration&) = 0;
>> +
>> + /** @brief Asks the service to destroy a session. The session is destroyed when the client exits. */
>> + virtual void destroy_session(const std::string& uuid, const Player::Configuration&) = 0;
>> +
>> + /** @brief Creates a fixed-named session with the media-hub service. */
>> virtual std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&) = 0;
>> +
>> + /** @brief Resumes a fixed-name session directly by player key. */
>> virtual std::shared_ptr<Player> resume_session(Player::Play...

145. By Ricardo Mendoza

Remove printfs

Revision history for this message
Thomas Voß (thomas-voss) wrote :

LGTM.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
146. By Ricardo Mendoza

Revert last changes

147. By Ricardo Mendoza

Delete player instance instead of abandoning

148. By Ricardo Mendoza

Update tracklist cli for new api

149. By Ricardo Mendoza

Merge parent

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
150. By Ricardo Mendoza

Implement full player destruction

151. By Ricardo Mendoza

Merge parent

152. By Ricardo Mendoza

Syntax error

153. By Ricardo Mendoza

Sync test cli

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
154. By Ricardo Mendoza

Merge parent

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
155. By Ricardo Mendoza

Merge parent

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-01-23 13:00:36 +0000
+++ CMakeLists.txt 2015-04-20 15:56:34 +0000
@@ -3,7 +3,7 @@
3project(ubuntu-media-hub)3project(ubuntu-media-hub)
44
5set(UBUNTU_MEDIA_HUB_VERSION_MAJOR 3)5set(UBUNTU_MEDIA_HUB_VERSION_MAJOR 3)
6set(UBUNTU_MEDIA_HUB_VERSION_MINOR 0)6set(UBUNTU_MEDIA_HUB_VERSION_MINOR 1)
7set(UBUNTU_MEDIA_HUB_VERSION_PATCH 0)7set(UBUNTU_MEDIA_HUB_VERSION_PATCH 0)
88
9set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fPIC -pthread")9set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fPIC -pthread")
1010
=== modified file 'debian/changelog'
--- debian/changelog 2015-04-02 16:43:42 +0000
+++ debian/changelog 2015-04-20 15:56:34 +0000
@@ -1,3 +1,9 @@
1media-hub (3.1.0) UNRELEASED; urgency=medium
2
3 * Support for signalling player reconnection up the stack.
4
5 -- Ricardo Mendoza <ricardo.mendoza@canonical.com> Fri, 10 Apr 2015 18:20:32 +0200
6
1media-hub (3.0.0+15.04.20150402-0ubuntu1) vivid; urgency=medium7media-hub (3.0.0+15.04.20150402-0ubuntu1) vivid; urgency=medium
28
3 [ Jim Hodapp ]9 [ Jim Hodapp ]
410
=== modified file 'include/core/media/player.h'
--- include/core/media/player.h 2015-04-20 15:56:34 +0000
+++ include/core/media/player.h 2015-04-20 15:56:34 +0000
@@ -126,6 +126,10 @@
126 Player& operator=(const Player&) = delete;126 Player& operator=(const Player&) = delete;
127 bool operator==(const Player&) const = delete;127 bool operator==(const Player&) const = delete;
128128
129 virtual std::string uuid() const = 0;
130 virtual void reconnect() = 0;
131 virtual void abandon() = 0;
132
129 virtual std::shared_ptr<TrackList> track_list() = 0;133 virtual std::shared_ptr<TrackList> track_list() = 0;
130 virtual PlayerKey key() const = 0;134 virtual PlayerKey key() const = 0;
131135
132136
=== modified file 'include/core/media/service.h'
--- include/core/media/service.h 2014-09-30 06:51:15 +0000
+++ include/core/media/service.h 2015-04-20 15:56:34 +0000
@@ -42,9 +42,25 @@
42 Service& operator=(const Service&) = delete;42 Service& operator=(const Service&) = delete;
43 bool operator==(const Service&) const = delete;43 bool operator==(const Service&) const = delete;
4444
45 /** @brief Creates a session with the media-hub service. */
45 virtual std::shared_ptr<Player> create_session(const Player::Configuration&) = 0;46 virtual std::shared_ptr<Player> create_session(const Player::Configuration&) = 0;
47
48 /** @brief Detaches a UUID-identified session for later resuming. */
49 virtual void detach_session(const std::string& uuid, const Player::Configuration&) = 0;
50
51 /** @brief Reattaches to a UUID-identified session that is in detached state. */
52 virtual std::shared_ptr<Player> reattach_session(const std::string& uuid, const Player::Configuration&) = 0;
53
54 /** @brief Asks the service to destroy a session. The session is destroyed when the client exits. */
55 virtual void destroy_session(const std::string& uuid, const Player::Configuration&) = 0;
56
57 /** @brief Creates a fixed-named session with the media-hub service. */
46 virtual std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&) = 0;58 virtual std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&) = 0;
59
60 /** @brief Resumes a fixed-name session directly by player key. */
47 virtual std::shared_ptr<Player> resume_session(Player::PlayerKey) = 0;61 virtual std::shared_ptr<Player> resume_session(Player::PlayerKey) = 0;
62
63 /** @brief Pauses sessions other than the supplied one. */
48 virtual void pause_other_sessions(Player::PlayerKey) = 0;64 virtual void pause_other_sessions(Player::PlayerKey) = 0;
4965
50 protected:66 protected:
5167
=== modified file 'src/core/media/mpris/service.h'
--- src/core/media/mpris/service.h 2014-09-30 06:51:15 +0000
+++ src/core/media/mpris/service.h 2015-04-20 15:56:34 +0000
@@ -48,6 +48,42 @@
48 }48 }
49 };49 };
5050
51 struct DetachingSession
52 {
53 static const std::string& name()
54 {
55 static const std::string s
56 {
57 "core.ubuntu.media.Service.Error.DetachingSession"
58 };
59 return s;
60 }
61 };
62
63 struct ReattachingSession
64 {
65 static const std::string& name()
66 {
67 static const std::string s
68 {
69 "core.ubuntu.media.Service.Error.ReattachingSession"
70 };
71 return s;
72 }
73 };
74
75 struct DestroyingSession
76 {
77 static const std::string& name()
78 {
79 static const std::string s
80 {
81 "core.ubuntu.media.Service.Error.DestroyingSession"
82 };
83 return s;
84 }
85 };
86
51 struct CreatingFixedSession87 struct CreatingFixedSession
52 {88 {
53 static const std::string& name()89 static const std::string& name()
@@ -74,6 +110,9 @@
74 };110 };
75111
76 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(CreateSession, Service, 1000)112 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(CreateSession, Service, 1000)
113 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(DetachSession, Service, 1000)
114 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(ReattachSession, Service, 1000)
115 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(DestroySession, Service, 1000)
77 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(CreateFixedSession, Service, 1000)116 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(CreateFixedSession, Service, 1000)
78 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(ResumeSession, Service, 1000)117 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(ResumeSession, Service, 1000)
79 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(PauseOtherSessions, Service, 1000)118 DBUS_CPP_METHOD_WITH_TIMEOUT_DEF(PauseOtherSessions, Service, 1000)
80119
=== modified file 'src/core/media/player_configuration.h'
--- src/core/media/player_configuration.h 2015-04-20 15:56:34 +0000
+++ src/core/media/player_configuration.h 2015-04-20 15:56:34 +0000
@@ -27,7 +27,7 @@
27// to the implementation in a way that is opaque to the client.27// to the implementation in a way that is opaque to the client.
28struct core::ubuntu::media::Player::Configuration28struct core::ubuntu::media::Player::Configuration
29{29{
30 // Unique key for identifying the session.30 // Unique key for identifying the session path.
31 core::ubuntu::media::Player::PlayerKey key;31 core::ubuntu::media::Player::PlayerKey key;
32 // The bus connection to expose objects on.32 // The bus connection to expose objects on.
33 std::shared_ptr<core::dbus::Bus> bus;33 std::shared_ptr<core::dbus::Bus> bus;
3434
=== modified file 'src/core/media/player_implementation.cpp'
--- src/core/media/player_implementation.cpp 2015-04-20 15:56:34 +0000
+++ src/core/media/player_implementation.cpp 2015-04-20 15:56:34 +0000
@@ -68,7 +68,7 @@
68 previous_state(Engine::State::stopped),68 previous_state(Engine::State::stopped),
69 engine_state_change_connection(engine->state().changed().connect(make_state_change_handler())),69 engine_state_change_connection(engine->state().changed().connect(make_state_change_handler())),
70 engine_playback_status_change_connection(engine->playback_status_changed_signal().connect(make_playback_status_change_handler())),70 engine_playback_status_change_connection(engine->playback_status_changed_signal().connect(make_playback_status_change_handler())),
71 doing_go_to_track(false)71 doing_abandon(false)
72 {72 {
73 // Poor man's logging of release/acquire events.73 // Poor man's logging of release/acquire events.
74 display_state_lock->acquired().connect([](media::power::DisplayState state)74 display_state_lock->acquired().connect([](media::power::DisplayState state)
@@ -301,7 +301,8 @@
301 core::Connection engine_state_change_connection;301 core::Connection engine_state_change_connection;
302 core::Connection engine_playback_status_change_connection;302 core::Connection engine_playback_status_change_connection;
303 // Prevent the TrackList from auto advancing to the next track303 // Prevent the TrackList from auto advancing to the next track
304 std::atomic<bool> doing_go_to_track;304 std::mutex doing_go_to_track;
305 std::atomic<bool> doing_abandon;
305};306};
306307
307template<typename Parent>308template<typename Parent>
@@ -390,23 +391,26 @@
390391
391 d->engine->about_to_finish_signal().connect([this]()392 d->engine->about_to_finish_signal().connect([this]()
392 {393 {
394 if (d->doing_abandon)
395 return;
396
393 Parent::about_to_finish()();397 Parent::about_to_finish()();
394398
395 if (!d->doing_go_to_track)399 // This lambda needs to be mutually exclusive with the on_go_to_track lambda below
400 d->doing_go_to_track.lock();
401
402 const media::Track::Id prev_track_id = d->track_list->current();
403 // Make sure that the TrackList keeps advancing. The logic for what gets played next,
404 // if anything at all, occurs in TrackListSkeleton::next()
405 const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next());
406 if (prev_track_id != d->track_list->current() && !uri.empty())
396 {407 {
397 const media::Track::Id prev_track_id = d->track_list->current();408 std::cout << "Setting next track on playbin: " << uri << std::endl;
398 // Make sure that the TrackList keeps advancing. The logic for what gets played next,409 static const bool do_pipeline_reset = false;
399 // if anything at all, occurs in TrackListSkeleton::next()410 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
400 const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next());
401 if (prev_track_id != d->track_list->current() && !uri.empty())
402 {
403 std::cout << "Setting next track on playbin: " << uri << std::endl;
404 static const bool do_pipeline_reset = false;
405 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
406 }
407 }411 }
408 else412
409 std::cout << "Not auto-advancing the TrackList since doing_go_to_track is true" << std::endl;413 d->doing_go_to_track.unlock();
410 });414 });
411415
412 d->engine->client_disconnected_signal().connect([this]()416 d->engine->client_disconnected_signal().connect([this]()
@@ -443,7 +447,8 @@
443 {447 {
444 // This prevents the TrackList from auto advancing in other areas such as the about_to_finish signal448 // This prevents the TrackList from auto advancing in other areas such as the about_to_finish signal
445 // handler.449 // handler.
446 d->doing_go_to_track = true;450 // This lambda needs to be mutually exclusive with the about_to_finish lambda above
451 d->doing_go_to_track.lock();
447452
448 const media::Track::Id id = p.first;453 const media::Track::Id id = p.first;
449 const bool toggle_player_state = p.second;454 const bool toggle_player_state = p.second;
@@ -463,7 +468,8 @@
463 if (toggle_player_state)468 if (toggle_player_state)
464 d->engine->play();469 d->engine->play();
465470
466 d->doing_go_to_track = false;471 d->doing_go_to_track.unlock();
472
467 });473 });
468474
469 // Everything is setup, we now subscribe to death notifications.475 // Everything is setup, we now subscribe to death notifications.
@@ -474,6 +480,9 @@
474 {480 {
475 if (auto sp = wp.lock())481 if (auto sp = wp.lock())
476 {482 {
483 if (sp->doing_abandon)
484 return;
485
477 if (died != sp->config.key)486 if (died != sp->config.key)
478 return;487 return;
479488
@@ -519,6 +528,27 @@
519}528}
520529
521template<typename Parent>530template<typename Parent>
531std::string media::PlayerImplementation<Parent>::uuid() const
532{
533 // No impl for now, as not needed internally.
534 return std::string{};
535}
536
537template<typename Parent>
538void media::PlayerImplementation<Parent>::reconnect()
539{
540 d->config.client_death_observer->register_for_death_notifications_with_key(d->config.key);
541}
542
543template<typename Parent>
544void media::PlayerImplementation<Parent>::abandon()
545{
546 // Signal client disconnection due to abandonment of player
547 d->doing_abandon = true;
548 d->on_client_died();
549}
550
551template<typename Parent>
522std::shared_ptr<media::TrackList> media::PlayerImplementation<Parent>::track_list()552std::shared_ptr<media::TrackList> media::PlayerImplementation<Parent>::track_list()
523{553{
524 return d->track_list;554 return d->track_list;
525555
=== modified file 'src/core/media/player_implementation.h'
--- src/core/media/player_implementation.h 2015-04-20 15:56:34 +0000
+++ src/core/media/player_implementation.h 2015-04-20 15:56:34 +0000
@@ -55,6 +55,10 @@
55 PlayerImplementation(const Configuration& configuration);55 PlayerImplementation(const Configuration& configuration);
56 ~PlayerImplementation();56 ~PlayerImplementation();
5757
58 virtual std::string uuid() const;
59 virtual void reconnect();
60 virtual void abandon();
61
58 virtual std::shared_ptr<TrackList> track_list();62 virtual std::shared_ptr<TrackList> track_list();
59 virtual Player::PlayerKey key() const;63 virtual Player::PlayerKey key() const;
6064
6165
=== modified file 'src/core/media/player_stub.cpp'
--- src/core/media/player_stub.cpp 2015-04-20 15:56:34 +0000
+++ src/core/media/player_stub.cpp 2015-04-20 15:56:34 +0000
@@ -44,11 +44,13 @@
44{44{
45 Private(const std::shared_ptr<Service>& parent,45 Private(const std::shared_ptr<Service>& parent,
46 const std::shared_ptr<core::dbus::Service>& service,46 const std::shared_ptr<core::dbus::Service>& service,
47 const std::shared_ptr<core::dbus::Object>& object47 const std::shared_ptr<core::dbus::Object>& object,
48 const std::string& uuid
48 ) : parent(parent),49 ) : parent(parent),
49 service(service),50 service(service),
50 object(object),51 object(object),
51 key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()),52 key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()),
53 uuid(uuid),
52 sink_factory(media::video::make_platform_default_sink_factory(key)),54 sink_factory(media::video::make_platform_default_sink_factory(key)),
53 properties55 properties
54 {56 {
@@ -96,6 +98,7 @@
96 dbus::Service::Ptr service;98 dbus::Service::Ptr service;
97 dbus::Object::Ptr object;99 dbus::Object::Ptr object;
98 media::Player::PlayerKey key;100 media::Player::PlayerKey key;
101 std::string uuid;
99 media::video::SinkFactory sink_factory;102 media::video::SinkFactory sink_factory;
100 struct103 struct
101 {104 {
@@ -213,8 +216,9 @@
213media::PlayerStub::PlayerStub(216media::PlayerStub::PlayerStub(
214 const std::shared_ptr<Service>& parent,217 const std::shared_ptr<Service>& parent,
215 const std::shared_ptr<core::dbus::Service>& service,218 const std::shared_ptr<core::dbus::Service>& service,
216 const std::shared_ptr<core::dbus::Object>& object)219 const std::shared_ptr<core::dbus::Object>& object,
217 : d(new Private{parent, service, object})220 const std::string& uuid)
221 : d(new Private{parent, service, object, uuid})
218{222{
219}223}
220224
@@ -222,6 +226,21 @@
222{226{
223}227}
224228
229std::string media::PlayerStub::uuid() const
230{
231 return d->uuid;
232}
233
234void media::PlayerStub::reconnect()
235{
236 // No implementation
237}
238
239void media::PlayerStub::abandon()
240{
241 // No implementation
242}
243
225std::shared_ptr<media::TrackList> media::PlayerStub::track_list()244std::shared_ptr<media::TrackList> media::PlayerStub::track_list()
226{245{
227 if (!d->track_list)246 if (!d->track_list)
228247
=== modified file 'src/core/media/player_stub.h'
--- src/core/media/player_stub.h 2015-04-20 15:56:34 +0000
+++ src/core/media/player_stub.h 2015-04-20 15:56:34 +0000
@@ -40,10 +40,15 @@
40 explicit PlayerStub(40 explicit PlayerStub(
41 const std::shared_ptr<Service>& parent,41 const std::shared_ptr<Service>& parent,
42 const std::shared_ptr<core::dbus::Service>& service,42 const std::shared_ptr<core::dbus::Service>& service,
43 const std::shared_ptr<core::dbus::Object>& object);43 const std::shared_ptr<core::dbus::Object>& object,
44 const std::string& uuid = std::string{});
4445
45 ~PlayerStub();46 ~PlayerStub();
4647
48 virtual std::string uuid() const;
49 virtual void reconnect();
50 virtual void abandon();
51
47 virtual std::shared_ptr<TrackList> track_list();52 virtual std::shared_ptr<TrackList> track_list();
48 virtual PlayerKey key() const;53 virtual PlayerKey key() const;
4954
5055
=== modified file 'src/core/media/server/server.cpp'
--- src/core/media/server/server.cpp 2014-12-15 14:43:44 +0000
+++ src/core/media/server/server.cpp 2015-04-20 15:56:34 +0000
@@ -123,7 +123,7 @@
123 {123 {
124 impl,124 impl,
125 player_store,125 player_store,
126126 external_services
127 });127 });
128128
129 std::thread service_worker129 std::thread service_worker
130130
=== modified file 'src/core/media/service_implementation.cpp'
--- src/core/media/service_implementation.cpp 2015-04-20 15:56:34 +0000
+++ src/core/media/service_implementation.cpp 2015-04-20 15:56:34 +0000
@@ -218,6 +218,22 @@
218 return player;218 return player;
219}219}
220220
221void media::ServiceImplementation::detach_session(const std::string&, const media::Player::Configuration&)
222{
223 // no impl
224}
225
226std::shared_ptr<media::Player> media::ServiceImplementation::reattach_session(const std::string&, const media::Player::Configuration&)
227{
228 // no impl
229 return std::shared_ptr<media::Player>();
230}
231
232void media::ServiceImplementation::destroy_session(const std::string&, const media::Player::Configuration&)
233{
234 // no impl
235}
236
221std::shared_ptr<media::Player> media::ServiceImplementation::create_fixed_session(const std::string&, const media::Player::Configuration&)237std::shared_ptr<media::Player> media::ServiceImplementation::create_fixed_session(const std::string&, const media::Player::Configuration&)
222{238{
223 // no impl239 // no impl
224240
=== modified file 'src/core/media/service_implementation.h'
--- src/core/media/service_implementation.h 2015-04-02 14:46:52 +0000
+++ src/core/media/service_implementation.h 2015-04-20 15:56:34 +0000
@@ -44,6 +44,9 @@
44 ~ServiceImplementation ();44 ~ServiceImplementation ();
4545
46 std::shared_ptr<Player> create_session(const Player::Configuration&);46 std::shared_ptr<Player> create_session(const Player::Configuration&);
47 void detach_session(const std::string&, const Player::Configuration&);
48 std::shared_ptr<Player> reattach_session(const std::string&, const Player::Configuration&);
49 void destroy_session(const std::string&, const Player::Configuration&);
47 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);50 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);
48 std::shared_ptr<Player> resume_session(Player::PlayerKey key);51 std::shared_ptr<Player> resume_session(Player::PlayerKey key);
49 void pause_other_sessions(Player::PlayerKey key);52 void pause_other_sessions(Player::PlayerKey key);
5053
=== modified file 'src/core/media/service_skeleton.cpp'
--- src/core/media/service_skeleton.cpp 2015-04-20 15:56:34 +0000
+++ src/core/media/service_skeleton.cpp 2015-04-20 15:56:34 +0000
@@ -35,6 +35,10 @@
3535
36#include <core/posix/this_process.h>36#include <core/posix/this_process.h>
3737
38#include <boost/uuid/uuid.hpp>
39#include <boost/uuid/uuid_generators.hpp>
40#include <boost/uuid/uuid_io.hpp>
41
38#include <map>42#include <map>
39#include <regex>43#include <regex>
40#include <sstream>44#include <sstream>
@@ -50,17 +54,33 @@
50struct media::ServiceSkeleton::Private54struct media::ServiceSkeleton::Private
51{55{
52 Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config)56 Private(media::ServiceSkeleton* impl, const ServiceSkeleton::Configuration& config)
53 : impl(impl),57 : request_context_resolver(media::apparmor::ubuntu::make_platform_default_request_context_resolver(config.external_services)),
58 impl(impl),
54 object(impl->access_service()->add_object_for_path(59 object(impl->access_service()->add_object_for_path(
55 dbus::traits::Service<media::Service>::object_path())),60 dbus::traits::Service<media::Service>::object_path())),
56 exported(impl->access_bus(), config.cover_art_resolver),61 configuration(config),
57 configuration(config)62 exported(impl->access_bus(), config.cover_art_resolver)
58 {63 {
59 object->install_method_handler<mpris::Service::CreateSession>(64 object->install_method_handler<mpris::Service::CreateSession>(
60 std::bind(65 std::bind(
61 &Private::handle_create_session,66 &Private::handle_create_session,
62 this,67 this,
63 std::placeholders::_1));68 std::placeholders::_1));
69 object->install_method_handler<mpris::Service::DetachSession>(
70 std::bind(
71 &Private::handle_detach_session,
72 this,
73 std::placeholders::_1));
74 object->install_method_handler<mpris::Service::ReattachSession>(
75 std::bind(
76 &Private::handle_reattach_session,
77 this,
78 std::placeholders::_1));
79 object->install_method_handler<mpris::Service::DestroySession>(
80 std::bind(
81 &Private::handle_destroy_session,
82 this,
83 std::placeholders::_1));
64 object->install_method_handler<mpris::Service::CreateFixedSession>(84 object->install_method_handler<mpris::Service::CreateFixedSession>(
65 std::bind(85 std::bind(
66 &Private::handle_create_fixed_session,86 &Private::handle_create_fixed_session,
@@ -78,24 +98,26 @@
78 std::placeholders::_1));98 std::placeholders::_1));
79 }99 }
80100
81 std::pair<std::string, media::Player::PlayerKey> create_session_info()101 std::tuple<std::string, media::Player::PlayerKey, std::string> create_session_info()
82 {102 {
83 static unsigned int session_counter = 0;103 static unsigned int session_counter = 0;
84104
85 unsigned int current_session = session_counter++;105 unsigned int current_session = session_counter++;
106 boost::uuids::uuid uuid = gen();
86107
87 std::stringstream ss;108 std::stringstream ss;
88 ss << "/core/ubuntu/media/Service/sessions/" << current_session;109 ss << "/core/ubuntu/media/Service/sessions/" << current_session;
89110
90 return std::make_pair(ss.str(), media::Player::PlayerKey(current_session));111 return std::make_tuple(ss.str(), media::Player::PlayerKey(current_session), to_string(uuid));
91 }112 }
92113
93 void handle_create_session(const core::dbus::Message::Ptr& msg)114 void handle_create_session(const core::dbus::Message::Ptr& msg)
94 {115 {
95 auto session_info = create_session_info();116 auto session_info = create_session_info();
96117
97 dbus::types::ObjectPath op{session_info.first};118 dbus::types::ObjectPath op{std::get<0>(session_info)};
98 media::Player::PlayerKey key{session_info.second};119 media::Player::PlayerKey key{std::get<1>(session_info)};
120 std::string uuid{std::get<2>(session_info)};
99121
100 media::Player::Configuration config122 media::Player::Configuration config
101 {123 {
@@ -105,11 +127,21 @@
105 impl->access_service()->add_object_for_path(op)127 impl->access_service()->add_object_for_path(op)
106 };128 };
107129
130 std::cout << "Session created by request of: " << msg->sender() << ", uuid: " << uuid << ", path:" << op << std::endl;
131
108 try132 try
109 {133 {
110 configuration.player_store->add_player_for_key(key, impl->create_session(config));134 configuration.player_store->add_player_for_key(key, impl->create_session(config));
135 uuid_player_map.insert(std::make_pair(uuid, key));
136
137 request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, key, msg](const media::apparmor::ubuntu::Context& context)
138 {
139 fprintf(stderr, "%s():%d -- app_name='%s', attached\n", __func__, __LINE__, context.str().c_str());
140 player_owner_map.insert(std::make_pair(key, std::make_tuple(context.str(), true, msg->sender())));
141 });
142
111 auto reply = dbus::Message::make_method_return(msg);143 auto reply = dbus::Message::make_method_return(msg);
112 reply->writer() << op;144 reply->writer() << std::make_tuple(op, uuid);
113145
114 impl->access_bus()->send(reply);146 impl->access_bus()->send(reply);
115 } catch(const std::runtime_error& e)147 } catch(const std::runtime_error& e)
@@ -122,6 +154,174 @@
122 }154 }
123 }155 }
124156
157 void handle_detach_session(const core::dbus::Message::Ptr& msg)
158 {
159 try
160 {
161 std::string uuid;
162 msg->reader() >> uuid;
163
164 auto key = uuid_player_map.at(uuid);
165
166 if (player_owner_map.count(key) != 0) {
167 auto info = player_owner_map.at(key);
168 // Check if session is attached(1) and that the detachment
169 // request comes from the same peer(2) that created the session.
170 if (std::get<1>(info) && (std::get<2>(info) == msg->sender())) { // Player is attached
171 std::get<1>(info) = false; // Detached
172 std::get<2>(info).clear(); // Clear registered sender/peer
173 auto player = configuration.player_store->player_for_key(key);
174 player->lifetime().set(media::Player::Lifetime::resumable);
175 }
176 }
177
178 auto reply = dbus::Message::make_method_return(msg);
179 impl->access_bus()->send(reply);
180
181 } catch(const std::runtime_error& e)
182 {
183 auto reply = dbus::Message::make_error(
184 msg,
185 mpris::Service::Errors::DetachingSession::name(),
186 e.what());
187 impl->access_bus()->send(reply);
188 }
189 }
190
191 void handle_reattach_session(const core::dbus::Message::Ptr& msg)
192 {
193 try
194 {
195 std::string uuid;
196 msg->reader() >> uuid;
197
198 if (uuid_player_map.count(uuid) != 0) {
199 auto key = uuid_player_map.at(uuid);
200 if (not configuration.player_store->has_player_for_key(key)) {
201 auto reply = dbus::Message::make_error(
202 msg,
203 mpris::Service::Errors::ReattachingSession::name(),
204 "Unable to locate player session");
205 impl->access_bus()->send(reply);
206 return;
207 }
208 std::stringstream ss;
209 ss << "/core/ubuntu/media/Service/sessions/" << key;
210 dbus::types::ObjectPath op{ss.str()};
211
212 request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, msg, key, op](const media::apparmor::ubuntu::Context& context)
213 {
214 auto info = player_owner_map.at(key);
215 fprintf(stderr, "%s():%d -- reattach app_name='%s', info='%s', '%s'\n", __func__, __LINE__, context.str().c_str(), std::get<0>(info).c_str(), std::get<2>(info).c_str());
216 if (std::get<0>(info) == context.str()) {
217 std::get<1>(info) = true; // Set to Attached
218 std::get<2>(info) = msg->sender(); // Register new owner
219
220 // Signal player reconnection
221 auto player = configuration.player_store->player_for_key(key);
222 player->reconnect();
223
224 auto reply = dbus::Message::make_method_return(msg);
225 reply->writer() << op;
226
227 impl->access_bus()->send(reply);
228 }
229 else {
230 auto reply = dbus::Message::make_error(
231 msg,
232 mpris::Service::Errors::ReattachingSession::name(),
233 "Invalid permissions for the requested session");
234 impl->access_bus()->send(reply);
235 return;
236 }
237 });
238 }
239 else {
240 auto reply = dbus::Message::make_error(
241 msg,
242 mpris::Service::Errors::ReattachingSession::name(),
243 "Invalid session");
244 impl->access_bus()->send(reply);
245 return;
246 }
247 } catch(const std::runtime_error& e)
248 {
249 auto reply = dbus::Message::make_error(
250 msg,
251 mpris::Service::Errors::ReattachingSession::name(),
252 e.what());
253 impl->access_bus()->send(reply);
254 }
255 }
256
257 void handle_destroy_session(const core::dbus::Message::Ptr& msg)
258 {
259
260 try
261 {
262 std::string uuid;
263 msg->reader() >> uuid;
264
265 if (uuid_player_map.count(uuid) != 0) {
266 auto key = uuid_player_map.at(uuid);
267 if (not configuration.player_store->has_player_for_key(key)) {
268 auto reply = dbus::Message::make_error(
269 msg,
270 mpris::Service::Errors::DestroyingSession::name(),
271 "Unable to locate player session");
272 impl->access_bus()->send(reply);
273 return;
274 }
275
276 // Remove control entries from the map, at this point
277 // the session is no longer usable.
278 uuid_player_map.erase(uuid);
279
280 request_context_resolver->resolve_context_for_dbus_name_async(msg->sender(), [this, msg, key](const media::apparmor::ubuntu::Context& context)
281 {
282 auto info = player_owner_map.at(key);
283 fprintf(stderr, "%s():%d -- Destroying app_name='%s', info='%s', '%s'\n", __func__, __LINE__, context.str().c_str(), std::get<0>(info).c_str(), std::get<2>(info).c_str());
284 if (std::get<0>(info) == context.str()) {
285 player_owner_map.erase(key);
286
287 // Reset lifecycle to non-resumable on the now-abandoned session
288 auto player = configuration.player_store->player_for_key(key);
289
290 // Delete player instance by abandonment
291 player->lifetime().set(media::Player::Lifetime::normal);
292 player->abandon();
293
294 auto reply = dbus::Message::make_method_return(msg);
295 impl->access_bus()->send(reply);
296 }
297 else {
298 auto reply = dbus::Message::make_error(
299 msg,
300 mpris::Service::Errors::DestroyingSession::name(),
301 "Invalid permissions for the requested session");
302 impl->access_bus()->send(reply);
303 return;
304 }
305 });
306 }
307 else {
308 auto reply = dbus::Message::make_error(
309 msg,
310 mpris::Service::Errors::DestroyingSession::name(),
311 "Invalid session");
312 impl->access_bus()->send(reply);
313 return;
314 }
315 } catch(const std::runtime_error& e)
316 {
317 auto reply = dbus::Message::make_error(
318 msg,
319 mpris::Service::Errors::DestroyingSession::name(),
320 e.what());
321 impl->access_bus()->send(reply);
322 }
323 }
324
125 void handle_create_fixed_session(const core::dbus::Message::Ptr& msg)325 void handle_create_fixed_session(const core::dbus::Message::Ptr& msg)
126 {326 {
127 try327 try
@@ -133,8 +333,8 @@
133 // Create new session333 // Create new session
134 auto session_info = create_session_info();334 auto session_info = create_session_info();
135335
136 dbus::types::ObjectPath op{session_info.first};336 dbus::types::ObjectPath op{std::get<0>(session_info)};
137 media::Player::PlayerKey key{session_info.second};337 media::Player::PlayerKey key{std::get<1>(session_info)};
138338
139 media::Player::Configuration config339 media::Player::Configuration config
140 {340 {
@@ -149,7 +349,6 @@
149349
150 configuration.player_store->add_player_for_key(key, session);350 configuration.player_store->add_player_for_key(key, session);
151351
152
153 named_player_map.insert(std::make_pair(name, key));352 named_player_map.insert(std::make_pair(name, key));
154353
155 auto reply = dbus::Message::make_method_return(msg);354 auto reply = dbus::Message::make_method_return(msg);
@@ -233,6 +432,7 @@
233 impl->access_bus()->send(reply);432 impl->access_bus()->send(reply);
234 }433 }
235434
435 media::apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver;
236 media::ServiceSkeleton* impl;436 media::ServiceSkeleton* impl;
237 dbus::Object::Ptr object;437 dbus::Object::Ptr object;
238438
@@ -240,6 +440,14 @@
240 ServiceSkeleton::Configuration configuration;440 ServiceSkeleton::Configuration configuration;
241 // We map named/fixed player instances to their respective keys.441 // We map named/fixed player instances to their respective keys.
242 std::map<std::string, media::Player::PlayerKey> named_player_map;442 std::map<std::string, media::Player::PlayerKey> named_player_map;
443 // We map UUIDs to their respective keys.
444 std::map<std::string, media::Player::PlayerKey> uuid_player_map;
445 // We keep a list of keys and their respective owners and states.
446 // value: (owner context, attached state, attached dbus name)
447 std::map<media::Player::PlayerKey, std::tuple<std::string, bool, std::string>> player_owner_map;
448
449 boost::uuids::random_generator gen;
450
243 // We expose the entire service as an MPRIS player.451 // We expose the entire service as an MPRIS player.
244 struct Exported452 struct Exported
245 {453 {
@@ -527,6 +735,21 @@
527 return d->configuration.impl->create_session(config);735 return d->configuration.impl->create_session(config);
528}736}
529737
738void media::ServiceSkeleton::detach_session(const std::string& uuid, const media::Player::Configuration& config)
739{
740 return d->configuration.impl->detach_session(uuid, config);
741}
742
743std::shared_ptr<media::Player> media::ServiceSkeleton::reattach_session(const std::string& uuid, const media::Player::Configuration& config)
744{
745 return d->configuration.impl->reattach_session(uuid, config);
746}
747
748void media::ServiceSkeleton::destroy_session(const std::string& uuid, const media::Player::Configuration& config)
749{
750 return d->configuration.impl->destroy_session(uuid, config);
751}
752
530std::shared_ptr<media::Player> media::ServiceSkeleton::create_fixed_session(const std::string& name, const media::Player::Configuration&config)753std::shared_ptr<media::Player> media::ServiceSkeleton::create_fixed_session(const std::string& name, const media::Player::Configuration&config)
531{754{
532 return d->configuration.impl->create_fixed_session(name, config);755 return d->configuration.impl->create_fixed_session(name, config);
533756
=== modified file 'src/core/media/service_skeleton.h'
--- src/core/media/service_skeleton.h 2014-12-15 14:43:44 +0000
+++ src/core/media/service_skeleton.h 2015-04-20 15:56:34 +0000
@@ -19,6 +19,8 @@
19#ifndef CORE_UBUNTU_MEDIA_SERVICE_SKELETON_H_19#ifndef CORE_UBUNTU_MEDIA_SERVICE_SKELETON_H_
20#define CORE_UBUNTU_MEDIA_SERVICE_SKELETON_H_20#define CORE_UBUNTU_MEDIA_SERVICE_SKELETON_H_
2121
22#include "apparmor/ubuntu.h"
23
22#include <core/media/service.h>24#include <core/media/service.h>
2325
24#include "cover_art_resolver.h"26#include "cover_art_resolver.h"
@@ -43,6 +45,7 @@
43 {45 {
44 std::shared_ptr<Service> impl;46 std::shared_ptr<Service> impl;
45 KeyedPlayerStore::Ptr player_store;47 KeyedPlayerStore::Ptr player_store;
48 helper::ExternalServices& external_services;
46 CoverArtResolver cover_art_resolver;49 CoverArtResolver cover_art_resolver;
47 };50 };
4851
@@ -51,6 +54,9 @@
5154
52 // From media::Service55 // From media::Service
53 std::shared_ptr<Player> create_session(const Player::Configuration&);56 std::shared_ptr<Player> create_session(const Player::Configuration&);
57 void detach_session(const std::string&, const Player::Configuration&);
58 std::shared_ptr<Player> reattach_session(const std::string&, const Player::Configuration&);
59 void destroy_session(const std::string&, const media::Player::Configuration&);
54 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);60 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);
55 std::shared_ptr<Player> resume_session(Player::PlayerKey);61 std::shared_ptr<Player> resume_session(Player::PlayerKey);
56 void pause_other_sessions(Player::PlayerKey key);62 void pause_other_sessions(Player::PlayerKey key);
5763
=== modified file 'src/core/media/service_stub.cpp'
--- src/core/media/service_stub.cpp 2015-04-20 15:56:34 +0000
+++ src/core/media/service_stub.cpp 2015-04-20 15:56:34 +0000
@@ -58,7 +58,7 @@
58std::shared_ptr<media::Player> media::ServiceStub::create_session(const media::Player::Configuration&)58std::shared_ptr<media::Player> media::ServiceStub::create_session(const media::Player::Configuration&)
59{59{
60 auto op = d->object->invoke_method_synchronously<mpris::Service::CreateSession,60 auto op = d->object->invoke_method_synchronously<mpris::Service::CreateSession,
61 dbus::types::ObjectPath>();61 std::tuple<dbus::types::ObjectPath, std::string>>();
6262
63 if (op.is_error())63 if (op.is_error())
64 throw std::runtime_error("Problem creating session: " + op.error());64 throw std::runtime_error("Problem creating session: " + op.error());
@@ -67,8 +67,44 @@
67 {67 {
68 shared_from_this(),68 shared_from_this(),
69 access_service(),69 access_service(),
70 access_service()->object_for_path(op.value())70 access_service()->object_for_path(std::get<0>(op.value())),
71 });71 std::get<1>(op.value())
72 });
73}
74
75void media::ServiceStub::detach_session(const std::string& uuid, const media::Player::Configuration&)
76{
77 auto op = d->object->invoke_method_synchronously<mpris::Service::DetachSession,
78 void>(uuid);
79
80 if (op.is_error())
81 throw std::runtime_error("Problem detaching session: " + op.error());
82}
83
84std::shared_ptr<media::Player> media::ServiceStub::reattach_session(const std::string& uuid, const media::Player::Configuration&)
85{
86 auto op = d->object->invoke_method_synchronously<mpris::Service::ReattachSession,
87 dbus::types::ObjectPath>(uuid);
88
89 if (op.is_error())
90 throw std::runtime_error("Problem reattaching session: " + op.error());
91
92 return std::shared_ptr<media::Player>(new media::PlayerStub
93 {
94 shared_from_this(),
95 access_service(),
96 access_service()->object_for_path(op.value()),
97 uuid
98 });
99}
100
101void media::ServiceStub::destroy_session(const std::string& uuid, const media::Player::Configuration&)
102{
103 auto op = d->object->invoke_method_synchronously<mpris::Service::DestroySession,
104 void>(uuid);
105
106 if (op.is_error())
107 throw std::runtime_error("Problem destroying session: " + op.error());
72}108}
73109
74std::shared_ptr<media::Player> media::ServiceStub::create_fixed_session(const std::string& name, const media::Player::Configuration&)110std::shared_ptr<media::Player> media::ServiceStub::create_fixed_session(const std::string& name, const media::Player::Configuration&)
75111
=== modified file 'src/core/media/service_stub.h'
--- src/core/media/service_stub.h 2014-10-23 14:42:59 +0000
+++ src/core/media/service_stub.h 2015-04-20 15:56:34 +0000
@@ -40,6 +40,9 @@
40 ~ServiceStub();40 ~ServiceStub();
4141
42 std::shared_ptr<Player> create_session(const Player::Configuration&);42 std::shared_ptr<Player> create_session(const Player::Configuration&);
43 void detach_session(const std::string& uuid, const Player::Configuration&);
44 std::shared_ptr<Player> reattach_session(const std::string& uuid, const Player::Configuration&);
45 void destroy_session(const std::string& uuid, const Player::Configuration&);
43 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);46 std::shared_ptr<Player> create_fixed_session(const std::string& name, const Player::Configuration&);
44 std::shared_ptr<Player> resume_session(Player::PlayerKey key);47 std::shared_ptr<Player> resume_session(Player::PlayerKey key);
45 void pause_other_sessions(Player::PlayerKey key);48 void pause_other_sessions(Player::PlayerKey key);
4649
=== modified file 'tests/test-track-list/test_track_list.cpp'
--- tests/test-track-list/test_track_list.cpp 2015-04-20 15:56:34 +0000
+++ tests/test-track-list/test_track_list.cpp 2015-04-20 15:56:34 +0000
@@ -44,7 +44,7 @@
44{44{
45}45}
4646
47void media::TestTrackList::create_new_player_session()47std::string media::TestTrackList::create_new_player_session()
48{48{
49 try {49 try {
50 m_hubPlayerSession = m_hubService->create_session(media::Player::Client::default_configuration());50 m_hubPlayerSession = m_hubService->create_session(media::Player::Client::default_configuration());
@@ -59,12 +59,53 @@
59 catch (std::runtime_error &e) {59 catch (std::runtime_error &e) {
60 cerr << "FATAL: Failed to retrieve the current player's TrackList: " << e.what() << endl;60 cerr << "FATAL: Failed to retrieve the current player's TrackList: " << e.what() << endl;
61 }61 }
62}62
6363 std::string uuid;
64void media::TestTrackList::destroy_player_session()64 try {
65{65 uuid.assign(m_hubPlayerSession->uuid());
66 // TODO: explicitly add a destroy session to the Service class after ricmm lands his new creation_session66 }
67 // that returns a session ID. This will allow me to clear the tracklist after each test.67 catch (std::runtime_error &e) {
68 cerr << "FATAL: Failed to retrieve the current player's uuid: " << e.what() << endl;
69 }
70
71 cout << "Connected to session " << uuid << endl;
72 return uuid;
73}
74
75void media::TestTrackList::detach_player_session(const std::string &uuid)
76{
77 try {
78 m_hubService->detach_session(uuid, media::Player::Client::default_configuration());
79 }
80 catch (std::runtime_error &e) {
81 cerr << "FATAL: Failed to detach the media-hub player session: " << e.what() << endl;
82 }
83
84 cout << "Detached session " << uuid << endl;
85}
86
87void media::TestTrackList::reattach_player_session(const std::string &uuid)
88{
89 try {
90 m_hubPlayerSession = m_hubService->reattach_session(uuid, media::Player::Client::default_configuration());
91 }
92 catch (std::runtime_error &e) {
93 cerr << "FATAL: Failed to reattach the media-hub player session: " << e.what() << endl;
94 }
95
96 try {
97 m_hubTrackList = m_hubPlayerSession->track_list();
98 }
99 catch (std::runtime_error &e) {
100 cerr << "FATAL: Failed to retrieve the current player's TrackList: " << e.what() << endl;
101 }
102
103 cout << "Re-connected to session " << uuid << endl;
104}
105
106void media::TestTrackList::destroy_player_session(const std::string &uuid)
107{
108 m_hubService->destroy_session(uuid, media::Player::Client::default_configuration());
68 m_hubPlayerSession.reset();109 m_hubPlayerSession.reset();
69}110}
70111
@@ -92,13 +133,13 @@
92{133{
93 cout << "--> Running test: test_basic_playback" << std::endl;134 cout << "--> Running test: test_basic_playback" << std::endl;
94135
95 core::Connection c =m_hubTrackList->on_track_added().connect([](const media::Track::Id &new_id)136 const std::string uuid = create_new_player_session();
137
138 core::Connection c = m_hubTrackList->on_track_added().connect([](const media::Track::Id &new_id)
96 {139 {
97 cout << "Added track to TrackList with Id: " << new_id << endl;140 cout << "Added track to TrackList with Id: " << new_id << endl;
98 });141 });
99142
100 //create_new_player_session();
101
102 m_hubPlayerSession->open_uri(uri1);143 m_hubPlayerSession->open_uri(uri1);
103 if (!uri2.empty())144 if (!uri2.empty())
104 add_track(uri2);145 add_track(uri2);
@@ -118,13 +159,34 @@
118159
119 c.disconnect();160 c.disconnect();
120161
121 //destroy_player_session();162 destroy_player_session(uuid);
163}
164
165void media::TestTrackList::test_tracklist_resume(const std::string &uri1, const std::string &uri2, const std::string &uuid)
166{
167 cout << "--> Running test: test_tracklist_resume" << std::endl;
168
169 add_track(uri1);
170 add_track(uri2);
171
172 const size_t initial_size = m_hubTrackList->tracks().get().size();
173 cout << "Tracklist size: " << initial_size << endl;
174 detach_player_session(uuid);
175 reattach_player_session(uuid);
176 cout << "Tracklist size: " << m_hubTrackList->tracks().get().size() << endl;
177
178 m_hubPlayerSession->play();
179
180 if (initial_size != m_hubTrackList->tracks().get().size())
181 cout << "Tracklist sizes are different, error in resuming" << endl;
122}182}
123183
124void media::TestTrackList::test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2)184void media::TestTrackList::test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2)
125{185{
126 cout << "--> Running test: test_ensure_tracklist_is_not_empty" << std::endl;186 cout << "--> Running test: test_ensure_tracklist_is_not_empty" << std::endl;
127187
188 const std::string uuid = create_new_player_session();
189
128 add_track(uri1);190 add_track(uri1);
129 if (!uri2.empty())191 if (!uri2.empty())
130 add_track(uri2);192 add_track(uri2);
@@ -133,13 +195,15 @@
133 cout << "TrackList is not empty, test success" << endl;195 cout << "TrackList is not empty, test success" << endl;
134 else196 else
135 cout << "TrackList is empty, test failure" << endl;197 cout << "TrackList is empty, test failure" << endl;
198
199 destroy_player_session(uuid);
136}200}
137201
138void media::TestTrackList::test_has_next_track(const std::string &uri1, const std::string &uri2)202void media::TestTrackList::test_has_next_track(const std::string &uri1, const std::string &uri2)
139{203{
140 cout << "--> Running test: test_has_next_track" << std::endl;204 cout << "--> Running test: test_has_next_track" << std::endl;
141205
142 //create_new_player_session();206 const std::string uuid = create_new_player_session();
143207
144 add_track(uri1);208 add_track(uri1);
145 add_track(uri2);209 add_track(uri2);
@@ -158,13 +222,15 @@
158 else222 else
159 cerr << "Playback did not start successfully" << endl;223 cerr << "Playback did not start successfully" << endl;
160224
161 //destroy_player_session();225 destroy_player_session(uuid);
162}226}
163227
164void media::TestTrackList::test_shuffle(const std::string &uri1, const std::string &uri2, const std::string &uri3)228void media::TestTrackList::test_shuffle(const std::string &uri1, const std::string &uri2, const std::string &uri3)
165{229{
166 cout << "--> Running test: test_shuffle" << std::endl;230 cout << "--> Running test: test_shuffle" << std::endl;
167231
232 const std::string uuid = create_new_player_session();
233
168 add_track(uri1);234 add_track(uri1);
169 add_track(uri2);235 add_track(uri2);
170 add_track(uri3);236 add_track(uri3);
@@ -189,22 +255,27 @@
189 cout << "Waiting for second track to finish playing..." << endl;255 cout << "Waiting for second track to finish playing..." << endl;
190 wait_for_about_to_finish();256 wait_for_about_to_finish();
191257
192 cout << "Going straight to the Track with Id of '/core/ubuntu/media/Service/sessions/0/TrackList/4'" << std::endl;258 const media::Track::Id id{m_hubTrackList->tracks().get()[3]};
193 const media::Track::Id id{"/core/ubuntu/media/Service/sessions/0/TrackList/4"};259 cout << "Going straight to the Track with Id " << id << std::endl;
194 const bool toggle_player_state = true;260 const bool toggle_player_state = true;
195 m_hubTrackList->go_to(id, toggle_player_state);261 m_hubTrackList->go_to(id, toggle_player_state);
262
196 cout << "Waiting for third track to finish playing..." << endl;263 cout << "Waiting for third track to finish playing..." << endl;
197 wait_for_about_to_finish();264 wait_for_about_to_finish();
198 }265 }
199 else266 else
200 cerr << "Playback did not start successfully" << endl;267 cerr << "Playback did not start successfully" << endl;
268
269 destroy_player_session(uuid);
201}270}
202271
203void media::TestTrackList::test_remove_track(const std::string &uri1, const std::string &uri2, const std::string &uri3)272void media::TestTrackList::test_remove_track(const std::string &uri1, const std::string &uri2, const std::string &uri3)
204{273{
205 cout << "--> Running test: test_remove_track" << std::endl;274 cout << "--> Running test: test_remove_track" << std::endl;
206275
207 core::Connection c =m_hubTrackList->on_track_removed().connect([](const media::Track::Id &new_id)276 const std::string uuid = create_new_player_session();
277
278 core::Connection c = m_hubTrackList->on_track_removed().connect([](const media::Track::Id &new_id)
208 {279 {
209 cout << "Removed track from TrackList with Id: " << new_id << endl;280 cout << "Removed track from TrackList with Id: " << new_id << endl;
210 });281 });
@@ -220,7 +291,8 @@
220 cout << "Waiting for first track to finish playing..." << endl;291 cout << "Waiting for first track to finish playing..." << endl;
221 wait_for_about_to_finish();292 wait_for_about_to_finish();
222293
223 const media::Track::Id id{"/core/ubuntu/media/Service/sessions/0/TrackList/1"};294 const media::Track::Id id{m_hubTrackList->tracks().get()[1]};
295 cout << "Removing Track with Id of '" << id << "'" << std::endl;
224 m_hubTrackList->remove_track(id);296 m_hubTrackList->remove_track(id);
225297
226 cout << "Waiting for track after removed track to finish playing..." << endl;298 cout << "Waiting for track after removed track to finish playing..." << endl;
@@ -228,6 +300,8 @@
228 }300 }
229 else301 else
230 cerr << "Playback did not start successfully" << endl;302 cerr << "Playback did not start successfully" << endl;
303
304 destroy_player_session(uuid);
231}305}
232306
233template<class T>307template<class T>
@@ -316,26 +390,31 @@
316390
317 if (argc == 2)391 if (argc == 2)
318 {392 {
319 tracklist->create_new_player_session();
320 tracklist->test_basic_playback(argv[1]);393 tracklist->test_basic_playback(argv[1]);
321 tracklist->test_ensure_tracklist_is_not_empty(argv[1]);394 tracklist->test_ensure_tracklist_is_not_empty(argv[1]);
322 }395 }
323 else if (argc == 3)396 else if (argc == 3)
324 {397 {
325 tracklist->create_new_player_session();
326 tracklist->test_basic_playback(argv[1], argv[2]);398 tracklist->test_basic_playback(argv[1], argv[2]);
327 tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]);399 tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]);
328 tracklist->test_has_next_track(argv[1], argv[2]);400 tracklist->test_has_next_track(argv[1], argv[2]);
329 }401 }
330 else if (argc == 4)402 else if (argc == 4)
331 {403 {
332 tracklist->create_new_player_session();
333 tracklist->test_basic_playback(argv[1]);404 tracklist->test_basic_playback(argv[1]);
334 tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]);405 tracklist->test_ensure_tracklist_is_not_empty(argv[1], argv[2]);
335 tracklist->test_has_next_track(argv[1], argv[2]);406 tracklist->test_has_next_track(argv[1], argv[2]);
336 tracklist->test_shuffle(argv[1], argv[2], argv[3]);407 tracklist->test_shuffle(argv[1], argv[2], argv[3]);
337 tracklist->test_remove_track(argv[1], argv[2], argv[3]);408 tracklist->test_remove_track(argv[1], argv[2], argv[3]);
338 }409 }
410 else if (argc == 5)
411 {
412 std::string uuid = tracklist->create_new_player_session();
413
414 tracklist->test_tracklist_resume(argv[1], argv[2], uuid);
415
416 tracklist->destroy_player_session(uuid);
417 }
339 else418 else
340 {419 {
341 cout << "Can't test TrackList, no track(s) specified." << endl;420 cout << "Can't test TrackList, no track(s) specified." << endl;
342421
=== modified file 'tests/test-track-list/test_track_list.h'
--- tests/test-track-list/test_track_list.h 2015-04-20 15:56:34 +0000
+++ tests/test-track-list/test_track_list.h 2015-04-20 15:56:34 +0000
@@ -45,14 +45,19 @@
45 TestTrackList();45 TestTrackList();
46 ~TestTrackList();46 ~TestTrackList();
4747
48 void create_new_player_session();48 std::string create_new_player_session();
49 void destroy_player_session();49 void detach_player_session(const std::string &uuid);
50 void reattach_player_session(const std::string &uuid);
51 void destroy_player_session(const std::string &uuid);
5052
51 void add_track(const std::string &uri, bool make_current = false);53 void add_track(const std::string &uri, bool make_current = false);
5254
53 // Takes in one or two files for playback, adds it/them to the TrackList, and plays55 // Takes in one or two files for playback, adds it/them to the TrackList, and plays
54 void test_basic_playback(const std::string &uri1, const std::string &uri2 = std::string{});56 void test_basic_playback(const std::string &uri1, const std::string &uri2 = std::string{});
5557
58 // Takes two uris and confirms that they remain after a detach/reattach
59 void test_tracklist_resume(const std::string &uri1, const std::string &uri2, const std::string &uuid);
60
56 void test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2 = std::string{});61 void test_ensure_tracklist_is_not_empty(const std::string &uri1, const std::string &uri2 = std::string{});
5762
58 // Takes in one or two files for playback, adds it/them to the TrackList, plays and makes sure63 // Takes in one or two files for playback, adds it/them to the TrackList, plays and makes sure

Subscribers

People subscribed via source and target branches